From b0611627c150a473a838e4d8d011be8ed5035be2 Mon Sep 17 00:00:00 2001
From: Lingxiao Jiang
Date: Sun, 17 Oct 2010 11:33:26 +0800
Subject: [PATCH] Release 1.2
---
LICENSE | 30 +
README | 259 ++
.../sample-clone-report_100_0_allg_1.0_50 | 15 +
samples/config | 70 +
samples/src/AbstractAsyncTableRendering.java | 3065 ++++++++++++++
samples/src/AbstractTableRendering.java | 3740 +++++++++++++++++
samples/vectors/sample-vectors_100_0 | 188 +
scripts/bugdetect/bugcounting | 66 +
scripts/bugdetect/bugfiltering | 92 +
scripts/bugdetect/bugmerging | 165 +
scripts/bugdetect/bugordering | 101 +
scripts/bugdetect/bugtypecounting | 153 +
scripts/bugdetect/mergecomments | 178 +
scripts/clonedetect/cd_coverage | 68 +
scripts/clonedetect/config-sample | 102 +
scripts/clonedetect/configure | 132 +
scripts/clonedetect/deckard.sh | 133 +
scripts/clonedetect/generateparam | 48 +
scripts/clonedetect/paramsetting | 96 +
scripts/clonedetect/post_process_groupfile | 248 ++
scripts/clonedetect/vdbgen | 159 +
scripts/clonedetect/vertical-param-batch | 434 ++
src/examples/GridLayout.java | 742 ++++
src/examples/swim3.c | 1155 +++++
src/include/ptree.h | 295 ++
src/lsh/Makefile | 79 +
src/lsh/README | 85 +
src/lsh/bin/compile | 32 +
src/lsh/bin/exact | 18 +
src/lsh/bin/lsh | 42 +
src/lsh/bin/lsh_computeParams | 38 +
src/lsh/bin/lsh_fromParams | 27 +
src/lsh/manual.ps | Bin 0 -> 233549 bytes
src/lsh/sources/BasicDefinitions.h | 200 +
src/lsh/sources/BucketHashing.cpp | 698 +++
src/lsh/sources/BucketHashing.h | 214 +
src/lsh/sources/Geometry.cpp | 39 +
src/lsh/sources/Geometry.h | 46 +
src/lsh/sources/GlobalVars.cpp | 19 +
src/lsh/sources/GlobalVars.h | 62 +
src/lsh/sources/LSHMain.cpp | 362 ++
src/lsh/sources/LocalitySensitiveHashing.cpp | 762 ++++
src/lsh/sources/LocalitySensitiveHashing.h | 162 +
src/lsh/sources/Makefile | 49 +
src/lsh/sources/NearNeighbors.cpp | 199 +
src/lsh/sources/NearNeighbors.h | 27 +
src/lsh/sources/Random.cpp | 76 +
src/lsh/sources/Random.h | 31 +
src/lsh/sources/SelfTuning.cpp | 574 +++
src/lsh/sources/SelfTuning.h | 47 +
src/lsh/sources/Util.cpp | 88 +
src/lsh/sources/Util.h | 35 +
src/lsh/sources/compareOutputs.cpp | 126 +
src/lsh/sources/enumBuckets.cpp | 733 ++++
src/lsh/sources/exactNNs.cpp | 186 +
src/lsh/sources/exploreBuckets.cpp | 431 ++
src/lsh/sources/genDS.cpp | 75 +
src/lsh/sources/genPlantedDS.cpp | 81 +
src/lsh/sources/headers.h | 41 +
src/lsh/sources/testFloat.cpp | 24 +
src/main/Makefile | 118 +
src/main/bugmain.cc | 172 +
src/main/build.sh | 89 +
src/main/clean.sh | 59 +
src/main/main.cc | 296 ++
src/main/out2html.C | 86 +
src/main/out2xml.C | 95 +
src/main/parseTreeMain.cc | 141 +
src/main/ptree.cc | 423 ++
src/ptgen/Makefile | 47 +
src/ptgen/YaccLexer.py | 483 +++
src/ptgen/YaccParser.py | 269 ++
src/ptgen/antlr.py | 2833 +++++++++++++
src/ptgen/gcc/Makefile | 60 +
src/ptgen/gcc/c.l | 408 ++
src/ptgen/gcc/c.y | 2233 ++++++++++
src/ptgen/gcc/c.y.foot | 12 +
src/ptgen/gcc/c.y.head | 97 +
src/ptgen/gcc/catomicNodes.h | 34 +
src/ptgen/gcc/ccontextualNodes.h | 42 +
src/ptgen/gcc/cparentNodes.h | 37 +
src/ptgen/gcc/crelevantNodes.h | 129 +
src/ptgen/gcc/main.cc | 69 +
src/ptgen/gcc/mainc.py | 184 +
src/ptgen/java/Makefile | 60 +
src/ptgen/java/j.l | 225 +
src/ptgen/java/j.y | 2076 +++++++++
src/ptgen/java/j.y.foot | 12 +
src/ptgen/java/j.y.head | 54 +
src/ptgen/java/jatomicNodes.h | 34 +
src/ptgen/java/jcontextualNodes.h | 55 +
src/ptgen/java/jparentNodes.h | 34 +
src/ptgen/java/jrelevantNodes.h | 175 +
src/ptgen/java/main.cc | 66 +
src/ptgen/java/mainj.py | 187 +
src/ptgen/php5/Makefile | 61 +
src/ptgen/php5/mainphp.py | 187 +
src/ptgen/php5/phpatomicNodes.h | 97 +
src/ptgen/php5/phpcontextualNodes.h | 45 +
src/ptgen/php5/phpparentNodes.h | 40 +
src/ptgen/php5/phprelevantNodes.h | 242 ++
src/ptgen/php5/zend_language_parser.y | 778 ++++
src/ptgen/php5/zend_language_parser.y.foot | 12 +
src/ptgen/php5/zend_language_parser.y.head | 97 +
src/ptgen/php5/zend_language_scanner.l | 941 +++++
src/ptgen/simple/Makefile | 54 +
src/ptgen/simple/c.l | 450 ++
src/ptgen/simple/c.y | 419 ++
src/ptgen/simple/c.y.foot | 13 +
src/ptgen/simple/c.y.head | 14 +
src/ptgen/simple/main.cc | 60 +
src/ptgen/simple/tokid.h | 179 +
src/ptgen/yacc.g | 156 +
src/vgen/samplevec | 21 +
src/vgen/tra-gen-test.C | 45 +
src/vgen/treeTra/Makefile | 76 +
src/vgen/treeTra/clone-context-php.C | 417 ++
src/vgen/treeTra/clone-context-php.h | 59 +
src/vgen/treeTra/node-vec-gen.C | 119 +
src/vgen/treeTra/node-vec-gen.h | 66 +
src/vgen/treeTra/sq-tree.C | 213 +
src/vgen/treeTra/sq-tree.h | 93 +
src/vgen/treeTra/token-counter.C | 205 +
src/vgen/treeTra/token-counter.h | 90 +
src/vgen/treeTra/token-tree-map.C | 1414 +++++++
src/vgen/treeTra/token-tree-map.h | 201 +
src/vgen/treeTra/tra-gen.C | 215 +
src/vgen/treeTra/tra-gen.h | 70 +
src/vgen/treeTra/tree-accessor.C | 342 ++
src/vgen/treeTra/tree-accessor.h | 66 +
src/vgen/treeTra/tree-traversal.C | 157 +
src/vgen/treeTra/tree-vector.C | 397 ++
src/vgen/treeTra/tree-vector.h | 89 +
src/vgen/treeTra/vector-merger.C | 670 +++
src/vgen/treeTra/vector-merger.h | 131 +
src/vgen/treeTra/vector-output.C | 168 +
src/vgen/treeTra/vector-output.h | 77 +
src/vgen/treeTra/vgen-config.C | 192 +
src/vgen/treeTra/vgen-config.h | 88 +
src/vgen/treeTra/vgen-utils.c | 59 +
src/vgen/treeTra/vgen-utils.h | 57 +
src/vgen/vgrouping/Makefile | 45 +
src/vgen/vgrouping/computeranges.c | 145 +
src/vgen/vgrouping/dispatchvectors.c | 414 ++
src/vgen/vgrouping/rundispatch | 97 +
src/vgen/vgrouping/rundispatchonefile | 97 +
src/vgen/vgrouping/runsplit | 74 +
src/vgen/vgrouping/runvectorsort | 74 +
src/vgen/vgrouping/split.c | 490 +++
src/vgen/vgrouping/vectorsort.c | 411 ++
150 files changed, 40325 insertions(+)
create mode 100644 LICENSE
create mode 100755 README
create mode 100644 samples/clusters/sample-clone-report_100_0_allg_1.0_50
create mode 100644 samples/config
create mode 100644 samples/src/AbstractAsyncTableRendering.java
create mode 100644 samples/src/AbstractTableRendering.java
create mode 100644 samples/vectors/sample-vectors_100_0
create mode 100644 scripts/bugdetect/bugcounting
create mode 100644 scripts/bugdetect/bugfiltering
create mode 100644 scripts/bugdetect/bugmerging
create mode 100644 scripts/bugdetect/bugordering
create mode 100644 scripts/bugdetect/bugtypecounting
create mode 100644 scripts/bugdetect/mergecomments
create mode 100644 scripts/clonedetect/cd_coverage
create mode 100644 scripts/clonedetect/config-sample
create mode 100644 scripts/clonedetect/configure
create mode 100644 scripts/clonedetect/deckard.sh
create mode 100644 scripts/clonedetect/generateparam
create mode 100644 scripts/clonedetect/paramsetting
create mode 100644 scripts/clonedetect/post_process_groupfile
create mode 100644 scripts/clonedetect/vdbgen
create mode 100644 scripts/clonedetect/vertical-param-batch
create mode 100644 src/examples/GridLayout.java
create mode 100644 src/examples/swim3.c
create mode 100755 src/include/ptree.h
create mode 100755 src/lsh/Makefile
create mode 100755 src/lsh/README
create mode 100755 src/lsh/bin/compile
create mode 100755 src/lsh/bin/exact
create mode 100755 src/lsh/bin/lsh
create mode 100755 src/lsh/bin/lsh_computeParams
create mode 100755 src/lsh/bin/lsh_fromParams
create mode 100755 src/lsh/manual.ps
create mode 100755 src/lsh/sources/BasicDefinitions.h
create mode 100755 src/lsh/sources/BucketHashing.cpp
create mode 100755 src/lsh/sources/BucketHashing.h
create mode 100755 src/lsh/sources/Geometry.cpp
create mode 100755 src/lsh/sources/Geometry.h
create mode 100755 src/lsh/sources/GlobalVars.cpp
create mode 100755 src/lsh/sources/GlobalVars.h
create mode 100755 src/lsh/sources/LSHMain.cpp
create mode 100755 src/lsh/sources/LocalitySensitiveHashing.cpp
create mode 100755 src/lsh/sources/LocalitySensitiveHashing.h
create mode 100755 src/lsh/sources/Makefile
create mode 100755 src/lsh/sources/NearNeighbors.cpp
create mode 100755 src/lsh/sources/NearNeighbors.h
create mode 100755 src/lsh/sources/Random.cpp
create mode 100755 src/lsh/sources/Random.h
create mode 100755 src/lsh/sources/SelfTuning.cpp
create mode 100755 src/lsh/sources/SelfTuning.h
create mode 100755 src/lsh/sources/Util.cpp
create mode 100755 src/lsh/sources/Util.h
create mode 100755 src/lsh/sources/compareOutputs.cpp
create mode 100755 src/lsh/sources/enumBuckets.cpp
create mode 100755 src/lsh/sources/exactNNs.cpp
create mode 100755 src/lsh/sources/exploreBuckets.cpp
create mode 100755 src/lsh/sources/genDS.cpp
create mode 100755 src/lsh/sources/genPlantedDS.cpp
create mode 100755 src/lsh/sources/headers.h
create mode 100755 src/lsh/sources/testFloat.cpp
create mode 100755 src/main/Makefile
create mode 100755 src/main/bugmain.cc
create mode 100755 src/main/build.sh
create mode 100644 src/main/clean.sh
create mode 100755 src/main/main.cc
create mode 100755 src/main/out2html.C
create mode 100755 src/main/out2xml.C
create mode 100755 src/main/parseTreeMain.cc
create mode 100755 src/main/ptree.cc
create mode 100644 src/ptgen/Makefile
create mode 100755 src/ptgen/YaccLexer.py
create mode 100755 src/ptgen/YaccParser.py
create mode 100755 src/ptgen/antlr.py
create mode 100755 src/ptgen/gcc/Makefile
create mode 100755 src/ptgen/gcc/c.l
create mode 100755 src/ptgen/gcc/c.y
create mode 100755 src/ptgen/gcc/c.y.foot
create mode 100755 src/ptgen/gcc/c.y.head
create mode 100644 src/ptgen/gcc/catomicNodes.h
create mode 100644 src/ptgen/gcc/ccontextualNodes.h
create mode 100644 src/ptgen/gcc/cparentNodes.h
create mode 100644 src/ptgen/gcc/crelevantNodes.h
create mode 100755 src/ptgen/gcc/main.cc
create mode 100644 src/ptgen/gcc/mainc.py
create mode 100755 src/ptgen/java/Makefile
create mode 100755 src/ptgen/java/j.l
create mode 100755 src/ptgen/java/j.y
create mode 100755 src/ptgen/java/j.y.foot
create mode 100755 src/ptgen/java/j.y.head
create mode 100644 src/ptgen/java/jatomicNodes.h
create mode 100644 src/ptgen/java/jcontextualNodes.h
create mode 100644 src/ptgen/java/jparentNodes.h
create mode 100644 src/ptgen/java/jrelevantNodes.h
create mode 100755 src/ptgen/java/main.cc
create mode 100644 src/ptgen/java/mainj.py
create mode 100755 src/ptgen/php5/Makefile
create mode 100644 src/ptgen/php5/mainphp.py
create mode 100755 src/ptgen/php5/phpatomicNodes.h
create mode 100755 src/ptgen/php5/phpcontextualNodes.h
create mode 100755 src/ptgen/php5/phpparentNodes.h
create mode 100755 src/ptgen/php5/phprelevantNodes.h
create mode 100755 src/ptgen/php5/zend_language_parser.y
create mode 100755 src/ptgen/php5/zend_language_parser.y.foot
create mode 100755 src/ptgen/php5/zend_language_parser.y.head
create mode 100755 src/ptgen/php5/zend_language_scanner.l
create mode 100755 src/ptgen/simple/Makefile
create mode 100755 src/ptgen/simple/c.l
create mode 100755 src/ptgen/simple/c.y
create mode 100644 src/ptgen/simple/c.y.foot
create mode 100644 src/ptgen/simple/c.y.head
create mode 100755 src/ptgen/simple/main.cc
create mode 100755 src/ptgen/simple/tokid.h
create mode 100755 src/ptgen/yacc.g
create mode 100755 src/vgen/samplevec
create mode 100755 src/vgen/tra-gen-test.C
create mode 100755 src/vgen/treeTra/Makefile
create mode 100755 src/vgen/treeTra/clone-context-php.C
create mode 100755 src/vgen/treeTra/clone-context-php.h
create mode 100755 src/vgen/treeTra/node-vec-gen.C
create mode 100755 src/vgen/treeTra/node-vec-gen.h
create mode 100755 src/vgen/treeTra/sq-tree.C
create mode 100755 src/vgen/treeTra/sq-tree.h
create mode 100755 src/vgen/treeTra/token-counter.C
create mode 100755 src/vgen/treeTra/token-counter.h
create mode 100755 src/vgen/treeTra/token-tree-map.C
create mode 100755 src/vgen/treeTra/token-tree-map.h
create mode 100755 src/vgen/treeTra/tra-gen.C
create mode 100755 src/vgen/treeTra/tra-gen.h
create mode 100755 src/vgen/treeTra/tree-accessor.C
create mode 100755 src/vgen/treeTra/tree-accessor.h
create mode 100755 src/vgen/treeTra/tree-traversal.C
create mode 100755 src/vgen/treeTra/tree-vector.C
create mode 100755 src/vgen/treeTra/tree-vector.h
create mode 100755 src/vgen/treeTra/vector-merger.C
create mode 100755 src/vgen/treeTra/vector-merger.h
create mode 100755 src/vgen/treeTra/vector-output.C
create mode 100755 src/vgen/treeTra/vector-output.h
create mode 100755 src/vgen/treeTra/vgen-config.C
create mode 100755 src/vgen/treeTra/vgen-config.h
create mode 100755 src/vgen/treeTra/vgen-utils.c
create mode 100755 src/vgen/treeTra/vgen-utils.h
create mode 100755 src/vgen/vgrouping/Makefile
create mode 100644 src/vgen/vgrouping/computeranges.c
create mode 100644 src/vgen/vgrouping/dispatchvectors.c
create mode 100644 src/vgen/vgrouping/rundispatch
create mode 100644 src/vgen/vgrouping/rundispatchonefile
create mode 100755 src/vgen/vgrouping/runsplit
create mode 100755 src/vgen/vgrouping/runvectorsort
create mode 100755 src/vgen/vgrouping/split.c
create mode 100755 src/vgen/vgrouping/vectorsort.c
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4c77d6c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+
+Copyright (c) 2007-2010,
+ Lingxiao Jiang
+ Ghassan Misherghi
+ Zhendong Su
+ Stephane Glondu
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the University of California nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README b/README
new file mode 100755
index 0000000..641c8a8
--- /dev/null
+++ b/README
@@ -0,0 +1,259 @@
+
+This is a release package of Deckard -- a tree-based, scalable, and accurate
+code clone detection tool. It is also capable of reporting clone-related bugs.
+
+
+**********************************************************************
+*
+* LICENSE
+*
+**********************************************************************
+
+Copyright (c) 2007-2010, University of California
+ Lingxiao Jiang
+ Ghassan Misherghi
+ Zhendong Su
+ Stephane Glondu
+All rights reserved.
+Three-clause BSD licence
+
+
+**********************************************************************
+*
+* Version 1.2
+* Oct 17, 2010
+*
+**********************************************************************
+
+
+**********************************************************************
+*
+* Installation
+*
+**********************************************************************
+
+In bash shell or cygwin, run the build script:
+
+/path/to/src/main/build.sh
+
+For convenience, add "src/main" into $PATH.
+
+NOTE: Deckard's built-in parser for Java cannot handle Java 1.5 or later
+features, which means when Deckard processes a Java 1.5 file, it is very likely
+there will be no vector generated.
+
+NOTE: The compiled executables may not be "executable" (showing "Permission
+Denied") on Windows Vista/7 due to false alarms of UAC rules (based on file
+path/hash of a .exe). A simple (but may not be desirable) workaround is to run
+cygwin shell with elevated privileges before invoking the above scripts. Also,
+Deckard's performance may be tens of times slower when executed in cygwin than
+on Linux due to slow I/O operations.
+
+To uninstall, simply
+
+/path/to/src/main/clean.sh
+
+
+*********************************************************************
+*
+* Usage
+*
+*********************************************************************
+
+1. For clone detection (suppose the source code of your application is
+in /path/to/app/src):
+
+ - Specify the location of your source code, say /path/to/app/src.
+
+ - Create a "config" file in /path/to/app/, following the sample "config" in
+ samples/ or the template "config-sample" in scripts/clonedetect/. Make sure
+ all paths are valid and the programming language is specified correctly.
+
+ - (Optional) create other three directories in /path/to/app/ for storing
+ outputs (see what's in samples/). These directories may be automatically
+ created if specified in 'config'.
+
+ - Batch mode run of clone detection (no bug detection by default):
+
+ "/path/to/scripts/clonedetect/deckard.sh"
+
+ An optional parameter to the script is 'clean', 'clean_all', or 'overwrite'
+
+ - Instead of running 'deckard.sh', you may also run the scripts called in
+ 'deckard.sh' step-by-step by yourself:
+
+ -- Vector generation: from where "config" is, run
+
+ "/path/to/scripts/clonedetect/vdbgen"
+
+ An optional parameter to the script is 'clean', 'clean_all', or 'overwrite'
+
+ -- Vector clustering (i.e., clone detection): from where "config" is, run
+
+ "/path/to/scripts/clonedetect/vertical-param-batch"
+
+ An optional parameter to the script is 'clean', 'clean_all', or 'overwrite'
+
+2. Vector generation for parts of a file:
+
+ - Identify the source file name, say /path/to/src/filename.java and the range
+ [s, e] of line numbers you'd like to have a vector generated
+
+ - Run "src/main/jvecgen [options] /path/to/src/filename.java --start-line-number s --end-line-number e"
+ Run "jvecgen -h" for more options. Note that different vecgen (cvecgen,
+ jvecgen, phpvecgen) should be used for files in different languages.
+
+This vecgen command will generate a vector representing the code between Line 's' and
+'e' in the source file, and store the vector in "filename.java.vec" by default.
+
+3. Detection of clone-related bugs:
+
+ - Invoke 'bugfiltering' on a clone report file with a specified language, e.g.,
+
+ /path/to/scripts/bugdetect/bugfiltering cluster_result c > bug_result
+
+ - Optionally transform 'bug_result' to a html file for easier inspection of
+ the reported potentially buggy clones in a web browser:
+
+ /path/to/src/main/out2html bug_result > bug_result.html
+
+ - See 'deckard.sh' for how to run it in a batch mode (not enabled by default).
+
+
+*********************************************************************
+*
+* What are in the package
+*
+*********************************************************************
+
+1. Organization
+
+The whole package is organized according to the several components in Deckard:
+
+ - Parse tree generation
+ -- src/include/ : a generic interface for trees
+ -- src/ptgen/ : ANTLR parser generator
+ -- src/ptgen/gcc : a grammar for C (GNU C extensions) and its parse tree generator
+ -- src/ptgen/java : a grammar for Java (<=1.4) and its parse tree generator
+ -- src/ptgen/php5 : a grammar for php5 and its parse tree generator
+
+ - Vector generation
+ -- src/vgen/treeTra/ : a generic tree traversal framework based on the
+ generic tree interface in src/include, and vector generation based on tree
+ traversal, mostly C++.
+ -- src/vgen/vgrouping/ : code for vector grouping (mix of C,C++,python,bash)
+
+ - Vector clustering
+ -- src/lsh/ : the LSH package and an interface for Deckard to use
+ (src/lsh/source/enumBuckets.cpp).
+
+ - Main entrances
+ -- src/main/ptree.cc : an implementation of the tree interface
+ -- src/main/main.cc : entrance for vector generation
+ -- src/main/parseTreeMain.cc : entrance for parse tree dumping, can be
+ useful for inspecting detected clones, bugs, and their related parse trees
+ -- src/main/bugmain.cc : entrance for bug filtering
+ -- src/main/out2html.C : entrance for adding html tags into clone/bug reports
+
+ - Scripts gluing things together
+ -- scripts/clonedetect/ : bash and python scripts
+ --- deckard.sh : batch-mode clone detection
+ --- vdbgen : batch-mode vector generation
+ --- vertical-param-batch : batch-mode vector clustering
+ -- scripts/bugdetect/ : bash and python scripts
+ -- various auxiliary scripts for simple statistics
+
+ - Others
+ -- README
+ -- LICENSE
+
+2. Details about the clone/bug detection algorithms can be found in these two
+papers:
+
+ - DECKARD: Scalable and Accurate Tree-based Detection of Code Clones, by
+ Lingxiao JIANG, Ghassan MISHERGHI, Zhendong SU, and Stephane GLONDU. In the
+ proceedings of 29th International Conference on Software Engineering (ICSE
+ '07), Minneapolis, Minnesota, USA, 2007.
+
+ - Context-Based Detection of Clone-Related Bugs, by Lingxiao JIANG, Zhendong
+ SU, and Edwin CHIU. In the proceedings of the 6th joint meeting of the
+ European Software Engineering Conference and the ACM SIGSOFT Symposium on the
+ Foundations of Software Engineering (ESEC/FSE'07), Dubrovnik, Croatia, 2007.
+
+
+**********************************************************************
+*
+* How to programmably use the vectors and the clone reports?
+*
+**********************************************************************
+
+1. How to get the subtree representing each clone?
+
+Each clone in the reports has a TBID and a TEID, in addition to the file name,
+and line numbers. The TBID and TEID uniquely identify the IDs of the first
+token and the last token in the clone from the original file (possibly
+containing parsing errors). To maintain consistent counting of the IDs, you
+should leave the work to "yyparse()" and Deckard's TokenCounter for how the IDs
+are calculated (see TraGenMain::run() for implementation details).
+
+The following are the main steps for getting the subtree for a clone (please
+refer to "src/vgen/treeTra/token-tree-map.h" for more implementation details):
+
+ - Given a line from the clone report file, parse it to get file name, line
+ numbers, TBID, and TEID, etc. C.f. the function:
+
+ bool parse(char * line, regex_t patterns[], int dim=ENUM_CLONE_THE_END)
+
+ - Call the following function (which calls "yyparse()" and a token counter) to
+ get a whole parse tree for the source file and the token IDs for every node:
+
+ ParseTree* TokenTreeMap::parseFile(const char * filename)
+
+ - Call the following function to get the smallest tree that contains all
+ tokens between TBID and TEID:
+
+ Tree* tokenRange2Tree2(std::pair tokenrange, ParseTree* pt)
+
+ - Then do whatever you'd like with the returned tree. Note that vectors are
+ NOT generated for this tree yet. If vectors are needed, do the following:
+
+ -- Create a new object of type TraGenMain and call "TraGenMain::run(0, 0)"
+ (c.f., src/main/main.cc)
+
+ -- Retrieve the vector for the tree:
+
+ TreeVector* tv = TreeAccessor::get_node_vector(Tree* tree_node_pointer)
+
+ -- If you also want some merged vectors from the child nodes of this tree,
+ that would require calls to TraGenMain::run() with different parameters
+ or adjust the internals of TraGenMain::run(), depending on how you want
+ the vectors to be presented to you. Feel free to improve the vector
+ generation, both the core and its interface/APIs.
+
+2. How to get the vector for a line or a sequence of lines from a file?
+
+ - Option 1: See above: Use "vector generation for parts of a file" with your
+ scripts.
+
+ - Option 2: Given the parse tree for a file (produced by
+ TokenTreeMap::parseFile() and yyparse()) and the starting and ending line
+ numbers, do the following:
+
+ -- (If not done before,) Call Deckard's vector generator on the parse tree
+ through TraGenMain::run, same as above. Please refer to src/main/main.cc,
+ TraGenMain::run(int startln, int endln), and
+ VecGenerator::traverse(Tree* root, Tree* init).
+
+ -- Call the following function (c.f. src/include/ptree.h, src/main/ptree.cc) to
+ return the smallest tree enclosing all elements from these lines:
+
+ Tree* ParseTree::line2Tree(int startln, int endln)
+
+ -- Then retrieve the vector (the actual vector generation is done beforehand):
+
+ TreeVector* tv = TreeAccessor::get_node_vector(tree_node_pointer)
+
+
+Enjoy and Feedback :=)
+@Deckard : Am I a clone?
+
diff --git a/samples/clusters/sample-clone-report_100_0_allg_1.0_50 b/samples/clusters/sample-clone-report_100_0_allg_1.0_50
new file mode 100644
index 0000000..f06c0b6
--- /dev/null
+++ b/samples/clusters/sample-clone-report_100_0_allg_1.0_50
@@ -0,0 +1,15 @@
+000000000 dist:0.0 FILE src/AbstractAsyncTableRendering.java LINE:845:46 NODE_KIND:103 nVARs:26 NUM_NODE:592 TBID:4144 TEID:4354
+000000001 dist:0.0 FILE src/AbstractTableRendering.java LINE:900:46 NODE_KIND:103 nVARs:26 NUM_NODE:592 TBID:3928 TEID:4138
+
+000000000 dist:0.0 FILE src/AbstractAsyncTableRendering.java LINE:1187:28 NODE_KIND:103 nVARs:16 NUM_NODE:364 TBID:5638 TEID:5757
+000000001 dist:0.0 FILE src/AbstractTableRendering.java LINE:960:28 NODE_KIND:103 nVARs:16 NUM_NODE:364 TBID:4188 TEID:4307
+
+000000000 dist:0.0 FILE src/AbstractAsyncTableRendering.java LINE:1226:28 NODE_KIND:103 nVARs:16 NUM_NODE:384 TBID:5806 TEID:5932
+000000001 dist:0.0 FILE src/AbstractTableRendering.java LINE:999:28 NODE_KIND:103 nVARs:16 NUM_NODE:384 TBID:4356 TEID:4482
+
+000000000 dist:0.0 FILE src/AbstractAsyncTableRendering.java LINE:1756:26 NODE_KIND:103 nVARs:17 NUM_NODE:380 TBID:7812 TEID:7951
+000000002 dist:0.0 FILE src/AbstractTableRendering.java LINE:1938:26 NODE_KIND:103 nVARs:17 NUM_NODE:380 TBID:7830 TEID:7969
+
+000000000 dist:0.0 FILE src/AbstractAsyncTableRendering.java LINE:2707:8 NODE_KIND:103 nVARs:15 NUM_NODE:332 TBID:11300 TEID:11407
+000000001 dist:0.0 FILE src/AbstractTableRendering.java LINE:3559:8 NODE_KIND:103 nVARs:15 NUM_NODE:332 TBID:13928 TEID:14035
+
diff --git a/samples/config b/samples/config
new file mode 100644
index 0000000..513c0f0
--- /dev/null
+++ b/samples/config
@@ -0,0 +1,70 @@
+###################################################################
+# Configuration file for clone detection.
+#
+
+###################################################################
+# Often, need to change these common parameters:
+# - FILE_PATTERN : for source files in different languages
+# - SRC_DIR : the root directory containing the source files
+# - DECKARD_DIR : Where is the home directory of DECKARD
+# - clone detection parameters: c.f. DECKARD's paper
+# -- MIN_TOKENS
+# -- STRIDE
+# -- SIMILARITY
+#
+# java, c, or php?
+FILE_PATTERN='*.java' # used for the 'find' command
+# where are the source files?
+SRC_DIR='src'
+# where is Deckard?
+DECKARD_DIR=".."
+# clone parameters; refer to paper.
+MIN_TOKENS='50 100'
+STRIDE='2 0'
+#DISTANCE='2.236 0.70711 1.58114'
+SIMILARITY='1.0 0.95'
+
+###################################################################
+# Where to store result files?
+#
+# where to output generated vectors?
+VECTOR_DIR='vectors'
+# where to output detected clone clusters?
+CLUSTER_DIR='clusters'
+# where to output timing/debugging info?
+TIME_DIR='times'
+
+###################################################################
+# where are several programs we need?
+#
+# where is the vector generator?
+VGEN_EXEC="$DECKARD_DIR/src/main"
+case $FILE_PATTERN in
+ *.java )
+ VGEN_EXEC="$VGEN_EXEC/jvecgen" ;;
+ *.php )
+ VGEN_EXEC="$VGEN_EXEC/phpvecgen" ;;
+ *.c | *.h )
+ VGEN_EXEC="$VGEN_EXEC/cvecgen" ;;
+ * )
+ echo "Error: invalid FILE_PATTERN: $FILE_PATTERN"
+ VGEN_EXEC="$VGEN_EXEC/invalidvecgen" ;;
+esac
+# how to divide the vectors into groups? It's just the directory name that matters
+GROUPING_EXEC="$DECKARD_DIR/src/vgen/vgrouping/runvectorsort"
+# where is the lsh?
+CLUSTER_EXEC="$DECKARD_DIR/src/lsh/bin/enumBuckets"
+# how to post process clone groups?
+POSTPRO_EXEC="$DECKARD_DIR/scripts/clonedetect/post_process_groupfile"
+# how to transform source code html?
+SRC2HTM_EXEC=source-highlight
+SRC2HTM_OPTS=--line-number-ref
+
+###################################################################
+# Some additional, internal parameters; can be ignored
+#
+# the maximal vector size for the first group; not really useful
+GROUPING_S='50'
+#GROUPING_D
+#GROUPING_C
+
diff --git a/samples/src/AbstractAsyncTableRendering.java b/samples/src/AbstractAsyncTableRendering.java
new file mode 100644
index 0000000..315f061
--- /dev/null
+++ b/samples/src/AbstractAsyncTableRendering.java
@@ -0,0 +1,3065 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.debug.internal.ui.memory.provisional;
+
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IMemoryBlockExtension;
+import org.eclipse.debug.core.model.MemoryByte;
+import org.eclipse.debug.internal.ui.DebugUIMessages;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.internal.ui.memory.IPersistableDebugElement;
+import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStatusMonitor;
+import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AbstractBaseTableRendering;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AbstractVirtualContentTableModel;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncCopyTableRenderingAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncPrintTableRenderingAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncTableRenderingCellModifier;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncTableRenderingViewer;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncVirtualContentTableViewer;
+import org.eclipse.debug.internal.ui.views.memory.renderings.CopyTableRenderingToClipboardAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.FormatTableRenderingAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.FormatTableRenderingDialog;
+import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressComposite;
+import org.eclipse.debug.internal.ui.views.memory.renderings.IPresentationErrorListener;
+import org.eclipse.debug.internal.ui.views.memory.renderings.IVirtualContentListener;
+import org.eclipse.debug.internal.ui.views.memory.renderings.MemorySegment;
+import org.eclipse.debug.internal.ui.views.memory.renderings.PendingPropertyChanges;
+import org.eclipse.debug.internal.ui.views.memory.renderings.PrintTableRenderingAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.ReformatAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.ResetToBaseAddressAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentDescriptor;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLine;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.memory.AbstractTableRendering;
+import org.eclipse.debug.ui.memory.IMemoryBlockTablePresentation;
+import org.eclipse.debug.ui.memory.IMemoryRendering;
+import org.eclipse.debug.ui.memory.IMemoryRenderingContainer;
+import org.eclipse.debug.ui.memory.IMemoryRenderingSite;
+import org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService;
+import org.eclipse.debug.ui.memory.IMemoryRenderingType;
+import org.eclipse.debug.ui.memory.IResettableMemoryRendering;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.IBasicPropertyConstants;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseTrackAdapter;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.dialogs.PropertyDialogAction;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.progress.UIJob;
+
+/**
+ * Abstract implementation of a table rendering.
+ *
+ * Clients should subclass from this class if they wish to provide a
+ * table rendering.
+ *
+ *
+ *
+ * The label of the rendering is constructed by retrieving the expression from
+ * IMemoryBlockExtension
. For IMemoryBlock, the label is constructed
+ * using the memory block's start address.
+ *
+ * This rendering manages the change states of its memory bytes if the memory
+ * block does not opt to manage the change states. For IMemoryBlockExtension, if
+ * the memory block returns false when #supportsChangeManagement() is called, this
+ * rendering will calculate the change state for each byte when its content is updated.
+ * Clients may manages the change states of its memory block by returning true when
+ * #supportsChangeManagement() is called. This will cause this rendering to stop
+ * calculating the change states of the memory block. Instead it would rely on the
+ * attributes returned in the MemoryByte array to determine if a byte has changed.
+ * For IMemoryBlock, this rendering will manage the change states its content.
+ *
+ * When firing change event, be aware of the following:
+ * - whenever a change event is fired, the content provider for Memory View
+ * view checks to see if memory has actually changed.
+ * - If memory has actually changed, a refresh will commence. Changes to the memory block
+ * will be computed and will be shown with the delta icons.
+ * - If memory has not changed, content will not be refreshed. However, previous delta information
+ * will be erased. The screen will be refreshed to show that no memory has been changed. (All
+ * delta icons will be removed.)
+ *
+ * Please note that these APIs will be called multiple times by the Memory View.
+ * To improve performance, debug adapters need to cache the content of its memory block and only
+ * retrieve updated data when necessary.
+ *
+
+ * @since 3.2
+ */
+public abstract class AbstractAsyncTableRendering extends AbstractBaseTableRendering implements IPropertyChangeListener, IResettableMemoryRendering {
+
+ /**
+ * Property identifier for the selected address in a table rendering
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_SELECTED_ADDRESS = AbstractTableRendering.PROPERTY_SELECTED_ADDRESS;
+
+ /**
+ * Property identifier for the column size in a table rendering
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_COL_SIZE = AbstractTableRendering.PROPERTY_COL_SIZE;
+
+ /**
+ * Property identifier for the top row address in a table rendering.
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_TOP_ADDRESS = AbstractTableRendering.PROPERTY_TOP_ADDRESS;
+
+ private static final String ID_ASYNC_TABLE_RENDERING_CONTEXT = "org.eclipse.debug.ui.memory.abstractasynctablerendering"; //$NON-NLS-1$
+ private static final String ID_GO_TO_ADDRESS_COMMAND = "org.eclipse.debug.ui.command.gotoaddress"; //$NON-NLS-1$
+
+ /**
+ * Property identifier for the row size in a table rendering
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_ROW_SIZE = AbstractTableRendering.PROPERTY_ROW_SIZE;
+
+ private boolean fActivated = false;
+
+// TODO: review use of MemorySegment, need to be careful to ensure flexible hierarchy
+
+ private class ToggleAddressColumnAction extends Action {
+
+ public ToggleAddressColumnAction() {
+ super();
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID
+ + ".ShowAddressColumnAction_context"); //$NON-NLS-1$
+ updateActionLabel();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.action.IAction#run()
+ */
+ public void run() {
+ fIsShowAddressColumn = !fIsShowAddressColumn;
+ if (!fIsShowAddressColumn)
+ {
+ fTableViewer.getTable().getColumn(0).setWidth(0);
+ }
+ else
+ {
+ fTableViewer.getTable().getColumn(0).pack();
+ }
+ updateActionLabel();
+ }
+
+ /**
+ *
+ */
+ private void updateActionLabel() {
+ if (fIsShowAddressColumn) {
+ setText(DebugUIMessages.ShowAddressColumnAction_0);
+ } else {
+ setText(DebugUIMessages.ShowAddressColumnAction_1);
+ }
+ }
+ }
+
+ private class NextPageAction extends Action
+ {
+ private NextPageAction()
+ {
+ super();
+ setText(DebugUIMessages.AbstractTableRendering_4);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".NextPageAction_context"); //$NON-NLS-1$
+ }
+
+ public void run() {
+ BigInteger address = fContentDescriptor.getLoadAddress();
+ address = address.add(BigInteger.valueOf(getPageSizeInUnits()));
+ handlePageStartAddressChanged(address);
+ }
+ }
+
+ private class PrevPageAction extends Action
+ {
+ private PrevPageAction()
+ {
+ super();
+ setText(DebugUIMessages.AbstractTableRendering_6);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".PrevPageAction_context"); //$NON-NLS-1$
+ }
+
+ public void run() {
+ BigInteger address = fContentDescriptor.getLoadAddress();
+ address = address.subtract(BigInteger.valueOf(getPageSizeInUnits()));
+ handlePageStartAddressChanged(address);
+ }
+ }
+
+ private class RenderingGoToAddressAction extends GoToAddressAction
+ {
+ public RenderingGoToAddressAction(AbstractBaseTableRendering rendering) {
+ super(rendering);
+ }
+
+ public void run() {
+ showGoToAddressComposite();
+ }
+ }
+
+ private class SwitchPageJob extends UIJob {
+ private Object fLock = new Object();
+ private boolean fShowMessagePage = false;
+ private String fMessage = ""; //$NON-NLS-1$
+
+ private SwitchPageJob() {
+ super("SwitchPageJob");//$NON-NLS-1$
+ setSystem(true);
+ }
+
+ private void setShowMessagePage(boolean showMsg) {
+ synchronized(fLock)
+ {
+ fShowMessagePage = showMsg;
+ }
+ }
+
+ private void setMessage(String message) {
+ synchronized(fLock)
+ {
+ fMessage = message;
+ }
+ }
+
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+
+ if (fPageBook.isDisposed())
+ return Status.OK_STATUS;
+
+ String msgToShow = null;
+ boolean showMsgPage = false;
+ synchronized (fLock) {
+ msgToShow = fMessage;
+ showMsgPage = fShowMessagePage;
+ }
+
+ if (showMsgPage) {
+ StyledText styleText = null;
+ fShowMessage = true;
+
+ styleText = fTextViewer.getTextWidget();
+
+ if (styleText != null)
+ styleText.setText(msgToShow);
+ fPageBook.showPage(fTextViewer.getControl());
+ } else {
+ fShowMessage = false;
+ fPageBook.showPage(fTableViewer.getControl().getParent());
+ }
+ return Status.OK_STATUS;
+ }
+ }
+
+
+ private class SerialByObjectRule implements ISchedulingRule
+ {
+ private Object fObject = null;
+
+ public SerialByObjectRule(Object lock) {
+ fObject = lock;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
+ */
+ public boolean contains(ISchedulingRule rule) {
+ return rule == this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
+ */
+ public boolean isConflicting(ISchedulingRule rule) {
+ if (rule instanceof SerialByObjectRule) {
+ SerialByObjectRule rRule = (SerialByObjectRule) rule;
+ return fObject == rRule.fObject;
+ }
+ return false;
+ }
+ }
+
+ private PageBook fPageBook;
+ private AsyncTableRenderingViewer fTableViewer;
+ private TextViewer fTextViewer;
+ private Shell fToolTipShell;
+ private MemoryViewPresentationContext fPresentationContext;
+ private int fAddressableSize;
+ private TableRenderingContentDescriptor fContentDescriptor;
+ private int fBytePerLine;
+ private int fColumnSize;
+ private boolean fShowMessage = false;
+ private String fLabel;
+ private IWorkbenchAdapter fWorkbenchAdapter;
+ private int fPageSize;
+ private SashForm fSashForm;
+ private GoToAddressComposite fGoToAddressComposite;
+
+ // actions
+ private GoToAddressAction fGoToAddressAction;
+ private PrintTableRenderingAction fPrintViewTabAction;
+ private CopyTableRenderingToClipboardAction fCopyToClipboardAction;
+ private FormatTableRenderingAction fFormatRenderingAction;
+ private ReformatAction fReformatAction;
+ private ToggleAddressColumnAction fToggleAddressColumnAction;
+ private ResetToBaseAddressAction fResetMemoryBlockAction;
+ private PropertyDialogAction fPropertiesDialogAction;
+ private NextPageAction fNextAction;
+ private PrevPageAction fPrevAction;
+
+ private ArrayList fContext = new ArrayList();
+ private AbstractHandler fGoToAddressHandler;
+
+ private boolean fIsCreated = false;
+ private boolean fIsDisposed = false;
+ private boolean fIsShowAddressColumn = true;
+
+ private SwitchPageJob fSwitchPageJob = new SwitchPageJob();
+ private boolean fError = false;
+
+ private PendingPropertyChanges fPendingSyncProperties;
+
+ // list of menu listeners for popupMenuMgr.
+ private ArrayList fMenuListeners;
+ private MenuManager fMenuMgr;
+
+ private ISchedulingRule serialByRenderingRule = new SerialByObjectRule(this);
+
+ /**
+ * Identifier for an empty group preceding all context menu actions
+ * (value "popUpBegin"
).
+ */
+ public static final String EMPTY_MEMORY_GROUP = "popUpBegin"; //$NON-NLS-1$
+
+ /**
+ * Identifier for an empty group following navigation actions in the rendering
+ * (value navigationGroup
).
+ */
+ public static final String EMPTY_NAVIGATION_GROUP = "navigationGroup"; //$NON-NLS-1$
+
+ /**
+ * Identifier for an empty group following actions that are only applicable in
+ * non-auto loading mode
+ * (value nonAutoLoadGroup
).
+ */
+ public static final String EMPTY_NON_AUTO_LOAD_GROUP = "nonAutoLoadGroup"; //$NON-NLS-1$
+
+ /**
+ * Identifier for an empty group following properties actions
+ * (value propertyGroup
).
+ */
+ public static final String EMPTY_PROPERTY_GROUP = "propertyGroup"; //$NON-NLS-1$
+
+ private ISelectionChangedListener fViewerSelectionChangedListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateSyncTopAddress(getTopVisibleAddress());
+ updateSyncSelectedAddress(getSelectedAddress());
+ }
+ };
+
+ private SelectionAdapter fScrollBarSelectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ updateSyncTopAddress(getTopVisibleAddress());
+ }
+ };
+
+ private IModelChangedListener fModelChangedListener = new IModelChangedListener() {
+ public void modelChanged(IModelDelta delta, IModelProxy proxy) {
+ if (delta.getElement() == getMemoryBlock())
+ {
+ showTable();
+ updateRenderingLabel(isVisible());
+ }
+ }};
+
+ private IVirtualContentListener fViewerListener = new IVirtualContentListener() {
+
+ public void handledAtBufferStart() {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ if (isDynamicLoad())
+ {
+ BigInteger address = getTopVisibleAddress();
+ if (address != null && !isAtTopLimit())
+ reloadTable(address);
+ }
+ }
+ }
+
+ public void handleAtBufferEnd() {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ if (isDynamicLoad())
+ {
+ BigInteger address = getTopVisibleAddress();
+ if (address != null && !isAtBottomLimit())
+ reloadTable(address);
+ }
+ }
+ }
+
+ public int getThreshold() {
+ return 3;
+ }};
+
+ private IPresentationErrorListener fPresentationErrorListener = new IPresentationErrorListener() {
+ public void handlePresentationFailure(IStatusMonitor monitor, IStatus status) {
+ showMessage(status.getMessage());
+ }};
+
+
+ /**
+ * Constructs a new table rendering of the specified type.
+ *
+ * @param renderingId memory rendering type identifier
+ */
+ public AbstractAsyncTableRendering(String renderingId) {
+ super(renderingId);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IResettableMemoryRendering#resetRendering()
+ */
+ public void resetRendering() throws DebugException {
+ BigInteger baseAddress = fContentDescriptor.getContentBaseAddress();
+ goToAddress(baseAddress);
+ fTableViewer.setSelection(baseAddress);
+ fTableViewer.setTopIndex(baseAddress);
+
+ updateSyncTopAddress(baseAddress);
+ updateSyncSelectedAddress(baseAddress);
+ }
+
+ public Control createControl(Composite parent) {
+
+ fPageBook = new PageBook(parent, SWT.NONE);
+ createMessagePage(fPageBook);
+ createTableViewer(fPageBook);
+ addListeners();
+
+ return fPageBook;
+ }
+
+ /**
+ * Create the error page of this rendering
+ * @param parent
+ */
+ private void createMessagePage(Composite parent)
+ {
+ if (fTextViewer == null)
+ {
+ fTextViewer = new TextViewer(parent, SWT.WRAP);
+ fTextViewer.setDocument(new Document());
+ StyledText styleText = fTextViewer.getTextWidget();
+ styleText.setEditable(false);
+ styleText.setEnabled(false);
+ }
+ }
+
+ /**
+ * @param parent
+ */
+ private void createTableViewer(final Composite parent)
+ {
+ StringBuffer buffer = new StringBuffer();
+ IMemoryRenderingType type = DebugUITools.getMemoryRenderingManager().getRenderingType(getRenderingId());
+ buffer.append(type.getLabel());
+ buffer.append(": "); //$NON-NLS-1$
+ buffer.append(DebugUIMessages.AbstractAsyncTableRendering_2);
+
+ Job job = new Job(buffer.toString()) {
+
+ protected IStatus run(IProgressMonitor monitor) {
+
+ // gather information from memory block
+ initAddressableSize();
+ final BigInteger topVisibleAddress = getInitialTopVisibleAddress();
+ BigInteger mbBaseAddress = null;
+ try {
+ mbBaseAddress = getMemoryBlockBaseAddress();
+ } catch (DebugException e) {
+ fError = true;
+ showMessage(e.getMessage());
+ }
+
+ // if it takes too long to get the base address, and user has canceled
+ // remove this rendering.
+ if (monitor.isCanceled())
+ {
+ getMemoryRenderingContainer().removeMemoryRendering(AbstractAsyncTableRendering.this);
+ return Status.CANCEL_STATUS;
+ }
+
+ final BigInteger finalMbBaseAddress = mbBaseAddress;
+ final BigInteger initialSelectedAddress = getInitialSelectedAddress();
+
+ if (monitor.isCanceled())
+ {
+ getMemoryRenderingContainer().removeMemoryRendering(AbstractAsyncTableRendering.this);
+ return Status.CANCEL_STATUS;
+ }
+
+ createContentDescriptor(topVisibleAddress);
+
+ // if it takes too long to get other information, and user has canceled
+ // remove this rendering.
+ if (monitor.isCanceled())
+ {
+ getMemoryRenderingContainer().removeMemoryRendering(AbstractAsyncTableRendering.this);
+ return Status.CANCEL_STATUS;
+ }
+
+ // batch update on UI thread
+ UIJob uiJob = new UIJob("Create Table Viewer UI Job"){ //$NON-NLS-1$
+ public IStatus runInUIThread(IProgressMonitor progressMonitor) {
+
+ if (fPageBook.isDisposed())
+ return Status.OK_STATUS;
+
+ fSashForm = new SashForm(parent, SWT.VERTICAL);
+ fTableViewer = new AsyncTableRenderingViewer(AbstractAsyncTableRendering.this, fSashForm, SWT.VIRTUAL | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.HIDE_SELECTION | SWT.BORDER);
+
+ GridData data = new GridData(GridData.FILL_BOTH);
+ fTableViewer.getControl().setLayoutData(data);
+
+ createGoToAddressComposite(fSashForm);
+ hideGotoAddressComposite();
+
+ IMemoryRenderingSite site = getMemoryRenderingContainer().getMemoryRenderingSite();
+ IMemoryRenderingContainer container = getMemoryRenderingContainer();
+ fPresentationContext = new MemoryViewPresentationContext(site, container, AbstractAsyncTableRendering.this);
+ fTableViewer.setContext(fPresentationContext);
+
+ // must call this after the context is created as the information is stored in the context
+ getDynamicLoadFromPreference();
+ getPageSizeFromPreference();
+
+ int numberOfLines = getNumLinesToLoad();
+ fContentDescriptor.setNumLines(numberOfLines);
+
+ BigInteger baseAddress = finalMbBaseAddress;
+ if (baseAddress == null)
+ baseAddress = BigInteger.ZERO;
+
+
+ if (!(getMemoryBlock() instanceof IMemoryBlockExtension) || !isDynamicLoad())
+ {
+ // If not extended memory block, do not create any buffer
+ // no scrolling
+ fContentDescriptor.setPreBuffer(0);
+ fContentDescriptor.setPostBuffer(0);
+ }
+
+ setupInitialFormat();
+ fTableViewer.setCellModifier(createCellModifier());
+ fTableViewer.getTable().setHeaderVisible(true);
+ fTableViewer.getTable().setLinesVisible(true);
+ fTableViewer.addPresentationErrorListener(fPresentationErrorListener);
+ fTableViewer.setInput(getMemoryBlock());
+ fTableViewer.resizeColumnsToPreferredSize();
+ fTableViewer.setTopIndex(topVisibleAddress);
+
+ fTableViewer.setSelection(initialSelectedAddress);
+
+ // SET UP FONT
+ // set to a non-proportional font
+ fTableViewer.getTable().setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
+
+ if (!fError)
+ showTable();
+
+ fTableViewer.addVirtualContentListener(fViewerListener);
+
+ // create context menu
+ // create pop up menu for the rendering
+ createActions();
+ IMenuListener menuListener = new IMenuListener() {
+ public void menuAboutToShow(IMenuManager mgr) {
+ fillContextMenu(mgr);
+ }
+ };
+ createPopupMenu(fTableViewer.getControl(), menuListener);
+ createPopupMenu(fTableViewer.getCursor(), menuListener);
+
+ fTableViewer.addSelectionChangedListener(fViewerSelectionChangedListener);
+ fTableViewer.getTable().getVerticalBar().addSelectionListener(fScrollBarSelectionListener);
+
+ createToolTip();
+
+ // now the rendering is successfully created
+ fIsCreated = true;
+
+ return Status.OK_STATUS;
+ }};
+ uiJob.setSystem(true);
+ uiJob.schedule();
+
+ return Status.OK_STATUS;
+
+ }};
+
+ job.schedule();
+ }
+
+ /**
+ * Create popup menu for this rendering
+ * @param control - control to create the popup menu for
+ * @param menuListener - listener to notify when popup menu is about to show
+ */
+ private void createPopupMenu(Control control, IMenuListener menuListener)
+ {
+ IMemoryRenderingContainer container = getMemoryRenderingContainer();
+ if (fMenuMgr == null)
+ {
+ fMenuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ fMenuMgr.setRemoveAllWhenShown(true);
+ IMemoryRenderingSite site = container.getMemoryRenderingSite();
+ String menuId = container.getId();
+
+ ISelectionProvider selProvider = site.getSite().getSelectionProvider();
+
+ addMenuListener(menuListener);
+
+ site.getSite().registerContextMenu(menuId, fMenuMgr, selProvider);
+ }
+
+ addMenuListener(menuListener);
+
+ Menu popupMenu = fMenuMgr.createContextMenu(control);
+ control.setMenu(popupMenu);
+ }
+
+
+ private void addMenuListener(IMenuListener menuListener) {
+ if (fMenuListeners == null)
+ fMenuListeners = new ArrayList();
+
+ if (!fMenuListeners.contains(menuListener))
+ {
+ fMenuMgr.addMenuListener(menuListener);
+ fMenuListeners.add(menuListener);
+ }
+ }
+
+ private BigInteger getInitialSelectedAddress() {
+ // figure out selected address
+ BigInteger selectedAddress = (BigInteger) getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS);
+ if (selectedAddress == null)
+ {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension) {
+ try {
+ selectedAddress = ((IMemoryBlockExtension) getMemoryBlock()).getBigBaseAddress();
+ } catch (DebugException e) {
+ selectedAddress = BigInteger.ZERO;
+ }
+
+ if (selectedAddress == null) {
+ selectedAddress =BigInteger.ZERO;
+ }
+
+ } else {
+ long address = getMemoryBlock().getStartAddress();
+ selectedAddress = BigInteger.valueOf(address);
+ }
+ }
+ return selectedAddress;
+ }
+
+ private void addListeners()
+ {
+ DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
+ addRenderingToSyncService();
+ JFaceResources.getFontRegistry().addListener(this);
+ }
+
+ private void removeListeners()
+ {
+ DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
+ removeRenderingFromSyncService();
+ JFaceResources.getFontRegistry().removeListener(this);
+
+ Iterator iter = fMenuListeners.iterator();
+ while (iter.hasNext())
+ {
+ fMenuMgr.removeMenuListener((IMenuListener)iter.next());
+ }
+
+ fMenuListeners.clear();
+ }
+
+ private void addRenderingToSyncService()
+ {
+ IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
+
+ if (syncService == null)
+ return;
+
+ syncService.addPropertyChangeListener(this, null);
+ }
+
+ private void removeRenderingFromSyncService()
+ {
+ IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
+
+ if (syncService == null)
+ return;
+
+ syncService.removePropertyChangeListener(this);
+ }
+
+ private void initAddressableSize()
+ {
+ // set up addressable size and figure out number of bytes required per line
+ fAddressableSize = -1;
+ try {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ fAddressableSize = ((IMemoryBlockExtension)getMemoryBlock()).getAddressableSize();
+ else
+ fAddressableSize = 1;
+ } catch (DebugException e1) {
+ DebugUIPlugin.log(e1);
+ // log error and default to 1
+ fAddressableSize = 1;
+ return;
+
+ }
+ if (fAddressableSize < 1)
+ {
+ DebugUIPlugin.logErrorMessage("Invalid addressable size"); //$NON-NLS-1$
+ fAddressableSize = 1;
+ }
+ }
+
+ private BigInteger getInitialTopVisibleAddress() {
+ BigInteger topVisibleAddress = (BigInteger) getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS);
+ if (topVisibleAddress == null)
+ {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ try {
+ topVisibleAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
+ } catch (DebugException e1) {
+ topVisibleAddress = new BigInteger("0"); //$NON-NLS-1$
+ }
+ }
+ else
+ {
+ topVisibleAddress = BigInteger.valueOf(getMemoryBlock().getStartAddress());
+ }
+ }
+ return topVisibleAddress;
+ }
+
+ private void setupInitialFormat() {
+
+ boolean validated = validateInitialFormat();
+
+ if (!validated)
+ {
+ // pop up dialog to ask user for default values
+ StringBuffer msgBuffer = new StringBuffer(DebugUIMessages.AbstractTableRendering_20);
+ msgBuffer.append(" "); //$NON-NLS-1$
+ msgBuffer.append(this.getLabel());
+ msgBuffer.append("\n\n"); //$NON-NLS-1$
+ msgBuffer.append(DebugUIMessages.AbstractTableRendering_16);
+ msgBuffer.append("\n"); //$NON-NLS-1$
+ msgBuffer.append(DebugUIMessages.AbstractTableRendering_18);
+ msgBuffer.append("\n\n"); //$NON-NLS-1$
+
+ int bytePerLine = fBytePerLine;
+ int columnSize = fColumnSize;
+
+ // initialize this value to populate the dialog properly
+ fBytePerLine = getDefaultRowSize() / getAddressableSize();
+ fColumnSize = getDefaultColumnSize() / getAddressableSize();
+
+ FormatTableRenderingDialog dialog = new FormatTableRenderingDialog(this, DebugUIPlugin.getShell());
+ dialog.openError(msgBuffer.toString());
+
+ // restore to original value before formatting
+ fBytePerLine = bytePerLine;
+ fColumnSize = columnSize;
+
+ bytePerLine = dialog.getRowSize() * getAddressableSize();
+ columnSize = dialog.getColumnSize() * getAddressableSize();
+
+ format(bytePerLine, columnSize);
+ }
+ else
+ {
+ // Row size is stored as number of addressable units in preference store
+ int bytePerLine = getDefaultRowSize();
+ // column size is now stored as number of addressable units
+ int columnSize = getDefaultColumnSize();
+
+ // format memory block with specified "bytesPerLine" and "columnSize"
+ boolean ok = format(bytePerLine, columnSize);
+
+ if (!ok)
+ {
+ // this is to ensure that the rest of the rendering can be created
+ // and we can recover from a format error
+ format(bytePerLine, bytePerLine);
+ }
+ }
+ }
+
+ private boolean validateInitialFormat()
+ {
+ int rowSize = getDefaultRowSize();
+ int columnSize = getDefaultColumnSize();
+
+ if (rowSize < columnSize || rowSize % columnSize != 0 || rowSize == 0 || columnSize == 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#getControl()
+ */
+ public Control getControl() {
+ return fPageBook.getParent();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+
+ if (!fIsCreated)
+ return;
+
+ // if memory view table font has changed
+ if (event.getProperty().equals(IInternalDebugUIConstants.FONT_NAME))
+ {
+ if (!fIsDisposed)
+ {
+ Font memoryViewFont = JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME);
+ setFont(memoryViewFont);
+ }
+ return;
+ }
+
+ Object evtSrc = event.getSource();
+
+ if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
+ // always update page size, only refresh if the table is visible
+ getPageSizeFromPreference();
+ }
+
+ // do not handle event if the rendering is displaying an error
+ // or if it's not visible
+ if (isDisplayingError() || !isVisible())
+ {
+ handlePropertiesChangeWhenHidden(event);
+ return;
+ }
+
+
+ if (event.getProperty().equals(IDebugUIConstants.PREF_PADDED_STR) ||
+ event.getProperty().equals(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR) ||
+ event.getProperty().equals(IDebugUIConstants.PREF_MEMORY_HISTORY_KNOWN_COLOR) ||
+ event.getProperty().equals(IDebugUIConstants.PREF_MEMORY_HISTORY_UNKNOWN_COLOR))
+ {
+ if (!fIsDisposed)
+ {
+ fTableViewer.refresh(false);
+ }
+ return;
+ }
+
+ if (event.getProperty().equals(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM)) {
+ handleDyanicLoadChanged();
+ return;
+ }
+
+ if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
+ if (!isDynamicLoad())
+ {
+ int pageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
+ handlePageSizeChanged(pageSize);
+ }
+ return;
+ }
+
+ if (evtSrc == this)
+ return;
+
+ if (evtSrc instanceof IMemoryRendering)
+ {
+ IMemoryRendering rendering = (IMemoryRendering)evtSrc;
+ IMemoryBlock memoryBlock = rendering.getMemoryBlock();
+
+ // do not handle event from renderings displaying other memory blocks
+ if (memoryBlock != getMemoryBlock())
+ return;
+ }
+
+ String propertyName = event.getProperty();
+ Object value = event.getNewValue();
+
+ if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS) && value instanceof BigInteger)
+ {
+ selectedAddressChanged((BigInteger)value);
+ }
+ else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_COL_SIZE) && value instanceof Integer)
+ {
+ columnSizeChanged(((Integer)value).intValue());
+ }
+ else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_ROW_SIZE) && value instanceof Integer)
+ {
+ rowSizeChanged(((Integer)value).intValue());
+ }
+ else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS) && value instanceof BigInteger)
+ {
+ topVisibleAddressChanged((BigInteger)value);
+ }
+ else if (propertyName.equals(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS) && value instanceof BigInteger)
+ {
+ handlePageStartAddressChanged((BigInteger)value);
+ }
+ }
+
+ /**
+ *
+ */
+ private void handlePageSizeChanged(int pageSize) {
+ fPageSize = pageSize;
+ // only refresh if in non-auto-load mode
+ fContentDescriptor.setNumLines(pageSize);
+ refresh();
+ }
+
+ private void handlePropertiesChangeWhenHidden(PropertyChangeEvent event)
+ {
+ if (fPendingSyncProperties == null)
+ return;
+
+ String propertyName = event.getProperty();
+ Object value = event.getNewValue();
+
+ if (event.getSource() instanceof IMemoryRendering)
+ {
+ IMemoryRendering rendering = (IMemoryRendering)event.getSource();
+ if (rendering == this || rendering.getMemoryBlock() != getMemoryBlock())
+ {
+ return;
+ }
+ }
+
+ if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_COL_SIZE) && value instanceof Integer)
+ {
+ fPendingSyncProperties.setColumnSize(((Integer)value).intValue());
+ }
+ else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_ROW_SIZE) && value instanceof Integer)
+ {
+ fPendingSyncProperties.setRowSize(((Integer)value).intValue());
+ }
+
+ else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS) && value instanceof BigInteger)
+ {
+ fPendingSyncProperties.setSelectedAddress((BigInteger)value);
+ }
+ else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS) && value instanceof BigInteger)
+ {
+ fPendingSyncProperties.setTopVisibleAddress((BigInteger)value);
+ }
+ else if (propertyName.equals(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS) && value instanceof BigInteger)
+ {
+ fPendingSyncProperties.setPageStartAddress((BigInteger)value);
+ }
+ else if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
+ int pageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
+ fPendingSyncProperties.setPageSize(pageSize);
+ }
+ }
+
+ private void topVisibleAddressChanged(final BigInteger address)
+ {
+ final Runnable runnable = new Runnable() {
+ public void run() {
+ if (fTableViewer.getTable().isDisposed())
+ return;
+
+ doTopVisibleAddressChanged(address);
+ }};
+ runOnUIThread(runnable);
+ }
+
+ /**
+ * @param address
+ */
+ private void doTopVisibleAddressChanged(final BigInteger address) {
+ if (fIsDisposed)
+ return;
+
+ if (!isDynamicLoad())
+ {
+ fTableViewer.setTopIndex(address);
+ fTableViewer.topIndexChanged();
+ return;
+ }
+
+ if (!isAtTopBuffer(address) && !isAtBottomBuffer(address))
+ {
+ fTableViewer.setTopIndex(address);
+ fTableViewer.topIndexChanged();
+ }
+ else
+ {
+ reloadTable(address);
+ }
+ }
+
+ private boolean isAtBottomBuffer(BigInteger address)
+ {
+ int idx = fTableViewer.indexOf(address);
+ if (idx < 0)
+ return true;
+
+ int bottomIdx = idx + getNumberOfVisibleLines();
+ int elementsCnt = fTableViewer.getVirtualContentModel().getElements().length;
+ int numLinesLeft = elementsCnt - bottomIdx;
+
+ if (numLinesLeft <= 3)
+ return true;
+
+ return false;
+ }
+
+ private boolean isAtTopBuffer(BigInteger address)
+ {
+ int topIdx = fTableViewer.indexOf(address);
+ if (topIdx <= 3)
+ return true;
+
+ return false;
+ }
+
+ private void runOnUIThread(final Runnable runnable)
+ {
+ if (Display.getCurrent() != null)
+ {
+ runnable.run();
+ }
+ else
+ {
+ UIJob job = new UIJob("Async Table Rendering UI Job"){ //$NON-NLS-1$
+
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ runnable.run();
+ return Status.OK_STATUS;
+ }};
+ job.setSystem(true);
+ job.schedule();
+ }
+ }
+
+ private void selectedAddressChanged(final BigInteger address)
+ {
+ Runnable runnable = new Runnable() {
+
+ public void run() {
+
+ if (fTableViewer.getTable().isDisposed())
+ return;
+
+ // call this to make the table viewer to reload when needed
+ int i = fTableViewer.indexOf(address);
+ if (i < 0)
+ {
+ topVisibleAddressChanged(address);
+ }
+ fTableViewer.setSelection(address);
+ }
+ };
+
+ runOnUIThread(runnable);
+ }
+
+ private void setFont(Font font)
+ {
+ // set font
+ fTableViewer.getTable().setFont(font);
+ fTableViewer.getCursor().setFont(font);
+ }
+
+ private int getDefaultColumnSize() {
+
+ // default to global preference store
+ IPreferenceStore prefStore = DebugUITools.getPreferenceStore();
+ int columnSize = prefStore.getInt(IDebugPreferenceConstants.PREF_COLUMN_SIZE);
+ // actual column size is number of addressable units * size of the addressable unit
+ columnSize = columnSize * getAddressableSize();
+
+ // check synchronized col size
+ Integer colSize = (Integer)getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_COL_SIZE);
+ if (colSize != null)
+ {
+ // column size is stored as actual number of bytes in synchronizer
+ int syncColSize = colSize.intValue();
+ if (syncColSize > 0)
+ {
+ columnSize = syncColSize;
+ }
+ }
+ else
+ {
+ IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
+ int defaultColSize = -1;
+
+ if (elmt != null)
+ {
+ if (elmt.supportsProperty(this, IDebugPreferenceConstants.PREF_COL_SIZE_BY_MODEL))
+ defaultColSize = getDefaultFromPersistableElement(IDebugPreferenceConstants.PREF_COL_SIZE_BY_MODEL);
+ }
+
+ if (defaultColSize <= 0)
+ {
+ // if not provided, get default by model
+ defaultColSize = getDefaultColumnSizeByModel(getMemoryBlock().getModelIdentifier());
+ }
+
+ if (defaultColSize > 0)
+ columnSize = defaultColSize * getAddressableSize();
+ }
+ return columnSize;
+ }
+
+ private int getDefaultRowSize() {
+
+ int rowSize = DebugUITools.getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_ROW_SIZE);
+ int bytePerLine = rowSize * getAddressableSize();
+
+ // check synchronized row size
+ Integer size = (Integer)getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_ROW_SIZE);
+ if (size != null)
+ {
+ // row size is stored as actual number of bytes in synchronizer
+ int syncRowSize = size.intValue();
+ if (syncRowSize > 0)
+ {
+ bytePerLine = syncRowSize;
+ }
+ }
+ else
+ {
+ int defaultRowSize = -1;
+ IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
+ if (elmt != null)
+ {
+ if (elmt.supportsProperty(this, IDebugPreferenceConstants.PREF_ROW_SIZE_BY_MODEL))
+ {
+ defaultRowSize = getDefaultFromPersistableElement(IDebugPreferenceConstants.PREF_ROW_SIZE_BY_MODEL);
+ return defaultRowSize * getAddressableSize();
+ }
+ }
+
+ if (defaultRowSize <= 0)
+ // no synchronized property, ask preference store by id
+ defaultRowSize = getDefaultRowSizeByModel(getMemoryBlock().getModelIdentifier());
+
+ if (defaultRowSize > 0)
+ bytePerLine = defaultRowSize * getAddressableSize();
+ }
+ return bytePerLine;
+ }
+
+ /**
+ * Returns the addressable size of this rendering's memory block in bytes.
+ *
+ * @return the addressable size of this rendering's memory block in bytes
+ */
+ public int getAddressableSize() {
+ return fAddressableSize;
+ }
+
+ private Object getSynchronizedProperty(String propertyId)
+ {
+ IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
+
+ if (syncService == null)
+ return null;
+
+ return syncService.getProperty(getMemoryBlock(), propertyId);
+ }
+
+ private int getDefaultFromPersistableElement(String propertyId) {
+ int defaultValue = -1;
+ IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
+ if (elmt != null)
+ {
+ try {
+ Object valueMB = elmt.getProperty(this, propertyId);
+ if (valueMB != null && !(valueMB instanceof Integer))
+ {
+ IStatus status = DebugUIPlugin.newErrorStatus("Model returned invalid type on " + propertyId, null); //$NON-NLS-1$
+ DebugUIPlugin.log(status);
+ }
+
+ if (valueMB != null)
+ {
+ Integer value = (Integer)valueMB;
+ defaultValue = value.intValue();
+ }
+ } catch (CoreException e) {
+ DebugUIPlugin.log(e);
+ }
+ }
+ return defaultValue;
+ }
+
+ /**
+ * @param modelId
+ * @return default number of addressable units per line for the model
+ */
+ private int getDefaultRowSizeByModel(String modelId)
+ {
+ int row = DebugUITools.getPreferenceStore().getInt(getRowPrefId(modelId));
+ if (row == 0)
+ {
+ DebugUITools.getPreferenceStore().setValue(getRowPrefId(modelId), IDebugPreferenceConstants.PREF_ROW_SIZE_DEFAULT);
+ }
+
+ row = DebugUITools.getPreferenceStore().getInt(getRowPrefId(modelId));
+ return row;
+
+ }
+
+ /**
+ * @param modelId
+ * @return default number of addressable units per column for the model
+ */
+ private int getDefaultColumnSizeByModel(String modelId)
+ {
+ int col = DebugUITools.getPreferenceStore().getInt(getColumnPrefId(modelId));
+ if (col == 0)
+ {
+ DebugUITools.getPreferenceStore().setValue(getColumnPrefId(modelId), IDebugPreferenceConstants.PREF_COLUMN_SIZE_DEFAULT);
+ }
+
+ col = DebugUITools.getPreferenceStore().getInt(getColumnPrefId(modelId));
+ return col;
+ }
+
+
+ private String getRowPrefId(String modelId) {
+ String rowPrefId = IDebugPreferenceConstants.PREF_ROW_SIZE + ":" + modelId; //$NON-NLS-1$
+ return rowPrefId;
+ }
+
+ private String getColumnPrefId(String modelId) {
+ String colPrefId = IDebugPreferenceConstants.PREF_COLUMN_SIZE + ":" + modelId; //$NON-NLS-1$
+ return colPrefId;
+ }
+
+ /**
+ * Format view tab based on the bytes per line and column.
+ *
+ * @param bytesPerLine - number of bytes per line, possible values: (1 / 2 / 4 / 8 / 16) * addressableSize
+ * @param columnSize - number of bytes per column, possible values: (1 / 2 / 4 / 8 / 16) * addressableSize
+ * @return true if format is successful, false, otherwise
+ */
+ public boolean format(int bytesPerLine, int columnSize)
+ {
+
+ // bytes per cell must be divisible to bytesPerLine
+ if (bytesPerLine % columnSize != 0)
+ {
+ return false;
+ }
+
+ if (bytesPerLine < columnSize)
+ {
+ return false;
+ }
+
+ // do not format if the view tab is already in that format
+ if(fBytePerLine == bytesPerLine && fColumnSize == columnSize){
+ return false;
+ }
+
+ fBytePerLine = bytesPerLine;
+ fColumnSize = columnSize;
+ formatViewer();
+
+ updateSyncRowSize();
+ updateSyncColSize();
+
+ return true;
+ }
+
+
+ /**
+ * Returns the number of addressable units per row.
+ *
+ * @return number of addressable units per row
+ */
+ public int getAddressableUnitPerLine() {
+ return fBytePerLine / getAddressableSize();
+ }
+
+ /**
+ * Returns the number of addressable units per column.
+ *
+ * @return number of addressable units per column
+ */
+ public int getAddressableUnitPerColumn() {
+ return fColumnSize / getAddressableSize();
+ }
+
+
+ /**
+ * This method estimates the number of visible lines in the rendering
+ * table.
+ * @return estimated number of visible lines in the table
+ */
+ private int getNumberOfVisibleLines()
+ {
+ if(fTableViewer == null)
+ return -1;
+
+ Table table = fTableViewer.getTable();
+ int height = fTableViewer.getTable().getSize().y;
+
+ // when table is not yet created, height is zero
+ if (height == 0)
+ {
+ // make use of the table viewer to estimate table size
+ height = fTableViewer.getTable().getParent().getSize().y;
+ }
+
+ // height of border
+ int border = fTableViewer.getTable().getHeaderHeight();
+
+ // height of scroll bar
+ int scroll = fTableViewer.getTable().getHorizontalBar().getSize().y;
+
+ // height of table is table's area minus border and scroll bar height
+ height = height-border-scroll;
+
+ // calculate number of visible lines
+ int lineHeight = getMinTableItemHeight(table);
+
+ int numberOfLines = height/lineHeight;
+
+ if (numberOfLines <= 0)
+ return 20;
+
+ return numberOfLines;
+ }
+
+ private int getMinTableItemHeight(Table table){
+
+ // Hack to get around Linux GTK problem.
+ // On Linux GTK, table items have variable item height as
+ // carriage returns are actually shown in a cell. Some rows will be
+ // taller than others. When calculating number of visible lines, we
+ // need to find the smallest table item height. Otherwise, the rendering
+ // underestimates the number of visible lines. As a result the rendering
+ // will not be able to get more memory as needed.
+ if (MemoryViewUtil.isLinuxGTK())
+ {
+ // check each of the items and find the minimum
+ TableItem[] items = table.getItems();
+ int minHeight = table.getItemHeight();
+ for (int i=0; i topIndex)
+ {
+ MemorySegment topItem = (MemorySegment)table.getItem(topIndex).getData();
+ if (topItem != null)
+ {
+ return topItem.getAddress();
+ }
+ }
+ return null;
+ }
+
+ private synchronized void reloadTable(final BigInteger topAddress) {
+
+ if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
+ System.out.println(this + " reload at: " + topAddress.toString(16)); //$NON-NLS-1$
+
+ fContentDescriptor.setLoadAddress(topAddress);
+ fContentDescriptor.setNumLines(getNumLinesToLoad());
+ fTableViewer.setTopIndex(topAddress);
+ fTableViewer.refresh();
+
+ }
+
+ private boolean isAtTopLimit()
+ {
+ BigInteger startAddress = fContentDescriptor.getStartAddress();
+ startAddress = MemoryViewUtil.alignToBoundary(startAddress, getAddressableUnitPerLine());
+ AbstractVirtualContentTableModel model = fTableViewer.getVirtualContentModel();
+
+ if (model != null)
+ {
+ Object key = model.getKey(0);
+ if (key instanceof BigInteger)
+ {
+ BigInteger startBufferAddress = (BigInteger)key;
+ startBufferAddress = MemoryViewUtil.alignToBoundary(startBufferAddress, getAddressableUnitPerLine());
+
+ if (startAddress.compareTo(startBufferAddress) == 0)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isAtBottomLimit()
+ {
+ BigInteger endAddress = fContentDescriptor.getEndAddress();
+ endAddress = MemoryViewUtil.alignToBoundary(endAddress, getAddressableUnitPerLine());
+
+ AbstractVirtualContentTableModel model = fTableViewer.getVirtualContentModel();
+ if (model != null)
+ {
+ int numElements = model.getElements().length;
+ Object key = model.getKey(numElements-1);
+ if (key instanceof BigInteger)
+ {
+ BigInteger endBufferAddress = (BigInteger)key;
+ endBufferAddress = MemoryViewUtil.alignToBoundary(endBufferAddress, getAddressableUnitPerLine());
+
+ if (endAddress.compareTo(endBufferAddress) == 0)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void formatViewer() {
+
+ fTableViewer.disposeColumns();
+ fTableViewer.disposeCellEditors();
+ doFormatTable();
+ fTableViewer.setColumnHeaders(getColumnProperties());
+ fTableViewer.showColumnHeader(true);
+ fTableViewer.setCellEditors(createCellEditors(fTableViewer.getTable()));
+
+ fTableViewer.formatViewer();
+
+ // This resize needs to happen after the viewer has finished
+ // getting the labels.
+ // This fix is a hack to delay the resize until the viewer has a chance to get
+ // the setData event from the UI thread. Otherwise, the columns will be
+ // squeezed together.
+ UIJob job = new UIJob("resize to fit"){ //$NON-NLS-1$
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ resizeColumnsToPreferredSize();
+ return Status.OK_STATUS;
+ }};
+
+ job.setSystem(true);
+ job.schedule();
+ }
+
+ private void doFormatTable() {
+ int bytesPerLine = getBytesPerLine();
+ int columnSize = getBytesPerColumn();
+ int numColumns = bytesPerLine/columnSize;
+
+ Table table = fTableViewer.getTable();
+ TableColumn column0 = new TableColumn(table,SWT.LEFT,0);
+ column0.setText(DebugUIMessages.AbstractTableRendering_2);
+
+ // create new byte columns
+ TableColumn [] byteColumns = new TableColumn[numColumns];
+ for (int i=0;i"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ return decorateLabel(label);
+ }
+
+ /* Returns the label of this rendering.
+ *
+ * @return label of this rendering
+ */
+ public String getLabel() {
+
+ if (fLabel == null)
+ {
+ fLabel = DebugUIMessages.AbstractAsyncTableRendering_1;
+ updateRenderingLabel(isVisible());
+ }
+
+ return fLabel;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class adapter) {
+
+ if (adapter == IColorProvider.class)
+ return getColorProviderAdapter();
+
+ if (adapter == ILabelProvider.class)
+ return getLabelProviderAdapter();
+
+ if (adapter == IFontProvider.class)
+ return getFontProviderAdapter();
+
+ if (adapter == IModelChangedListener.class)
+ {
+ return fModelChangedListener;
+ }
+
+ if (adapter == IWorkbenchAdapter.class)
+ {
+ // needed workbench adapter to fill the title of property page
+ if (fWorkbenchAdapter == null) {
+ fWorkbenchAdapter = new IWorkbenchAdapter() {
+ public Object[] getChildren(Object o) {
+ return new Object[0];
+ }
+
+ public ImageDescriptor getImageDescriptor(Object object) {
+ return null;
+ }
+
+ public String getLabel(Object o) {
+ return AbstractAsyncTableRendering.this.getLabel();
+ }
+
+ public Object getParent(Object o) {
+ return null;
+ }
+ };
+ }
+ return fWorkbenchAdapter;
+ }
+
+ if (adapter == TableRenderingContentDescriptor.class)
+ return getContentDescriptor();
+
+ return super.getAdapter(adapter);
+ }
+
+ /**
+ * Returns the number of characters a byte will convert to
+ * or -1 if unknown.
+ *
+ * @return the number of characters a byte will convert to
+ * or -1 if unknown
+ */
+ public int getNumCharsPerByte()
+ {
+ return -1;
+ }
+
+ /**
+ * Create actions for this rendering
+ */
+ protected void createActions() {
+
+ fCopyToClipboardAction = new AsyncCopyTableRenderingAction(this, fTableViewer);
+ fGoToAddressAction = new RenderingGoToAddressAction(this);
+ fResetMemoryBlockAction = new ResetToBaseAddressAction(this);
+
+ fPrintViewTabAction = new AsyncPrintTableRenderingAction(this, fTableViewer);
+
+ fFormatRenderingAction = new FormatTableRenderingAction(this);
+ fReformatAction = new ReformatAction(this);
+ fToggleAddressColumnAction = new ToggleAddressColumnAction();
+
+ IMemoryRenderingSite site = getMemoryRenderingContainer().getMemoryRenderingSite();
+ if (site.getSite().getSelectionProvider() != null)
+ {
+ fPropertiesDialogAction = new PropertyDialogAction(site.getSite(),site.getSite().getSelectionProvider());
+ }
+
+ fNextAction = new NextPageAction();
+ fPrevAction = new PrevPageAction();
+ }
+
+ /**
+ * Returns the currently selected address in this rendering.
+ *
+ * @return the currently selected address in this rendering
+ */
+ public BigInteger getSelectedAddress() {
+ Object key = fTableViewer.getSelectionKey();
+
+ if (key != null && key instanceof BigInteger)
+ return (BigInteger)key;
+
+ return null;
+ }
+
+ /**
+ * Returns the currently selected content in this rendering as MemoryByte.
+ *
+ * @return the currently selected content in array of MemoryByte.
+ * Returns an empty array if the selected address is out of buffered range.
+ */
+ public MemoryByte[] getSelectedAsBytes()
+ {
+ if (getSelectedAddress() == null)
+ return new MemoryByte[0];
+
+ Object key = fTableViewer.getSelectionKey();
+ AbstractVirtualContentTableModel model = fTableViewer.getVirtualContentModel();
+
+ if (model != null)
+ {
+ model = (AbstractVirtualContentTableModel)fTableViewer.getModel();
+ int row = model.indexOfKey(key);
+ Object element = model.getElement(row);
+ int col = model.columnOf(element, key);
+
+ // check precondition
+ if (col <= 0 || col > getBytesPerLine()/getBytesPerColumn())
+ {
+ return new MemoryByte[0];
+ }
+
+ if (!(element instanceof MemorySegment))
+ return new MemoryByte[0];
+
+ MemorySegment line = (MemorySegment)element;
+ int offset = (col-1)*(getAddressableUnitPerColumn()*getAddressableSize());
+
+ // make a copy of the bytes to ensure that data cannot be changed
+ // by caller
+ MemoryByte[] bytes = line.getBytes(offset, getAddressableUnitPerColumn()*getAddressableSize());
+ MemoryByte[] retBytes = new MemoryByte[bytes.length];
+
+ System.arraycopy(bytes, 0, retBytes, 0, bytes.length);
+ return retBytes;
+ }
+ return new MemoryByte[0];
+ }
+
+ /**
+ * Returns the currently selected content in this rendering as a String.
+ *
+ * @return the currently selected content in this rendering
+ */
+ public String getSelectedAsString() {
+
+ if (getSelectedAddress() == null)
+ return ""; //$NON-NLS-1$
+
+ MemoryByte[] bytes = getSelectedAsBytes();
+ if (bytes.length > 0)
+ {
+ return getString(this.getRenderingId(), getSelectedAddress(), bytes);
+ }
+ else
+ return ""; //$NON-NLS-1$
+
+ }
+
+ /**
+ * Moves the cursor to the specified address.
+ * Will load more memory if the address is not currently visible.
+ *
+ * @param address address to position cursor at
+ * @throws DebugException if an exception occurs
+ */
+ public void goToAddress(BigInteger address) throws DebugException {
+
+ if (fTableViewer.getVirtualContentModel() == null)
+ return;
+
+ int i = fTableViewer.getVirtualContentModel().indexOfKey(address);
+
+ if (i >= 0)
+ {
+ // address is within range, set cursor and reveal
+ fTableViewer.setSelection(address);
+ updateSyncTopAddress(getTopVisibleAddress());
+ updateSyncSelectedAddress(address);
+ }
+ else
+ {
+ // if not extended memory block
+ // do not allow user to go to an address that's out of range
+ if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
+ {
+ Status stat = new Status(
+ IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(),
+ DebugException.NOT_SUPPORTED, DebugUIMessages.AbstractTableRendering_11, null
+ );
+ DebugException e = new DebugException(stat);
+ throw e;
+ }
+
+ BigInteger startAdd = fContentDescriptor.getStartAddress();
+ BigInteger endAdd = fContentDescriptor.getEndAddress();
+
+ if (address.compareTo(startAdd) < 0 ||
+ address.compareTo(endAdd) > 0)
+ {
+ Status stat = new Status(
+ IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(),
+ DebugException.NOT_SUPPORTED, DebugUIMessages.AbstractTableRendering_11, null
+ );
+ DebugException e = new DebugException(stat);
+ throw e;
+ }
+
+ // load at the address
+ fTableViewer.setSelection(address);
+ reloadTable(address);
+
+ updateSyncSelectedAddress(address);
+
+ if (!isDynamicLoad())
+ {
+ updateSyncPageStartAddress(address);
+ }
+
+ updateSyncTopAddress(address);
+ }
+ }
+
+ /**
+ * Refresh the table viewer with the current top visible address.
+ * Update labels in the memory rendering.
+ */
+ public void refresh() {
+ fTableViewer.refresh();
+ }
+
+
+ /**
+ * Resize column to the preferred size.
+ */
+ public void resizeColumnsToPreferredSize() {
+ fTableViewer.resizeColumnsToPreferredSize();
+ if (!fIsShowAddressColumn)
+ {
+ final TableColumn column = fTableViewer.getTable().getColumn(0);
+ column.addControlListener(new ControlListener() {
+
+ public void controlMoved(ControlEvent e) {
+ }
+
+ public void controlResized(ControlEvent e) {
+ column.removeControlListener(this);
+ column.setWidth(0);
+ }});
+ }
+ }
+
+ /**
+ * Updates labels of this rendering.
+ */
+ public void updateLabels()
+ {
+ UIJob job = new UIJob("updateLabels"){ //$NON-NLS-1$
+
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+
+ // do not handle if the rendering is already disposed
+ if (fPageBook.isDisposed())
+ return Status.OK_STATUS;
+
+ // update tab labels
+ updateRenderingLabel(true);
+
+ if (fTableViewer != null)
+ {
+ // update column labels
+ setColumnHeadings();
+
+ // rebuild cache and force labels to be refreshed
+ fTableViewer.formatViewer();
+ }
+ return Status.OK_STATUS;
+ }};
+ job.setSystem(true);
+ job.schedule();
+ }
+
+ /**
+ * Fills the context menu for this rendering
+ *
+ * @param menu menu to fill
+ */
+ protected void fillContextMenu(IMenuManager menu) {
+
+ menu.add(new Separator(EMPTY_MEMORY_GROUP));
+ menu.add(new Separator());
+ menu.add(fResetMemoryBlockAction);
+ menu.add(fGoToAddressAction);
+ menu.add(new Separator(EMPTY_NAVIGATION_GROUP));
+
+ menu.add(new Separator());
+ menu.add(fFormatRenderingAction);
+
+ if (!isDynamicLoad() && getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ menu.add(new Separator());
+ menu.add(fPrevAction);
+ menu.add(fNextAction);
+ menu.add(new Separator(EMPTY_NON_AUTO_LOAD_GROUP));
+ }
+
+ menu.add(new Separator());
+ menu.add(fReformatAction);
+ menu.add(fToggleAddressColumnAction);
+ menu.add(new Separator());
+ menu.add(fCopyToClipboardAction);
+ menu.add(fPrintViewTabAction);
+ if (fPropertiesDialogAction != null)
+ {
+ menu.add(new Separator());
+ menu.add(fPropertiesDialogAction);
+ menu.add(new Separator(EMPTY_PROPERTY_GROUP));
+ }
+
+ menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+
+ private int getPageSizeInUnits()
+ {
+ return fPageSize * getAddressableUnitPerLine();
+ }
+
+ private void getPageSizeFromPreference()
+ {
+ fPageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
+ }
+
+ private void updateDynamicLoadProperty() {
+
+ boolean value = DebugUIPlugin
+ .getDefault()
+ .getPreferenceStore()
+ .getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM);
+
+ if (value != isDynamicLoad())
+ {
+ setDynamicLoad(value);
+
+ if (!fIsDisposed) {
+ if (isDynamicLoad()) {
+ fContentDescriptor.setPostBuffer(20);
+ fContentDescriptor.setPreBuffer(20);
+ fContentDescriptor.setNumLines(getNumberOfVisibleLines());
+
+ } else {
+ fContentDescriptor.setPostBuffer(0);
+ fContentDescriptor.setPreBuffer(0);
+ fContentDescriptor.setNumLines(fPageSize);
+ }
+ }
+ }
+ }
+
+ private void getDynamicLoadFromPreference()
+ {
+ setDynamicLoad(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM));
+ }
+
+ private boolean isDynamicLoad()
+ {
+ return fContentDescriptor.isDynamicLoad();
+ }
+
+ private int getPageSize()
+ {
+ return fPageSize;
+ }
+
+ private int getNumLinesToLoad() {
+ int numberOfLines = -1;
+
+ if (isDynamicLoad())
+ numberOfLines = getNumberOfVisibleLines();
+ else
+ numberOfLines = getPageSize();
+
+ return numberOfLines;
+ }
+
+ private void setDynamicLoad(boolean load)
+ {
+ fContentDescriptor.setDynamicLoad(load);
+ }
+
+ private void handlePageStartAddressChanged(BigInteger address)
+ {
+ // do not handle if in dynamic mode
+ if (isDynamicLoad())
+ return;
+
+ if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
+ return;
+
+ // do not handle event if the base address of the memory
+ // block has changed, wait for debug event to update to
+ // new location
+ if (isMemoryBlockBaseAddressChanged())
+ return;
+
+ if(fTableViewer.getKey(0).equals(address))
+ return;
+
+ BigInteger start = fContentDescriptor.getStartAddress();
+ BigInteger end = fContentDescriptor.getEndAddress();
+
+ // smaller than start address, load at start address
+ if (address.compareTo(start) < 0)
+ {
+ if (isAtTopLimit())
+ return;
+
+ address = start;
+ }
+
+ // bigger than end address, no need to load, already at top
+ if (address.compareTo(end) > 0)
+ {
+ if (isAtBottomLimit())
+ return;
+
+ address = end.subtract(BigInteger.valueOf(getPageSizeInUnits()));
+ }
+
+ fContentDescriptor.setLoadAddress(address);
+ final BigInteger finaladdress = address;
+ Runnable runnable = new Runnable() {
+ public void run() {
+ if (fTableViewer.getTable().isDisposed())
+ return;
+
+ fTableViewer.setTopIndex(finaladdress);
+ refresh();
+ }};
+
+ runOnUIThread(runnable);
+
+ updateSyncPageStartAddress(address);
+ updateSyncTopAddress(address);
+ }
+ private void handleDyanicLoadChanged() {
+
+ // if currently in dynamic load mode, update page
+ // start address
+ BigInteger pageStart = getTopVisibleAddress();
+ updateSyncPageStartAddress(pageStart);
+
+ updateDynamicLoadProperty();
+ if (isDynamicLoad())
+ {
+ refresh();
+ fTableViewer.setTopIndex(pageStart);
+ }
+ else
+ {
+ handlePageStartAddressChanged(pageStart);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#becomesHidden()
+ */
+ public void becomesHidden() {
+ // creates new object for storing potential changes in sync properties
+ fPendingSyncProperties = new PendingPropertyChanges();
+ super.becomesHidden();
+
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ updateRenderingLabel(false);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#becomesVisible()
+ */
+ public void becomesVisible() {
+
+ if (!fIsCreated)
+ {
+ // label can still be constructed even though the rendering has not finished being
+ // initialized
+ updateRenderingLabel(true);
+ super.becomesVisible();
+ return;
+ }
+
+ // do not do anything if already visible
+ if (isVisible() == true)
+ {
+ // super should always be called
+ super.becomesVisible();
+ return;
+ }
+
+ super.becomesVisible();
+
+ if (fPendingSyncProperties != null)
+ {
+ // deal with format
+ boolean format = false;
+ int rowSize = getBytesPerLine();
+ if (fPendingSyncProperties.getRowSize() > 0)
+ {
+ format = true;
+ rowSize = fPendingSyncProperties.getRowSize();
+ }
+
+ int colSize = getBytesPerColumn();
+ if (fPendingSyncProperties.getColumnSize() > 0)
+ {
+ format = true;
+ colSize = fPendingSyncProperties.getColumnSize();
+ }
+
+ if (format)
+ format(rowSize, colSize);
+
+ BigInteger selectedAddress = fPendingSyncProperties.getSelectedAddress();
+ if (selectedAddress != null)
+ fTableViewer.setSelection(selectedAddress);
+
+ updateDynamicLoadProperty();
+
+ if (isDynamicLoad())
+ {
+ BigInteger topVisibleAddress = fPendingSyncProperties.getTopVisibleAddress();
+ if (topVisibleAddress != null)
+ {
+ fContentDescriptor.setLoadAddress(topVisibleAddress);
+ fTableViewer.setTopIndex(topVisibleAddress);
+ }
+ }
+ else if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
+ {
+ BigInteger topVisibleAddress = fPendingSyncProperties.getTopVisibleAddress();
+ if (topVisibleAddress != null)
+ fTableViewer.setTopIndex(topVisibleAddress);
+ }
+ else
+ {
+ if (fPendingSyncProperties.getPageSize() > 0)
+ {
+ fPageSize = fPendingSyncProperties.getPageSize();
+ fContentDescriptor.setNumLines(fPageSize);
+ }
+
+ BigInteger pageStartAddress = fPendingSyncProperties.getPageStartAddress();
+ if (pageStartAddress != null)
+ fContentDescriptor.setLoadAddress(pageStartAddress);
+
+ fTableViewer.setTopIndex(pageStartAddress);
+ }
+
+ showTable();
+ refresh();
+ }
+
+ updateRenderingLabel(true);
+
+ Job job = new Job("becomesVisible") //$NON-NLS-1$
+ {
+ protected IStatus run(IProgressMonitor monitor) {
+ if (fIsDisposed)
+ return Status.OK_STATUS;
+ try {
+ fContentDescriptor.updateContentBaseAddress();
+ } catch (DebugException e) {
+ showMessage(e.getMessage());
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setSystem(true);
+ job.schedule();
+
+ // discard these properties
+ fPendingSyncProperties = null;
+ }
+
+ /**
+ * Handle column size changed event from synchronizer
+ * @param newColumnSize
+ */
+ private void columnSizeChanged(final int newColumnSize) {
+ // ignore event if rendering is not visible
+ if (!isVisible())
+ return;
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ int rowSize = getBytesPerLine();
+ if (rowSize < newColumnSize)
+ rowSize = newColumnSize;
+
+ format(rowSize, newColumnSize);
+ }
+ });
+ }
+
+ /**
+ * @param newRowSize - new row size in number of bytes
+ */
+ private void rowSizeChanged(final int newRowSize)
+ {
+ // ignore event if rendering is not visible
+ if (!isVisible())
+ return;
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ int colSize = getBytesPerColumn();
+ if (newRowSize < colSize)
+ colSize = newRowSize;
+
+ format(newRowSize, colSize);
+ }
+ });
+ }
+
+ /**
+ * update selected address in synchronizer if update is true.
+ */
+ private void updateSyncSelectedAddress(BigInteger address) {
+
+ if (!fIsCreated)
+ return;
+ PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS, null, address);
+ firePropertyChangedEvent(event);
+ }
+
+ /**
+ * update column size in synchronizer
+ */
+ private void updateSyncColSize() {
+
+ if (!fIsCreated)
+ return;
+
+ PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_COL_SIZE, null, new Integer(fColumnSize));
+ firePropertyChangedEvent(event);
+ }
+
+ /**
+ * update column size in synchronizer
+ */
+ private void updateSyncRowSize() {
+
+ if (!fIsCreated)
+ return;
+
+ PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_ROW_SIZE, null, new Integer(fBytePerLine));
+ firePropertyChangedEvent(event);
+ }
+
+ /**
+ * update top visible address in synchronizer
+ */
+ private void updateSyncTopAddress(BigInteger address) {
+
+ if (!fIsCreated)
+ return;
+
+ PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS, null, address);
+ firePropertyChangedEvent(event);
+ }
+
+ private void updateSyncPageStartAddress(BigInteger address) {
+
+ if (!fIsCreated)
+ return;
+
+ if (isMemoryBlockBaseAddressChanged())
+ return;
+
+ PropertyChangeEvent event = new PropertyChangeEvent(this, IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS, null, address);
+ firePropertyChangedEvent(event);
+ }
+
+ /**
+ * Returns the color provider for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a color provider is obtained by asking this rendering's
+ * memory block for its {@link IColorProvider} adapter. When the color
+ * provider is queried for color information, it is provided with a
+ * {@link MemoryRenderingElement} as an argument.
+ *
+ * @return the color provider for this rendering's memory block,
+ * or null
+ */
+ protected IColorProvider getColorProviderAdapter()
+ {
+ return (IColorProvider)getMemoryBlock().getAdapter(IColorProvider.class);
+ }
+
+ /**
+ * Returns the label provider for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a label provider is obtained by asking this rendering's
+ * memory block for its {@link ILabelProvider} adapter. When the label
+ * provider is queried for label information, it is provided with a
+ * {@link MemoryRenderingElement} as an argument.
+ *
+ * @return the label provider for this rendering's memory block,
+ * or null
+ */
+ protected ILabelProvider getLabelProviderAdapter()
+ {
+ return (ILabelProvider)getMemoryBlock().getAdapter(ILabelProvider.class);
+ }
+
+ /**
+ * Returns the font provider for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a font provider is obtained by asking this rendering's
+ * memory block for its {@link IFontProvider} adapter. When the font
+ * provider is queried for font information, it is provided with a
+ * {@link MemoryRenderingElement} as an argument.
+ *
+ * @return the font provider for this rendering's memory block,
+ * or null
+ */
+ protected IFontProvider getFontProviderAdapter()
+ {
+ return (IFontProvider)getMemoryBlock().getAdapter(IFontProvider.class);
+ }
+
+ /**
+ * Returns the table presentation for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a table presentation is obtained by asking this rendering's
+ * memory block for its {@link IMemoryBlockTablePresentation} adapter.
+ *
+ * @return the table presentation for this rendering's memory block,
+ * or null
+ */
+ protected IMemoryBlockTablePresentation getTablePresentationAdapter()
+ {
+ return (IMemoryBlockTablePresentation)getMemoryBlock().getAdapter(IMemoryBlockTablePresentation.class);
+ }
+
+ /**
+ * Setup the viewer so it supports hovers to show the offset of each field
+ */
+ private void createToolTip() {
+
+ fToolTipShell = new Shell(DebugUIPlugin.getShell(), SWT.ON_TOP | SWT.RESIZE );
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.marginWidth = 2;
+ gridLayout.marginHeight = 0;
+ fToolTipShell.setLayout(gridLayout);
+ fToolTipShell.setBackground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ final Control toolTipControl = createToolTipControl(fToolTipShell);
+
+ if (toolTipControl == null)
+ {
+ // if client decide not to use tooltip support
+ fToolTipShell.dispose();
+ return;
+ }
+
+ MouseTrackAdapter listener = new MouseTrackAdapter(){
+
+ private TableItem fTooltipItem = null;
+ private int fCol = -1;
+
+ public void mouseExit(MouseEvent e){
+
+ if (!fToolTipShell.isDisposed())
+ fToolTipShell.setVisible(false);
+ fTooltipItem = null;
+ }
+
+ public void mouseHover(MouseEvent e){
+
+ Point hoverPoint = new Point(e.x, e.y);
+ Control control = null;
+
+ if (e.widget instanceof Control)
+ control = (Control)e.widget;
+
+ if (control == null)
+ return;
+
+ hoverPoint = control.toDisplay(hoverPoint);
+ TableItem item = getItem(hoverPoint);
+ int column = getColumn(hoverPoint);
+
+ //Only if there is a change in hover
+ if(this.fTooltipItem != item || fCol != column){
+
+ //Keep Track of the latest hover
+ fTooltipItem = item;
+ fCol = column;
+
+ if(item != null){
+ toolTipAboutToShow(toolTipControl, fTooltipItem, column);
+
+ //Setting location of the tooltip
+ Rectangle shellBounds = fToolTipShell.getBounds();
+ shellBounds.x = hoverPoint.x;
+ shellBounds.y = hoverPoint.y + item.getBounds(0).height;
+
+ fToolTipShell.setBounds(shellBounds);
+ fToolTipShell.pack();
+
+ fToolTipShell.setVisible(true);
+ }
+ else {
+ fToolTipShell.setVisible(false);
+ }
+ }
+ }
+ };
+
+ fTableViewer.getTable().addMouseTrackListener(listener);
+ fTableViewer.getCursor().addMouseTrackListener(listener);
+ }
+
+ /**
+ * Creates the control used to display tool tips for cells in this table. By default
+ * a label is used to display the address of the cell. Clients may override this
+ * method to create custom tooltip controls.
+ *
+ * Also see the methods getToolTipText(...)
and
+ * toolTipAboutToShow(...)
.
+ *
+ * @param composite parent for the tooltip control
+ * @return the tooltip control to be displayed
+ * @since 3.2
+ */
+ protected Control createToolTipControl(Composite composite) {
+ Control fToolTipLabel = new Label(composite, SWT.NONE);
+ fToolTipLabel.setForeground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ fToolTipLabel.setBackground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ fToolTipLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |
+ GridData.VERTICAL_ALIGN_CENTER));
+ return fToolTipLabel;
+ }
+
+ /**
+ * Bug with table widget,BUG 113015, the widget is not able to return the correct
+ * table item if SWT.FULL_SELECTION is not on when the table is created.
+ * Created the following function to work around the problem.
+ * We can remove this method when the bug is fixed.
+ * @param point
+ * @return the table item where the point is located, return null if the item cannot be located.
+ */
+ private TableItem getItem(Point point)
+ {
+ TableItem[] items = fTableViewer.getTable().getItems();
+ for (int i=0; i point.x)
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Called when the tool tip is about to show in this rendering.
+ * Clients who overrides createTooltipControl
may need to
+ * also override this method to ensure that the tooltip shows up properly
+ * in their customized control.
+ *
+ * By default a text tooltip is displayed, and the contents for the tooltip
+ * are generated by the getToolTipText(...)
method.
+ *
+ * @param toolTipControl - the control for displaying the tooltip
+ * @param item - the table item where the mouse is pointing.
+ * @param col - the column at which the mouse is pointing.
+ * @since 3.2
+ */
+ protected void toolTipAboutToShow(Control toolTipControl, TableItem item,
+ int col) {
+ if (toolTipControl instanceof Label) {
+ Object address = fTableViewer.getKey(fTableViewer.getTable().indexOf(item), col);
+ if (address != null && address instanceof BigInteger) {
+ Object data = item.getData();
+ if (data instanceof MemorySegment) {
+ MemorySegment line = (MemorySegment) data;
+
+ if (col > 0) {
+ int start = (col - 1) * getBytesPerColumn();
+ int end = start + getBytesPerColumn();
+ MemoryByte[] bytes = line.getBytes(start, end);
+
+ String str = getToolTipText((BigInteger)address, bytes);
+
+ if (str != null)
+ ((Label) toolTipControl).setText(str);
+ } else {
+ String str = getToolTipText((BigInteger)address,
+ new MemoryByte[] {});
+
+ if (str != null)
+ ((Label) toolTipControl).setText(str);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the text to display in a tool tip at the specified address
+ * for the specified bytes. By default the address of the bytes is displayed.
+ * Subclasses may override.
+ *
+ * @param address address of cell that tool tip is displayed for
+ * @param bytes the bytes in the cell
+ * @return the tooltip text for the memory bytes located at the specified
+ * address
+ * @since 3.2
+ */
+ protected String getToolTipText(BigInteger address, MemoryByte[] bytes)
+ {
+ StringBuffer buf = new StringBuffer("0x"); //$NON-NLS-1$
+ buf.append(address.toString(16).toUpperCase());
+
+ return buf.toString();
+ }
+
+ private void setColumnHeadings()
+ {
+ String[] columnLabels = new String[0];
+
+ IMemoryBlockTablePresentation presentation = getTablePresentationAdapter();
+ if (presentation != null)
+ {
+ columnLabels = presentation.getColumnLabels(getMemoryBlock(), getBytesPerLine(), getBytesPerLine()/getBytesPerColumn());
+ }
+
+ // check that column labels returned are not null
+ if (columnLabels == null)
+ columnLabels = new String[0];
+
+ int numByteColumns = fBytePerLine/fColumnSize;
+
+ TableColumn[] columns = fTableViewer.getTable().getColumns();
+
+ int j=0;
+ for (int i=1; i= 4)
+ {
+ columns[i].setText(Integer.toHexString(j*addressableUnit).toUpperCase() +
+ " - " + Integer.toHexString(j*addressableUnit+addressableUnit-1).toUpperCase()); //$NON-NLS-1$
+ }
+ else
+ {
+ columns[i].setText(Integer.toHexString(j*addressableUnit).toUpperCase());
+ }
+ j++;
+ }
+ }
+ }
+
+ /**
+ *
+ * Return this rendering's viewer
+ * @return this rendering's viewer
+ */
+ public StructuredViewer getViewer()
+ {
+ return fTableViewer;
+ }
+
+ private boolean isMemoryBlockBaseAddressChanged()
+ {
+ try {
+ BigInteger address = getMemoryBlockBaseAddress();
+ BigInteger oldBaseAddress = fContentDescriptor.getContentBaseAddress();
+ if (!oldBaseAddress.equals(address))
+ return true;
+ } catch (DebugException e) {
+ // fail silently
+ }
+ return false;
+ }
+
+ /**
+ * @param topVisibleAddress
+ */
+ private void createContentDescriptor(final BigInteger topVisibleAddress) {
+ fContentDescriptor = new TableRenderingContentDescriptor(AbstractAsyncTableRendering.this);
+ fContentDescriptor.setPostBuffer(20);
+ fContentDescriptor.setPreBuffer(20);
+ fContentDescriptor.setLoadAddress(topVisibleAddress);
+ try {
+ fContentDescriptor.updateContentBaseAddress();
+
+ } catch (DebugException e) {
+ fError = true;
+ showMessage(e.getMessage());
+ }
+
+ fContentDescriptor.setAddressableSize(getAddressableSize());
+
+ try {
+ int addressSize = 4;
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ IMemoryBlockExtension extMb = (IMemoryBlockExtension)getMemoryBlock();
+ addressSize = extMb.getAddressSize();
+
+ if (addressSize <= 0)
+ {
+ DebugUIPlugin.logErrorMessage("Invalid address Size: " + addressSize); //$NON-NLS-1$
+ addressSize = 4;
+ }
+ fContentDescriptor.setAddressSize(addressSize);
+ }
+ fContentDescriptor.setAddressSize(addressSize);
+ } catch (DebugException e) {
+ fError = true;
+ showMessage(e.getMessage());
+ } finally {
+ if (fContentDescriptor.getAddressSize() <= 0)
+ fContentDescriptor.setAddressSize(4);
+ }
+
+ }
+
+ private TableRenderingContentDescriptor getContentDescriptor()
+ {
+ return fContentDescriptor;
+ }
+
+ private void createGoToAddressComposite(Composite parent)
+ {
+ fGoToAddressComposite = new GoToAddressComposite();
+ fGoToAddressComposite.createControl(parent);
+ Button button = fGoToAddressComposite.getButton(IDialogConstants.OK_ID);
+ if (button != null)
+ {
+ button.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent e) {
+ doGoToAddress();
+ }
+ });
+
+ button = fGoToAddressComposite.getButton(IDialogConstants.CANCEL_ID);
+ if (button != null)
+ {
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ hideGotoAddressComposite();
+ }});
+ }
+ }
+
+ fGoToAddressComposite.getExpressionWidget().addSelectionListener(new SelectionAdapter() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ doGoToAddress();
+ }});
+
+ fGoToAddressComposite.getExpressionWidget().addKeyListener(new KeyAdapter() {
+
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.ESC)
+ hideGotoAddressComposite();
+ super.keyPressed(e);
+ }});
+ }
+
+ private void showGoToAddressComposite() {
+
+ String selectedStr = getSelectedAsString();
+ Text text = fGoToAddressComposite.getExpressionWidget();
+ text.setText(selectedStr);
+ text.setSelection(0, text.getCharCount());
+
+ double height = fGoToAddressComposite.getHeight();
+ double canvasHeight = fSashForm.getParent().getClientArea().height;
+ double tableHeight = canvasHeight - height;
+
+ double tableWeight = (tableHeight/canvasHeight) * 100;
+ double textWeight = (height / canvasHeight) * 100;
+ fSashForm.setWeights(new int[]{(int)tableWeight, (int)textWeight});
+ fSashForm.setMaximizedControl(null);
+
+ fGoToAddressComposite.getExpressionWidget().setFocus();
+ }
+
+ private void hideGotoAddressComposite()
+ {
+ fSashForm.setMaximizedControl(fTableViewer.getControl());
+ if (isActivated())
+ fTableViewer.getControl().setFocus();
+ }
+
+ /**
+ *
+ */
+ private void doGoToAddress() {
+ try {
+ BigInteger address = fGoToAddressComposite.getGoToAddress(fContentDescriptor.getContentBaseAddress(), getSelectedAddress());
+ fGoToAddressAction.doGoToAddress(address.toString(16));
+ hideGotoAddressComposite();
+ } catch (DebugException e1) {
+ MemoryViewUtil.openError(DebugUIMessages.GoToAddressAction_Go_to_address_failed,
+ DebugUIMessages.GoToAddressAction_Go_to_address_failed, e1);
+ } catch (NumberFormatException e1)
+ {
+ MemoryViewUtil.openError(DebugUIMessages.GoToAddressAction_Go_to_address_failed,
+ DebugUIMessages.GoToAddressAction_Address_is_invalid, e1);
+ }
+ }
+
+ public void activated() {
+ super.activated();
+
+ fActivated = true;
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ ICommandService commandSupport = (ICommandService)workbench.getAdapter(ICommandService.class);
+ IContextService contextSupport = (IContextService)workbench.getAdapter(IContextService.class);
+
+ if (commandSupport != null && contextSupport != null)
+ {
+ fContext.add(contextSupport.activateContext(ID_ASYNC_TABLE_RENDERING_CONTEXT));
+ Command gotoCommand = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND);
+
+ if (fGoToAddressHandler == null)
+ {
+ fGoToAddressHandler = new AbstractHandler() {
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ if (fSashForm.getMaximizedControl() != null)
+ fGoToAddressAction.run();
+ else
+ hideGotoAddressComposite();
+ return null;
+ }};
+ }
+ gotoCommand.setHandler(fGoToAddressHandler);
+ }
+
+ }
+
+
+ public void deactivated() {
+
+ fActivated = false;
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ ICommandService commandSupport = (ICommandService)workbench.getAdapter(ICommandService.class);
+ IContextService contextSupport = (IContextService)workbench.getAdapter(IContextService.class);
+
+ if (commandSupport != null && contextSupport != null)
+ {
+ // remove handler
+ Command command = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND);
+ command.setHandler(null);
+
+ if (fContext != null)
+ contextSupport.deactivateContexts(fContext);
+ }
+ super.deactivated();
+ }
+
+ private boolean isActivated()
+ {
+ return fActivated;
+ }
+
+ /**
+ * Returns text for the given memory bytes at the specified address for the specified
+ * rendering type. This is called by the label provider for.
+ * Subclasses must override.
+ *
+ * @param renderingTypeId rendering type identifier
+ * @param address address where the bytes belong to
+ * @param data the bytes
+ * @return a string to represent the memory. Cannot not return null
.
+ * Returns a string to pad the cell if the memory cannot be converted
+ * successfully.
+ */
+ abstract public String getString(String renderingTypeId, BigInteger address, MemoryByte[] data);
+
+ /**
+ * Returns bytes for the given text corresponding to bytes at the given
+ * address for the specified rendering type. This is called by the cell modifier
+ * when modifying bytes in a memory block.
+ * Subclasses must convert the string value to an array of bytes. The bytes will
+ * be passed to the debug adapter for memory block modification.
+ * Returns null
if the bytes cannot be formatted properly.
+ *
+ * @param renderingTypeId rendering type identifier
+ * @param address address the bytes begin at
+ * @param currentValues current values of the data in bytes format
+ * @param newValue the string to be converted to bytes
+ * @return the bytes converted from a string
+ */
+ abstract public byte[] getBytes(String renderingTypeId, BigInteger address, MemoryByte[] currentValues, String newValue);
+}
diff --git a/samples/src/AbstractTableRendering.java b/samples/src/AbstractTableRendering.java
new file mode 100644
index 0000000..6896937
--- /dev/null
+++ b/samples/src/AbstractTableRendering.java
@@ -0,0 +1,3740 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.debug.ui.memory;
+
+import java.math.BigInteger;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IMemoryBlockExtension;
+import org.eclipse.debug.core.model.MemoryByte;
+import org.eclipse.debug.internal.ui.DebugUIMessages;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.internal.ui.memory.IMemoryBlockConnection;
+import org.eclipse.debug.internal.ui.memory.IPersistableDebugElement;
+import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
+import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
+import org.eclipse.debug.internal.ui.views.memory.renderings.CopyTableRenderingToClipboardAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.FormatTableRenderingAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.FormatTableRenderingDialog;
+import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.AbstractBaseTableRendering;
+import org.eclipse.debug.internal.ui.views.memory.renderings.PrintTableRenderingAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.ReformatAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.ResetToBaseAddressAction;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingCellModifier;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentInput;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentProvider;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLabelProvider;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLabelProviderEx;
+import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLine;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.IBasicPropertyConstants;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.TableCursor;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseTrackAdapter;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyDialogAction;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+import org.eclipse.ui.part.PageBook;
+
+/**
+ * Abstract implementation of a table rendering.
+ *
+ * Clients should subclass from this class if they wish to provide a
+ * table rendering.
+ *
+ *
+ *
+ * The label of the rendering is constructed by retrieving the expression from
+ * IMemoryBlockExtension
. For IMemoryBlock, the label is constructed
+ * using the memory block's start address.
+ *
+ * This rendering manages the change states of its memory bytes if the memory
+ * block does not opt to manage the change states. For IMemoryBlockExtension, if
+ * the memory block returns false when #supportsChangeManagement() is called, this
+ * rendering will calculate the change state for each byte when its content is updated.
+ * Clients may manages the change states of its memory block by returning true when
+ * #supportsChangeManagement() is called. This will cause this rendering to stop
+ * calculating the change states of the memory block. Instead it would rely on the
+ * attributes returned in the MemoryByte array to determine if a byte has changed.
+ * For IMemoryBlock, this rendering will manage the change states its content.
+ *
+ * When firing change event, be aware of the following:
+ * - whenever a change event is fired, the content provider for Memory View
+ * view checks to see if memory has actually changed.
+ * - If memory has actually changed, a refresh will commence. Changes to the memory block
+ * will be computed and will be shown with the delta icons.
+ * - If memory has not changed, content will not be refreshed. However, previous delta information
+ * will be erased. The screen will be refreshed to show that no memory has been changed. (All
+ * delta icons will be removed.)
+ *
+ * Please note that these APIs will be called multiple times by the Memory View.
+ * To improve performance, debug adapters need to cache the content of its memory block and only
+ * retrieve updated data when necessary.
+ *
+
+ * @since 3.1
+ */
+public abstract class AbstractTableRendering extends AbstractBaseTableRendering implements IPropertyChangeListener, IResettableMemoryRendering{
+
+ /**
+ * Property identifier for the selected address in a table rendering
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_SELECTED_ADDRESS = "selectedAddress"; //$NON-NLS-1$
+
+ /**
+ * Property identifier for the column size in a table rendering
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_COL_SIZE = "columnSize"; //$NON-NLS-1$
+
+ /**
+ * Property identifier for the top row address in a table rendering.
+ * This property is used for synchronization between renderings.
+ */
+ public static final String PROPERTY_TOP_ADDRESS = "topAddress"; //$NON-NLS-1$
+
+ /**
+ * Property identifier for the row size in a table rendering
+ * This property is used for synchronization between renderings.
+ * @since 3.2
+ */
+ public static final String PROPERTY_ROW_SIZE = "rowSize"; //$NON-NLS-1$
+
+ private PageBook fPageBook;
+ private TableViewer fTableViewer;
+ private TextViewer fTextViewer;
+
+ private int fBytePerLine; // number of bytes per line: 16
+ private int fColumnSize; // number of bytes per column: 1,2,4,8
+ private int fAddressableSize;
+
+ private boolean fIsShowingErrorPage;
+
+ private TableRenderingContentProvider fContentProvider;
+ private BigInteger fSelectedAddress;
+ private TableRenderingContentInput fContentInput;
+ private TableRenderingCellModifier fCellModifier;
+ private boolean fIsCreated;
+ private CellEditor[] fEditors;
+ private String fLabel;
+ private TableCursor fTableCursor;
+ private boolean fIsDisposed;
+ private TraverseListener fCursorTraverseListener;
+ private KeyAdapter fCursorKeyAdapter;
+ private BigInteger fTopRowAddress;
+
+ private CopyTableRenderingToClipboardAction fCopyToClipboardAction;
+ private GoToAddressAction fGoToAddressAction;
+ private ResetToBaseAddressAction fResetMemoryBlockAction;
+ private PrintTableRenderingAction fPrintViewTabAction;
+ private ReformatAction fReformatAction;
+ private ToggleAddressColumnAction fToggleAddressColumnAction;
+ private EventHandleLock fEvtHandleLock = new EventHandleLock();
+ private TableEditor fCursorEditor;
+ private FocusAdapter fEditorFocusListener;
+ private MouseAdapter fCursorMouseListener;
+ private KeyAdapter fEditorKeyListener;
+ private SelectionAdapter fCursorSelectionListener;
+ private IWorkbenchAdapter fWorkbenchAdapter;
+ private IMemoryBlockConnection fConnection;
+
+ private boolean fIsShowAddressColumn = true;
+ private SelectionAdapter fScrollbarSelectionListener;
+
+ private PropertyDialogAction fPropertiesAction;
+
+ private int fPageSize;
+ private NextPageAction fNextAction;
+ private PrevPageAction fPrevAction;
+
+ private Shell fToolTipShell;
+ private FormatTableRenderingAction fFormatRenderingAction;
+
+ private IMenuListener fMenuListener;
+
+ private class EventHandleLock
+ {
+ Object fOwner;
+
+ public boolean acquireLock(Object client)
+ {
+ if (fOwner == null)
+ {
+ fOwner = client;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean releaseLock(Object client)
+ {
+ if (fOwner == client)
+ {
+ fOwner = null;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isLocked()
+ {
+ return (fOwner != null);
+ }
+ }
+
+
+ private class ToggleAddressColumnAction extends Action {
+
+ public ToggleAddressColumnAction() {
+ super();
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID
+ + ".ShowAddressColumnAction_context"); //$NON-NLS-1$
+ updateActionLabel();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.action.IAction#run()
+ */
+ public void run() {
+ fIsShowAddressColumn = !fIsShowAddressColumn;
+ resizeColumnsToPreferredSize();
+ updateActionLabel();
+ }
+
+ /**
+ *
+ */
+ private void updateActionLabel() {
+ if (fIsShowAddressColumn) {
+ setText(DebugUIMessages.ShowAddressColumnAction_0);
+ } else {
+ setText(DebugUIMessages.ShowAddressColumnAction_1);
+ }
+ }
+ }
+
+
+ private class NextPageAction extends Action
+ {
+ private NextPageAction()
+ {
+ super();
+ setText(DebugUIMessages.AbstractTableRendering_4);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".NextPageAction_context"); //$NON-NLS-1$
+ }
+
+ public void run() {
+ BigInteger address = fContentInput.getLoadAddress();
+ address = address.add(BigInteger.valueOf(getPageSizeInUnits()));
+ handlePageStartAddressChanged(address);
+ }
+ }
+
+ private class PrevPageAction extends Action
+ {
+ private PrevPageAction()
+ {
+ super();
+ setText(DebugUIMessages.AbstractTableRendering_6);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".PrevPageAction_context"); //$NON-NLS-1$
+ }
+
+ public void run() {
+ BigInteger address = fContentInput.getLoadAddress();
+ address = address.subtract(BigInteger.valueOf(getPageSizeInUnits()));
+ handlePageStartAddressChanged(address);
+ }
+ }
+
+ /**
+ * Constructs a new table rendering of the specified type.
+ *
+ * @param renderingId memory rendering type identifier
+ */
+ public AbstractTableRendering(String renderingId) {
+ super(renderingId);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ // if memory view table font has changed
+ if (event.getProperty().equals(IInternalDebugUIConstants.FONT_NAME))
+ {
+ if (!fIsDisposed)
+ {
+ Font memoryViewFont = JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME);
+ setFont(memoryViewFont);
+ }
+ return;
+ }
+
+ if (event.getProperty().equals(IDebugUIConstants.PREF_PADDED_STR) ||
+ event.getProperty().equals(IDebugUIConstants.PREF_MEMORY_HISTORY_KNOWN_COLOR) ||
+ event.getProperty().equals(IDebugUIConstants.PREF_MEMORY_HISTORY_UNKNOWN_COLOR))
+ {
+ if (!fIsDisposed)
+ {
+ fTableViewer.refresh();
+ fTableCursor.redraw();
+ }
+ return;
+ }
+
+ Object evtSrc = event.getSource();
+
+ if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
+ // always update page size, only refresh if the table is visible
+ getPageSizeFromPreference();
+ }
+
+ // do not handle event if the rendering is displaying an error
+ if (isDisplayingError())
+ return;
+
+ // do not handle property change event if the rendering is not visible
+ if (!isVisible())
+ return;
+
+ if (event.getProperty().equals(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM)) {
+ handleDyanicLoadChanged();
+ return;
+ }
+
+ if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
+ if (!isDynamicLoad())
+ {
+ // only refresh if in non-autoload mode
+ refresh();
+ }
+ return;
+ }
+
+ if (evtSrc == this)
+ return;
+
+ if (!(evtSrc instanceof IMemoryRendering))
+ return;
+
+ IMemoryRendering rendering = (IMemoryRendering)evtSrc;
+ IMemoryBlock memoryBlock = rendering.getMemoryBlock();
+
+ // do not handle event from renderings displaying other memory blocks
+ if (memoryBlock != getMemoryBlock())
+ return;
+
+ String propertyName = event.getProperty();
+ Object value = event.getNewValue();
+
+ if (propertyName.equals(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS) && value instanceof BigInteger)
+ {
+ selectedAddressChanged((BigInteger)value);
+ }
+ else if (propertyName.equals(AbstractTableRendering.PROPERTY_COL_SIZE) && value instanceof Integer)
+ {
+ columnSizeChanged(((Integer)value).intValue());
+ }
+ else if (propertyName.equals(AbstractTableRendering.PROPERTY_ROW_SIZE) && value instanceof Integer)
+ {
+ rowSizeChanged(((Integer)value).intValue());
+ }
+ else if (propertyName.equals(AbstractTableRendering.PROPERTY_TOP_ADDRESS) && value instanceof BigInteger)
+ {
+ if (needMoreLines())
+ {
+ if (isDynamicLoad())
+ reloadTable(getTopVisibleAddress(), false);
+ }
+ topVisibleAddressChanged((BigInteger)value, false);
+ }
+ else if (propertyName.equals(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS) && value instanceof BigInteger)
+ {
+ handlePageStartAddressChanged((BigInteger)value);
+ }
+ }
+
+ private void handleDyanicLoadChanged() {
+
+ // if currently in dynamic load mode, update page
+ // start address
+ updateSyncPageStartAddress();
+
+ updateDynamicLoadProperty();
+ if (isDynamicLoad())
+ {
+ refresh();
+ }
+ else
+ {
+ BigInteger pageStart = (BigInteger)getSynchronizedProperty(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS);
+ if (pageStart == null)
+ pageStart = fTopRowAddress;
+ handlePageStartAddressChanged(pageStart);
+ }
+ }
+
+ private void updateDynamicLoadProperty() {
+
+ boolean value = DebugUIPlugin
+ .getDefault()
+ .getPreferenceStore()
+ .getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM);
+
+ if (value != isDynamicLoad())
+ {
+ fContentProvider.setDynamicLoad(value);
+
+ if (!fIsDisposed) {
+ if (isDynamicLoad()) {
+ fContentInput.setPostBuffer(20);
+ fContentInput.setPreBuffer(20);
+ fContentInput.setDefaultBufferSize(20);
+ fContentInput.setNumLines(getNumberOfVisibleLines());
+
+ } else {
+ fContentInput.setPostBuffer(0);
+ fContentInput.setPreBuffer(0);
+ fContentInput.setDefaultBufferSize(0);
+ fContentInput.setNumLines(fPageSize);
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle top visible address change event from synchronizer
+ * @param address
+ */
+ private void topVisibleAddressChanged(final BigInteger address, boolean force)
+ {
+ // do not handle event if rendering is not visible
+ // continue to handle event if caller decides to force the rendering
+ // to move to the top visible address even when the rendering
+ // is not visible
+ if (!isVisible() && !force)
+ return;
+
+ // do not handle event if the base address of the memory
+ // block has changed, wait for debug event to update to
+ // new location
+ if (isBaseAddressChanged())
+ return;
+
+ if (!address.equals(fTopRowAddress))
+ {
+ fTopRowAddress = address;
+ updateSyncTopAddress();
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+
+ handleTopAddressChangedforExtended(address);
+ }
+ else
+ {
+ handleTopAddressChangedForSimple(address);
+ }
+ }
+ }
+
+ /**
+ * @param address
+ */
+ private void handleTopAddressChangedForSimple(final BigInteger address) {
+ // IMemoryBlock support
+ int index = findAddressIndex(address);
+ Table table = fTableViewer.getTable();
+ if (index >= 0)
+ {
+ setTopIndex(table, index);
+ }
+
+ if (isAddressVisible(fSelectedAddress))
+ fTableCursor.setVisible(true);
+ else
+ fTableCursor.setVisible(false);
+
+ }
+
+ /**
+ * @param address
+ */
+ private void handleTopAddressChangedforExtended(final BigInteger address) {
+
+ Object evtLockClient = new Object();
+ try
+ {
+ if (!fEvtHandleLock.acquireLock(evtLockClient))
+ return;
+
+ if (!isAddressOutOfRange(address))
+ {
+ Table table = fTableViewer.getTable();
+ int index = findAddressIndex(address);
+ if (index >= 3 && table.getItemCount() - (index+getNumberOfVisibleLines()) >= 3)
+ {
+ // update cursor position
+ setTopIndex(table, index);
+ }
+ else
+ {
+ int numInBuffer = table.getItemCount();
+ if (index < 3)
+ {
+ if(isAtTopLimit())
+ {
+ setTopIndex(table, index);
+ }
+ else
+ {
+ if (isDynamicLoad())
+ reloadTable(address, false);
+ else
+ setTopIndex(table, index);
+ }
+ }
+ else if ((numInBuffer-(index+getNumberOfVisibleLines())) < 3)
+ {
+ if (!isAtBottomLimit() && isDynamicLoad())
+ reloadTable(address, false);
+ else
+ setTopIndex(table, index);
+ }
+ }
+ }
+ else
+ {
+ // approaching limit, reload table
+ reloadTable(address, false);
+ }
+
+ if (isAddressVisible(fSelectedAddress))
+ fTableCursor.setVisible(true);
+ else
+ fTableCursor.setVisible(false);
+ }
+ finally
+ {
+ fEvtHandleLock.releaseLock(evtLockClient);
+ }
+ }
+
+ /**
+ * @param value
+ */
+ private void selectedAddressChanged(BigInteger value) {
+
+ // do not handle event if the base address of the memory
+ // block has changed, wait for debug event to update to
+ // new location
+ if (isBaseAddressChanged())
+ return;
+
+ try {
+ // do not handle event if the event is out of range and the
+ // rendering is in non-dynamic-load mode, otherwise, will
+ // cause rendering to continue to scroll when it shouldn't
+ if (isDynamicLoad())
+ goToAddress(value);
+ else if (!isAddressOutOfRange(value))
+ goToAddress(value);
+ } catch (DebugException e) {
+ // do nothing
+ }
+ }
+
+ private void handlePageStartAddressChanged(BigInteger address)
+ {
+ // do not handle if in dynamic mode
+ if (isDynamicLoad())
+ return;
+
+ if (fContentInput == null)
+ return;
+
+ if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
+ return;
+
+ // do not handle event if the base address of the memory
+ // block has changed, wait for debug event to update to
+ // new location
+ if (isBaseAddressChanged())
+ return;
+
+ if(fContentProvider.getBufferTopAddress().equals(address))
+ return;
+
+ BigInteger start = fContentInput.getStartAddress();
+ BigInteger end = fContentInput.getEndAddress();
+
+ // smaller than start address, load at start address
+ if (address.compareTo(start) < 0)
+ {
+ if (isAtTopLimit())
+ return;
+
+ address = start;
+ }
+
+ // bigger than end address, no need to load, already at top
+ if (address.compareTo(end) > 0)
+ {
+ if (isAtBottomLimit())
+ return;
+
+ address = end.subtract(BigInteger.valueOf(getPageSizeInUnits()));
+ }
+
+ fContentInput.setLoadAddress(address);
+ refresh();
+ updateSyncPageStartAddress();
+ setTopIndex(fTableViewer.getTable(), 0);
+ fTopRowAddress = address;
+ updateSyncTopAddress();
+
+ BigInteger selectedAddress = (BigInteger)getSynchronizedProperty(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
+ if (selectedAddress != null)
+ {
+ fSelectedAddress = selectedAddress;
+ if (!isAddressOutOfRange(fSelectedAddress))
+ {
+ setCursorAtAddress(fSelectedAddress);
+ fTableCursor.setVisible(true);
+ }
+ else
+ {
+ fTableCursor.setVisible(false);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public Control createControl(Composite parent) {
+
+ fPageBook = new PageBook(parent, SWT.NONE);
+ createErrorPage(fPageBook);
+ createTableViewer(fPageBook);
+
+ fTableViewer.getTable().redraw();
+ createToolTip();
+
+ return fPageBook;
+ }
+
+ /**
+ * Create the table viewer and other support controls
+ * for this rendering.
+ *
+ * @param parent parent composite
+ */
+ private void createTableViewer(Composite parent) {
+
+ fTableViewer= new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.HIDE_SELECTION | SWT.BORDER);
+
+ TableRenderingLabelProvider labelProvider;
+ if (hasCustomizedDecorations())
+ labelProvider = new TableRenderingLabelProviderEx(this);
+ else
+ labelProvider = new TableRenderingLabelProvider(this);
+
+ fTableViewer.setLabelProvider(labelProvider);
+
+ fContentProvider = new TableRenderingContentProvider();
+ fContentProvider.setDynamicLoad(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM));
+
+ fTableViewer.setContentProvider(fContentProvider);
+ fContentProvider.setViewer(fTableViewer);
+
+ ScrollBar scroll = ((Table)fTableViewer.getControl()).getVerticalBar();
+ scroll.setMinimum(-100);
+ scroll.setMaximum(200);
+
+ fTableViewer.getTable().setHeaderVisible(true);
+ fTableViewer.getTable().setLinesVisible(true);
+
+
+ // set up addressable size and figure out number of bytes required per line
+ fAddressableSize = -1;
+ try {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ fAddressableSize = ((IMemoryBlockExtension)getMemoryBlock()).getAddressableSize();
+ } catch (DebugException e1) {
+ // log error and default to 1
+ fAddressableSize = 1;
+ displayError(e1);
+ return;
+
+ }
+ if (getAddressableSize() < 1)
+ fAddressableSize = 1;
+
+// set up initial format
+ setupInitialFormat();
+
+// set up selected address
+ setupSelectedAddress();
+
+ // figure out top visible address
+ BigInteger topVisibleAddress = getInitialTopVisibleAddress();
+
+ getPageSizeFromPreference();
+
+ if (isDynamicLoad())
+ fContentInput = new TableRenderingContentInput(this, 20, 20, 20, topVisibleAddress, getNumberOfVisibleLines(), false, null);
+ else
+ {
+ BigInteger addressToLoad = topVisibleAddress;
+
+ // check synchronization service to see if we need to sync with another rendering
+ Object obj = getSynchronizedProperty(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS);
+ if (obj != null && obj instanceof BigInteger)
+ {
+ addressToLoad = (BigInteger)obj;
+ }
+ fContentInput = new TableRenderingContentInput(this, 0, 0, 0, addressToLoad, fPageSize, false, null);
+ }
+
+ fTableViewer.setInput(fContentInput);
+
+ // set up cell modifier
+ fCellModifier = new TableRenderingCellModifier(this);
+ fTableViewer.setCellModifier(fCellModifier);
+
+ // SET UP FONT
+ // set to a non-proportional font
+ fTableViewer.getTable().setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
+ if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
+ {
+ // If not extended memory block, do not create any buffer
+ // no scrolling
+ fContentInput.setPreBuffer(0);
+ fContentInput.setPostBuffer(0);
+ fContentInput.setDefaultBufferSize(0);
+ }
+
+ // set up table cursor
+ createCursor(fTableViewer.getTable(), fSelectedAddress);
+ fTableViewer.getTable().addMouseListener(new MouseAdapter() {
+ public void mouseDown(MouseEvent e) {
+ handleTableMouseEvent(e);
+ }});
+
+ // create pop up menu for the rendering
+ createActions();
+ createPopupMenu(fTableViewer.getControl());
+ createPopupMenu(fTableCursor);
+
+ fMenuListener = new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ fillContextMenu(manager);
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }};
+ getPopupMenuManager().addMenuListener(fMenuListener);
+
+ // now the rendering is successfully created
+ fIsCreated = true;
+
+ //synchronize
+ addRenderingToSyncService();
+ synchronize();
+
+ fTopRowAddress = getTopVisibleAddress();
+ // Need to resize column after content is filled in
+ // Pack function does not work unless content is not filled in
+ // since the table is not able to compute the preferred size.
+ resizeColumnsToPreferredSize();
+ try {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ if(((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress() == null)
+ {
+ DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.AbstractTableRendering_1, null));
+ displayError(e);
+ }
+ }
+ } catch (DebugException e1) {
+ displayError(e1);
+ }
+
+ // add font change listener and update font when the font has been changed
+ JFaceResources.getFontRegistry().addListener(this);
+ fScrollbarSelectionListener = new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent event) {
+ handleScrollBarSelection();
+
+ }};
+ scroll.addSelectionListener(fScrollbarSelectionListener);
+ DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
+ }
+
+ private boolean validateInitialFormat()
+ {
+ int rowSize = getDefaultRowSize();
+ int columnSize = getDefaultColumnSize();
+
+ if (rowSize < columnSize || rowSize % columnSize != 0 || rowSize == 0 || columnSize == 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private BigInteger getInitialTopVisibleAddress() {
+ BigInteger topVisibleAddress = (BigInteger) getSynchronizedProperty(AbstractTableRendering.PROPERTY_TOP_ADDRESS);
+ if (topVisibleAddress == null)
+ {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ try {
+ topVisibleAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
+ } catch (DebugException e1) {
+ topVisibleAddress = new BigInteger("0"); //$NON-NLS-1$
+ }
+ }
+ else
+ {
+ topVisibleAddress = BigInteger.valueOf(getMemoryBlock().getStartAddress());
+ }
+ }
+ return topVisibleAddress;
+ }
+
+ private void setupSelectedAddress() {
+ // figure out selected address
+ BigInteger selectedAddress = (BigInteger) getSynchronizedProperty(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
+ if (selectedAddress == null)
+ {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension) {
+ try {
+ selectedAddress = ((IMemoryBlockExtension) getMemoryBlock())
+ .getBigBaseAddress();
+ } catch (DebugException e1) {
+ selectedAddress = new BigInteger("0"); //$NON-NLS-1$
+ }
+ if (selectedAddress == null) {
+ selectedAddress = new BigInteger("0"); //$NON-NLS-1$
+ }
+
+ } else {
+ long address = getMemoryBlock().getStartAddress();
+ selectedAddress = BigInteger.valueOf(address);
+ }
+ }
+ setSelectedAddress(selectedAddress);
+ }
+
+ private void setupInitialFormat() {
+
+ boolean validated = validateInitialFormat();
+
+ if (!validated)
+ {
+ // pop up dialog to ask user for default values
+ StringBuffer msgBuffer = new StringBuffer(DebugUIMessages.AbstractTableRendering_20);
+ msgBuffer.append(" "); //$NON-NLS-1$
+ msgBuffer.append(this.getLabel());
+ msgBuffer.append("\n\n"); //$NON-NLS-1$
+ msgBuffer.append(DebugUIMessages.AbstractTableRendering_16);
+ msgBuffer.append("\n"); //$NON-NLS-1$
+ msgBuffer.append(DebugUIMessages.AbstractTableRendering_18);
+ msgBuffer.append("\n\n"); //$NON-NLS-1$
+
+ int bytePerLine = fBytePerLine;
+ int columnSize = fColumnSize;
+
+ // initialize this value to populate the dialog properly
+ fBytePerLine = getDefaultRowSize() / getAddressableSize();
+ fColumnSize = getDefaultColumnSize() / getAddressableSize();
+
+ FormatTableRenderingDialog dialog = new FormatTableRenderingDialog(this, DebugUIPlugin.getShell());
+ dialog.openError(msgBuffer.toString());
+
+ // restore to original value before formatting
+ fBytePerLine = bytePerLine;
+ fColumnSize = columnSize;
+
+ bytePerLine = dialog.getRowSize() * getAddressableSize();
+ columnSize = dialog.getColumnSize() * getAddressableSize();
+
+ format(bytePerLine, columnSize);
+ }
+ else
+ {
+ // Row size is stored as number of addressable units in preference store
+ int bytePerLine = getDefaultRowSize();
+ // column size is now stored as number of addressable units
+ int columnSize = getDefaultColumnSize();
+
+ // format memory block with specified "bytesPerLine" and "columnSize"
+ boolean ok = format(bytePerLine, columnSize);
+
+ if (!ok)
+ {
+ // this is to ensure that the rest of the rendering can be created
+ // and we can recover from a format error
+ format(bytePerLine, bytePerLine);
+ }
+ }
+ }
+
+ private int getDefaultColumnSize() {
+
+ // default to global preference store
+ IPreferenceStore prefStore = DebugUITools.getPreferenceStore();
+ int columnSize = prefStore.getInt(IDebugPreferenceConstants.PREF_COLUMN_SIZE);
+ // actual column size is number of addressable units * size of the addressable unit
+ columnSize = columnSize * getAddressableSize();
+
+ // check synchronized column size
+ Integer colSize = (Integer)getSynchronizedProperty(AbstractTableRendering.PROPERTY_COL_SIZE);
+ if (colSize != null)
+ {
+ // column size is stored as actual number of bytes in synchronizer
+ int syncColSize = colSize.intValue();
+ if (syncColSize > 0)
+ {
+ columnSize = syncColSize;
+ }
+ }
+ else
+ {
+ IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
+ int defaultColSize = -1;
+
+ if (elmt != null)
+ {
+ if (elmt.supportsProperty(this, IDebugPreferenceConstants.PREF_COL_SIZE_BY_MODEL))
+ defaultColSize = getDefaultFromPersistableElement(IDebugPreferenceConstants.PREF_COL_SIZE_BY_MODEL);
+ }
+
+ if (defaultColSize <= 0)
+ {
+ // if not provided, get default by model
+ defaultColSize = getDefaultColumnSizeByModel(getMemoryBlock().getModelIdentifier());
+ }
+
+ if (defaultColSize > 0)
+ columnSize = defaultColSize * getAddressableSize();
+ }
+ return columnSize;
+ }
+
+ private int getDefaultRowSize() {
+
+ int rowSize = DebugUITools.getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_ROW_SIZE);
+ int bytePerLine = rowSize * getAddressableSize();
+
+ // check synchronized row size
+ Integer size = (Integer)getSynchronizedProperty(AbstractTableRendering.PROPERTY_ROW_SIZE);
+ if (size != null)
+ {
+ // row size is stored as actual number of bytes in synchronizer
+ int syncRowSize = size.intValue();
+ if (syncRowSize > 0)
+ {
+ bytePerLine = syncRowSize;
+ }
+ }
+ else
+ {
+ int defaultRowSize = -1;
+ IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
+ if (elmt != null)
+ {
+ if (elmt.supportsProperty(this, IDebugPreferenceConstants.PREF_ROW_SIZE_BY_MODEL))
+ {
+ defaultRowSize = getDefaultFromPersistableElement(IDebugPreferenceConstants.PREF_ROW_SIZE_BY_MODEL);
+ return defaultRowSize * getAddressableSize();
+ }
+ }
+
+ if (defaultRowSize <= 0)
+ // no synchronized property, ask preference store by id
+ defaultRowSize = getDefaultRowSizeByModel(getMemoryBlock().getModelIdentifier());
+
+ if (defaultRowSize > 0)
+ bytePerLine = defaultRowSize * getAddressableSize();
+ }
+ return bytePerLine;
+ }
+
+ private int getDefaultFromPersistableElement(String propertyId) {
+ int defaultValue = -1;
+ IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
+ if (elmt != null)
+ {
+ try {
+ Object valueMB = elmt.getProperty(this, propertyId);
+ if (valueMB != null && !(valueMB instanceof Integer))
+ {
+ IStatus status = DebugUIPlugin.newErrorStatus("Model returned invalid type on " + propertyId, null); //$NON-NLS-1$
+ DebugUIPlugin.log(status);
+ }
+
+ if (valueMB != null)
+ {
+ Integer value = (Integer)valueMB;
+ defaultValue = value.intValue();
+ }
+ } catch (CoreException e) {
+ DebugUIPlugin.log(e);
+ }
+ }
+ return defaultValue;
+ }
+
+ private void getPageSizeFromPreference()
+ {
+ fPageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
+ }
+
+ private void createCursor(Table table, BigInteger address)
+ {
+ fTableCursor = new TableCursor(table, SWT.NONE);
+ Display display = fTableCursor.getDisplay();
+
+ // set up cursor color
+ fTableCursor.setBackground(display.getSystemColor(SWT.COLOR_LIST_SELECTION));
+ fTableCursor.setForeground(display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
+
+ fTableCursor.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
+ fTableCursor.setVisible(true);
+
+ fCursorKeyAdapter = new KeyAdapter() {
+ public void keyPressed(KeyEvent e)
+ {
+ handleCursorKeyPressed(e);
+ }
+ };
+ fTableCursor.addKeyListener(fCursorKeyAdapter);
+
+ fCursorTraverseListener = new TraverseListener() {
+ public void keyTraversed(TraverseEvent e) {
+ handleCursorTraverseEvt(e);
+ }};
+
+ fTableCursor.addTraverseListener(fCursorTraverseListener);
+
+ fCursorMouseListener = new MouseAdapter() {
+ public void mouseDown(MouseEvent e) {
+ handleCursorMouseEvent(e);
+ }};
+ fTableCursor.addMouseListener(fCursorMouseListener);
+
+ // cursor may be disposed before disposed is called
+ // remove listeners whenever the cursor is disposed
+ fTableCursor.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ if (fTableCursor == null)
+ return;
+ fTableCursor.removeTraverseListener(fCursorTraverseListener);
+ fTableCursor.removeKeyListener(fCursorKeyAdapter);
+ fTableCursor.removeMouseListener(fCursorMouseListener);
+ fTableCursor.removeSelectionListener(fCursorSelectionListener);
+ }});
+
+ fCursorSelectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+
+ if (!fEvtHandleLock.acquireLock(this))
+ return;
+
+ handleCursorMoved();
+
+ fEvtHandleLock.releaseLock(this);
+
+ }
+ };
+ fTableCursor.addSelectionListener(fCursorSelectionListener);
+
+
+ setCursorAtAddress(address);
+
+ fCursorEditor = new TableEditor (fTableViewer.getTable());
+ }
+
+ private void handleCursorTraverseEvt(TraverseEvent e){
+
+ if (fTableCursor.getRow() == null)
+ return;
+
+ Table table = (Table)fTableCursor.getParent();
+ int row = table.indexOf(fTableCursor.getRow());
+ int col = fTableCursor.getColumn();
+ if (col == getNumCol() && e.keyCode == SWT.ARROW_RIGHT)
+ {
+ if (row + 1>= table.getItemCount())
+ {
+ return;
+ }
+
+ row = row +1;
+ col = 0;
+ fTableCursor.setSelection(row, col);
+ }
+ if (col <= 1 && e.keyCode == SWT.ARROW_LEFT)
+ {
+ if (row-1 < 0)
+ {
+ return;
+ }
+
+ row = row - 1;
+ col = getNumCol()+1;
+ fTableCursor.setSelection(row, col);
+ }
+
+ Object evtLockClient = new Object();
+ if (!fEvtHandleLock.acquireLock(evtLockClient))
+ return;
+
+ handleCursorMoved();
+
+ fEvtHandleLock.releaseLock(evtLockClient);
+
+ }
+
+ /**
+ * Update selected address.
+ * Load more memory if required.
+ */
+ private void handleCursorMoved()
+ {
+ if (fIsDisposed)
+ return;
+
+ BigInteger selectedAddress = getSelectedAddressFromCursor(fTableCursor);
+
+ // when the cursor is moved, the selected address is changed
+ if (selectedAddress != null && !selectedAddress.equals(fSelectedAddress))
+ {
+ setSelectedAddress(selectedAddress);
+ updateSyncSelectedAddress();
+ }
+
+ // now check to see if the cursor is approaching buffer limit
+ TableItem item = fTableCursor.getRow();
+ if (item == null)
+ return;
+
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ int row = fTableViewer.getTable().indexOf(item);
+
+ if (row < 3)
+ {
+ if (!isAtTopLimit())
+ {
+ if (isDynamicLoad())
+ {
+ refresh();
+ setCursorAtAddress(fSelectedAddress);
+ }
+ }
+ }
+ else if (row >= fTableViewer.getTable().getItemCount() - 3)
+ {
+ if (!isAtBottomLimit())
+ {
+ if (isDynamicLoad())
+ {
+ refresh();
+ setCursorAtAddress(fSelectedAddress);
+ }
+ }
+ }
+ }
+
+ // if the cursor has moved, the top index of the table may change
+ // just update the synchronization service
+ BigInteger address = getTopVisibleAddress();
+ if (!address.equals(fTopRowAddress))
+ {
+ fTopRowAddress = address;
+ updateSyncTopAddress();
+ }
+ }
+
+ private void handleCursorKeyPressed(KeyEvent event)
+ {
+ // allow edit if user hits return
+ if (event.character == '\r' && event.getSource() instanceof TableCursor)
+ {
+ activateCellEditor(null);
+ return;
+ }
+
+ if (MemoryViewUtil.isValidEditEvent(event.keyCode))
+ {
+ // activate edit as soon as user types something at the cursor
+ if (event.getSource() instanceof TableCursor)
+ {
+ String initialValue = String.valueOf(event.character);
+ activateCellEditor(initialValue);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Calculate selected address based on cursor's current position
+ * @param cursor
+ * @return the selected address
+ */
+ private BigInteger getSelectedAddressFromCursor(TableCursor cursor)
+ {
+ TableItem row = cursor.getRow();
+ int col = cursor.getColumn();
+
+ return getAddressFromTableItem(row, col);
+ }
+
+ private BigInteger getAddressFromTableItem(TableItem row, int col) {
+ if (row == null)
+ return null;
+
+ // get row address
+ String temp = ((TableRenderingLine)row.getData()).getAddress();
+ BigInteger rowAddress = new BigInteger(temp, 16);
+
+ int offset;
+ if (col > 0)
+ {
+ // get address offset
+ int addressableUnit = getAddressableUnitPerColumn();
+ offset = (col-1) * addressableUnit;
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ return rowAddress.add(BigInteger.valueOf(offset));
+ }
+
+
+ /**
+ * Sets the cursor at the specified address
+ * @param address
+ * @return true if successful, false otherwise
+ */
+ private boolean setCursorAtAddress(BigInteger address)
+ {
+ // selected address is out of range, simply return false
+ if (address.compareTo(fContentProvider.getBufferTopAddress()) < 0)
+ return false;
+
+ // calculate selected row address
+ int addressableUnit = getAddressableUnitPerLine();
+ int numOfRows = address.subtract(fContentProvider.getBufferTopAddress()).intValue()/addressableUnit;
+ BigInteger rowAddress = fContentProvider.getBufferTopAddress().add(BigInteger.valueOf(numOfRows * addressableUnit));
+
+ // try to find the row of the selected address
+ int row = findAddressIndex(address);
+
+ if (row == -1)
+ {
+ return false;
+ }
+
+ // calculate offset to the row address
+ BigInteger offset = address.subtract(rowAddress);
+
+ // locate column
+ int colAddressableUnit = getAddressableUnitPerColumn();
+ int col = ((offset.intValue()/colAddressableUnit)+1);
+
+ if (col == 0)
+ col = 1;
+
+ fTableCursor.setSelection(row, col);
+
+ return true;
+ }
+
+
+ /**
+ * Format view tab based on the bytes per line and column.
+ *
+ * @param bytesPerLine - number of bytes per line, possible values: (1 / 2 / 4 / 8 / 16) * addressableSize
+ * @param columnSize - number of bytes per column, possible values: (1 / 2 / 4 / 8 / 16) * addressableSize
+ * @return true if format is successful, false, otherwise
+ */
+ public boolean format(int bytesPerLine, int columnSize)
+ {
+
+ // selected address gets changed as the cursor is moved
+ // during the reformat.
+ // Back up the address and restore it later.
+ BigInteger selectedAddress = fSelectedAddress;
+
+ // bytes per cell must be divisible to bytesPerLine
+ if (bytesPerLine % columnSize != 0)
+ {
+ return false;
+ }
+
+ if (bytesPerLine < columnSize)
+ {
+ return false;
+ }
+
+ // do not format if the view tab is already in that format
+ if(fBytePerLine == bytesPerLine && fColumnSize == columnSize){
+ return false;
+ }
+
+ fBytePerLine = bytesPerLine;
+ fColumnSize = columnSize;
+
+ Object evtLockClient = new Object();
+ if (!fEvtHandleLock.acquireLock(evtLockClient))
+ return false;
+
+ // if the tab is already created and is being reformatted
+ if (fIsCreated)
+ {
+ if (fTableViewer == null)
+ return false;
+
+ if (fTableViewer.getTable() == null)
+ return false;
+
+ // clean up old columns
+ TableColumn[] oldColumns = fTableViewer.getTable().getColumns();
+
+ for (int i=0; i= 4)
+ {
+ column.setText(Integer.toHexString(i*addressableUnit).toUpperCase() +
+ " - " + Integer.toHexString(i*addressableUnit+addressableUnit-1).toUpperCase()); //$NON-NLS-1$
+ }
+ else
+ {
+ column.setText(Integer.toHexString(i*addressableUnit).toUpperCase());
+ }
+ }
+ }
+
+ //Empty column for cursor navigation
+ TableColumn emptyCol = new TableColumn(fTableViewer.getTable(),SWT.LEFT,byteColumns.length+1);
+ emptyCol.setText(" "); //$NON-NLS-1$
+ emptyCol.setWidth(1);
+ emptyCol.setResizable(false);
+
+ // +2 to include properties for address and navigation column
+ String[] columnProperties = new String[byteColumns.length+2];
+ columnProperties[0] = TableRenderingLine.P_ADDRESS;
+
+ int addressableUnit = columnSize / getAddressableSize();
+
+ // use column beginning offset to the row address as properties
+ for (int i=1; i= 0)
+ setTopIndex(fTableViewer.getTable(), i);
+
+ if (isAddressVisible(selectedAddress))
+ // after refresh, make sure the cursor is at the correct position
+ setCursorAtAddress(selectedAddress);
+ }
+
+ fEvtHandleLock.releaseLock(evtLockClient);
+
+ return true;
+ }
+
+ /**
+ * Create the error page for this rendering.
+ * The error page is used to report any error resulted from
+ * getting memory from a memory block.
+ * @param parent
+ */
+ private void createErrorPage(Composite parent)
+ {
+ if (fTextViewer == null)
+ {
+ fTextViewer = new TextViewer(parent, SWT.WRAP);
+ fTextViewer.setDocument(new Document());
+ StyledText styleText = fTextViewer.getTextWidget();
+ styleText.setEditable(false);
+ styleText.setEnabled(false);
+ }
+ }
+
+ /**
+ * Displays the content of the table viewer.
+ */
+ public void displayTable()
+ {
+ fIsShowingErrorPage = false;
+ fPageBook.showPage(fTableViewer.getControl());
+ }
+
+ /**
+ * Displays an error message for the given exception.
+ *
+ * @param e exception to display
+ */
+ public void displayError(DebugException e)
+ {
+ StyledText styleText = null;
+ fIsShowingErrorPage = true;
+
+ styleText = fTextViewer.getTextWidget();
+
+ if (styleText != null)
+ styleText.setText(DebugUIMessages.AbstractTableRendering_3 + e.getMessage());
+ fPageBook.showPage(fTextViewer.getControl());
+
+ // clear content cache if we need to display error
+ fContentProvider.clearContentCache();
+ }
+
+ /**
+ * Returns whether the error page is displayed.
+ *
+ * @return whether the error page is displayed
+ */
+ public boolean isDisplayingError()
+ {
+ return fIsShowingErrorPage;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#getControl()
+ */
+ public Control getControl() {
+ return fPageBook;
+ }
+
+ /**
+ * Returns the addressable size of this rendering's memory block in bytes.
+ *
+ * @return the addressable size of this rendering's memory block in bytes
+ */
+ public int getAddressableSize() {
+ return fAddressableSize;
+ }
+
+ private Object getSynchronizedProperty(String propertyId)
+ {
+ IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
+
+ if (syncService == null)
+ return null;
+
+ return syncService.getProperty(getMemoryBlock(), propertyId);
+ }
+
+ /**
+ * This method estimates the number of visible lines in the rendering
+ * table.
+ * @return estimated number of visible lines in the table
+ */
+ private int getNumberOfVisibleLines()
+ {
+ if(fTableViewer == null)
+ return -1;
+
+ Table table = fTableViewer.getTable();
+ int height = fTableViewer.getTable().getSize().y;
+
+ // when table is not yet created, height is zero
+ if (height == 0)
+ {
+ // make use of the table viewer to estimate table size
+ height = fTableViewer.getTable().getParent().getSize().y;
+ }
+
+ // height of border
+ int border = fTableViewer.getTable().getHeaderHeight();
+
+ // height of scroll bar
+ int scroll = fTableViewer.getTable().getHorizontalBar().getSize().y;
+
+ // height of table is table's area minus border and scroll bar height
+ height = height-border-scroll;
+
+ // calculate number of visible lines
+ int lineHeight = getMinTableItemHeight(table);
+
+ int numberOfLines = height/lineHeight;
+
+ if (numberOfLines <= 0)
+ return 20;
+
+ return numberOfLines;
+ }
+
+ private static void setTopIndex(Table table, int index)
+ {
+ table.setTopIndex(index);
+ }
+
+ private void addRenderingToSyncService()
+ {
+ IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
+
+ if (syncService == null)
+ return;
+
+ syncService.addPropertyChangeListener(this, null);
+
+ // we could be in a format error even though the error is not yet displayed
+ // do not update sync property in this case
+ if (!isDisplayingError())
+ {
+ if (syncService.getSynchronizationProvider() == null)
+ syncService.setSynchronizationProvider(this);
+
+ // check if there is already synchronization info available
+ Object selectedAddress =getSynchronizedProperty( AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
+ Object rowSize = getSynchronizedProperty(AbstractTableRendering.PROPERTY_ROW_SIZE);
+ Object colSize =getSynchronizedProperty( AbstractTableRendering.PROPERTY_COL_SIZE);
+ Object topAddress =getSynchronizedProperty( AbstractTableRendering.PROPERTY_TOP_ADDRESS);
+
+ if (!isDynamicLoad())
+ {
+ Object pageStartAddress = getSynchronizedProperty(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS);
+ if (pageStartAddress == null)
+ updateSyncPageStartAddress();
+ }
+
+ // if info is available, some other view tab has already been
+ // created
+ // do not overwrite info in the synchronizer if that's the case
+ if (selectedAddress == null) {
+ updateSyncSelectedAddress();
+ }
+
+ if (rowSize == null)
+ {
+ updateSyncRowSize();
+ }
+
+ if (colSize == null) {
+ updateSyncColSize();
+ }
+ if (topAddress == null) {
+ updateSyncTopAddress();
+ }
+ }
+ }
+
+ /**
+ * Get properties from synchronizer and synchronize settings
+ */
+ private void synchronize()
+ {
+ if (!isDynamicLoad())
+ {
+ BigInteger pageStart = (BigInteger)getSynchronizedProperty(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS);
+ if (pageStart != null && fContentInput != null && fContentInput.getLoadAddress() != null)
+ {
+ if (!fContentInput.getLoadAddress().equals(pageStart))
+ handlePageStartAddressChanged(pageStart);
+ }
+ else if (pageStart != null)
+ {
+ handlePageStartAddressChanged(pageStart);
+ }
+ }
+
+ Integer rowSize = (Integer) getSynchronizedProperty(AbstractTableRendering.PROPERTY_ROW_SIZE);
+ Integer columnSize = (Integer) getSynchronizedProperty(AbstractTableRendering.PROPERTY_COL_SIZE);
+ BigInteger selectedAddress = (BigInteger)getSynchronizedProperty(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS);
+ BigInteger topAddress = (BigInteger)getSynchronizedProperty(AbstractTableRendering.PROPERTY_TOP_ADDRESS);
+
+ if (rowSize != null)
+ {
+ int rSize = rowSize.intValue();
+ if (rSize > 0 && rSize != fBytePerLine) {
+ rowSizeChanged(rSize);
+ }
+ }
+
+ if (columnSize != null) {
+ int colSize = columnSize.intValue();
+ if (colSize > 0 && colSize != fColumnSize) {
+ columnSizeChanged(colSize);
+ }
+ }
+ if (topAddress != null) {
+ if (!topAddress.equals(getTopVisibleAddress())) {
+ if (selectedAddress != null) {
+ if (!fSelectedAddress.equals(selectedAddress)) {
+ selectedAddressChanged(selectedAddress);
+ }
+ }
+ topVisibleAddressChanged(topAddress, false);
+ }
+ }
+ if (selectedAddress != null) {
+ if (selectedAddress.compareTo(fSelectedAddress) != 0) {
+ selectedAddressChanged(selectedAddress);
+ }
+ }
+ }
+
+ /**
+ * Resize column to the preferred size.
+ */
+ public void resizeColumnsToPreferredSize() {
+ // pack columns
+ Table table = fTableViewer.getTable();
+ TableColumn[] columns = table.getColumns();
+
+ for (int i=0 ;i"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ return decorateLabel(label);
+ }
+
+ private void setColumnHeadings()
+ {
+ String[] columnLabels = new String[0];
+
+ IMemoryBlockTablePresentation presentation = getTablePresentationAdapter();
+ if (presentation != null)
+ {
+ columnLabels = presentation.getColumnLabels(getMemoryBlock(), fBytePerLine, getNumCol());
+ }
+
+ // check that column labels returned are not null
+ if (columnLabels == null)
+ columnLabels = new String[0];
+
+ int numByteColumns = fBytePerLine/fColumnSize;
+
+ TableColumn[] columns = fTableViewer.getTable().getColumns();
+
+ int j=0;
+ for (int i=1; i= 4)
+ {
+ columns[i].setText(Integer.toHexString(j*fColumnSize).toUpperCase() +
+ " - " + Integer.toHexString(j*fColumnSize+fColumnSize-1).toUpperCase()); //$NON-NLS-1$
+ }
+ else
+ {
+ columns[i].setText(Integer.toHexString(j*fColumnSize).toUpperCase());
+ }
+ j++;
+ }
+ }
+ }
+
+ /**
+ * Refresh the table viewer with the current top visible address.
+ * Update labels in the memory rendering.
+ */
+ public void refresh()
+ {
+ // refresh at start address of this memory block
+ // address may change if expression is evaluated to a different value
+ IMemoryBlock mem = getMemoryBlock();
+ BigInteger address;
+
+ if (mem instanceof IMemoryBlockExtension)
+ {
+ try {
+ address = ((IMemoryBlockExtension)mem).getBigBaseAddress();
+ if (address == null)
+ {
+ DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.AbstractTableRendering_10, null));
+ displayError(e);
+ return;
+ }
+ updateRenderingLabel(true);
+ // base address has changed
+ if (address.compareTo(fContentProvider.getContentBaseAddress()) != 0)
+ {
+ // get to new address
+ setSelectedAddress(address);
+ updateSyncSelectedAddress();
+
+ reloadTable(address, true);
+
+ if (!isDynamicLoad())
+ {
+ updateSyncPageStartAddress();
+ setTopIndex(fTableViewer.getTable(), 0);
+ }
+
+ fTopRowAddress = getTopVisibleAddress();
+ updateSyncTopAddress();
+
+ fContentInput.updateContentBaseAddress();
+ }
+ else
+ {
+ // reload at top of table
+ if (isDynamicLoad())
+ address = getTopVisibleAddress();
+ else
+ address = fContentInput.getLoadAddress();
+ reloadTable(address, true);
+ }
+ } catch (DebugException e) {
+ displayError(e);
+ return;
+ }
+ }
+ else
+ {
+ address = BigInteger.valueOf(mem.getStartAddress());
+ reloadTable(address, true);
+ }
+ }
+
+ synchronized private void reloadTable(BigInteger topAddress, boolean updateDelta){
+
+ if (fTableViewer == null)
+ return;
+
+ try
+ {
+ Table table = (Table)fTableViewer.getControl();
+
+ TableRenderingContentInput input;
+ if (isDynamicLoad())
+ input = new TableRenderingContentInput(this, fContentInput.getPreBuffer(), fContentInput.getPostBuffer(), fContentInput.getDefaultBufferSize(), topAddress, getNumberOfVisibleLines(), updateDelta, null);
+ else
+ input = new TableRenderingContentInput(this, fContentInput.getPreBuffer(), fContentInput.getPostBuffer(), fContentInput.getDefaultBufferSize(), topAddress, fPageSize, updateDelta, null);
+
+ fContentInput = input;
+ fTableViewer.setInput(fContentInput);
+
+ if (isDynamicLoad())
+ {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ int topIdx = findAddressIndex(topAddress);
+
+ if (topIdx != -1)
+ {
+ setTopIndex(table, topIdx);
+ }
+ }
+
+ // cursor needs to be refreshed after reload
+ if (isAddressVisible(fSelectedAddress))
+ setCursorAtAddress(fSelectedAddress);
+ }
+ else
+ {
+ if (!isAddressOutOfRange(fSelectedAddress))
+ {
+ setCursorAtAddress(fSelectedAddress);
+ fTableCursor.setVisible(true);
+ }
+ else
+ {
+ fTableCursor.setVisible(false);
+ }
+ }
+ }
+ finally
+ {
+ }
+ }
+
+ private BigInteger getTopVisibleAddress() {
+
+ if (fTableViewer == null)
+ return BigInteger.valueOf(0);
+
+ Table table = fTableViewer.getTable();
+ int topIndex = getTopVisibleIndex(table);
+
+ if (topIndex < 1) { topIndex = 0; }
+
+ if (table.getItemCount() > topIndex)
+ {
+ TableRenderingLine topItem = (TableRenderingLine)table.getItem(topIndex).getData();
+
+ String calculatedAddress = null;
+ if (topItem == null)
+ {
+ calculatedAddress = table.getItem(topIndex).getText();
+ }
+ else
+ {
+ calculatedAddress = topItem.getAddress();
+ }
+
+ BigInteger bigInt = new BigInteger(calculatedAddress, 16);
+ return bigInt;
+ }
+ return BigInteger.valueOf(0);
+ }
+
+ private int findAddressIndex(BigInteger address)
+ {
+ TableItem items[] = fTableViewer.getTable().getItems();
+
+ for (int i=0; i 0)
+ {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private static int getTopVisibleIndex(Table table)
+ {
+ int index = table.getTopIndex();
+
+ TableItem item = table.getItem(index);
+ int cnt = table.getItemCount();
+
+ while (item.getBounds(0).y < 0)
+ {
+ index++;
+ if (index >= cnt)
+ {
+ index--;
+ break;
+ }
+ item = table.getItem(index);
+ }
+
+ return index;
+ }
+
+ /**
+ * Returns this rendering's table viewer.
+ */
+ public TableViewer getTableViewer()
+ {
+ return fTableViewer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#dispose()
+ */
+ public void dispose() {
+ try {
+ // prevent rendering from being disposed again
+ if (fIsDisposed)
+ return;
+
+ fIsDisposed = true;
+
+ if (fContentProvider != null)
+ fContentProvider.dispose();
+
+ ScrollBar scroll = ((Table)fTableViewer.getControl()).getVerticalBar();
+ if (scroll != null && !scroll.isDisposed())
+ scroll.removeSelectionListener(fScrollbarSelectionListener);
+
+ if (!fTableCursor.isDisposed())
+ {
+ fTableCursor.removeTraverseListener(fCursorTraverseListener);
+ fTableCursor.removeKeyListener(fCursorKeyAdapter);
+ fTableCursor.removeMouseListener(fCursorMouseListener);
+ }
+
+ fCursorEditor.dispose();
+
+ fTextViewer = null;
+ fTableViewer = null;
+ fTableCursor = null;
+
+ // clean up cell editors
+ for (int i=0; i 0)
+ {
+ Status stat = new Status(
+ IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(),
+ DebugException.NOT_SUPPORTED, DebugUIMessages.AbstractTableRendering_11, null
+ );
+ DebugException e = new DebugException(stat);
+ throw e;
+ }
+
+ setSelectedAddress(address);
+ updateSyncSelectedAddress();
+
+ reloadTable(address, false);
+
+ if (!isDynamicLoad())
+ {
+ updateSyncPageStartAddress();
+ }
+
+ // if the table is reloaded, the top address is changed in this case
+ fTopRowAddress = address;
+ updateSyncTopAddress();
+
+ // set the cursor at the selected address after reload
+ setCursorAtAddress(address);
+ }
+ fTableCursor.setVisible(true);
+ }
+ catch (DebugException e)
+ {
+ throw e;
+ }
+ finally
+ {
+ fEvtHandleLock.releaseLock(evtLockClient);
+ }
+ }
+
+ /**
+ * Check if address provided is out of buffered range
+ * @param address
+ * @return if address is out of buffered range
+ */
+ private boolean isAddressOutOfRange(BigInteger address)
+ {
+ return fContentProvider.isAddressOutOfRange(address);
+ }
+
+ /**
+ * Check if address is visible
+ * @param address
+ * @return if the given address is visible
+ */
+ private boolean isAddressVisible(BigInteger address)
+ {
+ // if view tab is not yet created
+ // cursor should always be visible
+ if (!fIsCreated)
+ return true;
+
+ BigInteger topVisible = getTopVisibleAddress();
+ int addressableUnit = getAddressableUnitPerLine();
+ BigInteger lastVisible = getTopVisibleAddress().add(BigInteger.valueOf((getNumberOfVisibleLines() * addressableUnit) + addressableUnit));
+
+ if (topVisible.compareTo(address) <= 0 && lastVisible.compareTo(address) > 0)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Create actions for this rendering
+ */
+ protected void createActions() {
+ fCopyToClipboardAction = new CopyTableRenderingToClipboardAction(this, fTableViewer);
+ fGoToAddressAction = new GoToAddressAction(this);
+ fResetMemoryBlockAction = new ResetToBaseAddressAction(this);
+ fPrintViewTabAction = new PrintTableRenderingAction(this, fTableViewer);
+
+ fFormatRenderingAction = new FormatTableRenderingAction(this);
+ fReformatAction = new ReformatAction(this);
+ fToggleAddressColumnAction = new ToggleAddressColumnAction();
+
+ IMemoryRenderingSite site = getMemoryRenderingContainer().getMemoryRenderingSite();
+ if (site.getSite().getSelectionProvider() != null)
+ {
+ fPropertiesAction = new PropertyDialogAction(site.getSite(),site.getSite().getSelectionProvider());
+ }
+
+ fNextAction = new NextPageAction();
+ fPrevAction = new PrevPageAction();
+ }
+
+ /**
+ * Handle scrolling and reload table if necessary
+ * @param event
+ */
+ private synchronized void handleScrollBarSelection()
+ {
+ Object evtLockClient = new Object();
+ try
+ {
+ if (fIsDisposed)
+ return;
+
+ BigInteger address = getTopVisibleAddress();
+
+ if (!fTopRowAddress.equals(address))
+ {
+ fTopRowAddress = address;
+ updateSyncTopAddress();
+ }
+
+ if (!fEvtHandleLock.acquireLock(evtLockClient))
+ return;
+
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+
+ if (isDynamicLoad())
+ {
+ if (!isAddressOutOfRange(address))
+ {
+ Table table = fTableViewer.getTable();
+ int numInBuffer = table.getItemCount();
+ int index = findAddressIndex(address);
+ if (index < 3)
+ {
+ if (isAtTopLimit())
+ {
+ setTopIndex(table, index);
+ }
+ else
+ {
+ reloadTable(address, false);
+ }
+ }
+ else if ((numInBuffer-(index+getNumberOfVisibleLines())) < 3)
+ {
+ if (!isAtBottomLimit())
+ reloadTable(address, false);
+ }
+ }
+ else
+ {
+ // approaching limit, reload table
+ reloadTable(address, false);
+ }
+ }
+
+ if (isAddressVisible(fSelectedAddress))
+ fTableCursor.setVisible(true);
+ else
+ fTableCursor.setVisible(false);
+ }
+ }
+ finally
+ {
+ fEvtHandleLock.releaseLock(evtLockClient);
+ }
+ }
+
+
+ private boolean isAtTopLimit()
+ {
+ BigInteger startAddress = fContentInput.getStartAddress();
+ startAddress = MemoryViewUtil.alignToBoundary(startAddress, getAddressableUnitPerLine() );
+
+ BigInteger startBufferAddress = fContentProvider.getBufferTopAddress();
+ startBufferAddress = MemoryViewUtil.alignToBoundary(startBufferAddress, getAddressableUnitPerLine());
+
+ if (startAddress.compareTo(startBufferAddress) == 0)
+ return true;
+
+ return false;
+ }
+
+ private boolean isAtBottomLimit()
+ {
+ BigInteger endAddress = fContentInput.getEndAddress();
+ endAddress = MemoryViewUtil.alignToBoundary(endAddress, getAddressableUnitPerLine());
+
+ BigInteger endBufferAddress = fContentProvider.getBufferEndAddress();
+ endBufferAddress = MemoryViewUtil.alignToBoundary(endBufferAddress, getAddressableUnitPerLine());
+
+ if (endAddress.compareTo(endBufferAddress) == 0)
+ return true;
+
+ return false;
+ }
+
+ private boolean needMoreLines()
+ {
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ Table table = fTableViewer.getTable();
+ TableItem firstItem = table.getItem(0);
+ TableItem lastItem = table.getItem(table.getItemCount()-1);
+
+ if (firstItem == null || lastItem == null)
+ return true;
+
+ TableRenderingLine first = (TableRenderingLine)firstItem.getData();
+ TableRenderingLine last = (TableRenderingLine) lastItem.getData();
+
+ if (first == null ||last == null)
+ {
+ // For some reason, the table does not return the correct number
+ // of table items in table.getItemCount(), causing last to be null.
+ // This check is to ensure that we don't get a null pointer exception.
+ return true;
+ }
+
+ BigInteger startAddress = new BigInteger(first.getAddress(), 16);
+ BigInteger lastAddress = new BigInteger(last.getAddress(), 16);
+ int addressableUnit = getAddressableUnitPerLine();
+ lastAddress = lastAddress.add(BigInteger.valueOf(addressableUnit));
+
+ BigInteger topVisibleAddress = getTopVisibleAddress();
+ long numVisibleLines = getNumberOfVisibleLines();
+ long numOfBytes = numVisibleLines * addressableUnit;
+
+ BigInteger lastVisibleAddrss = topVisibleAddress.add(BigInteger.valueOf(numOfBytes));
+
+ // if there are only 3 lines left at the top, refresh
+ BigInteger numTopLine = topVisibleAddress.subtract(startAddress).divide(BigInteger.valueOf(addressableUnit));
+ if (numTopLine.compareTo(BigInteger.valueOf(3)) <= 0 && (startAddress.compareTo(BigInteger.valueOf(0)) != 0))
+ {
+ if (!isAtTopLimit())
+ return true;
+ }
+
+ // if there are only 3 lines left at the bottom, refresh
+ BigInteger numBottomLine = lastAddress.subtract(lastVisibleAddrss).divide(BigInteger.valueOf(addressableUnit));
+ if (numBottomLine.compareTo(BigInteger.valueOf(3)) <= 0)
+ {
+ if (!isAtBottomLimit())
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+
+ private void handleTableMouseEvent(MouseEvent e) {
+ // figure out new cursor position based on here the mouse is pointing
+ TableItem[] tableItems = fTableViewer.getTable().getItems();
+ TableItem selectedRow = null;
+ int colNum = -1;
+ int numCol = fTableViewer.getColumnProperties().length;
+
+ for (int j=0; j 0 && col <= (getNumCol()))
+ activateCellEditor(null);
+ }
+ }
+
+ /**
+ * Activate cell editor and pre-fill it with initial value.
+ * If initialValue is null, use cell content as initial value
+ * @param initialValue
+ */
+ private void activateCellEditor(String initialValue) {
+
+ int col = fTableCursor.getColumn();
+ int row = findAddressIndex(fSelectedAddress);
+
+ if (row < 0)
+ return;
+ // do not allow user to edit address column
+ if (col == 0 || col > getNumCol())
+ {
+ return;
+ }
+
+ ICellModifier cellModifier = null;
+
+ if (fTableViewer == null)
+ {
+ return;
+ }
+ cellModifier = fTableViewer.getCellModifier();
+
+ TableItem tableItem = fTableViewer.getTable().getItem(row);
+
+ Object element = tableItem.getData();
+ Object property = fTableViewer.getColumnProperties()[col];
+ Object value = cellModifier.getValue(element, (String)property);
+
+ // The cell modifier canModify function always returns false if the edit action
+ // is not invoked from here. This is to prevent data to be modified when
+ // the table cursor loses focus from a cell. By default, data will
+ // be changed in a table when the cell loses focus. This is to workaround
+ // this default behavior and only change data when the cell editor
+ // is activated.
+ ((TableRenderingCellModifier)cellModifier).setEditActionInvoked(true);
+ boolean canEdit = cellModifier.canModify(element, (String)property);
+ ((TableRenderingCellModifier)cellModifier).setEditActionInvoked(false);
+
+ if (!canEdit)
+ return;
+
+ // activate based on current cursor position
+ TextCellEditor selectedEditor = (TextCellEditor)fTableViewer.getCellEditors()[col];
+
+
+ if (fTableViewer != null && selectedEditor != null)
+ {
+ // The control that will be the editor must be a child of the Table
+ Text text = (Text)selectedEditor.getControl();
+
+ String cellValue = null;
+
+ if (initialValue != null)
+ {
+ cellValue = initialValue;
+ }
+ else
+ {
+ cellValue = ((String)value);
+ }
+
+ text.setText(cellValue);
+
+ fCursorEditor.horizontalAlignment = SWT.LEFT;
+ fCursorEditor.grabHorizontal = true;
+
+ // Open the text editor in selected column of the selected row.
+ fCursorEditor.setEditor (text, tableItem, col);
+
+ // Assign focus to the text control
+ selectedEditor.setFocus();
+
+ if (initialValue != null)
+ {
+ text.clearSelection();
+ }
+
+ text.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
+
+ // add listeners for the text control
+ addListeners(text);
+
+ // move cursor below text control
+ fTableCursor.moveBelow(text);
+ }
+ }
+
+ /**
+ * @param text
+ */
+ private void addListeners(Text text) {
+ fEditorFocusListener = new FocusAdapter() {
+ public void focusLost(FocusEvent e)
+ {
+ handleTableEditorFocusLost(e);
+ }
+ };
+ text.addFocusListener(fEditorFocusListener);
+
+ fEditorKeyListener = new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ handleKeyEventInEditor(e);
+ }
+ };
+
+ text.addKeyListener(fEditorKeyListener);
+ }
+
+ /**
+ * @param text
+ */
+ private void removeListeners(Text text) {
+
+ text.removeFocusListener(fEditorFocusListener);
+ text.removeKeyListener(fEditorKeyListener);
+ }
+
+ private void handleTableEditorFocusLost(FocusEvent event)
+ {
+ final FocusEvent e = event;
+
+ Display.getDefault().syncExec(new Runnable() {
+
+ public void run()
+ {
+ try
+ {
+ int row = findAddressIndex(fSelectedAddress);
+ int col = fTableCursor.getColumn();
+
+ Text text = (Text)e.getSource();
+ removeListeners(text);
+
+ // get new value
+ String newValue = text.getText();
+
+ // modify memory at fRow and fCol
+ modifyValue(row, col, newValue);
+
+ // show cursor after modification is completed
+ setCursorAtAddress(fSelectedAddress);
+ fTableCursor.moveAbove(text);
+ fTableCursor.setVisible(false);
+ fTableCursor.setVisible(true);
+ }
+ catch (NumberFormatException e1)
+ {
+ MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title,
+ DebugUIMessages.MemoryViewCellModifier_data_is_invalid, null);
+ }
+ }
+ });
+ }
+
+ /**
+ * @param event
+ */
+ private void handleKeyEventInEditor(KeyEvent event) {
+ final KeyEvent e = event;
+ Display.getDefault().asyncExec(new Runnable()
+ {
+ public void run()
+ {
+ Text text = (Text)e.getSource();
+ int row = findAddressIndex(fSelectedAddress);
+ int col = fTableCursor.getColumn();
+
+ try
+ {
+ switch (e.keyCode)
+ {
+ case SWT.ARROW_UP :
+
+ // move text editor box up one row
+ if (row-1 < 0)
+ return;
+
+ // modify value for current cell
+ modifyValue(row, col, text.getText());
+
+ row--;
+
+ // update cursor location and selection in table
+ fTableCursor.setSelection(row, col);
+ handleCursorMoved();
+
+ // remove listeners when focus is lost
+ removeListeners(text);
+ activateCellEditor(null);
+ break;
+ case SWT.ARROW_DOWN :
+
+ // move text editor box down one row
+
+ if (row+1 >= fTableViewer.getTable().getItemCount())
+ return;
+
+ // modify value for current cell
+ modifyValue(row, col, text.getText());
+
+ row++;
+
+ // update cursor location and selection in table
+ fTableCursor.setSelection(row, col);
+ handleCursorMoved();
+
+ // remove traverse listener when focus is lost
+ removeListeners(text);
+ activateCellEditor(null);
+ break;
+ case 0:
+
+ // if user has entered the max number of characters allowed in a cell, move to next cell
+ // Extra changes will be used as initial value for the next cell
+ int numCharsPerByte = getNumCharsPerByte();
+ if (numCharsPerByte > 0)
+ {
+ if (text.getText().length() > getBytesPerColumn()*numCharsPerByte)
+ {
+ String newValue = text.getText();
+ text.setText(newValue.substring(0, getBytesPerColumn()*numCharsPerByte));
+
+ modifyValue(row, col, text.getText());
+
+ // if cursor is at the end of a line, move to next line
+ if (col >= getNumCol())
+ {
+ col = 1;
+ row++;
+ }
+ else
+ {
+ // move to next column
+ row++;
+ }
+
+ // update cursor position and selected address
+ fTableCursor.setSelection(row, col);
+ handleCursorMoved();
+
+ removeListeners(text);
+
+ // activate text editor at next cell
+ activateCellEditor(newValue.substring(getBytesPerColumn()*numCharsPerByte));
+ }
+ }
+ break;
+ case SWT.ESC:
+
+ // if user has pressed escape, do not commit the changes
+ // that's why "modifyValue" is not called
+ fTableCursor.setSelection(row, col);
+ handleCursorMoved();
+
+ removeListeners(text);
+
+ // cursor needs to have focus to remove focus from cell editor
+ fTableCursor.setFocus();
+ break;
+ default :
+ numCharsPerByte = getNumCharsPerByte();
+ if (numCharsPerByte > 0)
+ {
+ if (text.getText().length()> getBytesPerColumn()* numCharsPerByte)
+ {
+ String newValue = text.getText();
+ text.setText(newValue.substring(0,getBytesPerColumn()* numCharsPerByte));
+ modifyValue(row, col, text.getText());
+ // if cursor is at the end of a line, move to next line
+ if (col >= getNumCol())
+ {
+ col = 1;
+ row++;
+ }
+ else
+ {
+ col++;
+ }
+
+ fTableCursor.setSelection(row, col);
+ handleCursorMoved();
+
+ removeListeners(text);
+
+ activateCellEditor(newValue.substring(getBytesPerColumn()*numCharsPerByte));
+ }
+ }
+ break;
+ }
+ }
+ catch (NumberFormatException e1)
+ {
+ MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title,
+ DebugUIMessages.MemoryViewCellModifier_data_is_invalid, null);
+
+ fTableCursor.setSelection(row, col);
+ handleCursorMoved();
+
+ removeListeners(text);
+ }
+ }
+ });
+ }
+
+
+ /**
+ * Modify value and send new value to debug adapter
+ * @param row
+ * @param col
+ * @param newValue
+ * @throws NumberFormatException
+ */
+ private void modifyValue(int row, int col, String newValue) throws NumberFormatException
+ {
+ if (newValue.length() == 0)
+ {
+ // do not do anything if user has not entered anything
+ return;
+ }
+
+ TableItem tableItem = fTableViewer.getTable().getItem(row);
+
+ Object property = fTableViewer.getColumnProperties()[col];
+ fTableViewer.getCellModifier().modify(tableItem, (String)property, newValue);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#becomesHidden()
+ */
+ public void becomesHidden() {
+
+ if (isVisible() == false)
+ {
+ // super should always be called
+ super.becomesHidden();
+ return;
+ }
+
+ super.becomesHidden();
+
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ updateRenderingLabel(false);
+ }
+
+ // once the view tab is disabled, all deltas information becomes invalid.
+ // reset changed information and recompute if data has really changed when
+ // user revisits the same tab.
+ fContentProvider.resetDeltas();
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IMemoryRendering#becomesVisible()
+ */
+ public void becomesVisible() {
+
+ // do not do anything if already visible
+ if (isVisible() == true)
+ {
+ // super should always be called
+ super.becomesVisible();
+ return;
+ }
+
+ super.becomesVisible();
+
+ boolean value = DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM);
+ if (value != isDynamicLoad())
+ // this call will cause a reload
+ handleDyanicLoadChanged();
+ else
+ refresh();
+
+ synchronize();
+ updateRenderingLabel(true);
+ }
+
+ /**
+ * Resets this memory rendering.
+ * The cursor will be moved to the base address of the memory block.
+ * The table will be positioned to have the base address
+ * at the top.
+ *
+ * @deprecated use resetRendering
to reset this rendering.
+ */
+ public void reset()
+ {
+ try {
+ resetToBaseAddress();
+ } catch (DebugException e) {
+ MemoryViewUtil.openError(DebugUIMessages.AbstractTableRendering_12, DebugUIMessages.AbstractTableRendering_13, e); //
+ }
+ }
+
+ /**
+ * Reset this rendering to the base address.
+ * The cursor will be moved to the base address of the memory block.
+ * The table will be positioned to have the base address
+ * at the top.
+ * @throws DebugException
+ */
+ private void resetToBaseAddress() throws DebugException
+ {
+ BigInteger baseAddress;
+
+ if (getMemoryBlock() instanceof IMemoryBlockExtension)
+ {
+ baseAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
+ }
+ else
+ {
+ baseAddress = BigInteger.valueOf(getMemoryBlock().getStartAddress());
+ }
+
+ goToAddress(baseAddress);
+ topVisibleAddressChanged(baseAddress, true);
+ }
+
+ /**
+ * Returns the currently selected address in this rendering.
+ *
+ * @return the currently selected address in this rendering
+ */
+ public BigInteger getSelectedAddress() {
+ return fSelectedAddress;
+ }
+
+ /**
+ * Returns the currently selected content in this rendering as a String.
+ *
+ * @return the currently selected content in this rendering
+ */
+ public String getSelectedAsString() {
+
+ if (isAddressOutOfRange(fSelectedAddress))
+ return ""; //$NON-NLS-1$
+
+ int col = fTableCursor.getColumn();
+ TableItem rowItem = fTableCursor.getRow();
+ int row = fTableViewer.getTable().indexOf(rowItem);
+
+ if (col == 0)
+ {
+ return rowItem.getText(0);
+ }
+
+ // check precondition
+ if (col > getBytesPerLine()/getBytesPerColumn())
+ {
+ return ""; //$NON-NLS-1$
+ }
+
+ TableItem tableItem = getTableViewer().getTable().getItem(row);
+
+ return tableItem.getText(col);
+ }
+
+ /**
+ * Returns the currently selected content in this rendering as MemoryByte.
+ *
+ * @return the currently selected content in array of MemoryByte.
+ * Returns an empty array if the selected address is out of buffered range.
+ */
+ public MemoryByte[] getSelectedAsBytes()
+ {
+ if (isAddressOutOfRange(fSelectedAddress))
+ return new MemoryByte[0];
+
+ int col = fTableCursor.getColumn();
+ TableItem rowItem = fTableCursor.getRow();
+
+ // check precondition
+ if (col == 0 || col > getBytesPerLine()/getBytesPerColumn())
+ {
+ return new MemoryByte[0];
+ }
+
+ Object data = rowItem.getData();
+ if (data == null || !(data instanceof TableRenderingLine))
+ return new MemoryByte[0];
+
+ TableRenderingLine line = (TableRenderingLine)data;
+ int offset = (col-1)*(getAddressableUnitPerColumn()*getAddressableSize());
+ int end = offset + (getAddressableUnitPerColumn()*getAddressableSize());
+
+ // make a copy of the bytes to ensure that data cannot be changed
+ // by caller
+ MemoryByte[] bytes = line.getBytes(offset, end);
+ MemoryByte[] retBytes = new MemoryByte[bytes.length];
+
+ System.arraycopy(bytes, 0, retBytes, 0, bytes.length);
+
+ return retBytes;
+ }
+
+ /**
+ * Returns the number of characters a byte will convert to
+ * or -1 if unknown.
+ *
+ * @return the number of characters a byte will convert to
+ * or -1 if unknown
+ */
+ public int getNumCharsPerByte()
+ {
+ return -1;
+ }
+
+ private int getMinTableItemHeight(Table table){
+
+ // Hack to get around Linux GTK problem.
+ // On Linux GTK, table items have variable item height as
+ // carriage returns are actually shown in a cell. Some rows will be
+ // taller than others. When calculating number of visible lines, we
+ // need to find the smallest table item height. Otherwise, the rendering
+ // underestimates the number of visible lines. As a result the rendering
+ // will not be able to get more memory as needed.
+ if (MemoryViewUtil.isLinuxGTK())
+ {
+ // check each of the items and find the minimum
+ TableItem[] items = table.getItems();
+ int minHeight = table.getItemHeight();
+ for (int i=0; inull if none.
+ *
+ * By default a color provider is obtained by asking this rendering's
+ * memory block for its {@link IColorProvider} adapter. When the color
+ * provider is queried for color information, it is provided with a
+ * {@link MemoryRenderingElement} as an argument.
+ *
+ * @return the color provider for this rendering's memory block,
+ * or null
+ */
+ protected IColorProvider getColorProviderAdapter()
+ {
+ return (IColorProvider)getMemoryBlock().getAdapter(IColorProvider.class);
+ }
+
+ /**
+ * Returns the label provider for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a label provider is obtained by asking this rendering's
+ * memory block for its {@link ILabelProvider} adapter. When the label
+ * provider is queried for label information, it is provided with a
+ * {@link MemoryRenderingElement} as an argument.
+ *
+ * @return the label provider for this rendering's memory block,
+ * or null
+ */
+ protected ILabelProvider getLabelProviderAdapter()
+ {
+ return (ILabelProvider)getMemoryBlock().getAdapter(ILabelProvider.class);
+ }
+
+ /**
+ * Returns the font provider for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a font provider is obtained by asking this rendering's
+ * memory block for its {@link IFontProvider} adapter. When the font
+ * provider is queried for font information, it is provided with a
+ * {@link MemoryRenderingElement} as an argument.
+ *
+ * @return the font provider for this rendering's memory block,
+ * or null
+ */
+ protected IFontProvider getFontProviderAdapter()
+ {
+ return (IFontProvider)getMemoryBlock().getAdapter(IFontProvider.class);
+ }
+
+ /**
+ * Returns the table presentation for this rendering's memory block or
+ * null
if none.
+ *
+ * By default a table presentation is obtained by asking this rendering's
+ * memory block for its {@link IMemoryBlockTablePresentation} adapter.
+ *
+ * @return the table presentation for this rendering's memory block,
+ * or null
+ */
+ protected IMemoryBlockTablePresentation getTablePresentationAdapter()
+ {
+ return (IMemoryBlockTablePresentation)getMemoryBlock().getAdapter(IMemoryBlockTablePresentation.class);
+ }
+
+ private boolean isDynamicLoad()
+ {
+ return fContentProvider.isDynamicLoad();
+ }
+
+ private int getPageSizeInUnits()
+ {
+ return fPageSize * getAddressableUnitPerLine();
+ }
+
+ private void setSelectedAddress(BigInteger address)
+ {
+ fSelectedAddress = address;
+ }
+
+ /**
+ * Setup the viewer so it supports hovers to show the offset of each field
+ */
+ private void createToolTip() {
+
+ fToolTipShell = new Shell(DebugUIPlugin.getShell(), SWT.ON_TOP | SWT.RESIZE );
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.marginWidth = 2;
+ gridLayout.marginHeight = 0;
+ fToolTipShell.setLayout(gridLayout);
+ fToolTipShell.setBackground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ final Control toolTipControl = createToolTipControl(fToolTipShell);
+
+ if (toolTipControl == null)
+ {
+ // if client decide not to use tooltip support
+ fToolTipShell.dispose();
+ return;
+ }
+
+ MouseTrackAdapter listener = new MouseTrackAdapter(){
+
+ private TableItem fTooltipItem = null;
+ private int fCol = -1;
+
+ public void mouseExit(MouseEvent e){
+
+ if (!fToolTipShell.isDisposed())
+ fToolTipShell.setVisible(false);
+ fTooltipItem = null;
+ }
+
+ public void mouseHover(MouseEvent e){
+
+ Point hoverPoint = new Point(e.x, e.y);
+ Control control = null;
+
+ if (e.widget instanceof Control)
+ control = (Control)e.widget;
+
+ if (control == null)
+ return;
+
+ hoverPoint = control.toDisplay(hoverPoint);
+ TableItem item = getItem(hoverPoint);
+ int column = getColumn(hoverPoint);
+
+ //Only if there is a change in hover
+ if(this.fTooltipItem != item || fCol != column){
+
+ //Keep Track of the latest hover
+ fTooltipItem = item;
+ fCol = column;
+
+ if(item != null){
+ toolTipAboutToShow(toolTipControl, fTooltipItem, column);
+
+ //Setting location of the tooltip
+ Rectangle shellBounds = fToolTipShell.getBounds();
+ shellBounds.x = hoverPoint.x;
+ shellBounds.y = hoverPoint.y + item.getBounds(0).height;
+
+ fToolTipShell.setBounds(shellBounds);
+ fToolTipShell.pack();
+
+ fToolTipShell.setVisible(true);
+ }
+ else {
+ fToolTipShell.setVisible(false);
+ }
+ }
+ }
+ };
+
+ fTableViewer.getTable().addMouseTrackListener(listener);
+ fTableCursor.addMouseTrackListener(listener);
+ }
+
+ /**
+ * Bug with table widget,BUG 113015, the widget is not able to return the correct
+ * table item if SWT.FULL_SELECTION is not on when the table is created.
+ * Created the following function to work around the problem.
+ * We can remove this method when the bug is fixed.
+ * @param point
+ * @return the table item where the point is located, return null if the item cannot be located.
+ */
+ private TableItem getItem(Point point)
+ {
+ TableItem[] items = fTableViewer.getTable().getItems();
+ for (int i=0; i point.x)
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Creates the control used to display tool tips for cells in this table. By default
+ * a label is used to display the address of the cell. Clients may override this
+ * method to create custom tooltip controls.
+ *
+ * Also see the methods getToolTipText(...)
and
+ * toolTipAboutToShow(...)
.
+ *
+ * @param composite parent for the tooltip control
+ * @return the tooltip control to be displayed
+ * @since 3.2
+ */
+ protected Control createToolTipControl(Composite composite) {
+ Control fToolTipLabel = new Label(composite, SWT.NONE);
+ fToolTipLabel.setForeground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ fToolTipLabel.setBackground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ fToolTipLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |
+ GridData.VERTICAL_ALIGN_CENTER));
+ return fToolTipLabel;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.memory.IResettableMemoryRendering#resetRendering()
+ */
+ public void resetRendering() throws DebugException {
+ resetToBaseAddress();
+ }
+
+ /**
+ * Called when the tool tip is about to show in this rendering.
+ * Clients who overrides createTooltipControl
may need to
+ * also override this method to ensure that the tooltip shows up properly
+ * in their customized control.
+ *
+ * By default a text tooltip is displayed, and the contents for the tooltip
+ * are generated by the getToolTipText(...)
method.
+ *
+ * @param toolTipControl - the control for displaying the tooltip
+ * @param item - the table item where the mouse is pointing.
+ * @param col - the column at which the mouse is pointing.
+ * @since 3.2
+ */
+ protected void toolTipAboutToShow(Control toolTipControl, TableItem item,
+ int col) {
+ if (toolTipControl instanceof Label) {
+ BigInteger address = getAddressFromTableItem(item, col);
+ if (address != null) {
+ Object data = item.getData();
+ if (data instanceof TableRenderingLine) {
+ TableRenderingLine line = (TableRenderingLine) data;
+
+ if (col > 0) {
+ int start = (col - 1) * getBytesPerColumn();
+ int end = start + getBytesPerColumn();
+ MemoryByte[] bytes = line.getBytes(start, end);
+
+ String str = getToolTipText(address, bytes);
+
+ if (str != null)
+ ((Label) toolTipControl).setText(str);
+ } else {
+ String str = getToolTipText(address,
+ new MemoryByte[] {});
+
+ if (str != null)
+ ((Label) toolTipControl).setText(str);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the text to display in a tool tip at the specified address
+ * for the specified bytes. By default the address of the bytes is displayed.
+ * Subclasses may override.
+ *
+ * @param address address of cell that tool tip is displayed for
+ * @param bytes the bytes in the cell
+ * @return the tooltip text for the memory bytes located at the specified
+ * address
+ * @since 3.2
+ */
+ protected String getToolTipText(BigInteger address, MemoryByte[] bytes)
+ {
+ StringBuffer buf = new StringBuffer("0x"); //$NON-NLS-1$
+ buf.append(address.toString(16).toUpperCase());
+
+ return buf.toString();
+ }
+
+
+ private String getRowPrefId(String modelId) {
+ String rowPrefId = IDebugPreferenceConstants.PREF_ROW_SIZE + ":" + modelId; //$NON-NLS-1$
+ return rowPrefId;
+ }
+
+ private String getColumnPrefId(String modelId) {
+ String colPrefId = IDebugPreferenceConstants.PREF_COLUMN_SIZE + ":" + modelId; //$NON-NLS-1$
+ return colPrefId;
+ }
+
+ /**
+ * @param modelId
+ * @return default number of addressable units per line for the model
+ */
+ private int getDefaultRowSizeByModel(String modelId)
+ {
+ int row = DebugUITools.getPreferenceStore().getInt(getRowPrefId(modelId));
+ if (row == 0)
+ {
+ DebugUITools.getPreferenceStore().setValue(getRowPrefId(modelId), IDebugPreferenceConstants.PREF_ROW_SIZE_DEFAULT);
+ }
+
+ row = DebugUITools.getPreferenceStore().getInt(getRowPrefId(modelId));
+ return row;
+
+ }
+
+ /**
+ * @param modelId
+ * @return default number of addressable units per column for the model
+ */
+ private int getDefaultColumnSizeByModel(String modelId)
+ {
+ int col = DebugUITools.getPreferenceStore().getInt(getColumnPrefId(modelId));
+ if (col == 0)
+ {
+ DebugUITools.getPreferenceStore().setValue(getColumnPrefId(modelId), IDebugPreferenceConstants.PREF_COLUMN_SIZE_DEFAULT);
+ }
+
+ col = DebugUITools.getPreferenceStore().getInt(getColumnPrefId(modelId));
+ return col;
+ }
+
+
+ /**
+ * Returns text for the given memory bytes at the specified address for the specified
+ * rendering type. This is called by the label provider for.
+ * Subclasses must override.
+ *
+ * @param renderingTypeId rendering type identifier
+ * @param address address where the bytes belong to
+ * @param data the bytes
+ * @return a string to represent the memory. Cannot not return null
.
+ * Returns a string to pad the cell if the memory cannot be converted
+ * successfully.
+ */
+ abstract public String getString(String renderingTypeId, BigInteger address, MemoryByte[] data);
+
+ /**
+ * Returns bytes for the given text corresponding to bytes at the given
+ * address for the specified rendering type. This is called by the cell modifier
+ * when modifying bytes in a memory block.
+ * Subclasses must convert the string value to an array of bytes. The bytes will
+ * be passed to the debug adapter for memory block modification.
+ * Returns null
if the bytes cannot be formatted properly.
+ *
+ * @param renderingTypeId rendering type identifier
+ * @param address address the bytes begin at
+ * @param currentValues current values of the data in bytes format
+ * @param newValue the string to be converted to bytes
+ * @return the bytes converted from a string
+ */
+ abstract public byte[] getBytes(String renderingTypeId, BigInteger address, MemoryByte[] currentValues, String newValue);
+
+
+}
+
diff --git a/samples/vectors/sample-vectors_100_0 b/samples/vectors/sample-vectors_100_0
new file mode 100644
index 0000000..c7b63bd
--- /dev/null
+++ b/samples/vectors/sample-vectors_100_0
@@ -0,0 +1,188 @@
+# FILE:src/AbstractAsyncTableRendering.java, LINE:173, OFFSET:3064, NODE_KIND:128, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:29472, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:1539, TEID:12881, VARs:{}740,
+472 0 10 0 0 0 0 0 0 0 0 0 1 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 3479 0 0 0 0 1706 0 0 0 0 0 0 0 0 0 1411 0 0 0 12 0 0 0 286 0 0 131 0 0 1667 17 0 7 0 0 0 0 0 0 7 0 0 220 0 0 0 0 0 0 1280 0 341 34 0 0 0 1101 0 0 187 0 0 0 0 156 1 0 1598 0 0 0 0 996 902 0 0 0 1634 0 0 0 0 0 1553 0 0 0 0 0 0 0 58 0 228 273 0 0 1 0 0 0 0 0 0 52 0 0 0 0 0 0 0 0 21 1635 0 0 6 0 7 0 0 1411 0 0 41 0 0 2 386 0 80 8 36 65 134 221 0 2 0 0 12 0 0 28 4 15 3 21 8 0 54 0 0 806 100 0 1 0 0 37 0 0 0 5 18 3 0 34 0 0 0 0 0 44 84 28 14 0 0 0 0 10 0 2 0 12 7 1 0 95 10 0 42 0 0 0 0 0 0 151 2 21 0 0 117 11 4 0 14 0 0 1 46 2 0 12 3479 0 0 1 24 44 0 25 0 0 6 23 107
+# FILE:src/AbstractAsyncTableRendering.java, LINE:845, OFFSET:890, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:592, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:4144, TEID:4354, VARs:{}26,
+16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 71 0 0 0 0 38 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 7 0 0 6 0 0 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 3 1 0 0 0 22 0 0 1 0 0 0 0 0 0 0 32 0 0 0 0 20 24 0 0 0 32 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 32 0 0 4 0 0 0 13 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 2 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 71 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:991, OFFSET:1009, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:410, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:4736, TEID:4876, VARs:{}18,
+5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 0 0 0 0 27 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 5 4 0 0 0 9 0 0 1 0 0 0 0 0 0 0 27 0 0 0 0 11 12 0 0 0 32 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 5 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 0 0 0 0 0 0 0 0 0 0 5 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:995, OFFSET:1009, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:334, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:4762, TEID:4876, VARs:{}16,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 38 0 0 0 0 22 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 4 3 0 0 0 8 0 0 1 0 0 0 0 0 0 0 22 0 0 0 0 9 10 0 0 0 26 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 4 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 38 0 0 0 0 0 0 0 0 0 0 4 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1040, OFFSET:1063, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:530, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:4980, TEID:5175, VARs:{}29,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 67 0 0 0 0 32 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 1 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 6 5 0 0 0 14 0 0 1 0 0 0 0 0 0 0 32 0 0 0 0 13 18 0 0 0 37 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 27 0 0 0 0 0 0 1 0 0 0 5 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 67 0 0 0 0 0 0 0 0 0 0 5 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1044, OFFSET:1063, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:436, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5014, TEID:5175, VARs:{}27,
+5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 56 0 0 0 0 26 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 1 0 0 0 0 0 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 5 4 0 0 0 11 0 0 1 0 0 0 0 0 0 0 26 0 0 0 0 11 15 0 0 0 30 0 0 0 0 0 26 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 26 0 0 0 0 0 0 0 22 0 0 0 0 0 0 1 0 0 0 4 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 56 0 0 0 0 0 0 0 0 0 0 4 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1049, OFFSET:1063, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:342, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5048, TEID:5175, VARs:{}23,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 20 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 1 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 0 4 3 0 0 0 8 0 0 1 0 0 0 0 0 0 0 20 0 0 0 0 9 12 0 0 0 23 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 17 0 0 0 0 0 0 1 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 0 0 0 0 0 0 3 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1053, OFFSET:1063, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:263, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5076, TEID:5175, VARs:{}21,
+3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 15 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 0 0 1 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 3 2 0 0 0 7 0 0 1 0 0 0 0 0 0 0 15 0 0 0 0 7 10 0 0 0 17 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 0 0 13 0 0 0 0 0 0 1 0 0 0 2 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 0 0 0 0 0 0 2 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1187, OFFSET:1214, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:364, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5638, TEID:5757, VARs:{}16,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 25 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 3 0 0 4 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 5 1 0 0 0 17 0 0 5 0 0 0 0 0 0 0 24 0 0 0 0 14 9 0 0 0 24 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 19 0 0 0 0 0 0 7 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 7 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 1 0 0 4 0 0 0 2 0 0 0 0 0 0 0 32 0 0 0 1 0 0 0 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1226, OFFSET:1253, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:384, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5806, TEID:5932, VARs:{}16,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 27 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 3 0 0 4 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 5 1 0 0 0 18 0 0 5 0 0 0 0 0 0 0 25 0 0 0 0 15 10 0 0 0 25 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 20 0 0 0 0 0 0 7 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 7 2 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 1 0 1 0 0 4 0 0 0 2 0 0 0 0 0 0 0 34 0 0 0 1 0 0 0 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1756, OFFSET:1781, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:380, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:7812, TEID:7951, VARs:{}17,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 24 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 1 0 0 6 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 6 1 0 0 0 23 0 0 3 0 0 0 0 0 0 0 23 0 0 0 0 14 14 0 0 0 24 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 20 0 0 3 0 0 0 5 0 0 0 1 0 0 4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 10 2 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 35 0 0 0 0 0 0 1 0 0 0 1 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1922, OFFSET:1947, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:567, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8408, TEID:8579, VARs:{}26,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 0 0 0 0 43 0 0 0 0 0 0 0 0 0 33 0 0 0 0 0 0 0 7 0 0 1 0 0 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 2 0 0 0 0 24 0 0 3 0 0 0 0 0 0 0 37 0 0 0 0 10 12 0 0 0 38 0 0 0 0 0 35 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 38 0 0 0 0 0 0 0 33 0 0 0 0 0 0 8 0 0 0 1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 8 1 0 0 0 0 1 0 0 0 0 3 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 0 0 0 0 0 0 3 0 1 0 0 6 0 0 0 1 0 0 0 0 0 0 1 54 0 0 0 0 5 0 0 0 0 0 0 3
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1924, OFFSET:1947, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:544, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8414, TEID:8579, VARs:{}26,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 53 0 0 0 0 41 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 7 0 0 1 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 2 0 0 0 0 23 0 0 2 0 0 0 0 0 0 0 35 0 0 0 0 9 12 0 0 0 36 0 0 0 0 0 33 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 36 0 0 0 0 0 0 0 32 0 0 0 0 0 0 8 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 8 0 0 0 0 0 1 0 0 0 0 3 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 0 0 0 0 0 0 3 0 1 0 0 6 0 0 0 1 0 0 0 0 0 0 1 53 0 0 0 0 5 0 0 0 0 0 0 3
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1986, OFFSET:2032, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:601, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8681, TEID:8877, VARs:{}30,
+8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 68 0 0 0 0 41 0 0 0 0 0 0 0 0 0 35 0 0 0 0 0 0 0 6 0 0 0 0 0 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 5 1 0 0 0 19 0 0 3 0 0 0 0 0 0 0 39 0 0 0 0 18 17 0 0 0 40 0 0 0 0 0 36 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 0 0 0 0 0 0 0 35 0 0 0 0 0 2 6 0 0 0 1 0 0 4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 14 2 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 0 0 68 0 0 0 0 0 0 0 0 0 0 0 4
+# FILE:src/AbstractAsyncTableRendering.java, LINE:1997, OFFSET:2032, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:524, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8709, TEID:8877, VARs:{}28,
+5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 0 0 0 36 0 0 0 0 0 0 0 0 0 31 0 0 0 0 0 0 0 6 0 0 0 0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 4 0 0 0 0 17 0 0 3 0 0 0 0 0 0 0 34 0 0 0 0 14 13 0 0 0 35 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 0 0 0 31 0 0 0 0 0 2 6 0 0 0 1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 13 2 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 60 0 0 0 0 0 0 0 0 0 0 0 4
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2312, OFFSET:2370, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:691, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9854, TEID:10107, VARs:{}29,
+16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 74 0 0 0 0 42 0 0 0 0 0 0 0 0 0 33 0 0 0 0 0 0 0 7 0 0 5 0 0 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 8 2 0 0 0 26 0 0 9 0 0 0 0 0 0 0 41 0 0 0 0 33 25 0 0 0 42 0 0 0 0 0 38 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 0 0 0 33 0 0 0 0 0 0 12 0 0 0 1 3 0 11 0 0 0 0 0 0 0 1 0 0 0 0 0 0 5 0 0 17 5 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 3 0 0 0 0 0 0 0 74 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2315, OFFSET:2370, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:668, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9860, TEID:10107, VARs:{}29,
+16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 0 0 0 0 40 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 7 0 0 5 0 0 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 8 2 0 0 0 25 0 0 8 0 0 0 0 0 0 0 39 0 0 0 0 32 25 0 0 0 40 0 0 0 0 0 36 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 0 0 0 0 0 0 0 32 0 0 0 0 0 0 12 0 0 0 1 3 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 4 0 0 17 4 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 3 0 0 0 0 0 0 0 73 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2339, OFFSET:2366, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:358, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9965, TEID:10098, VARs:{}16,
+7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 22 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 3 0 0 1 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 5 2 0 0 0 12 0 0 4 0 0 0 0 0 0 0 21 0 0 0 0 16 13 0 0 0 22 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 17 0 0 0 0 0 0 4 0 0 0 1 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 11 3 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 41 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2672, OFFSET:2682, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:398, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11084, TEID:11213, VARs:{}18,
+1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 47 0 0 0 0 26 0 0 0 0 0 0 0 0 0 19 0 0 0 1 0 0 0 4 0 0 1 0 0 26 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 2 0 0 0 0 20 0 0 2 0 0 0 0 0 0 0 24 0 0 0 0 7 7 0 0 0 24 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 0 0 0 0 0 0 19 0 0 0 0 0 0 5 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 3 0 0 1 0 0 18 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 47 0 0 0 0 1 0 2 0 0 0 1 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2674, OFFSET:2682, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:352, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11100, TEID:11213, VARs:{}17,
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0 0 0 0 23 0 0 0 0 0 0 0 0 0 17 0 0 0 1 0 0 0 3 0 0 1 0 0 23 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 2 0 0 0 0 19 0 0 2 0 0 0 0 0 0 0 21 0 0 0 0 6 7 0 0 0 21 0 0 0 0 0 19 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 17 0 0 0 0 0 0 4 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 42 0 0 0 0 1 0 2 0 0 0 1 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2675, OFFSET:2682, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:317, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11109, TEID:11212, VARs:{}14,
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 38 0 0 0 0 21 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 0 0 2 0 0 1 0 0 21 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 1 0 0 0 0 18 0 0 2 0 0 0 0 0 0 0 19 0 0 0 0 5 7 0 0 0 19 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 15 0 0 0 0 0 0 3 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 38 0 0 0 0 0 0 2 0 0 0 1 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2705, OFFSET:2714, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:357, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11293, TEID:11408, VARs:{}15,
+1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 24 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 3 0 0 1 0 0 24 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 2 0 0 0 0 14 0 0 2 0 0 0 0 0 0 0 22 0 0 0 0 7 6 0 0 0 22 0 0 0 0 0 19 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 17 0 0 0 0 0 0 4 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 16 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 45 0 0 0 0 0 0 2 0 0 0 1 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2707, OFFSET:2714, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:334, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11299, TEID:11408, VARs:{}15,
+1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 44 0 0 0 0 22 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 3 0 0 1 0 0 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 2 0 0 0 0 13 0 0 1 0 0 0 0 0 0 0 20 0 0 0 0 6 6 0 0 0 20 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 16 0 0 0 0 0 0 4 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 44 0 0 0 0 0 0 2 0 0 0 1 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2707, OFFSET:2714, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:332, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11300, TEID:11407, VARs:{}15,
+1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 44 0 0 0 0 22 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 3 0 0 1 0 0 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 1 0 0 0 0 13 0 0 1 0 0 0 0 0 0 0 20 0 0 0 0 5 6 0 0 0 20 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 16 0 0 0 0 0 0 4 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 44 0 0 0 0 0 0 2 0 0 0 1 2
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2736, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:577, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11428, TEID:11607, VARs:{}25,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 0 0 0 0 41 0 0 0 0 0 0 0 0 0 33 0 0 0 0 0 0 0 8 0 0 0 0 0 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33 0 5 1 0 0 0 18 0 0 5 0 0 0 0 0 0 0 38 0 0 0 0 12 11 0 0 0 41 0 0 0 0 0 37 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 2 40 0 0 0 0 0 0 0 33 0 0 0 0 0 0 8 0 0 0 3 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 7 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 59 0 0 0 0 2 0 1 0 0 0 1 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2737, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:559, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11434, TEID:11607, VARs:{}25,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 0 0 0 0 40 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 8 0 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 5 1 0 0 0 18 0 0 4 0 0 0 0 0 0 0 37 0 0 0 0 11 11 0 0 0 39 0 0 0 0 0 36 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 2 39 0 0 0 0 0 0 0 32 0 0 0 0 0 0 8 0 0 0 2 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 7 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 57 0 0 0 0 2 0 1 0 0 0 1 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2738, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:491, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11456, TEID:11606, VARs:{}21,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 36 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 7 0 0 0 0 0 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 4 1 0 0 0 15 0 0 4 0 0 0 0 0 0 0 33 0 0 0 0 10 8 0 0 0 35 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 2 35 0 0 0 0 0 0 0 28 0 0 0 0 0 0 7 0 0 0 2 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 48 0 0 0 0 2 0 1 0 0 0 1 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2739, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:455, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11466, TEID:11606, VARs:{}21,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 33 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 7 0 0 0 0 0 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 4 1 0 0 0 14 0 0 3 0 0 0 0 0 0 0 30 0 0 0 0 9 8 0 0 0 31 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 2 32 0 0 0 0 0 0 0 27 0 0 0 0 0 0 7 0 0 0 1 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 4 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 45 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2740, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:430, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11476, TEID:11605, VARs:{}18,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 32 0 0 0 0 0 0 0 0 0 26 0 0 0 0 0 0 0 6 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 3 1 0 0 0 13 0 0 3 0 0 0 0 0 0 0 29 0 0 0 0 8 7 0 0 0 30 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 2 31 0 0 0 0 0 0 0 26 0 0 0 0 0 0 6 0 0 0 1 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 41 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2741, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:412, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11482, TEID:11605, VARs:{}18,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 0 0 0 0 31 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 6 0 0 0 0 0 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 3 1 0 0 0 13 0 0 2 0 0 0 0 0 0 0 28 0 0 0 0 7 7 0 0 0 28 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 2 30 0 0 0 0 0 0 0 25 0 0 0 0 0 0 6 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 39 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2743, OFFSET:2757, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:380, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11491, TEID:11604, VARs:{}16,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 29 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 5 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 0 2 1 0 0 0 13 0 0 2 0 0 0 0 0 0 0 26 0 0 0 0 6 7 0 0 0 26 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 2 28 0 0 0 0 0 0 0 23 0 0 0 0 0 0 5 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 35 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2802, OFFSET:2824, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:360, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11751, TEID:11881, VARs:{}12,
+5 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 26 0 0 0 0 0 0 0 0 0 15 0 0 0 4 0 0 0 2 0 0 0 0 0 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 5 2 0 0 0 16 0 0 0 0 0 0 0 0 0 0 18 0 0 0 0 11 10 0 0 0 18 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 15 0 0 1 0 0 0 2 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 3 0 0 0 0 0 0 0 0 0 0 2 0 0 4 0 0 0 0 0 0 0 1 0 0 0 40 0 0 0 0 4 0 3 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2806, OFFSET:2824, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:308, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11769, TEID:11881, VARs:{}12,
+5 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 22 0 0 0 0 0 0 0 0 0 13 0 0 0 4 0 0 0 1 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 5 2 0 0 0 14 0 0 0 0 0 0 0 0 0 0 15 0 0 0 0 10 10 0 0 0 15 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 13 0 0 1 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 1 0 0 0 35 0 0 0 0 4 0 3 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2806, OFFSET:2824, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:306, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11770, TEID:11880, VARs:{}12,
+5 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 22 0 0 0 0 0 0 0 0 0 13 0 0 0 4 0 0 0 1 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 4 2 0 0 0 14 0 0 0 0 0 0 0 0 0 0 15 0 0 0 0 9 10 0 0 0 15 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 13 0 0 1 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 1 0 0 0 35 0 0 0 0 4 0 3 0 0 0 0 0
+# FILE:src/AbstractAsyncTableRendering.java, LINE:2870, OFFSET:2890, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:290, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:12020, TEID:12130, VARs:{}14,
+8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 0 0 0 17 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 2 0 0 3 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 5 0 0 0 0 12 0 0 3 0 0 0 0 0 1 0 16 0 0 0 0 14 10 0 0 0 17 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 14 0 0 1 0 0 0 5 0 0 0 1 1 0 3 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 1 0 0 0 0 0 1 0 0 0 0 31 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:141, OFFSET:3736, NODE_KIND:128, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:36432, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:1100, TEID:14587, VARs:{}686,
+564 0 22 0 0 0 0 2 0 0 0 0 1 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 4070 0 0 0 0 2239 0 0 0 0 0 0 0 0 1 1815 0 0 0 26 0 0 0 340 0 0 162 0 0 2176 16 0 5 0 0 0 0 0 0 5 0 0 194 0 0 0 0 0 0 1653 0 419 55 0 0 0 1401 0 0 249 0 0 0 0 141 4 0 2076 0 0 0 0 1265 1123 0 0 0 2110 0 0 0 0 0 1998 0 0 0 0 0 0 0 49 0 291 223 0 0 1 0 0 0 0 0 0 61 0 0 0 0 0 0 0 0 22 2131 0 0 4 0 5 0 0 1815 0 0 30 0 5 3 452 0 65 14 34 90 123 304 4 2 0 0 15 0 0 28 4 10 3 35 9 0 58 0 0 867 126 0 7 1 0 63 0 0 0 0 29 3 0 55 0 0 0 0 0 61 79 14 10 0 0 0 0 6 0 12 1 12 6 1 0 127 22 0 39 0 0 0 0 0 0 165 4 34 0 2 186 18 2 0 22 0 0 4 76 1 0 14 4070 0 1 1 18 61 0 35 0 0 4 31 106
+# FILE:src/AbstractTableRendering.java, LINE:397, OFFSET:420, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:484, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:1946, TEID:2111, VARs:{}22,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 0 0 0 32 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 6 4 0 0 0 14 0 0 3 0 0 0 0 0 0 0 32 0 0 0 0 15 16 0 0 0 37 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 5 2 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 0 0 0 0 0 0 0 0 0 5 0
+# FILE:src/AbstractTableRendering.java, LINE:401, OFFSET:420, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:408, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:1972, TEID:2111, VARs:{}20,
+5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0 0 0 0 27 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 0 5 3 0 0 0 13 0 0 3 0 0 0 0 0 0 0 27 0 0 0 0 13 14 0 0 0 31 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 0 4 2 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0 0 0 0 0 0 0 0 0 0 4 0
+# FILE:src/AbstractTableRendering.java, LINE:405, OFFSET:420, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:317, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:2004, TEID:2111, VARs:{}18,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 21 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 4 2 0 0 0 10 0 0 3 0 0 0 0 0 0 0 21 0 0 0 0 11 11 0 0 0 24 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 3 2 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 3 0
+# FILE:src/AbstractTableRendering.java, LINE:532, OFFSET:585, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:640, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:2448, TEID:2666, VARs:{}24,
+10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 55 0 0 0 0 49 0 0 0 0 0 0 0 0 0 36 0 0 0 0 0 0 0 3 0 0 0 0 0 46 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 10 7 0 0 0 25 0 0 2 0 0 0 0 0 1 0 42 0 0 0 0 22 23 0 0 0 42 0 0 0 0 0 38 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 46 0 0 0 0 0 0 0 36 0 0 0 0 0 0 3 0 0 0 0 5 0 9 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 7 0 0 0 0 0 3 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 2 0 0 4 1 0 0 0 0 0 1 0 0 0 0 55 0 0 0 0 0 0 2 0 0 0 2 0
+# FILE:src/AbstractTableRendering.java, LINE:537, OFFSET:575, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:516, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:2462, TEID:2633, VARs:{}16,
+7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 41 0 0 0 0 0 0 0 0 0 29 0 0 0 0 0 0 0 3 0 0 0 0 0 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 0 8 6 0 0 0 21 0 0 1 0 0 0 0 0 0 0 35 0 0 0 0 16 18 0 0 0 35 0 0 0 0 0 31 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 0 0 0 0 0 0 0 29 0 0 0 0 0 0 3 0 0 0 0 3 0 7 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 3 0 0 0 0 0 2 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 4 0 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 0 0 2 0 0 0 2 0
+# FILE:src/AbstractTableRendering.java, LINE:541, OFFSET:568, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:403, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:2488, TEID:2622, VARs:{}11,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 33 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 1 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 6 5 0 0 0 17 0 0 1 0 0 0 0 0 0 0 28 0 0 0 0 13 14 0 0 0 28 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 22 0 0 0 0 0 0 1 0 0 0 0 2 0 6 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 4 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 2 0 0 0 2 0
+# FILE:src/AbstractTableRendering.java, LINE:548, OFFSET:568, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:306, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:2520, TEID:2622, VARs:{}11,
+5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 24 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 1 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 5 4 0 0 0 12 0 0 1 0 0 0 0 0 0 0 21 0 0 0 0 11 11 0 0 0 21 0 0 0 0 0 19 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 18 0 0 0 0 0 0 1 0 0 0 0 2 0 5 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 1 0 0 0 1 0
+# FILE:src/AbstractTableRendering.java, LINE:900, OFFSET:945, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:592, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:3928, TEID:4138, VARs:{}26,
+16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 71 0 0 0 0 38 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 7 0 0 6 0 0 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 3 1 0 0 0 22 0 0 1 0 0 0 0 0 0 0 32 0 0 0 0 20 24 0 0 0 32 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 32 0 0 4 0 0 0 13 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 2 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 71 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:960, OFFSET:987, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:364, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:4188, TEID:4307, VARs:{}16,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 25 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 3 0 0 4 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 5 1 0 0 0 17 0 0 5 0 0 0 0 0 0 0 24 0 0 0 0 14 9 0 0 0 24 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 19 0 0 0 0 0 0 7 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 7 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 1 0 0 4 0 0 0 2 0 0 0 0 0 0 0 32 0 0 0 1 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:999, OFFSET:1026, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:384, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:4356, TEID:4482, VARs:{}16,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 27 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 3 0 0 4 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 5 1 0 0 0 18 0 0 5 0 0 0 0 0 0 0 25 0 0 0 0 15 10 0 0 0 25 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 20 0 0 0 0 0 0 7 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 7 2 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 1 0 1 0 0 4 0 0 0 2 0 0 0 0 0 0 0 34 0 0 0 1 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1190, OFFSET:1212, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:242, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5192, TEID:5294, VARs:{}14,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 16 0 0 0 0 0 0 0 0 0 11 0 0 0 0 0 0 0 1 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 7 1 0 0 0 11 0 0 6 0 0 0 0 0 0 0 13 0 0 0 0 17 13 0 0 0 14 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 11 0 0 0 0 0 0 1 0 0 0 1 0 0 7 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 4 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1365, OFFSET:1386, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:292, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5769, TEID:5876, VARs:{}12,
+2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 29 0 0 0 0 17 0 0 0 0 0 0 0 0 0 13 0 0 0 2 0 0 0 4 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 3 0 0 0 0 12 0 0 3 0 0 0 0 0 0 0 17 0 0 0 0 12 6 0 0 0 17 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 0 0 0 0 0 0 0 13 0 0 0 0 0 0 4 0 0 2 0 2 0 3 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 29 0 0 0 0 4 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1367, OFFSET:1386, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:278, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5773, TEID:5876, VARs:{}11,
+2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 16 0 0 0 0 0 0 0 0 0 12 0 0 0 2 0 0 0 4 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 3 0 0 0 0 12 0 0 2 0 0 0 0 0 0 0 16 0 0 0 0 11 6 0 0 0 16 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 0 0 0 0 0 0 0 12 0 0 0 0 0 0 4 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 28 0 0 0 0 4 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1407, OFFSET:1428, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:374, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5975, TEID:6115, VARs:{}18,
+3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 28 0 0 0 0 0 0 0 0 0 16 0 0 0 1 0 0 0 3 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 5 2 0 0 0 16 0 0 0 0 0 0 0 0 0 0 19 0 0 0 0 9 12 0 0 0 19 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 16 0 0 1 0 0 0 3 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 1 0 0 4 0 0 0 0 0 0 0 1 0 0 1 45 0 0 0 0 1 0 4 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:1409, OFFSET:1428, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:328, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:5991, TEID:6115, VARs:{}18,
+3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 25 0 0 0 0 0 0 0 0 0 14 0 0 0 1 0 0 0 2 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 5 2 0 0 0 15 0 0 0 0 0 0 0 0 0 0 16 0 0 0 0 8 12 0 0 0 16 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 14 0 0 1 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 3 0 0 0 0 0 0 0 1 0 0 1 40 0 0 0 0 1 0 4 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:1413, OFFSET:1428, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:259, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:6013, TEID:6114, VARs:{}13,
+3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 20 0 0 0 0 0 0 0 0 0 10 0 0 0 1 0 0 0 1 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 4 2 0 0 0 12 0 0 0 0 0 0 0 0 0 0 12 0 0 0 0 7 11 0 0 0 12 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 10 0 0 1 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 1 0 0 1 32 0 0 0 0 1 0 3 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1635, OFFSET:1669, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:405, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:6799, TEID:6941, VARs:{}24,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 27 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 5 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 0 6 0 0 0 0 15 0 0 8 0 0 0 0 0 0 0 25 0 0 0 0 20 14 0 0 0 25 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 19 0 0 0 0 0 0 5 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 6 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 41 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1637, OFFSET:1669, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:387, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:6806, TEID:6941, VARs:{}23,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 25 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 5 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 6 0 0 0 0 14 0 0 7 0 0 0 0 0 0 0 24 0 0 0 0 19 13 0 0 0 24 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 18 0 0 0 0 0 0 5 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 6 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1938, OFFSET:1963, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:380, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:7830, TEID:7969, VARs:{}17,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 0 0 0 24 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 1 0 0 6 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 6 1 0 0 0 23 0 0 3 0 0 0 0 0 0 0 23 0 0 0 0 14 14 0 0 0 24 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 20 0 0 3 0 0 0 5 0 0 0 1 0 0 4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 10 2 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 35 0 0 0 0 0 0 1 0 0 0 1 0
+# FILE:src/AbstractTableRendering.java, LINE:1993, OFFSET:2014, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:341, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8097, TEID:8220, VARs:{}11,
+5 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 38 0 0 0 0 25 0 0 0 0 0 0 0 0 0 14 0 0 0 4 0 0 0 1 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 5 2 0 0 0 15 0 0 0 0 0 0 0 0 0 0 17 0 0 0 0 11 9 0 0 0 17 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 14 0 0 1 0 0 0 1 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 3 0 0 0 0 0 0 0 0 0 0 2 0 0 4 0 0 0 0 0 0 0 1 0 0 0 38 0 0 0 0 4 0 3 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1997, OFFSET:2014, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:289, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8115, TEID:8220, VARs:{}11,
+5 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33 0 0 0 0 21 0 0 0 0 0 0 0 0 0 12 0 0 0 4 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 5 2 0 0 0 13 0 0 0 0 0 0 0 0 0 0 14 0 0 0 0 10 9 0 0 0 14 0 0 0 0 0 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 12 0 0 1 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 1 0 0 0 33 0 0 0 0 4 0 3 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:1997, OFFSET:2014, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:287, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8116, TEID:8219, VARs:{}11,
+5 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33 0 0 0 0 21 0 0 0 0 0 0 0 0 0 12 0 0 0 4 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 4 2 0 0 0 13 0 0 0 0 0 0 0 0 0 0 14 0 0 0 0 9 9 0 0 0 14 0 0 0 0 0 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 12 0 0 1 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 1 0 0 0 33 0 0 0 0 4 0 3 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2030, OFFSET:2078, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:542, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8238, TEID:8440, VARs:{}32,
+17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 55 0 0 0 0 33 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 1 0 0 5 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 8 3 0 0 0 22 0 0 2 0 0 0 0 0 0 0 32 0 0 0 0 28 24 0 0 0 33 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 30 0 0 0 0 0 0 6 0 0 0 1 4 0 5 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 10 2 0 0 0 0 1 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 2 1 0 0 0 0 0 0 1 0 0 0 55 0 0 0 0 0 0 0 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:2032, OFFSET:2072, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:456, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8245, TEID:8416, VARs:{}29,
+15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 46 0 0 0 0 28 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 1 0 0 4 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 6 2 0 0 0 19 0 0 2 0 0 0 0 0 0 0 27 0 0 0 0 24 21 0 0 0 27 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 25 0 0 0 0 0 0 5 0 0 0 0 3 0 4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 8 2 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 2 1 0 0 0 0 0 0 1 0 0 0 46 0 0 0 0 0 0 0 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:2042, OFFSET:2068, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:266, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8298, TEID:8401, VARs:{}18,
+11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 16 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 3 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 3 2 0 0 0 12 0 0 1 0 0 0 0 0 0 0 15 0 0 0 0 15 16 0 0 0 15 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 0 0 14 0 0 0 0 0 0 3 0 0 0 0 2 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 5 0 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2087, OFFSET:2129, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:597, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8462, TEID:8659, VARs:{}27,
+9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 0 0 0 0 40 0 0 0 0 0 0 0 0 0 38 0 0 0 0 0 0 0 3 0 0 3 0 0 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 0 8 3 0 0 0 23 0 0 3 0 0 0 0 0 1 0 39 0 0 0 0 19 20 0 0 0 40 0 0 0 0 0 39 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 39 0 0 0 0 0 0 0 38 0 0 0 0 0 0 5 0 0 0 1 2 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 10 2 0 0 0 0 1 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 57 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:2168, OFFSET:2181, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:340, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:8822, TEID:8927, VARs:{}16,
+0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 23 0 0 0 0 0 0 0 0 0 18 0 0 0 2 0 0 0 5 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 3 0 0 0 0 15 0 0 2 0 0 0 0 0 0 0 23 0 0 0 0 7 7 0 0 0 23 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 18 0 0 0 0 0 0 5 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 7 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 1 0 0 0 0 4 0 0 0 1 0 0 0 0 0 0 0 34 0 0 0 0 2 0 0 0 0 0 1 1
+# FILE:src/AbstractTableRendering.java, LINE:2222, OFFSET:2274, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:575, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9030, TEID:9261, VARs:{}42,
+17 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 65 0 0 0 0 33 0 0 0 0 0 0 0 0 0 25 0 0 0 1 0 0 0 3 0 0 4 0 0 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 5 0 0 0 0 26 0 0 6 0 0 0 0 0 0 0 31 0 0 0 0 29 25 0 0 0 31 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 31 0 0 0 0 0 0 0 25 0 0 0 0 0 0 7 0 0 1 0 1 0 6 0 0 0 0 1 0 0 0 0 1 0 1 0 0 4 0 0 23 7 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 3 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 65 0 0 0 0 1 0 0 0 0 0 1 0
+# FILE:src/AbstractTableRendering.java, LINE:2318, OFFSET:2390, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:802, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9377, TEID:9656, VARs:{}44,
+13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 0 0 0 0 54 0 0 0 0 0 0 0 0 0 46 0 0 0 0 0 0 0 7 0 0 1 0 0 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 9 1 0 0 0 26 0 0 5 0 0 0 0 0 1 0 49 0 0 0 0 29 27 0 0 0 50 0 0 0 0 0 47 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 49 0 0 0 0 0 0 0 46 0 0 0 0 0 3 8 0 0 0 1 2 0 6 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 19 2 0 0 0 0 5 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 1 0 0 1 0 0 1 0 0 0 0 90 0 0 0 0 0 0 0 0 0 0 0 4
+# FILE:src/AbstractTableRendering.java, LINE:2324, OFFSET:2380, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:705, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9391, TEID:9628, VARs:{}38,
+11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 79 0 0 0 0 48 0 0 0 0 0 0 0 0 0 41 0 0 0 0 0 0 0 7 0 0 1 0 0 44 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 6 1 0 0 0 24 0 0 4 0 0 0 0 0 0 0 44 0 0 0 0 23 24 0 0 0 45 0 0 0 0 0 42 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 0 0 0 0 0 0 0 41 0 0 0 0 0 2 8 0 0 0 1 1 0 5 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 16 2 0 0 0 0 4 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 79 0 0 0 0 0 0 0 0 0 0 0 4
+# FILE:src/AbstractTableRendering.java, LINE:2341, OFFSET:2380, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:531, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9454, TEID:9628, VARs:{}29,
+7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 0 0 0 36 0 0 0 0 0 0 0 0 0 31 0 0 0 0 0 0 0 6 0 0 1 0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 4 0 0 0 0 18 0 0 3 0 0 0 0 0 0 0 34 0 0 0 0 16 14 0 0 0 35 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 0 0 0 31 0 0 0 0 0 2 7 0 0 0 1 1 0 3 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 12 2 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 60 0 0 0 0 0 0 0 0 0 0 0 4
+# FILE:src/AbstractTableRendering.java, LINE:2457, OFFSET:2515, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:591, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9903, TEID:10112, VARs:{}32,
+9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 52 0 0 0 0 42 0 0 0 0 0 0 0 0 0 34 0 0 0 0 0 0 0 4 0 0 1 0 0 38 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33 0 11 4 0 0 0 22 0 0 7 0 0 0 0 0 1 0 36 0 0 0 0 28 21 0 0 0 37 0 0 0 0 0 34 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 38 0 0 0 0 0 0 0 34 0 0 0 0 0 0 5 0 0 0 1 5 0 11 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 7 0 0 0 0 0 4 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 2 0 1 0 0 2 1 0 0 0 0 0 1 0 0 0 0 52 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2473, OFFSET:2510, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:441, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9950, TEID:10101, VARs:{}22,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 0 0 32 0 0 0 0 0 0 0 0 0 26 0 0 0 0 0 0 0 3 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 8 4 0 0 0 19 0 0 4 0 0 0 0 0 0 0 28 0 0 0 0 18 16 0 0 0 29 0 0 0 0 0 26 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 26 0 0 0 0 0 0 3 0 0 0 1 5 0 8 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 4 0 0 0 0 0 2 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 36 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2476, OFFSET:2510, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:421, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9958, TEID:10101, VARs:{}20,
+6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 31 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 3 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 8 4 0 0 0 18 0 0 3 0 0 0 0 0 0 0 27 0 0 0 0 17 15 0 0 0 27 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 0 0 0 0 0 0 0 25 0 0 0 0 0 0 3 0 0 0 0 5 0 7 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 4 0 0 0 0 0 2 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 34 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2476, OFFSET:2503, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:354, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9959, TEID:10078, VARs:{}16,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 27 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 3 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 7 3 0 0 0 15 0 0 3 0 0 0 0 0 0 0 23 0 0 0 0 14 12 0 0 0 23 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 21 0 0 0 0 0 0 3 0 0 0 0 3 0 6 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2478, OFFSET:2503, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:338, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9965, TEID:10078, VARs:{}15,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 26 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 3 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 0 7 3 0 0 0 14 0 0 2 0 0 0 0 0 0 0 22 0 0 0 0 13 11 0 0 0 22 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 20 0 0 0 0 0 0 3 0 0 0 0 3 0 5 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2478, OFFSET:2503, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:336, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:9966, TEID:10077, VARs:{}15,
+4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 26 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 3 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 0 6 3 0 0 0 14 0 0 2 0 0 0 0 0 0 0 22 0 0 0 0 12 11 0 0 0 22 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 20 0 0 0 0 0 0 3 0 0 0 0 3 0 5 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 1 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2550, OFFSET:2597, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:955, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:10256, TEID:10554, VARs:{}36,
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 95 0 0 0 0 66 0 0 0 0 0 0 0 0 0 52 0 0 0 0 0 0 0 14 0 0 1 0 0 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 4 0 0 0 0 52 0 0 7 0 0 0 0 0 0 0 62 0 0 0 0 17 30 0 0 0 63 0 0 0 0 0 60 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 63 0 0 0 0 0 0 0 52 0 0 0 0 0 0 15 0 0 0 1 5 0 7 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 24 4 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 5 2 1 0 0 10 0 0 0 0 0 0 0 4 0 0 0 95 0 0 0 0 0 0 0 0 0 0 1 2
+# FILE:src/AbstractTableRendering.java, LINE:2552, OFFSET:2597, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:935, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:10264, TEID:10554, VARs:{}34,
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 93 0 0 0 0 65 0 0 0 0 0 0 0 0 0 51 0 0 0 0 0 0 0 14 0 0 1 0 0 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 0 4 0 0 0 0 51 0 0 6 0 0 0 0 0 0 0 61 0 0 0 0 16 29 0 0 0 61 0 0 0 0 0 59 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 62 0 0 0 0 0 0 0 51 0 0 0 0 0 0 15 0 0 0 0 5 0 6 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 24 4 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 5 2 1 0 0 10 0 0 0 0 0 0 0 4 0 0 0 93 0 0 0 0 0 0 0 0 0 0 1 2
+# FILE:src/AbstractTableRendering.java, LINE:2742, OFFSET:2780, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:392, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11106, TEID:11236, VARs:{}28,
+11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 25 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 2 0 0 4 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 4 1 0 0 0 9 0 0 2 0 0 0 0 0 0 0 25 0 0 0 0 17 9 0 0 0 25 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 20 0 0 0 0 0 0 6 0 0 0 0 1 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 12 5 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 0 0 0 0 0 0 0 0 0 0 1 0
+# FILE:src/AbstractTableRendering.java, LINE:2745, OFFSET:2780, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:351, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11116, TEID:11236, VARs:{}27,
+11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 21 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 2 0 0 4 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 4 1 0 0 0 7 0 0 1 0 0 0 0 0 0 0 21 0 0 0 0 16 9 0 0 0 21 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 19 0 0 0 0 0 0 6 0 0 0 0 1 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 12 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 0 0 0 0 0 0 0 0
+# FILE:src/AbstractTableRendering.java, LINE:2818, OFFSET:2845, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:327, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11344, TEID:11469, VARs:{}30,
+8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 18 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 4 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 18 0 3 0 0 0 0 9 0 0 0 0 0 0 0 1 0 0 18 0 0 0 0 9 13 0 0 0 18 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 4 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 18 0 0 0 0 0 0 4 0 1 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 11 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 0 0 0 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:2856, OFFSET:2995, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:1376, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:11485, TEID:12006, VARs:{}46,
+40 0 5 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 161 0 0 0 0 86 0 0 0 0 0 0 0 0 1 70 0 0 0 0 0 0 0 6 0 0 3 0 0 86 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 67 0 11 2 0 0 0 44 0 0 6 0 0 0 0 1 0 0 78 0 0 0 0 63 61 0 0 0 78 0 0 0 0 0 70 0 0 0 0 0 0 0 0 0 6 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 70 0 0 0 0 5 0 9 0 1 0 0 0 0 8 4 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 36 3 0 5 1 0 0 0 0 0 0 6 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 3 1 0 0 0 0 3 5 0 0 0 0 0 0 0 0 2 0 1 0 1 10 1 0 0 4 0 0 0 0 0 0 0 161 0 0 0 0 0 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3272, OFFSET:3332, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:618, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:12864, TEID:13133, VARs:{}48,
+19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 0 0 0 0 33 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 3 0 0 2 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 26 0 12 2 0 0 0 22 0 0 6 0 0 0 0 2 0 0 32 0 0 0 0 35 30 0 0 0 34 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 28 0 0 0 0 0 0 5 0 2 0 2 2 0 8 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 17 1 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 2 1 0 0 0 0 0 0 2 0 0 0 72 0 0 0 1 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:3273, OFFSET:3332, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:592, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:12872, TEID:13133, VARs:{}47,
+19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 0 0 0 0 31 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 3 0 0 2 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 25 0 12 2 0 0 0 21 0 0 5 0 0 0 0 2 0 0 30 0 0 0 0 34 30 0 0 0 32 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 27 0 0 0 0 0 0 5 0 2 0 2 2 0 7 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 16 1 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 2 1 0 0 0 0 0 0 1 0 0 0 70 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:3273, OFFSET:3327, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:577, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:12873, TEID:13129, VARs:{}47,
+19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 0 0 0 0 30 0 0 0 0 0 0 0 0 0 26 0 0 0 0 0 0 0 3 0 0 2 0 0 29 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 24 0 11 2 0 0 0 21 0 0 5 0 0 0 0 2 0 0 29 0 0 0 0 32 30 0 0 0 31 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 29 0 0 0 0 0 0 0 26 0 0 0 0 0 0 5 0 2 0 2 2 0 7 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 16 1 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 0 0 0 0 0 0 1 0 0 0 69 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:3274, OFFSET:3327, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:554, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:12879, TEID:13129, VARs:{}47,
+19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 68 0 0 0 0 28 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 3 0 0 2 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 23 0 11 2 0 0 0 20 0 0 4 0 0 0 0 2 0 0 27 0 0 0 0 31 30 0 0 0 29 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 25 0 0 0 0 0 0 5 0 2 0 2 2 0 6 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 16 0 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 68 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:3274, OFFSET:3327, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:552, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:12880, TEID:13128, VARs:{}47,
+19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 68 0 0 0 0 28 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 3 0 0 2 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 23 0 10 2 0 0 0 20 0 0 4 0 0 0 0 2 0 0 27 0 0 0 0 30 30 0 0 0 29 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 25 0 0 0 0 0 0 5 0 2 0 2 2 0 6 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 16 0 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 68 0 0 0 0 0 0 0 0 0 0 0 2
+# FILE:src/AbstractTableRendering.java, LINE:3538, OFFSET:3545, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:410, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:13764, TEID:13888, VARs:{}15,
+1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 46 0 0 0 0 27 0 0 0 0 0 0 0 0 0 21 0 0 0 5 0 0 0 3 0 0 1 0 0 27 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 0 1 0 0 0 0 22 0 0 1 0 0 0 0 0 0 0 25 0 0 0 0 5 6 0 0 0 25 0 0 0 0 0 22 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 21 0 0 0 0 0 0 4 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 46 0 0 0 0 5 0 2 0 0 0 1 2
+# FILE:src/AbstractTableRendering.java, LINE:3540, OFFSET:3545, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:364, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:13780, TEID:13888, VARs:{}14,
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 24 0 0 0 0 0 0 0 0 0 19 0 0 0 5 0 0 0 2 0 0 1 0 0 24 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 1 0 0 0 0 21 0 0 1 0 0 0 0 0 0 0 22 0 0 0 0 4 6 0 0 0 22 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 19 0 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 5 0 2 0 0 0 1 2
+# FILE:src/AbstractTableRendering.java, LINE:3559, OFFSET:3566, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:332, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:13928, TEID:14035, VARs:{}15,
+1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 44 0 0 0 0 22 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 3 0 0 1 0 0 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 1 0 0 0 0 13 0 0 1 0 0 0 0 0 0 0 20 0 0 0 0 5 6 0 0 0 20 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 0 0 0 0 0 0 16 0 0 0 0 0 0 4 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 44 0 0 0 0 0 0 2 0 0 0 1 2
+# FILE:src/AbstractTableRendering.java, LINE:3616, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:516, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14154, TEID:14312, VARs:{}22,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 0 0 0 37 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 8 0 0 0 0 0 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 5 1 0 0 0 16 0 0 5 0 0 0 0 0 0 0 34 0 0 0 0 12 9 0 0 0 36 0 0 0 0 0 33 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 2 36 0 0 0 0 0 0 0 30 0 0 0 0 0 0 8 0 0 0 2 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 51 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3617, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:498, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14160, TEID:14312, VARs:{}22,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 49 0 0 0 0 36 0 0 0 0 0 0 0 0 0 29 0 0 0 0 0 0 0 8 0 0 0 0 0 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 0 5 1 0 0 0 16 0 0 4 0 0 0 0 0 0 0 33 0 0 0 0 11 9 0 0 0 34 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 2 35 0 0 0 0 0 0 0 29 0 0 0 0 0 0 8 0 0 0 1 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 49 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3618, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:454, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14171, TEID:14311, VARs:{}20,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 0 0 0 0 33 0 0 0 0 0 0 0 0 0 26 0 0 0 0 0 0 0 7 0 0 0 0 0 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 4 1 0 0 0 15 0 0 4 0 0 0 0 0 0 0 30 0 0 0 0 10 8 0 0 0 31 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 2 32 0 0 0 0 0 0 0 26 0 0 0 0 0 0 7 0 0 0 1 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 44 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3619, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:431, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14177, TEID:14311, VARs:{}20,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 0 0 0 0 31 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 7 0 0 0 0 0 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 4 1 0 0 0 14 0 0 3 0 0 0 0 0 0 0 28 0 0 0 0 9 8 0 0 0 29 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 2 30 0 0 0 0 0 0 0 25 0 0 0 0 0 0 7 0 0 0 1 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 4 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 43 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3620, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:406, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14187, TEID:14310, VARs:{}17,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 0 0 0 0 30 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 6 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 3 1 0 0 0 13 0 0 3 0 0 0 0 0 0 0 27 0 0 0 0 8 7 0 0 0 28 0 0 0 0 0 26 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 2 29 0 0 0 0 0 0 0 24 0 0 0 0 0 0 6 0 0 0 1 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 39 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3621, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:388, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14193, TEID:14310, VARs:{}17,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 37 0 0 0 0 29 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 6 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 0 3 1 0 0 0 13 0 0 2 0 0 0 0 0 0 0 26 0 0 0 0 7 7 0 0 0 26 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 2 28 0 0 0 0 0 0 0 23 0 0 0 0 0 0 6 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 37 0 0 0 0 2 0 1 0 0 0 0 1
+# FILE:src/AbstractTableRendering.java, LINE:3623, OFFSET:3637, NODE_KIND:103, CONTEXT_KIND:0, NEIGHBOR_KIND:0, NUM_NODE:356, NUM_DECL:0, NUM_STMT:0, NUM_EXPR:0, TBID:14202, TEID:14309, VARs:{}15,
+2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33 0 0 0 0 27 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 5 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 0 2 1 0 0 0 13 0 0 2 0 0 0 0 0 0 0 24 0 0 0 0 6 7 0 0 0 24 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 26 0 0 0 0 0 0 0 21 0 0 0 0 0 0 5 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 3 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 0 0 0 0 0 0 0 33 0 0 0 0 2 0 1 0 0 0 0 1
diff --git a/scripts/bugdetect/bugcounting b/scripts/bugdetect/bugcounting
new file mode 100644
index 0000000..5417364
--- /dev/null
+++ b/scripts/bugdetect/bugcounting
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+if [[ $# -ne 1 ]]; then
+ echo "Usage: $0 "
+ exit 65
+fi
+
+if [[ ! (-f $1) ]]; then
+ echo "Usage: no file: $1"
+ exit 65
+fi
+
+RANKS='1 2 3 4 5 6 7'
+echo -n "Total: "
+grep "Rank score: " $1 | wc -l
+for i in ${RANKS}; do
+ echo -n "Rank $i: "
+ grep "Rank score: $i" $1 | wc -l
+done
+
+BUGS='1 2 3 4 5 6 7 8 9 10 11 12 13 14 15'
+echo -n "Bugs: "
+grep "^B" $1 | wc -l
+for i in ${BUGS}; do
+ echo -n "B${i}="
+ grep "^B" $1 | sed -r "s/^B([[:digit:]]+).*/B\1/" | grep "^B${i}$" | wc -l
+done
+echo -n "Styles: "
+grep "^S" $1 | wc -l
+for i in ${BUGS}; do
+ echo -n "S${i}="
+ grep "^S" $1 | sed -r "s/^S([[:digit:]]+).*/S\1/" | grep "^S${i}$" | wc -l
+done
diff --git a/scripts/bugdetect/bugfiltering b/scripts/bugdetect/bugfiltering
new file mode 100644
index 0000000..4a64dd5
--- /dev/null
+++ b/scripts/bugdetect/bugfiltering
@@ -0,0 +1,92 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# Usage: $0
+# output to stdout
+
+import re
+import sys
+import os
+#import shutil
+
+if len(sys.argv) != 3:
+ print "Usage: ", sys.argv[0], " "
+ sys.exit(1)
+elif sys.argv[2] != 'c' and sys.argv[2] != 'java' and sys.argv[2] != 'php':
+ print "We only support c, java, and php for now"
+ sys.exit(1)
+
+def readclusters( file ):
+ f= open(file,'r')
+ clusters= []
+ cluster= []
+ for line in f.readlines():
+ if line == '\n' or line == '':
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ cluster=[]
+ continue
+ cluster.append(line)
+ f.close()
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ return clusters
+
+clusters= readclusters( sys.argv[1] )
+#os.system('echo -n "" > ' + sys.argv[1] + '.bug')
+for cluster in clusters:
+ f=open( sys.argv[1] + '.clustertmp', 'w' )
+ for line in cluster:
+ f.write(line)
+ f.close()
+# meaning of IDs to cbugfilters:
+# 0: apply all filters and filter it iff all filters agree.
+# 1: apply context comparison
+# 2: apply context comparison and condition comparison
+# 3: apply variable filtering
+# none: apply all filters and filter it iff any filter says yes
+ if sys.argv[2] == 'c':
+ os.system('cbugfilters 2 < ' + sys.argv[1] + '.clustertmp')
+ elif sys.argv[2] == 'java':
+ os.system('jbugfilters 2 < ' + sys.argv[1] + '.clustertmp')
+ elif sys.argv[2] == 'php':
+ os.system('phpbugfilters 2 < ' + sys.argv[1] + '.clustertmp')
+ else:
+ print "parameter error for bugfiltering."
+ sys.exit(1)
+# os.system('cbugfilters < ' + sys.argv[1] + '.clustertmp >> ' + sys.argv[1] + '.bug')
+# os.system('echo "" >> ' + sys.argv[1] + '.bug')
+os.remove(sys.argv[1] + '.clustertmp')
+
diff --git a/scripts/bugdetect/bugmerging b/scripts/bugdetect/bugmerging
new file mode 100644
index 0000000..05a55cf
--- /dev/null
+++ b/scripts/bugdetect/bugmerging
@@ -0,0 +1,165 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# Usage: $0
+# output to stdout
+# only merge "category marks"
+
+import re
+import sys
+import os
+#import shutil
+
+if len(sys.argv) != 3:
+ print "Usage: ", sys.argv[0], " "
+ sys.exit(1)
+
+rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+).*')
+#rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+)\s(-?\d+)\s(-?\d+)\s(-?\d+).*')
+range_r= re.compile('.*FILE (.*) LINE:(\d+):(\d+) NODE_KIND.*')
+bugcategory_r= re.compile('(^B|^S|^G|^F)(\d+)\s*.*')
+def readclusters( file ):
+ f= open(file,'r')
+ clusters= []
+ cluster= []
+ for line in f.readlines():
+ if line == '\n' or line == '':
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ cluster=[]
+ continue
+ cluster.append(line)
+ f.close()
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ return clusters
+
+def print_cluster(cluster):
+ for line in cluster:
+ print line,
+
+def print_clusters(clusters):
+ for cluster in clusters:
+ print_cluster(cluster)
+ print
+
+def cluster_lineranges( cluster ):
+ size= len(cluster)
+# rsl[0]: rank score and other comments
+# rsl[1]: category marks, its length should be <=1
+# rsl[2]: the clones
+# rsl[3]: the ranges of clones
+# rsl[4]: the size of cluster
+ rsl=([], [], [], [], size)
+ for i in range(size):
+ rs_m= rs.match(cluster[i])
+ if rs_m != None:
+ rsl[0].append(cluster[i])
+ continue
+ bug_m= bugcategory_r.match(cluster[i])
+ if bug_m != None:
+ rsl[1].append(cluster[i])
+ continue
+ m= range_r.match(cluster[i])
+ if m != None:
+ rsl[2].append(cluster[i])
+ rsl[3].append( ( m.group(1), int(m.group(2)), int(m.group(2))+int(m.group(3))-1 ) )
+ continue
+ rsl[0].append(cluster[i])
+ return rsl
+
+def buggy_clusters( clusters ):
+ newlist= []
+ for i in range(len(clusters)):
+ keep= False
+ for j in range(len(clusters[i])):
+ m= bugcategory_r.match(clusters[i][j])
+ if m == None:
+ continue
+ else:
+ keep= True
+ if keep:
+ newlist.append(clusters[i])
+ return newlist
+
+def merge_clusters(c1, c2):
+ c1ranges= map(cluster_lineranges, c1)
+ c2ranges= map(cluster_lineranges, c2)
+ falseneg= 0
+ for i in range(len(c1ranges)):
+ findmatch= -1
+ for j in range(len(c2ranges)):
+ if len(c1ranges[i][3]) == len(c2ranges[j][3]):
+ matched= True
+ for k in range(len(c2ranges[j][3])):
+ linematched= False
+ for l in range(len(c2ranges[j][3])):
+ if c1ranges[i][3][k][2]<=c2ranges[j][3][l][2] and c1ranges[i][3][k][1]>=c2ranges[j][3][l][1] \
+ and c1ranges[i][3][k][0]==c2ranges[j][3][l][0]:
+ linematched= True
+ break
+ else:
+ continue
+ if not linematched:
+ matched= False
+ break
+ if matched:
+ findmatch= j
+ break
+ if findmatch>=0:
+# update c2:
+# only need B, S marks, and C2's own marks take priority:
+ if len(c2ranges[findmatch][1][:])<1:
+ c2ranges[findmatch][1][:] = c1ranges[i][1]
+ else:
+ falseneg = falseneg+1
+ for line in c1ranges[i][0]+c1ranges[i][1]+c1ranges[i][2]:
+ print >> sys.stderr, line,
+ print >> sys.stderr
+ newlist=[]
+ for i in range(len(c2ranges)):
+ newlist.append(c2ranges[i][0]+c2ranges[i][1]+c2ranges[i][2])
+ print >> sys.stderr, "Miss bugs: ", falseneg
+ return newlist
+
+clusters1= readclusters( sys.argv[1] )
+clusters2= readclusters( sys.argv[2] )
+clusters1= buggy_clusters(clusters1)
+merged_clusters=merge_clusters(clusters1, clusters2)
+# mark the output as auto generated:
+print "Auto generated: merging ", len(clusters1), len(clusters2)
+print_clusters(merged_clusters)
+
+
diff --git a/scripts/bugdetect/bugordering b/scripts/bugdetect/bugordering
new file mode 100644
index 0000000..0a16929
--- /dev/null
+++ b/scripts/bugdetect/bugordering
@@ -0,0 +1,101 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# Usage: $0
+# output to stdout
+
+# To change the way the clusters are sorted, change
+# the cmp_rank_score function
+
+import re
+import sys
+import os
+
+if len(sys.argv) != 2:
+ print "Usage: ", sys.argv[0], " "
+ sys.exit(1)
+
+rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+)\s(-?\d+)\s(-?\d+)\s(-?\d+).*')
+def cluster_rank_score( line ):
+ m= rs.match(line)
+ s= (0,0,0)
+ if m == None:
+ s= (0,0,0)
+ else:
+ s= ( int(m.group(1)), int(m.group(2)), int(m.group(4)) )
+ return s
+
+def cmp_rank_score( c1, c2 ):
+ s11= c1[0][0]*c1[0][1]
+ s12= c1[0][2]
+ s21= c2[0][0]*c2[0][1]
+ s22= c2[0][2]
+ if s11 > s21: return -1
+ elif s11 == s21 and s12 > s22: return -1
+ elif s11 < s21: return 1
+ elif s11 == s21 and s12 < s22: return 1
+ else: return 0
+
+def readclusters( file ):
+ f= open(file,'r')
+ clusters= []
+ cluster= []
+ for line in f.readlines():
+ if line == '\n' or line == '':
+ if len(cluster) > 0:
+ clusters.append((cluster_rank_score(cluster[0]), cluster))
+ cluster=[]
+ continue
+ cluster.append(line)
+ f.close()
+ if len(cluster) > 0:
+ clusters.append((cluster_rank_score(cluster[0]), cluster))
+ cluster=[]
+ return clusters
+
+clusters= readclusters( sys.argv[1] )
+#clusters= map( remove_overlaping, clusters )
+#clusters= filter( only_one_diff, clusters )
+clusters.sort( cmp_rank_score )
+
+
+#print len(clusters), 'clusters'
+#print
+for (score, cluster) in clusters:
+ for line in cluster:
+ print line,
+ print
+
+
diff --git a/scripts/bugdetect/bugtypecounting b/scripts/bugdetect/bugtypecounting
new file mode 100644
index 0000000..c34c11e
--- /dev/null
+++ b/scripts/bugdetect/bugtypecounting
@@ -0,0 +1,153 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# the regular expressions are copied from bugmerging
+# Usage: $0
+# output to stdout
+
+import re
+import sys
+import os
+#import shutil
+
+if len(sys.argv) != 2:
+ print "Usage: ", sys.argv[0], " "
+ sys.exit(1)
+
+rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+).*')
+#rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+)\s(-?\d+)\s(-?\d+)\s(-?\d+).*')
+range_r= re.compile('.*FILE (.*) LINE:(\d+):(\d+) NODE_KIND.*')
+bugcategory_r= re.compile('(^B|^S|^G|^F)(\d+)\s*.*')
+onlybug_r= re.compile('^B.*')
+onlystyle_r= re.compile('^S.*')
+def readclusters( file ):
+ f= open(file,'r')
+ clusters= []
+ cluster= []
+ for line in f.readlines():
+ if line == '\n' or line == '':
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ cluster=[]
+ continue
+ cluster.append(line)
+ f.close()
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ return clusters
+
+def print_cluster(cluster):
+ for line in cluster:
+ print line,
+
+def print_clusters(clusters):
+ for cluster in clusters:
+ print_cluster(cluster)
+ print
+
+def buggy_clusters( clusters ):
+ newlist= []
+ for i in range(len(clusters)):
+ keep= False
+ for j in range(len(clusters[i])):
+ m= bugcategory_r.match(clusters[i][j])
+ if m == None:
+ continue
+ else:
+ keep= True
+ if keep:
+ newlist.append(clusters[i])
+ return newlist
+
+# This function currently can't handle the cases when one cluster contains several lines of Rank score.
+def rank_buggy_clusters( rankid, clusters ):
+ newlist= []
+ for i in range(len(clusters)):
+ keep= False
+ rank= 0
+ marks= []
+ for j in range(len(clusters[i])):
+ rs_m= rs.match(clusters[i][j])
+ if rs_m != None:
+ rank= int(rs_m.group(1))
+ m= onlybug_r.match(clusters[i][j])
+ if m != None:
+ marks.append(clusters[i][j])
+ if len(marks)>0 and rank==rankid:
+ keep= True
+ if keep:
+ newlist.append(clusters[i])
+ return newlist
+
+def type_buggy_clusters( typeid, clusters ):
+ newlist= []
+ typeids= {}
+ if typeid==1:
+ typeids= set([1, 3, 5, 7])
+ elif typeid==2:
+ typeids= set([2, 3, 6, 7])
+ elif typeid==3:
+ typeids= set([4, 5, 6, 7])
+ for i in range(len(clusters)):
+ keep= False
+ rank= 0
+ marks= []
+ for j in range(len(clusters[i])):
+ rs_m= rs.match(clusters[i][j])
+ if rs_m != None:
+ rank= int(rs_m.group(1))
+ m= onlybug_r.match(clusters[i][j])
+ if m != None:
+ marks.append(clusters[i][j])
+ if len(marks)>0 and rank in typeids:
+ keep= True
+ if keep:
+ newlist.append(clusters[i])
+ return newlist
+
+clustersall= readclusters( sys.argv[1] )
+rankclusters= []
+for i in range(1,8):
+ rankclusters.append( rank_buggy_clusters(i, clustersall) )
+sum= 0
+for i in range(7):
+ sum += len(rankclusters[i])
+ print len(rankclusters[i]),
+print
+print "Total bugs: ", sum
+print "Type 1 bugs: ", len(rankclusters[0])+len(rankclusters[2])+len(rankclusters[4])+len(rankclusters[6])
+print "Type 2 bugs: ", len(rankclusters[1])+len(rankclusters[2])+len(rankclusters[5])+len(rankclusters[6])
+print "Type 3 bugs: ", len(rankclusters[3])+len(rankclusters[4])+len(rankclusters[5])+len(rankclusters[6])
+
diff --git a/scripts/bugdetect/mergecomments b/scripts/bugdetect/mergecomments
new file mode 100644
index 0000000..eb6d6a8
--- /dev/null
+++ b/scripts/bugdetect/mergecomments
@@ -0,0 +1,178 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# copied from bugmerging
+# Usage: $0
+# output to stdout
+
+import re
+import sys
+import os
+#import shutil
+
+if len(sys.argv) != 3:
+ print "Usage: ", sys.argv[0], " "
+ sys.exit(1)
+
+rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+).*')
+#rs= re.compile('.*Rank score:\s*(-?\d+)\s*\*\s*(\d+)\s*=\s*(-?\d+)\s*buggy score:\s*(-?\d+)\s(-?\d+)\s(-?\d+)\s(-?\d+).*')
+range_r= re.compile('.*FILE (.*) LINE:(\d+):(\d+) NODE_KIND.*')
+bugcategory_r= re.compile('(^B|^S|^G|^F)(\d+)\s*.*')
+bugflag_r= re.compile('(^\?|^Y|^N|^C).*')
+def readclusters( file ):
+ f= open(file,'r')
+ clusters= []
+ cluster= []
+ for line in f.readlines():
+ if line == '\n' or line == '':
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ cluster=[]
+ continue
+ cluster.append(line)
+ f.close()
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ return clusters
+
+def print_cluster(cluster):
+ for line in cluster:
+ print line,
+
+def print_clusters(clusters):
+ for cluster in clusters:
+ print_cluster(cluster)
+ print
+
+def cluster_lineranges( cluster ):
+ size= len(cluster)
+# rsl[0]: rank score, its length should be <=1
+# rsl[1]: category marks, its length should be <=1
+# rsl[2]: the clones
+# rsl[3]: the ranges of clones
+# rsl[4]: bug marks, its length should be <=1
+# rsl[5]: other comments
+# rsl[6]: the size of cluster
+ rsl=([], [], [], [], [], [], size)
+ for i in range(size):
+ rs_m= rs.match(cluster[i])
+ if rs_m != None:
+ rsl[0].append(cluster[i])
+ continue
+ bug_m= bugcategory_r.match(cluster[i])
+ if bug_m != None:
+ rsl[1].append(cluster[i])
+ continue
+ m= range_r.match(cluster[i])
+ if m != None:
+ rsl[2].append(cluster[i])
+ rsl[3].append( ( m.group(1), int(m.group(2)), int(m.group(2))+int(m.group(3))-1 ) )
+ continue
+ flag_m= bugflag_r.match(cluster[i])
+ if flag_m != None:
+ rsl[4].append(cluster[i])
+ continue
+ rsl[5].append(cluster[i])
+ return rsl
+
+def clear_clusters( clusters ):
+# only keep clones:
+ newlist= []
+ for i in range(len(clusters)):
+ newlines= []
+ for j in range(len(clusters[i])):
+ m= range_r.match(clusters[i][j])
+ if m == None:
+ continue
+ else:
+ newlines.append(clusters[i][j])
+ if len(newlines)>0:
+ newlist.append(newlines)
+ return newlist
+
+def merge_clusters(c1, c2):
+ c1ranges= map(cluster_lineranges, c1)
+ c2ranges= map(cluster_lineranges, c2)
+ falseneg= 0
+ for i in range(len(c1ranges)):
+ findmatch= -1
+ for j in range(len(c2ranges)):
+ if len(c1ranges[i][3]) == len(c2ranges[j][3]):
+ matched= True
+ for k in range(len(c1ranges[i][3])):
+ linematched= False
+ for l in range(len(c2ranges[j][3])):
+ if c1ranges[i][3][k][2]<=c2ranges[j][3][l][2] and c1ranges[i][3][k][1]>=c2ranges[j][3][l][1] \
+ and c1ranges[i][3][k][0]==c2ranges[j][3][l][0]:
+ linematched= True
+ break
+ else:
+ continue
+ if not linematched:
+ matched= False
+ break
+ if matched:
+ findmatch= j
+ break
+ if findmatch>=0:
+# update c2:
+# concatenate textual comments:
+ c2ranges[findmatch][5][:] = c2ranges[findmatch][5] + c1ranges[i][5]
+# replace category marks if there is no in the c2:
+ if len(c2ranges[findmatch][1])<1:
+ c2ranges[findmatch][1][:] = c1ranges[i][1]
+# replace bug marks if there is no in the c2:
+ if len(c2ranges[findmatch][4])<1:
+ c2ranges[findmatch][4][:] = c1ranges[i][4]
+ else:
+ falseneg = falseneg+1
+ for line in c1ranges[i][0]+c1ranges[i][4]+c1ranges[i][1]+c1ranges[i][5]+c1ranges[i][2]:
+ print >> sys.stderr, line,
+ print >> sys.stderr
+ newlist=[]
+ for i in range(len(c2ranges)):
+ newlist.append(c2ranges[i][0]+c2ranges[i][4]+c2ranges[i][1]+c2ranges[i][5]+c2ranges[i][2])
+ print >> sys.stderr, "Miss clusters: ", falseneg
+ return newlist
+
+clusters1= readclusters( sys.argv[1] )
+clusters2= readclusters( sys.argv[2] )
+#clusters2= clear_clusters( clusters2 )
+merged_clusters=merge_clusters(clusters1, clusters2)
+# mark the output as auto generated:
+print "Auto generated: merging ", len(clusters1), len(clusters2)
+print_clusters(merged_clusters)
+
+
diff --git a/scripts/clonedetect/cd_coverage b/scripts/clonedetect/cd_coverage
new file mode 100644
index 0000000..077de24
--- /dev/null
+++ b/scripts/clonedetect/cd_coverage
@@ -0,0 +1,68 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+#import psyco
+#psyco.full()
+
+import sys
+f= open(sys.argv[1])
+
+inputs=[]
+import re
+reg= re.compile(".*FILE (.*) LINE:(\d+):(\d+) NODE_KIND.*")
+for line in f.readlines():
+ m= reg.match(line)
+ if m != None:
+ l1= int(m.group(2))
+ l2= int(m.group(3))+l1
+ inputs.append( (m.group(1), (l1, l2)) )
+
+fileCoverSet={}
+
+for file,linerange in inputs:
+ if linerange[0] > linerange[1]:
+ print "bad linerange:",linerange
+ continue
+ if file not in fileCoverSet:
+ fileCoverSet[file] = set()
+ fileCoverSet[file].update(range(linerange[0],linerange[1]))
+
+sum = 0
+for file,coverset in fileCoverSet.items():
+ #print file,',',coverset
+ sum += len(coverset)
+
+print sum
+
diff --git a/scripts/clonedetect/config-sample b/scripts/clonedetect/config-sample
new file mode 100644
index 0000000..7556256
--- /dev/null
+++ b/scripts/clonedetect/config-sample
@@ -0,0 +1,102 @@
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+#############################################################
+# Configuration file for clone detection.
+#
+
+############################################################
+# Often, need to change these common parameters:
+# - FILE_PATTERN : for source files in different languages
+# - SRC_DIR : the root directory containing the source files
+# - DECKARD_DIR : Where is the home directory of DECKARD
+# - clone detection parameters: c.f. DECKARD's paper
+# -- MIN_TOKENS
+# -- STRIDE
+# -- SIMILARITY
+#
+# java, c, or php?
+FILE_PATTERN='*.java' # used for the 'find' command
+# where are the source files?
+SRC_DIR='src'
+# where is Deckard?
+DECKARD_DIR='/home/deckard'
+# clone parameters; refer to paper.
+MIN_TOKENS='50 100' # can be a sequence of integers
+STRIDE='2 0' # can be a sequence of integers
+SIMILARITY='1.0 0.95' # can be a sequence of values <= 1
+#DISTANCE='0 0.70711 1.58114 2.236'
+
+###########################################################
+# Where to store result files?
+#
+# where to output generated vectors?
+VECTOR_DIR='vectors'
+# where to output detected clone clusters?
+CLUSTER_DIR='clusters'
+# where to output timing/debugging info?
+TIME_DIR='times'
+
+##########################################################
+# where are several programs we need?
+#
+# where is the vector generator?
+VGEN_EXEC="$DECKARD_DIR/src/main"
+case $FILE_PATTERN in
+ *.java )
+ VGEN_EXEC="$VGEN_EXEC/jvecgen" ;;
+ *.php )
+ VGEN_EXEC="$VGEN_EXEC/phpvecgen" ;;
+ *.c | *.h )
+ VGEN_EXEC="$VGEN_EXEC/cvecgen" ;;
+ * )
+ echo "Error: invalid FILE_PATTERN: $FILE_PATTERN"
+ VGEN_EXEC="$VGEN_EXEC/invalidvecgen" ;;
+esac
+# how to divide the vectors into groups?
+GROUPING_EXEC="$DECKARD_DIR/src/vgen/vgrouping/runvectorsort"
+# where is the lsh for vector clustering?
+CLUSTER_EXEC="$DECKARD_DIR/src/lsh/bin/enumBuckets"
+# how to post process clone groups?
+POSTPRO_EXEC="$DECKARD_DIR/scripts/clonedetect/post_process_groupfile"
+# how to transform source code html?
+SRC2HTM_EXEC=source-highlight
+SRC2HTM_OPTS=--line-number-ref
+
+##################################################################
+# Some additional, internal parameters; can be ignored
+#
+# the maximal vector size for the first group; not really useful
+GROUPING_S='50' # should be a single value
+#GROUPING_D
+#GROUPING_C
+
diff --git a/scripts/clonedetect/configure b/scripts/clonedetect/configure
new file mode 100644
index 0000000..04cdceb
--- /dev/null
+++ b/scripts/clonedetect/configure
@@ -0,0 +1,132 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+check_or_create_dir()
+{
+ if [[ ! -d "${!1}" ]]; then
+ if [[ -e "${!1}" ]]; then
+ echo "Error: $1 should be a directory. Check your config"
+ exit 1
+ else
+ mkdir "${!1}"
+ if [[ $? -ne 0 ]]; then
+ echo "Error: $1 doesn't exist and cannot be created. Check your config"
+ exit 1
+ fi
+ fi
+fi
+}
+
+check_file()
+{
+ if [[ ! -f $1 ]]; then
+ echo "Error: missing file $1. Check your config"
+ exit 1
+ fi
+}
+
+check_var()
+{
+ if [[ -z ${!1} ]];
+ then
+ echo "Error: $1 not set in config. Check your config"
+ exit 1
+ fi
+
+ export $1
+}
+
+check_exe()
+{
+ if (which "$1" >& /dev/null); then
+ return 0
+ else
+ echo "Error: missing required program: $1"
+ exit 1
+ fi
+}
+
+if [[ -e config ]];
+then
+ . config
+else
+ echo "Error: no config file in current directory"
+ exit 0
+fi
+
+check_var "DECKARD_DIR"
+check_var "FILE_PATTERN"
+check_var "SRC_DIR"
+
+check_var "VECTOR_DIR"
+check_or_create_dir "VECTOR_DIR"
+check_var "CLUSTER_DIR"
+check_or_create_dir "CLUSTER_DIR"
+check_var "TIME_DIR"
+check_or_create_dir "TIME_DIR"
+
+check_var "VGEN_EXEC"
+check_file "$VGEN_EXEC"
+check_var "GROUPING_EXEC"
+check_file "$GROUPING_EXEC"
+check_var "CLUSTER_EXEC"
+check_file "$CLUSTER_EXEC"
+check_var "POSTPRO_EXEC"
+check_file "$POSTPRO_EXEC"
+
+check_var "MIN_TOKENS"
+check_var "STRIDE"
+#check_var "DISTANCE"
+check_var "SIMILARITY"
+check_var "GROUPING_S"
+#check_var "GROUPING_D"
+#check_var "GROUPING_C"
+
+check_exe "which"
+check_exe "env"
+check_exe "python"
+check_exe "awk"
+check_exe "sed"
+check_exe "grep"
+check_exe "find"
+check_exe "bash"
+check_exe "cat"
+check_exe "touch"
+check_exe "head"
+check_exe "tail"
+check_exe "time"
+
+
+
diff --git a/scripts/clonedetect/deckard.sh b/scripts/clonedetect/deckard.sh
new file mode 100644
index 0000000..a2166b1
--- /dev/null
+++ b/scripts/clonedetect/deckard.sh
@@ -0,0 +1,133 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+echo "DECKARD--A Tree-Based Code Clone Detection Toolkit. Version 1.0"
+echo "Copyright (c) 2007-2010. University of California"
+echo "Distributed under the three-clause BSD license."
+echo
+
+echo -n "==== Configuration checking..."
+. `dirname $0`/configure
+errcode=$?
+if [[ $errcode -eq 0 ]]; then
+ echo "Done."
+ echo
+else
+ exit $errcode
+fi
+
+TOOVERWRITE=
+if [[ $# -ge 1 ]]; then
+ case "$1" in
+ clean )
+ "`dirname $0`/vdbgen" clean
+ "`dirname $0`/vertical-param-batch" clean
+ exit $?
+ ;;
+ clean_all )
+ "`dirname $0`/vdbgen" clean_all
+ "`dirname $0`/vertical-param-batch" clean_all
+ exit $?
+ ;;
+ overwrite )
+ TOOVERWRITE="overwrite"
+ ;;
+ * )
+ echo "Usage: $0 [overwrite | clean | clean_all]"
+ exit 1
+ ;;
+ esac
+fi
+
+
+
+echo "==== Start clone detection ===="
+echo
+
+SRCLANG=${FILE_PATTERN##*.}
+case $SRCLANG in
+ c | h | java | php )
+ ;;
+ *)
+ echo "Error: language '$SRCLANG' not supported."
+ exit 1 ;;
+esac
+
+echo -n "Vector generation..."
+"`dirname $0`/vdbgen" $TOOVERWRITE
+errcode=$?
+if [[ $errcode -ne 0 ]]; then
+ echo "Error: problem in vec generator step. Stop and check logs in $TIME_DIR/"
+ exit $errcode
+else
+ echo "Vector generation done. Logs in $TIME_DIR/vgen_*"
+ echo "Vector files in $VECTOR_DIR/vdb_*"
+ echo
+fi
+
+echo "Vector clustering and filtering..."
+"`dirname $0`/vertical-param-batch" $TOOVERWRITE
+errcode=$?
+if [[ $errcode -ne 0 ]]; then
+ echo "Error: problem in vec clustering step. Stop and check logs in $TIME_DIR/"
+ exit $errcode
+fi
+
+echo "Clone detection done. Logs in $TIME_DIR/*"
+echo "Clone reports in $VECTOR_DIR/post_cluster_*"
+echo
+
+# Bug Finding:
+echo "In addition, potential clone-related bugs may be produced by running the scripts:"
+echo "(Be careful about the file overwriting and the choice for programming language)"
+
+echo "(1) search clone reports and find out suspicious ones: "
+echo " \"$DECKARD_DIR/scripts/bugdetect/bugfiltering\" \"${CLUSTER_DIR}/post_\" $SRCLANG > \"${CLUSTER_DIR}/bug_\" 2> \"${TIME_DIR}/bugfiltering_\""
+echo "(2) transform the bug reports to html for easier investigation:"
+echo " \"$DECKARD_DIR/src/main/out2html\" \"${CLUSTER_DIR}/bug_\" > \"${CLUSTER_DIR}/bug_.html\""
+echo
+## # the actual commands for bug finding:
+## find "$CLUSTER_DIR" -type f -name "post_cluster_vdb_*_*_allg_*_*" | while read cdb;
+## do
+## basecdb=`basename "$cdb"`
+## basecdb=${basecdb#post_}
+## ( time "`dirname $0`/../bugdetect/bugfiltering" "$cdb" $SRCLANG > "${CLUSTER_DIR}/bug_$basecdb" ) 2> "${TIME_DIR}/bugfiltering_$basecdb"
+## "$DECKARD_DIR/src/main/out2html" "${CLUSTER_DIR}/bug_$basecdb" > "${CLUSTER_DIR}/bug_${basecdb}.html"
+## done
+
+echo
+echo "==== All Done for the current 'config' file ===="
+echo
+
diff --git a/scripts/clonedetect/generateparam b/scripts/clonedetect/generateparam
new file mode 100644
index 0000000..57314bc
--- /dev/null
+++ b/scripts/clonedetect/generateparam
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+if [[ $# -ne 3 ]]; then
+ echo "Usage: $0 "
+ exit 65
+fi
+
+head -n 2 "$1"
+echo $3
+head -n 8 "$1" | tail -n 5
+echo $3 | awk '{printf("%.7g\n", $1*$1)}'
+head -n 20 "$1" | tail -n 11
+echo $2
+tail -n 2 "$1"
+
diff --git a/scripts/clonedetect/paramsetting b/scripts/clonedetect/paramsetting
new file mode 100644
index 0000000..7ea72f7
--- /dev/null
+++ b/scripts/clonedetect/paramsetting
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# Usage: $1=, $2=, $3=
+
+# make sure ${GROUPING_S} and ${VECTOR_DIR} are set correctly.
+
+if [[ $# -ne 3 ]]; then
+ echo "Usage: $0 "
+ exit 65
+fi
+
+# TODO: may check whether parameters have been set or not...
+
+t=$1
+s=$2
+sim=$3
+# convert SIMILARITY to DISTANCE:
+i=`echo "$sim ${GROUPING_S}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+find $VECTOR_DIR -type f -name "vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}" -not -name '*.param' -print0 | xargs -0 ls -S > tempfile
+# not easy to pipe "head -n 1" with "ls", coz. often cause signal 13 (no more reader, while writer's still writing)
+groupfortuning=`head -n 1 tempfile`
+rm tempfile
+grptuningid=`echo $vdb | sed "s/.*vdb_${t}_${s}_g\([0-9]*\)_${i}_${GROUPING_S}/\1/"`
+grpal=0
+grpdist=0
+# if $grptuningid is empty, error occurs...
+if [[ $grptuningid -eq 0 ]]; then
+ grpal=`head -n $(expr $grptuningid + 1) $(dirname $vdb)/vdb_${t}_${s}_ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $3}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+else
+ grpal=`head -n $(expr $grptuningid + 1) $(dirname $vdb)/vdb_${t}_${s}_ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $2}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*2*$2) )}'`
+fi
+echo "Looking for local optimal parameters by clustering $groupfortuning $grpdist ..."
+cluster $groupfortuning $grpdist
+
+if [[ ! -s ${groupfortuning}.param ]]; then
+ echo "Parameter tuning failed ... exit ..."
+ exit 3
+fi
+
+echo "Setting Parameters for all other groups..."
+find $VECTOR_DIR -type f -name "vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}" -not -name '*.param' | while read vdb;
+#NOTE: trouble with filenames with spaces:
+#for vdb in `find $VECTOR_DIR -type f -name "vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}" -not -name '*.param'`;
+ do
+ grpfileid=`echo "$vdb" | sed "s/.*vdb_${t}_${s}_g\([0-9]*\)_${i}_${GROUPING_S}/\1/"`
+ grpal=0
+ grpdist=0
+ if [[ $grptuningid -eq $grpfileid ]]; then
+ continue
+ elif [[ $grpfileid -eq 0 ]]; then
+ grpal=`head -n $(expr $grpfileid + 1) $(dirname "$vdb")/vdb_${t}_${s}_ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $3}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+ else
+ grpal=`head -n $(expr $grpfileid + 1) $(dirname "$vdb")/vdb_${t}_${s}_ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $2}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*2*$2) )}'`
+ fi
+ lineno=`wc -l "$vdb" | awk '{print $1}'`
+ lineno=$(($lineno / 2))
+ `dirname $0`/generateparam ${groupfortuning}.param $lineno $grpdist > "${vdb}.param"
+done
+
diff --git a/scripts/clonedetect/post_process_groupfile b/scripts/clonedetect/post_process_groupfile
new file mode 100644
index 0000000..9c5a31a
--- /dev/null
+++ b/scripts/clonedetect/post_process_groupfile
@@ -0,0 +1,248 @@
+#! /usr/bin/env python
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+import re
+import sys
+
+if len(sys.argv) != 2:
+ print "Usage: ", sys.argv[0], " "
+ sys.exit(1)
+
+#required_lines= int(sys.argv[2])
+el= re.compile('.*:(\d+) NODE_KIND.*')
+def vector_linecount( vector ):
+ m= el.match(vector)
+ if m == None:
+ return -1
+ return int( m.group(1) )
+
+#NOTE: filenames can contain spaces...
+range_r= re.compile('.*FILE (.*) LINE:(\d+):(\d+) NODE_KIND.*')
+def vector_linerange( vector ):
+ m= range_r.match(vector)
+ if m == None:
+ return (-1,-1,-1)
+ return ( int(m.group(2)), int(m.group(2))+int(m.group(3))-1, m.group(1) )
+
+
+vc= re.compile('.*nVARs:(\d+) NUM_NODE.*')
+def vector_varcount( vector ):
+ m= vc.match(vector)
+ if m == None:
+ return -1
+ return int( m.group(1) )
+
+
+def has_enough_lines( cluster ):
+ for vector in cluster:
+ lines= vector_linecount( vector )
+ if lines >= required_lines:
+ return True
+ return False
+
+def line_diff_big( cluster ):
+ maxl= reduce( lambda x,y: max(x,y), map( vector_linecount, cluster ))
+ minl= reduce( lambda x,y: min(x,y), map( vector_linecount, cluster ))
+ if maxl>minl+5:
+ return False
+ return True
+
+def count_duplicates( l, i ):
+ n= 0
+ for item in l:
+ if i==item:
+ n+=1
+ return n
+
+def only_one_diff( cluster ):
+ counts= map( vector_varcount, cluster )
+ counts.sort()
+ if counts[-1] - counts[0] > 2:
+ return False
+ front= count_duplicates(counts,counts[0])
+ back= count_duplicates(counts,counts[-1])
+ if front < len(counts) and front >= len(counts)-2:
+ return True
+ if back < len(counts) and back >= len(counts)-2:
+ return True
+ return False
+
+def remove_staggered( cluster ):
+ rs= map( vector_linerange, cluster )
+ keep= map( lambda x: True, cluster )
+ for i in range(len(rs)-1):
+ for j in range(i+1,len(rs)):
+ if rs[j][2] == rs[i][2] and rs[j][0] < rs[i][1] \
+ and rs[j][0] > rs[i][0] and rs[j][1] > rs[i][1] \
+ and (rs[i][1]-rs[j][0])*2 >= rs[i][1]-rs[i][0] \
+ and (rs[j][1]-rs[i][1])*2 <= rs[i][1]-rs[i][0]:
+ keep[j]= False
+ newlist= []
+ for i in range(len(cluster)):
+ if keep[i]:
+ newlist.append(cluster[i])
+ return newlist
+
+def remove_overlaping( cluster ):
+ rs= map( vector_linerange, cluster )
+ keep= map( lambda x: True, cluster )
+ for i in range(len(rs)-1):
+ for j in range(i+1,len(rs)):
+ if rs[j][2] == rs[i][2] and rs[j][0] < rs[i][1] \
+ and rs[j][0] > rs[i][0] and rs[j][1] > rs[i][1]: \
+ keep[j]= False
+ newlist= []
+ for i in range(len(cluster)):
+ if keep[i]:
+ newlist.append(cluster[i])
+ return newlist
+
+def cluster_lineranges( cluster ):
+ size= len(cluster)
+ rsl=([], [], size)
+ for i in range(size):
+ m= range_r.match(cluster[i])
+ if m != None:
+ rsl[0].append( (int(m.group(2)), int(m.group(2))+int(m.group(3))-1) )
+ rsl[1].append( m.group(1) )
+ return rsl
+
+def remove_contained_across_clusters ( clusters ):
+#should have no effect on cd_coverage: compare each range and filename (luckily sorted by filenames)
+#take quadratic time (from seconds to minutes; range trees will perform better), but it can help to reduce re-parsing time (about 1/3, several minutes)
+ rs= map( cluster_lineranges, clusters )
+ keep= map( lambda x: True, clusters )
+ for i in range(len(rs)):
+ for j in range(len(rs)):
+ if not keep[i] or not keep[j] or i == j:
+ continue
+ if rs[j][2] == rs[i][2] and len(rs[j][1]) == len(rs[i][1]):
+ filematch= True
+ for fn in range(len(rs[i][1])):
+ if rs[i][0][fn][0] >= rs[j][0][fn][0] and rs[i][0][fn][1] <= rs[j][0][fn][1] \
+ and rs[j][1][fn] == rs[i][1][fn]:
+ continue
+ else:
+ filematch= False
+ break
+ if filematch:
+ keep[i]= False
+ newlist= []
+ for i in range(len(clusters)):
+ if keep[i]:
+ newlist.append(clusters[i])
+ return newlist
+
+def remove_contained( cluster ):
+ rs= map( vector_linerange, cluster )
+ keep= map( lambda x: True, cluster )
+ for i in range(len(rs)):
+ for j in range(len(rs)):
+ if not keep[i] or i == j or not keep[j]:
+ continue
+ if rs[j][2] == rs[i][2] \
+ and rs[i][0] >= rs[j][0] and rs[i][1] <= rs[j][1]:
+ keep[i]= False
+ newlist= []
+ for i in range(len(cluster)):
+ if keep[i]:
+ newlist.append(cluster[i])
+ return newlist
+
+def not_empty( cluster ):
+ if len(cluster) <= 1:
+ return False
+ return True
+
+def cmp_linecount( c1, c2 ):
+ c1l= map( vector_linecount, c1 )
+ c2l= map( vector_linecount, c2 )
+ m1= reduce( max, c1l )
+ m2= reduce( max, c2l )
+ if m1 > m2: return -1
+ if m1 == m2: return 0
+ return 1
+
+def readclusters( file ):
+# print file
+ f= open(file,'r')
+ clusters= []
+ cluster= []
+ for line in f.readlines():
+ if line == '\n' or line == '':
+ if len(cluster) > 0:
+ clusters.append(cluster)
+ cluster=[]
+ continue
+ cluster.append(line)
+ f.close()
+ if len(cluster) > 0:
+ clusters.append(cluster)
+# clusters= clusters[1:]
+ return clusters
+
+
+# read in all clone clusters from a file
+clusters= readclusters( sys.argv[1] )
+
+# remove clones completely contained in another clone in the same cluster
+clusters= map( remove_contained, clusters )
+
+# remove clones overlapped with another clone more than 50%
+clusters= map( remove_staggered, clusters )
+
+# remove clones overlapped with another clone more than 0%
+# disabled: clusters= map( remove_overlaping, clusters )
+
+# remove clones contained in another clone in another cluster
+clusters= remove_contained_across_clusters(clusters)
+
+# some of the filtering may only be useful for bug detection purpose, which should and has been separated into another module
+#clusters= filter( has_enough_lines , clusters )
+#clusters= filter( line_diff_big, clusters )
+#clusters= filter( only_one_diff, clusters )
+
+# remove clusters containing less than 2 clones
+clusters= filter( not_empty, clusters )
+# sort clusters by the cloned lines of code
+clusters.sort( cmp_linecount )
+
+# print the result clusters
+for cluster in clusters:
+ for line in cluster:
+ print line,
+ print
+
+
diff --git a/scripts/clonedetect/vdbgen b/scripts/clonedetect/vdbgen
new file mode 100644
index 0000000..85ebbd7
--- /dev/null
+++ b/scripts/clonedetect/vdbgen
@@ -0,0 +1,159 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+TOOVERWRITE=
+
+clean()
+{
+ echo -n "...deleting intermediate vector files..."
+ find "$SRC_DIR" -iname '*.vec' -print0 | xargs -0 -r --max-args 500 rm -f
+ echo "Done"
+}
+
+clean_log()
+{
+ echo -n "...deleting vgen logs..."
+ find "$TIME_DIR" -iname 'vgen_*' -print0 | xargs -0 -r --max-args 500 rm -f
+ echo "Done"
+ echo -n "...deleting vector db files..."
+ find "$VECTOR_DIR" -iname 'vdb_*' -print0 | xargs -0 -r --max-args 500 rm -f
+ echo "Done"
+}
+
+#vgen $1 $2: $1=min_token; $2=stride
+vgen()
+{
+ if (($# != 2));
+ then
+ return 1
+ fi
+
+ echo -n "$FUNCNAME: $1 $2 ..." # FUNCNAME: the current function name; maintained by Bash
+ if [[ "$TOOVERWRITE" != "true" && -s "$VECTOR_DIR/vdb_$1_$2" ]];
+ then
+ echo
+ echo "Warning: Vec file $VECTOR_DIR/vdb_$1_$2 exists. Delete it manually or use '$0 overwrite'."
+ echo "$FUNCNAME: $1 $2 ...Skip."
+ else
+ echo -n > "$TIME_DIR/vgen_$1_$2"
+
+#NOTE: "for .. in .." has trouble when a filename contains spaces; use "while read .." instead:
+ ( time \
+ find "$SRC_DIR" -iname "$FILE_PATTERN" | while read file;
+# for file in `find $SRC_DIR/ -iname "$FILE_PATTERN"`;
+ do
+ echo "Parsing $file" >> "$TIME_DIR/vgen_$1_$2"
+ if [[ ! -s "${file}.vec" || "$TOOVERWRITE" = "true" ]];
+ then
+ "$VGEN_EXEC" -i "$file" -m $1 -t $2
+ fi
+ done \
+ ) 1>>"$TIME_DIR/vgen_$1_$2" 2>&1
+
+ find "$SRC_DIR" -iname '*.vec' -print0 | xargs -0 --max-args=100 cat > "$VECTOR_DIR/vdb_$1_$2"
+ echo "Done. Log: $TIME_DIR/vgen_$1_$2"
+ fi
+
+ if [[ -s "$VECTOR_DIR/vdb_$1_$2" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# transform source code to html:
+tohtml()
+{
+ if ( which "$SRC2HTM_EXEC" >& /dev/null );
+ then
+ echo -n "Transforming source code to html..."
+ ( time \
+ find $SRC_DIR/ -iname "$FILE_PATTERN" | while read file;
+ do
+ if [[ ! -e "${file}.html" || "$TOOVERWRITE" = "true" ]];
+ then
+ echo "$SRC2HTM_EXEC $SRC2HTM_OPTS $file"
+ "$SRC2HTM_EXEC" "$SRC2HTM_OPTS" "$file"
+ fi
+ done \
+ ) 1>>"$TIME_DIR/$SRC2HTM_EXEC.log" 2>&1
+ echo "Done. Log: $TIME_DIR/$SRC2HTM_EXEC.log"
+ fi
+}
+
+. `dirname $0`/configure
+
+if [[ $# -ge 1 ]]; then
+ case "$1" in
+ clean )
+ clean
+ exit $?
+ ;;
+ clean_all )
+ clean
+ clean_log
+ exit $?
+ ;;
+ overwrite )
+ TOOVERWRITE="true"
+ ;;
+ * )
+ echo "Usage: $0 [overwrite | clean | clean_all]"
+ exit 1
+ ;;
+ esac
+fi
+
+errcode=0
+echo "$VGEN_EXEC $FILE_PATTERN"
+echo
+
+for t in ${MIN_TOKENS};
+do
+ for s in ${STRIDE};
+ do
+ vgen $t $s
+ retcode=$?
+ if [[ $errcode -eq 0 ]]; then
+ errcode=$retcode
+ fi
+ clean # remove .vec so not to intervene with the following vgens
+ echo
+ done
+done
+
+tohtml
+exit $errcode
+
diff --git a/scripts/clonedetect/vertical-param-batch b/scripts/clonedetect/vertical-param-batch
new file mode 100644
index 0000000..7f3a181
--- /dev/null
+++ b/scripts/clonedetect/vertical-param-batch
@@ -0,0 +1,434 @@
+#!/bin/bash
+
+#
+#
+# Copyright (c) 2007-2010,
+# Lingxiao Jiang
+# Ghassan Misherghi
+# Zhendong Su
+# Stephane Glondu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the University of California nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# To save disk space, this script does everything (clustering and
+# post-processing) for each MIN_TOKENS, each STRIDE, and each SIMILARITY at
+# once, and delete intermediate files (cluster_*, post_*, ) before starting
+# processing the next parameter combination (thus the name of the scripts).
+# Feel free to adjust the workflows in the scripts to fit your needs.
+
+TOOVERWRITE=
+coverage=`dirname $0`/cd_coverage
+GROUPING_H=100000
+
+# Delete intermediate files, but leave times/*, cluster/coverage*, cluster/post_* files there:
+clean()
+{
+ echo "Cleaning up all intermediate files..."
+ echo -n "...deleting vdb_*_*_g*_*_*, including parameter files ..."
+ find "$VECTOR_DIR" -type f -name "vdb_*_*_g[0-9]*_*_*" -print0 | xargs -0 -r --max-args=500 rm -f
+# find "$VECTOR_DIR" -type f -name "vdb_*_*_g[0-9]*_*_${GROUPING_S}" -print0 | xargs -0 -r --max-args=500 rm -f
+# also delete parameter files, coz. the number of files is too big to be handled by certain OS:
+# find "$VECTOR_DIR" -type f -name "vdb_*_*_g[0-9]*_*_${GROUPING_S}.param" -print0 | xargs -0 -r --max-args=500 rm -f
+ echo "Done"
+ echo -n "...deleting cluster_vdb_*_*_g*_*_* ..."
+ find "$CLUSTER_DIR" -type f -name "cluster_vdb_*_*_g[0-9]*_*_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ echo "Done"
+}
+
+# Delete log files and result files: if no argv, delete all files
+clean_log()
+{
+ echo "Cleaning up all results and log files..."
+ echo -n "...deleting cluster_vdb_*_*_allg_*_* ..."
+ find "$CLUSTER_DIR" -type f -name "cluster_vdb_*_*_allg_*_*" -print0 | xargs -0 -r rm -f
+ echo "Done"
+ echo -n "...deleting post_cluster_vdb_*_*_allg_*_* ..."
+ find "$CLUSTER_DIR" -type f -name "post_cluster_vdb_*_*_allg_*_*" -print0 | xargs -0 -r rm -f
+ echo "Done"
+ echo -n "...deleting ranges_*_* ..."
+ find "$VECTOR_DIR" -type f -name "ranges_*_*" -print0 | xargs -0 -r rm -f
+ echo "Done"
+ echo -n "...deleting logs..."
+ find "$TIME_DIR" -type f -name "grouping_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ find "$TIME_DIR" -type f -name "paramsetting_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ find "$TIME_DIR" -type f -name "merging_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ find "$TIME_DIR" -type f -name "cluster_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ find "$TIME_DIR" -type f -name "post_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ find "$TIME_DIR" -type f -name "coverage_*" -print0 | xargs -0 -r --max-args=500 rm -f
+ echo "Done"
+}
+
+# vector grouping: $1=, $2=, $3=
+# group file names generated by rundispatchonefile: $VECTOR_DIR/vdb_$1_$2_g_$3_${GROUPING_S}_${GROUPING_H}
+grouping()
+{
+ echo -n "$FUNCNAME: $VECTOR_DIR/vdb_$1_$2 with distance=$3..." | tee -a "$TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}"
+ # note for bash: must have the space before and after '!=' to make it work correctly; otherwise, silent errors.
+ if [[ "$TOOVERWRITE" != "true" ]]; then
+ togroup=
+ grpnumber=`find "$VECTOR_DIR" -type f -regex ".*vdb_$1_$2_g[0-9]+_$3_${GROUPING_S}.*" | wc -l`
+ if [[ $grpnumber -le 0 ]]; then
+ togroup="true"
+ else
+ while read grpf; do
+ if [[ ! -s "$grpf" || "$grpf" -ot "$VECTOR_DIR/vdb_$1_$2" ]]; then
+ togroup="true"
+ break
+ fi
+ done < <( find "$VECTOR_DIR" -regex ".*vdb_$1_$2_g[0-9]+_$3_${GROUPING_S}.*" )
+ fi
+ if [[ "$togroup" != "true" ]]; then
+ echo "Warning: $VECTOR_DIR/vdb_$1_$2 has already been grouped for distance=$3 and starting range ${GROUPING_S}. Delete $VECTOR_DIR/vdb_$1_$2_g[0-9]* manually or use '$0 overwrite'." | tee -a "$TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}"
+ echo "$FUNCNAME: $1 $2 $3 ...Skip." | tee -a "$TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}"
+ return 0
+ fi
+ fi
+
+ # delete old vector groups, in case some files may not be overwritten:
+ find "$VECTOR_DIR/" -regex ".*vdb_$1_$2_g[0-9]+_$3_${GROUPING_S}.*" -print0 | xargs -0 -r --max-args=500 rm -f
+ ( time \
+ "`dirname ${GROUPING_EXEC}`/rundispatchonefile" "$VECTOR_DIR/vdb_$1_$2" $3 -l $GROUPING_S -h $GROUPING_H -o "$VECTOR_DIR" -p "vdb_$1_$2" || (echo "Error: $FUNCNAME failure: $1 $2 $3"; exit 1) \
+ ) 1>>"$TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}" 2>&1
+ errcode=$?
+ if [[ $errcode -ne 0 ]]; then
+ echo "$FUNCNAME: Possible errors occurred. Check log: $TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}" | tee -a "$TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}"
+ else
+ echo "Done $FUNCNAME $1 $2 $3. See groups in $VECTOR_DIR/vdb_$1_$2_g[0-9]*_$3_${GROUPING_S}*" | tee -a "$TIME_DIR/grouping_$1_$2_$3_${GROUPING_S}"
+ fi
+ return $errcode
+}
+
+# set parameter files: $1=, $2=, $3=
+paramsetting()
+{
+ t=$1
+ s=$2
+ sim=$3
+ echo -n "paramsetting: $t $s $sim ..." | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+# convert SIMILARITY to DISTANCE:
+ i=`echo "$sim ${GROUPING_S}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+# create the range file if not exist:
+ if [[ "$TOOVERWRITE" = "true" || ! -s "${VECTOR_DIR}/ranges_${i}_${GROUPING_S}" ]]; then
+ "`dirname $GROUPING_EXEC`/computeranges" $i $GROUPING_S $GROUPING_H > "${VECTOR_DIR}/ranges_${i}_${GROUPING_S}"
+ fi
+ if [[ ! -s "${VECTOR_DIR}/ranges_${i}_${GROUPING_S}" ]]; then
+ echo "Error: $FUNCNAME failure: Can't generate the range file: ranges_${i}_${GROUPING_S}" | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ exit 87
+ fi
+# use the largest group file for paramter tuning:
+# "head -n 1" may break the pipe coming from "ls", causing signal 13 (no more reader, while writer's still writing), but should not matter here:
+ groupfortuning=`find $VECTOR_DIR -type f -name "vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}*" -not -name '*.param' -print0 | xargs -0 ls -S | head -n 1`
+ grptuningid=`echo ${groupfortuning} | sed "s/.*vdb_${t}_${s}_g\([0-9]*\)_${i}_${GROUPING_S}.*/\1/"`
+ grpal=0
+ grpdist=0
+# if $grptuningid is empty, error occurs...
+ if [[ $grptuningid -le 0 ]]; then
+ echo "Error: $FUNCNAME: invalid group id: $grptuningid: $t $s $sim $i" | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ exit 127
+ elif [[ $grptuningid -eq 1 ]]; then
+ grpal=`head -n $(expr $grptuningid + 1) ${VECTOR_DIR}/ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $3}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+ else
+ grpal=`head -n $(expr $grptuningid + 1) ${VECTOR_DIR}/ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $2}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*2*$2) )}'`
+ fi
+ echo -n "Looking for optimal parameters by " | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ cluster $groupfortuning $grpdist -c | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ errcode=$?
+
+ if [[ $errcode -ne 0 || ! -s "${groupfortuning}.param" ]]; then
+ echo "Error: $FUNCNAME failure...exit." | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ exit 3
+ fi
+
+ echo -n "Setting Parameters for all other groups (may take hours on cygwin but only minutes on Linux...why?)..." | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ # TODO: performance improvements to reduce file I/O; replace head/tail/awk/generateparam
+ ( time \
+ find "$VECTOR_DIR" -type f -name "vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}*" -not -name '*.param' | while read vdb;
+ do
+ echo "$FUNCNAME: ${vdb}.param"
+ grpfileid=`echo "$vdb" | sed "s/.*vdb_${t}_${s}_g\([0-9]*\)_${i}_${GROUPING_S}.*/\1/"`
+ grpal=0
+ grpdist=0
+ if [[ ${grptuningid} -eq $grpfileid ]]; then
+ continue
+ elif [[ $grpfileid -eq 1 ]]; then
+ grpal=`head -n $(expr $grpfileid + 1) $(dirname "$vdb")/ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $3}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+ else
+ grpal=`head -n $(expr $grpfileid + 1) $(dirname "$vdb")/ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $2}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*2*$2) )}'`
+ fi
+ lineno=`wc -l "$vdb" | awk '{print $1}'`
+ lineno=$(($lineno / 2))
+ "`dirname $0`/generateparam" "${groupfortuning}.param" $lineno $grpdist > "${vdb}.param"
+ done \
+ ) 1>>"${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}" 2>&1
+ errcode=$?
+
+ if [[ $errcode -ne 0 ]]; then
+ echo "$FUNCNAME: Possible errors occurred. Check log: $TIME_DIR/paramsetting_${t}_${s}_${sim}_${GROUPING_S}" | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ else
+ echo "Done $FUNCNAME $t $s $sim. Log: $TIME_DIR/paramsetting_${t}_${s}_${sim}_${GROUPING_S}" | tee -a "${TIME_DIR}/paramsetting_${t}_${s}_${sim}_${GROUPING_S}"
+ fi
+ return $errcode
+}
+
+# clustering: $1=, $2=, $3=
+cluster()
+{
+ vdb="$1"
+ dist=$2
+ vfile=`basename "$vdb"`
+ flag=$3
+
+ if [[ $3 != "-c" ]]; then
+ flag=
+ fi
+
+ echo -n "Clustering '${vdb}' ${grpdist} ..." | tee -a "$TIME_DIR/cluster_${vfile}"
+
+ if [[ "$TOOVERWRITE" != "true" &&
+ -s "$CLUSTER_DIR/cluster_${vfile}_$2" &&
+ "$CLUSTER_DIR/cluster_${vfile}_$2" -nt "$vdb" ]];
+ then
+ echo "Warning: $CLUSTER_DIR/cluster_${vfile}_$2 exists...Skip." | tee -a "$TIME_DIR/cluster_${vfile}"
+ return 0
+ fi
+
+ # dumb (not flexible) memory limit setting
+ mem=`ls -l "$vdb" | awk '{printf("%.0f", $5/1024/1024+0.5)}'`
+ if [ $mem -lt 2 ]; then
+ mem=10000000
+ elif [ $mem -lt 5 ]; then
+ mem=20000000
+ elif [ $mem -lt 10 ]; then
+ mem=30000000
+ elif [ $mem -lt 20 ]; then
+ mem=60000000
+ elif [ $mem -lt 50 ]; then
+ mem=150000000
+ elif [ $mem -lt 100 ]; then
+ mem=300000000
+ elif [ $mem -lt 200 ]; then
+ mem=600000000
+ elif [ $mem -lt 500 ]; then
+ mem=900000000
+ elif [ $mem -lt 1024 ]; then
+ mem=1900000000
+ elif [ $mem -lt 2048 ]; then
+ mem=3800000000
+ else
+ echo "Error: Size of $vdb > 2G. I don't want to do it before you think of any optimization." | tee -a "$TIME_DIR/cluster_${vfile}"
+ exit 1;
+ fi
+
+ # group vector files should have already in their names; parameter files should also exist:
+ if [[ $3 != "-c" && -s "${vdb}" &&
+ ! -s "${vdb}.param" ]]; then
+ echo "Error: Parameter File missing for '$vdb' $dist...Exit" | tee -a "$TIME_DIR/cluster_${vfile}"
+ exit 65
+ fi
+ ( time \
+ "$CLUSTER_EXEC" -R $dist -M $mem -b 2 -A -f "$vdb" ${flag} -p "${vdb}.param" \
+ > "$CLUSTER_DIR/cluster_${vfile}" \
+ ) 1>>"$TIME_DIR/cluster_${vfile}" 2>&1
+ errcode=$?
+
+ if [[ $errcode -ne 0 ]]; then
+ echo "$FUNCNAME: Possible errors occurred. Check log: $TIME_DIR/cluster_${vfile}" | tee -a "$TIME_DIR/cluster_${vfile}"
+ else
+ echo "Done clustering '${vdb}' ${grpdist}. Log: $TIME_DIR/cluster_${vfile}" | tee -a "$TIME_DIR/cluster_${vfile}"
+ fi
+ return $errcode
+}
+
+# Post-processing and count clone line #:
+pcluster()
+{
+ cdb="$1"
+ cfile=`basename "$cdb"`
+# Count clone line # before post-processing:
+# echo "Count clone lines for '$cdb' ..."
+# ( time \
+# "$coverage" "$cdb" > "${CLUSTER_DIR}/coverage_${cfile}" \
+# ) >& "${TIME_DIR}/coverage_${cfile}"
+# Post-processing:
+ echo -n "Post processing $cdb ..." | tee -a "${TIME_DIR}/post_${cfile}"
+ if [[ $(wc -l "$cdb" | awk '{print $1}') -lt 2 ]];
+ then
+ echo "Warning: clone cluster file is too small to be right: $cdb...Skip." | tee -a "${TIME_DIR}/post_${cfile}"
+ return 1
+ fi
+
+ if [[ "$TOOVERWRITE" != "true" &&
+ -s "$CLUSTER_DIR/post_${cfile}" &&
+ "$CLUSTER_DIR/post_${cfile}" -nt "$cdb" ]];
+ then
+ echo "Warning: $CLUSTER_DIR/post_${cfile} exists...Skip. May manually delete it or set 'overwrite'" | tee -a "${TIME_DIR}/post_${cfile}"
+ return 0
+ else
+ ( time \
+ "$POSTPRO_EXEC" "$cdb" > "${CLUSTER_DIR}/post_${cfile}" \
+ ) 1>>"${TIME_DIR}/post_${cfile}" 2>&1
+ errcode=$?
+ if [[ $errcode -ne 0 ]]; then
+ echo "$FUNCNAME: Possible errors occurred. Check log: $TIME_DIR/post_${cfile}" | tee -a "${TIME_DIR}/post_${cfile}"
+ else
+ echo "Done post-processing $cdb. Log: $TIME_DIR/post_${cfile}" | tee -a "${TIME_DIR}/post_${cfile}"
+ fi
+ return $errcode
+ fi
+# Count clone line # after post-processing:
+# echo "Count clone lines for $CLUSTER_DIR/post_${cfile} ..."
+# ( time \
+# "$coverage" "${CLUSTER_DIR}/post_${cfile}" > "${CLUSTER_DIR}/coverage_post_${cfile}" \
+# ) 2& "${TIME_DIR}/coverage_post_${cfile}"
+
+ return 0
+}
+
+
+. `dirname $0`/configure
+
+if [[ $# -ge 1 ]]; then
+ case "$1" in
+ clean )
+ clean
+ exit $?
+ ;;
+ clean_all )
+ clean
+ clean_log
+ exit $?
+ ;;
+ overwrite )
+ TOOVERWRITE="true"
+ ;;
+ * )
+ echo "Usage: $0 [overwrite | clean | clean_all]"
+ exit 1
+ ;;
+ esac
+fi
+
+errcode=0
+for t in ${MIN_TOKENS};
+do
+ for s in ${STRIDE};
+ do
+ for sim in $SIMILARITY;
+ do
+ echo "Vector clustering w/ MIN_TOKENS=$t, STRIDE=$s, SIMILARITY=$sim ..."
+ echo
+
+# convert SIMILARITY to DISTANCE used by LSH:
+# (1) always round up; (2) different for different code sizes; (3) require 'awk' for sqrt
+ i=`echo "$sim ${GROUPING_S}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+# Grouping:
+ grouping $t $s $i
+ errcode=$?
+ # NOTE:
+ # range file name: ranges_${i}_${GROUPING_S}
+ # group file names: vdb_${t}_${s}_g[0-9]+_${i}_${GROUPING_S}
+# Set parameter files for LSH:
+ paramsetting $t $s $sim
+ errcode=$?
+# Clustering:
+ echo "Cluster every vector groups..." | tee "$TIME_DIR/cluster_vdb_${t}_${s}_allg_${i}_${GROUPING_S}"
+ find "$VECTOR_DIR" -type f -name "vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}*" -not -name '*.param' | while read vdb;
+ do
+ grpfileid=`echo "$vdb" | sed "s/.*vdb_${t}_${s}_g\([0-9]*\)_${i}_${GROUPING_S}.*/\1/"`
+ grpal=0
+ grpdist=0
+ # TODO: what are better distance parameters for the groups?
+ if [[ $grpfileid -le 0 ]]; then
+ echo "Warning: invalid group id: $grpfileid in group $vdb...Skip." | tee -a "$TIME_DIR/cluster_vdb_${t}_${s}_allg_${i}_${GROUPING_S}"
+ continue
+ elif [[ $grpfileid -eq 1 ]]; then
+ grpal=`head -n $(expr $grpfileid + 1) $(dirname "$vdb")/ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $3}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*$2) )}'`
+ else
+ grpal=`head -n $(expr $grpfileid + 1) $(dirname "$vdb")/ranges_${i}_${GROUPING_S} | tail -n 1 | awk '{print $2}'`
+ grpdist=`echo "$sim ${grpal}" | awk '{printf( "%.7g\n", sqrt((1-$1)*2*$2) )}'`
+ fi
+ cluster "$vdb" $grpdist 1>>"$TIME_DIR/cluster_vdb_${t}_${s}_allg_${i}_${GROUPING_S}" 2>&1
+ errcode=$?
+ if [[ $errcode -ne 0 ]]; then
+ echo "Clustering: Possible errors for vector group: $vdb $grpdist. Check log: $TIME_DIR/cluster_$(basename "${vdb}")" | tee -a "$TIME_DIR/cluster_vdb_${t}_${s}_allg_${i}_${GROUPING_S}"
+ fi
+ done
+ echo "Done clustering. Check log: $TIME_DIR/cluster_vdb_${t}_${s}_allg_${i}_${GROUPING_S} and $TIME_DIR/cluster_vdb_${t}_${s}_g[0-9]+_${i}_${GROUPING_S}" | tee -a "$TIME_DIR/cluster_vdb_${t}_${s}_allg_${i}_${GROUPING_S}"
+# Merging:
+ echo -n "Merging all clone reports into $CLUSTER_DIR/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S} ..." | tee -a "$TIME_DIR/merging_${t}_${s}_${sim}_${GROUPING_S}"
+ tomerge=
+ if [[ "$TOOVERWRITE" = "true" ]]; then
+ tomerge="true"
+ elif [[ ! -s "$CLUSTER_DIR/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}" ]]; then
+ tomerge="true"
+ else
+ while read grpf; do
+ if [[ "$CLUSTER_DIR/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}" -ot "$grpf" ]]; then
+ tomerge="true"
+ break
+ fi
+ done < <( find "$CLUSTER_DIR" -type f -name "cluster_vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}*" )
+ fi
+ if [[ "$tomerge" != "true" ]]; then
+ echo "Warning: '$CLUSTER_DIR/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}' exists...Skip." | tee -a "$TIME_DIR/merging_${t}_${s}_${sim}_${GROUPING_S}"
+ else
+ # Continue to merge:
+ echo -n > "$CLUSTER_DIR/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}"
+ ( time \
+ find "$CLUSTER_DIR" -type f -name "cluster_vdb_${t}_${s}_g[0-9]*_${i}_${GROUPING_S}*" | while read grpf;
+ do
+ # remove some output lines in each file outputted by LSH/enumBuckets:
+ lineno=`wc -l $grpf | awk '{print $1;}'`
+ head -n `expr $lineno - 2` $grpf | tail -n `expr $lineno - 11` >> "$CLUSTER_DIR/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}"
+ done \
+ ) 1>>"${TIME_DIR}/merging_${t}_${s}_${sim}_${GROUPING_S}" 2>&1
+ errcode=$?
+ if [[ $errcode -ne 0 ]]; then
+ echo "Merging: Possible errors occurred. Check log: $TIME_DIR/merging_${t}_${s}_${sim}_${GROUPING_S}" | tee -a "$TIME_DIR/merging_${t}_${s}_${sim}_${GROUPING_S}"
+ else
+ echo "Done merging $CLUSTER_DIR/cluster_vdb_${t}_${s}_all_${sim}_${GROUPING_S}. Log: $TIME_DIR/merging_${t}_${s}_${sim}_${GROUPING_S}" | tee -a "$TIME_DIR/merging_${t}_${s}_${sim}_${GROUPING_S}"
+ fi
+ fi
+# Post-processing:
+ pcluster "${CLUSTER_DIR}/cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}"
+ errcode=$?
+# Clean up intermediate files:
+ clean
+# Bug Finding: done in main.sh instead.
+
+ echo
+ echo "Done clustering: ${t} ${s} $sim. See clone reports in $CLUSTER_DIR/post_cluster_vdb_${t}_${s}_allg_${sim}_${GROUPING_S}"
+ echo
+ done
+ done
+done
+
+
diff --git a/src/examples/GridLayout.java b/src/examples/GridLayout.java
new file mode 100644
index 0000000..ffdf27e
--- /dev/null
+++ b/src/examples/GridLayout.java
@@ -0,0 +1,742 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Instances of this class lay out the control children of a
+ * Composite
in a grid.
+ *
+ * GridLayout
has a number of configuration fields, and the
+ * controls it lays out can have an associated layout data object, called
+ * GridData
. The power of GridLayout
lies in the
+ * ability to configure GridData
for each control in the layout.
+ *
+ *
+ * The following code creates a shell managed by a GridLayout
+ * with 3 columns:
+ *
+ * Display display = new Display();
+ * Shell shell = new Shell(display);
+ * GridLayout gridLayout = new GridLayout();
+ * gridLayout.numColumns = 3;
+ * shell.setLayout(gridLayout);
+ *
+ * The numColumns
field is the most important field in a
+ * GridLayout
. Widgets are laid out in columns from left
+ * to right, and a new row is created when numColumns
+ 1
+ * controls are added to the Composite.
+ *
+ *
+ * @see GridData
+ */
+public final class GridLayout extends Layout {
+
+ /**
+ * numColumns specifies the number of cell columns in the layout.
+ * If numColumns has a value less than 1, the layout will not
+ * set the size and postion of any controls.
+ *
+ * The default value is 1.
+ */
+ public int numColumns = 1;
+
+ /**
+ * makeColumnsEqualWidth specifies whether all columns in the layout
+ * will be forced to have the same width.
+ *
+ * The default value is false.
+ */
+ public boolean makeColumnsEqualWidth = false;
+
+ /**
+ * marginWidth specifies the number of pixels of horizontal margin
+ * that will be placed along the left and right edges of the layout.
+ *
+ * The default value is 5.
+ */
+ public int marginWidth = 5;
+
+ /**
+ * marginHeight specifies the number of pixels of vertical margin
+ * that will be placed along the top and bottom edges of the layout.
+ *
+ * The default value is 5.
+ */
+ public int marginHeight = 5;
+
+ /**
+ * marginLeft specifies the number of pixels of horizontal margin
+ * that will be placed along the left edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginLeft = 0;
+
+ /**
+ * marginTop specifies the number of pixels of vertical margin
+ * that will be placed along the top edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginTop = 0;
+
+ /**
+ * marginRight specifies the number of pixels of horizontal margin
+ * that will be placed along the right edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginRight = 0;
+
+ /**
+ * marginBottom specifies the number of pixels of vertical margin
+ * that will be placed along the bottom edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginBottom = 0;
+
+ /**
+ * horizontalSpacing specifies the number of pixels between the right
+ * edge of one cell and the left edge of its neighbouring cell to
+ * the right.
+ *
+ * The default value is 5.
+ */
+ public int horizontalSpacing = 5;
+
+ /**
+ * verticalSpacing specifies the number of pixels between the bottom
+ * edge of one cell and the top edge of its neighbouring cell underneath.
+ *
+ * The default value is 5.
+ */
+ public int verticalSpacing = 5;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public GridLayout () {}
+
+/**
+ * Constructs a new instance of this class given the
+ * number of columns, and whether or not the columns
+ * should be forced to have the same width.
+ * If numColumns has a value less than 1, the layout will not
+ * set the size and postion of any controls.
+ *
+ * @param numColumns the number of columns in the grid
+ * @param makeColumnsEqualWidth whether or not the columns will have equal width
+ *
+ * @since 2.0
+ */
+public GridLayout (int numColumns, boolean makeColumnsEqualWidth) {
+ this.numColumns = numColumns;
+ this.makeColumnsEqualWidth = makeColumnsEqualWidth;
+}
+
+protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
+ Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache);
+ if (wHint != SWT.DEFAULT) size.x = wHint;
+ if (hHint != SWT.DEFAULT) size.y = hHint;
+ return size;
+}
+
+protected boolean flushCache (Control control) {
+ Object data = control.getLayoutData ();
+ if (data != null) ((GridData) data).flushCache ();
+ return true;
+}
+
+GridData getData (Control [][] grid, int row, int column, int rowCount, int columnCount, boolean first) {
+ Control control = grid [row] [column];
+ if (control != null) {
+ GridData data = (GridData) control.getLayoutData ();
+ int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+ int vSpan = Math.max (1, data.verticalSpan);
+ int i = first ? row + vSpan - 1 : row - vSpan + 1;
+ int j = first ? column + hSpan - 1 : column - hSpan + 1;
+ if (0 <= i && i < rowCount) {
+ if (0 <= j && j < columnCount) {
+ if (control == grid [i][j]) return data;
+ }
+ }
+ }
+ return null;
+}
+
+protected void layout (Composite composite, boolean flushCache) {
+ Rectangle rect = composite.getClientArea ();
+ layout (composite, true, rect.x, rect.y, rect.width, rect.height, flushCache);
+}
+
+Point layout (Composite composite, boolean move, int x, int y, int width, int height, boolean flushCache) {
+ if (numColumns < 1) {
+ return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
+ }
+ Control [] children = composite.getChildren ();
+ int count = 0;
+ for (int i=0; i 0) {
+ if (data.cacheWidth < data.minimumWidth) {
+ int trim = 0;
+ //TEMPORARY CODE
+ if (child instanceof Scrollable) {
+ Rectangle rect = ((Scrollable) child).computeTrim (0, 0, 0, 0);
+ trim = rect.width;
+ } else {
+ trim = child.getBorderWidth () * 2;
+ }
+ data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
+ data.computeSize (child, Math.max (0, data.minimumWidth - trim), data.heightHint, false);
+ }
+ }
+ if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
+ data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight);
+ }
+ }
+
+ /* Build the grid */
+ int row = 0, column = 0, rowCount = 0, columnCount = numColumns;
+ Control [][] grid = new Control [4] [columnCount];
+ for (int i=0; i= grid.length) {
+ Control [][] newGrid = new Control [lastRow + 4] [columnCount];
+ System.arraycopy (grid, 0, newGrid, 0, grid.length);
+ grid = newGrid;
+ }
+ if (grid [row] == null) {
+ grid [row] = new Control [columnCount];
+ }
+ while (column < columnCount && grid [row] [column] != null) {
+ column++;
+ }
+ int endCount = column + hSpan;
+ if (endCount <= columnCount) {
+ int index = column;
+ while (index < endCount && grid [row] [index] == null) {
+ index++;
+ }
+ if (index == endCount) break;
+ column = index;
+ }
+ if (column + hSpan >= columnCount) {
+ column = 0;
+ row++;
+ }
+ }
+ for (int j=0; j 1) {
+ int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (makeColumnsEqualWidth) {
+ int equalWidth = (w + spanWidth) / hSpan;
+ int remainder = (w + spanWidth) % hSpan, last = -1;
+ for (int k = 0; k < hSpan; k++) {
+ widths [last=j-k] = Math.max (equalWidth, widths [j-k]);
+ }
+ if (last > -1) widths [last] += remainder;
+ } else {
+ if (spanExpandCount == 0) {
+ widths [j] += w;
+ } else {
+ int delta = w / spanExpandCount;
+ int remainder = w % spanExpandCount, last = -1;
+ for (int k = 0; k < hSpan; k++) {
+ if (expandColumn [j-k]) {
+ widths [last=j-k] += delta;
+ }
+ }
+ if (last > -1) widths [last] += remainder;
+ }
+ }
+ }
+ if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) {
+ w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+ w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing;
+ if (w > 0) {
+ if (spanExpandCount == 0) {
+ minWidths [j] += w;
+ } else {
+ int delta = w / spanExpandCount;
+ int remainder = w % spanExpandCount, last = -1;
+ for (int k = 0; k < hSpan; k++) {
+ if (expandColumn [j-k]) {
+ minWidths [last=j-k] += delta;
+ }
+ }
+ if (last > -1) minWidths [last] += remainder;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (makeColumnsEqualWidth) {
+ int minColumnWidth = 0;
+ int columnWidth = 0;
+ for (int i=0; i 0;
+ widths [i] = columnWidth;
+ }
+ } else {
+ if (width != SWT.DEFAULT && expandCount > 0) {
+ int totalWidth = 0;
+ for (int i=0; i minWidths [j]) {
+ widths [last = j] = widths [j] + delta;
+ } else {
+ widths [j] = minWidths [j];
+ expandColumn [j] = false;
+ c--;
+ }
+ }
+ }
+ if (last > -1) widths [last] += remainder;
+
+ for (int j=0; j 1) {
+ if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) {
+ int spanWidth = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (spanExpandCount == 0) {
+ widths [j] += w;
+ } else {
+ int delta2 = w / spanExpandCount;
+ int remainder2 = w % spanExpandCount, last2 = -1;
+ for (int k = 0; k < hSpan; k++) {
+ if (expandColumn [j-k]) {
+ widths [last2=j-k] += delta2;
+ }
+ }
+ if (last2 > -1) widths [last2] += remainder2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (c == 0) break;
+ totalWidth = 0;
+ for (int i=0; i currentWidth)) {
+ int trim = 0;
+ if (child instanceof Scrollable) {
+ Rectangle rect = ((Scrollable) child).computeTrim (0, 0, 0, 0);
+ trim = rect.width;
+ } else {
+ trim = child.getBorderWidth () * 2;
+ }
+ data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
+ data.computeSize (child, Math.max (0, currentWidth - trim), data.heightHint, false);
+ if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
+ data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight);
+ }
+ if (flush == null) flush = new GridData [count];
+ flush [flushLength++] = data;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Row heights */
+ int availableHeight = height - verticalSpacing * (rowCount - 1) - (marginTop + marginHeight * 2 + marginBottom);
+ expandCount = 0;
+ int [] heights = new int [rowCount];
+ int [] minHeights = new int [rowCount];
+ boolean [] expandRow = new boolean [rowCount];
+ for (int i=0; i 1) {
+ int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (spanExpandCount == 0) {
+ heights [i] += h;
+ } else {
+ int delta = h / spanExpandCount;
+ int remainder = h % spanExpandCount, last = -1;
+ for (int k = 0; k < vSpan; k++) {
+ if (expandRow [i-k]) {
+ heights [last=i-k] += delta;
+ }
+ }
+ if (last > -1) heights [last] += remainder;
+ }
+ }
+ if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) {
+ h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+ h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing;
+ if (h > 0) {
+ if (spanExpandCount == 0) {
+ minHeights [i] += h;
+ } else {
+ int delta = h / spanExpandCount;
+ int remainder = h % spanExpandCount, last = -1;
+ for (int k = 0; k < vSpan; k++) {
+ if (expandRow [i-k]) {
+ minHeights [last=i-k] += delta;
+ }
+ }
+ if (last > -1) minHeights [last] += remainder;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (height != SWT.DEFAULT && expandCount > 0) {
+ int totalHeight = 0;
+ for (int i=0; i minHeights [i]) {
+ heights [last = i] = heights [i] + delta;
+ } else {
+ heights [i] = minHeights [i];
+ expandRow [i] = false;
+ c--;
+ }
+ }
+ }
+ if (last > -1) heights [last] += remainder;
+
+ for (int i=0; i 1) {
+ if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) {
+ int spanHeight = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (spanExpandCount == 0) {
+ heights [i] += h;
+ } else {
+ int delta2 = h / spanExpandCount;
+ int remainder2 = h % spanExpandCount, last2 = -1;
+ for (int k = 0; k < vSpan; k++) {
+ if (expandRow [i-k]) {
+ heights [last2=i-k] += delta2;
+ }
+ }
+ if (last2 > -1) heights [last2] += remainder2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (c == 0) break;
+ totalHeight = 0;
+ for (int i=0; iswim3;
+
+ out_8(&sw->select, RELAX);
+ if (sel & 8)
+ out_8(&sw->control_bis, SELECT);
+ else
+ out_8(&sw->control_bic, SELECT);
+ out_8(&sw->select, sel & CA_MASK);
+}
+
+static void swim3_action(struct floppy_state *fs, int action)
+{
+ struct swim3 __iomem *sw = fs->swim3;
+
+ swim3_select(fs, action);
+ udelay(1);
+ out_8(&sw->select, sw->select | LSTRB);
+ udelay(2);
+ out_8(&sw->select, sw->select & ~LSTRB);
+ udelay(1);
+}
+
+static int swim3_readbit(struct floppy_state *fs, int bit)
+{
+ struct swim3 __iomem *sw = fs->swim3;
+ int stat;
+
+ swim3_select(fs, bit);
+ udelay(1);
+ stat = in_8(&sw->status);
+ return (stat & DATA) == 0;
+}
+
+static void do_fd_request(request_queue_t * q)
+{
+ int i;
+ for(i=0;istate == idle && fs->wanted) {
+ fs->state = available;
+ wake_up(&fs->wait);
+ return;
+ }
+ while (fs->state == idle && (req = elv_next_request(swim3_queue))) {
+#if 0
+ printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
+ req->rq_disk->disk_name, req->cmd,
+ (long)req->sector, req->nr_sectors, req->buffer);
+ printk(" errors=%d current_nr_sectors=%ld\n",
+ req->errors, req->current_nr_sectors);
+#endif
+
+ if (req->sector < 0 || req->sector >= fs->total_secs) {
+ end_request(req, 0);
+ continue;
+ }
+ if (req->current_nr_sectors == 0) {
+ end_request(req, 1);
+ continue;
+ }
+ if (fs->ejected) {
+ end_request(req, 0);
+ continue;
+ }
+
+ if (rq_data_dir(req) == WRITE) {
+ if (fs->write_prot < 0)
+ fs->write_prot = swim3_readbit(fs, WRITE_PROT);
+ if (fs->write_prot) {
+ end_request(req, 0);
+ continue;
+ }
+ }
+
+ /* Do not remove the cast. req->sector is now a sector_t and
+ * can be 64 bits, but it will never go past 32 bits for this
+ * driver anyway, so we can safely cast it down and not have
+ * to do a 64/32 division
+ */
+ fs->req_cyl = ((long)req->sector) / fs->secpercyl;
+ x = ((long)req->sector) % fs->secpercyl;
+ fs->head = x / fs->secpertrack;
+ fs->req_sector = x % fs->secpertrack + 1;
+ fd_req = req;
+ fs->state = do_transfer;
+ fs->retries = 0;
+
+ act(fs);
+ }
+}
+
+static void set_timeout(struct floppy_state *fs, int nticks,
+ void (*proc)(unsigned long))
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fs->lock, flags);
+ if (fs->timeout_pending)
+ del_timer(&fs->timeout);
+ fs->timeout.expires = jiffies + nticks;
+ fs->timeout.function = proc;
+ fs->timeout.data = (unsigned long) fs;
+ add_timer(&fs->timeout);
+ fs->timeout_pending = 1;
+ spin_unlock_irqrestore(&fs->lock, flags);
+}
+
+static inline void scan_track(struct floppy_state *fs)
+{
+ struct swim3 __iomem *sw = fs->swim3;
+
+ swim3_select(fs, READ_DATA_0);
+ in_8(&sw->intr); /* clear SEEN_SECTOR bit */
+ in_8(&sw->error);
+ out_8(&sw->intr_enable, SEEN_SECTOR);
+ out_8(&sw->control_bis, DO_ACTION);
+ /* enable intr when track found */
+ set_timeout(fs, HZ, scan_timeout); /* enable timeout */
+}
+
+static inline void seek_track(struct floppy_state *fs, int n)
+{
+ struct swim3 __iomem *sw = fs->swim3;
+
+ if (n >= 0) {
+ swim3_action(fs, SEEK_POSITIVE);
+ sw->nseek = n;
+ } else {
+ swim3_action(fs, SEEK_NEGATIVE);
+ sw->nseek = -n;
+ }
+ fs->expect_cyl = (fs->cur_cyl >= 0)? fs->cur_cyl + n: -1;
+ swim3_select(fs, STEP);
+ in_8(&sw->error);
+ /* enable intr when seek finished */
+ out_8(&sw->intr_enable, SEEK_DONE);
+ out_8(&sw->control_bis, DO_SEEK);
+ set_timeout(fs, 3*HZ, seek_timeout); /* enable timeout */
+ fs->settle_time = 0;
+}
+
+static inline void init_dma(struct dbdma_cmd *cp, int cmd,
+ void *buf, int count)
+{
+ st_le16(&cp->req_count, count);
+ st_le16(&cp->command, cmd);
+ st_le32(&cp->phy_addr, virt_to_bus(buf));
+ cp->xfer_status = 0;
+}
+
+static inline void setup_transfer(struct floppy_state *fs)
+{
+ int n;
+ struct swim3 __iomem *sw = fs->swim3;
+ struct dbdma_cmd *cp = fs->dma_cmd;
+ struct dbdma_regs __iomem *dr = fs->dma;
+
+ if (fd_req->current_nr_sectors <= 0) {
+ printk(KERN_ERR "swim3: transfer 0 sectors?\n");
+ return;
+ }
+ if (rq_data_dir(fd_req) == WRITE)
+ n = 1;
+ else {
+ n = fs->secpertrack - fs->req_sector + 1;
+ if (n > fd_req->current_nr_sectors)
+ n = fd_req->current_nr_sectors;
+ }
+ fs->scount = n;
+ swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0);
+ out_8(&sw->sector, fs->req_sector);
+ out_8(&sw->nsect, n);
+ out_8(&sw->gap3, 0);
+ out_le32(&dr->cmdptr, virt_to_bus(cp));
+ if (rq_data_dir(fd_req) == WRITE) {
+ /* Set up 3 dma commands: write preamble, data, postamble */
+ init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble));
+ ++cp;
+ init_dma(cp, OUTPUT_MORE, fd_req->buffer, 512);
+ ++cp;
+ init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble));
+ } else {
+ init_dma(cp, INPUT_LAST, fd_req->buffer, n * 512);
+ }
+ ++cp;
+ out_le16(&cp->command, DBDMA_STOP);
+ out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
+ in_8(&sw->error);
+ out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
+ if (rq_data_dir(fd_req) == WRITE)
+ out_8(&sw->control_bis, WRITE_SECTORS);
+ in_8(&sw->intr);
+ out_le32(&dr->control, (RUN << 16) | RUN);
+ /* enable intr when transfer complete */
+ out_8(&sw->intr_enable, TRANSFER_DONE);
+ out_8(&sw->control_bis, DO_ACTION);
+ set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */
+}
+
+static void act(struct floppy_state *fs)
+{
+ for (;;) {
+ switch (fs->state) {
+ case idle:
+ return; /* XXX shouldn't get here */
+
+ case locating:
+ if (swim3_readbit(fs, TRACK_ZERO)) {
+ fs->cur_cyl = 0;
+ if (fs->req_cyl == 0)
+ fs->state = do_transfer;
+ else
+ fs->state = seeking;
+ break;
+ }
+ scan_track(fs);
+ return;
+
+ case seeking:
+ if (fs->cur_cyl < 0) {
+ fs->expect_cyl = -1;
+ fs->state = locating;
+ break;
+ }
+ if (fs->req_cyl == fs->cur_cyl) {
+ printk("whoops, seeking 0\n");
+ fs->state = do_transfer;
+ break;
+ }
+ seek_track(fs, fs->req_cyl - fs->cur_cyl);
+ return;
+
+ case settling:
+ /* check for SEEK_COMPLETE after 30ms */
+ fs->settle_time = (HZ + 32) / 33;
+ set_timeout(fs, fs->settle_time, settle_timeout);
+ return;
+
+ case do_transfer:
+ if (fs->cur_cyl != fs->req_cyl) {
+ if (fs->retries > 5) {
+ end_request(fd_req, 0);
+ fs->state = idle;
+ return;
+ }
+ fs->state = seeking;
+ break;
+ }
+ setup_transfer(fs);
+ return;
+
+ case jogging:
+ seek_track(fs, -5);
+ return;
+
+ default:
+ printk(KERN_ERR"swim3: unknown state %d\n", fs->state);
+ return;
+ }
+ }
+}
+
+static void scan_timeout(unsigned long data)
+{
+ struct floppy_state *fs = (struct floppy_state *) data;
+ struct swim3 __iomem *sw = fs->swim3;
+
+ fs->timeout_pending = 0;
+ out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
+ out_8(&sw->select, RELAX);
+ out_8(&sw->intr_enable, 0);
+ fs->cur_cyl = -1;
+ if (fs->retries > 5) {
+ end_request(fd_req, 0);
+ fs->state = idle;
+ start_request(fs);
+ } else {
+ fs->state = jogging;
+ act(fs);
+ }
+}
+
+static void seek_timeout(unsigned long data)
+{
+ struct floppy_state *fs = (struct floppy_state *) data;
+ struct swim3 __iomem *sw = fs->swim3;
+
+ fs->timeout_pending = 0;
+ out_8(&sw->control_bic, DO_SEEK);
+ out_8(&sw->select, RELAX);
+ out_8(&sw->intr_enable, 0);
+ printk(KERN_ERR "swim3: seek timeout\n");
+ end_request(fd_req, 0);
+ fs->state = idle;
+ start_request(fs);
+}
+
+static void settle_timeout(unsigned long data)
+{
+ struct floppy_state *fs = (struct floppy_state *) data;
+ struct swim3 __iomem *sw = fs->swim3;
+
+ fs->timeout_pending = 0;
+ if (swim3_readbit(fs, SEEK_COMPLETE)) {
+ out_8(&sw->select, RELAX);
+ fs->state = locating;
+ act(fs);
+ return;
+ }
+ out_8(&sw->select, RELAX);
+ if (fs->settle_time < 2*HZ) {
+ ++fs->settle_time;
+ set_timeout(fs, 1, settle_timeout);
+ return;
+ }
+ printk(KERN_ERR "swim3: seek settle timeout\n");
+ end_request(fd_req, 0);
+ fs->state = idle;
+ start_request(fs);
+}
+
+static void xfer_timeout(unsigned long data)
+{
+ struct floppy_state *fs = (struct floppy_state *) data;
+ struct swim3 __iomem *sw = fs->swim3;
+ struct dbdma_regs __iomem *dr = fs->dma;
+ struct dbdma_cmd *cp = fs->dma_cmd;
+ unsigned long s;
+ int n;
+
+ fs->timeout_pending = 0;
+ out_le32(&dr->control, RUN << 16);
+ /* We must wait a bit for dbdma to stop */
+ for (n = 0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++)
+ udelay(1);
+ out_8(&sw->intr_enable, 0);
+ out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
+ out_8(&sw->select, RELAX);
+ if (rq_data_dir(fd_req) == WRITE)
+ ++cp;
+ if (ld_le16(&cp->xfer_status) != 0)
+ s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9);
+ else
+ s = 0;
+ fd_req->sector += s;
+ fd_req->current_nr_sectors -= s;
+ printk(KERN_ERR "swim3: timeout %sing sector %ld\n",
+ (rq_data_dir(fd_req)==WRITE? "writ": "read"), (long)fd_req->sector);
+ end_request(fd_req, 0);
+ fs->state = idle;
+ start_request(fs);
+}
+
+static irqreturn_t swim3_interrupt(int irq, void *dev_id)
+{
+ struct floppy_state *fs = (struct floppy_state *) dev_id;
+ struct swim3 __iomem *sw = fs->swim3;
+ int intr, err, n;
+ int stat, resid;
+ struct dbdma_regs __iomem *dr;
+ struct dbdma_cmd *cp;
+
+ intr = in_8(&sw->intr);
+ err = (intr & ERROR_INTR)? in_8(&sw->error): 0;
+ if ((intr & ERROR_INTR) && fs->state != do_transfer)
+ printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n",
+ fs->state, rq_data_dir(fd_req), intr, err);
+ switch (fs->state) {
+ case locating:
+ if (intr & SEEN_SECTOR) {
+ out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
+ out_8(&sw->select, RELAX);
+ out_8(&sw->intr_enable, 0);
+ del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
+ if (sw->ctrack == 0xff) {
+ printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
+ fs->cur_cyl = -1;
+ if (fs->retries > 5) {
+ end_request(fd_req, 0);
+ fs->state = idle;
+ start_request(fs);
+ } else {
+ fs->state = jogging;
+ act(fs);
+ }
+ break;
+ }
+ fs->cur_cyl = sw->ctrack;
+ fs->cur_sector = sw->csect;
+ if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl)
+ printk(KERN_ERR "swim3: expected cyl %d, got %d\n",
+ fs->expect_cyl, fs->cur_cyl);
+ fs->state = do_transfer;
+ act(fs);
+ }
+ break;
+ case seeking:
+ case jogging:
+ if (sw->nseek == 0) {
+ out_8(&sw->control_bic, DO_SEEK);
+ out_8(&sw->select, RELAX);
+ out_8(&sw->intr_enable, 0);
+ del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
+ if (fs->state == seeking)
+ ++fs->retries;
+ fs->state = settling;
+ act(fs);
+ }
+ break;
+ case settling:
+ out_8(&sw->intr_enable, 0);
+ del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
+ act(fs);
+ break;
+ case do_transfer:
+ if ((intr & (ERROR_INTR | TRANSFER_DONE)) == 0)
+ break;
+ out_8(&sw->intr_enable, 0);
+ out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
+ out_8(&sw->select, RELAX);
+ del_timer(&fs->timeout);
+ fs->timeout_pending = 0;
+ dr = fs->dma;
+ cp = fs->dma_cmd;
+ if (rq_data_dir(fd_req) == WRITE)
+ ++cp;
+ /*
+ * Check that the main data transfer has finished.
+ * On writing, the swim3 sometimes doesn't use
+ * up all the bytes of the postamble, so we can still
+ * see DMA active here. That doesn't matter as long
+ * as all the sector data has been transferred.
+ */
+ if ((intr & ERROR_INTR) == 0 && cp->xfer_status == 0) {
+ /* wait a little while for DMA to complete */
+ for (n = 0; n < 100; ++n) {
+ if (cp->xfer_status != 0)
+ break;
+ udelay(1);
+ barrier();
+ }
+ }
+ /* turn off DMA */
+ out_le32(&dr->control, (RUN | PAUSE) << 16);
+ stat = ld_le16(&cp->xfer_status);
+ resid = ld_le16(&cp->res_count);
+ if (intr & ERROR_INTR) {
+ n = fs->scount - 1 - resid / 512;
+ if (n > 0) {
+ fd_req->sector += n;
+ fd_req->current_nr_sectors -= n;
+ fd_req->buffer += n * 512;
+ fs->req_sector += n;
+ }
+ if (fs->retries < 5) {
+ ++fs->retries;
+ act(fs);
+ } else {
+ printk("swim3: error %sing block %ld (err=%x)\n",
+ rq_data_dir(fd_req) == WRITE? "writ": "read",
+ (long)fd_req->sector, err);
+ end_request(fd_req, 0);
+ fs->state = idle;
+ }
+ } else {
+ if ((stat & ACTIVE) == 0 || resid != 0) {
+ /* musta been an error */
+ printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
+ printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n",
+ fs->state, rq_data_dir(fd_req), intr, err);
+ end_request(fd_req, 0);
+ fs->state = idle;
+ start_request(fs);
+ break;
+ }
+ fd_req->sector += fs->scount;
+ fd_req->current_nr_sectors -= fs->scount;
+ fd_req->buffer += fs->scount * 512;
+ if (fd_req->current_nr_sectors <= 0) {
+ end_request(fd_req, 1);
+ fs->state = idle;
+ } else {
+ fs->req_sector += fs->scount;
+ if (fs->req_sector > fs->secpertrack) {
+ fs->req_sector -= fs->secpertrack;
+ if (++fs->head > 1) {
+ fs->head = 0;
+ ++fs->req_cyl;
+ }
+ }
+ act(fs);
+ }
+ }
+ if (fs->state == idle)
+ start_request(fs);
+ break;
+ default:
+ printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state);
+ }
+ return IRQ_HANDLED;
+}
+
+/*
+static void fd_dma_interrupt(int irq, void *dev_id)
+{
+}
+*/
+
+static int grab_drive(struct floppy_state *fs, enum swim_state state,
+ int interruptible)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fs->lock, flags);
+ if (fs->state != idle) {
+ ++fs->wanted;
+ while (fs->state != available) {
+ if (interruptible && signal_pending(current)) {
+ --fs->wanted;
+ spin_unlock_irqrestore(&fs->lock, flags);
+ return -EINTR;
+ }
+ interruptible_sleep_on(&fs->wait);
+ }
+ --fs->wanted;
+ }
+ fs->state = state;
+ spin_unlock_irqrestore(&fs->lock, flags);
+ return 0;
+}
+
+static void release_drive(struct floppy_state *fs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fs->lock, flags);
+ fs->state = idle;
+ start_request(fs);
+ spin_unlock_irqrestore(&fs->lock, flags);
+}
+
+static int fd_eject(struct floppy_state *fs)
+{
+ int err, n;
+
+ err = grab_drive(fs, ejecting, 1);
+ if (err)
+ return err;
+ swim3_action(fs, EJECT);
+ for (n = 20; n > 0; --n) {
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ swim3_select(fs, RELAX);
+ schedule_timeout_interruptible(1);
+ if (swim3_readbit(fs, DISK_IN) == 0)
+ break;
+ }
+ swim3_select(fs, RELAX);
+ udelay(150);
+ fs->ejected = 1;
+ release_drive(fs);
+ return err;
+}
+
+static struct floppy_struct floppy_type =
+ { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
+
+static int floppy_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long param)
+{
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ int err;
+
+ if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+#ifdef CONFIG_PMAC_MEDIABAY
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+#endif
+
+ switch (cmd) {
+ case FDEJECT:
+ if (fs->ref_count != 1)
+ return -EBUSY;
+ err = fd_eject(fs);
+ return err;
+ case FDGETPRM:
+ if (copy_to_user((void __user *) param, &floppy_type,
+ sizeof(struct floppy_struct)))
+ return -EFAULT;
+ return 0;
+ }
+ return -ENOTTY;
+}
+
+static int floppy_open(struct inode *inode, struct file *filp)
+{
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ struct swim3 __iomem *sw = fs->swim3;
+ int n, err = 0;
+
+ if (fs->ref_count == 0) {
+#ifdef CONFIG_PMAC_MEDIABAY
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+#endif
+ out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2);
+ out_8(&sw->control_bic, 0xff);
+ out_8(&sw->mode, 0x95);
+ udelay(10);
+ out_8(&sw->intr_enable, 0);
+ out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
+ swim3_action(fs, MOTOR_ON);
+ fs->write_prot = -1;
+ fs->cur_cyl = -1;
+ for (n = 0; n < 2 * HZ; ++n) {
+ if (n >= HZ/30 && swim3_readbit(fs, SEEK_COMPLETE))
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ swim3_select(fs, RELAX);
+ schedule_timeout_interruptible(1);
+ }
+ if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
+ || swim3_readbit(fs, DISK_IN) == 0))
+ err = -ENXIO;
+ swim3_action(fs, SETMFM);
+ swim3_select(fs, RELAX);
+
+ } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
+ return -EBUSY;
+
+ if (err == 0 && (filp->f_flags & O_NDELAY) == 0
+ && (filp->f_mode & 3)) {
+ check_disk_change(inode->i_bdev);
+ if (fs->ejected)
+ err = -ENXIO;
+ }
+
+ if (err == 0 && (filp->f_mode & 2)) {
+ if (fs->write_prot < 0)
+ fs->write_prot = swim3_readbit(fs, WRITE_PROT);
+ if (fs->write_prot)
+ err = -EROFS;
+ }
+
+ if (err) {
+ if (fs->ref_count == 0) {
+ swim3_action(fs, MOTOR_OFF);
+ out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE);
+ swim3_select(fs, RELAX);
+ }
+ return err;
+ }
+
+ if (filp->f_flags & O_EXCL)
+ fs->ref_count = -1;
+ else
+ ++fs->ref_count;
+
+ return 0;
+}
+
+static int floppy_release(struct inode *inode, struct file *filp)
+{
+ struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
+ struct swim3 __iomem *sw = fs->swim3;
+ if (fs->ref_count > 0 && --fs->ref_count == 0) {
+ swim3_action(fs, MOTOR_OFF);
+ out_8(&sw->control_bic, 0xff);
+ swim3_select(fs, RELAX);
+ }
+ return 0;
+}
+
+static int floppy_check_change(struct gendisk *disk)
+{
+ struct floppy_state *fs = disk->private_data;
+ return fs->ejected;
+}
+
+static int floppy_revalidate(struct gendisk *disk)
+{
+ struct floppy_state *fs = disk->private_data;
+ struct swim3 __iomem *sw;
+ int ret, n;
+
+#ifdef CONFIG_PMAC_MEDIABAY
+ if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
+ return -ENXIO;
+#endif
+
+ sw = fs->swim3;
+ grab_drive(fs, revalidating, 0);
+ out_8(&sw->intr_enable, 0);
+ out_8(&sw->control_bis, DRIVE_ENABLE);
+ swim3_action(fs, MOTOR_ON); /* necessary? */
+ fs->write_prot = -1;
+ fs->cur_cyl = -1;
+ mdelay(1);
+ for (n = HZ; n > 0; --n) {
+ if (swim3_readbit(fs, SEEK_COMPLETE))
+ break;
+ if (signal_pending(current))
+ break;
+ swim3_select(fs, RELAX);
+ schedule_timeout_interruptible(1);
+ }
+ ret = swim3_readbit(fs, SEEK_COMPLETE) == 0
+ || swim3_readbit(fs, DISK_IN) == 0;
+ if (ret)
+ swim3_action(fs, MOTOR_OFF);
+ else {
+ fs->ejected = 0;
+ swim3_action(fs, SETMFM);
+ }
+ swim3_select(fs, RELAX);
+
+ release_drive(fs);
+ return ret;
+}
+
+static struct block_device_operations floppy_fops = {
+ .open = floppy_open,
+ .release = floppy_release,
+ .ioctl = floppy_ioctl,
+ .media_changed = floppy_check_change,
+ .revalidate_disk= floppy_revalidate,
+};
+
+static int swim3_add_device(struct macio_dev *mdev, int index)
+{
+ struct device_node *swim = mdev->ofdev.node;
+ struct device_node *mediabay;
+ struct floppy_state *fs = &floppy_states[index];
+ int rc = -EBUSY;
+
+ /* Check & Request resources */
+ if (macio_resource_count(mdev) < 2) {
+ printk(KERN_WARNING "ifd%d: no address for %s\n",
+ index, swim->full_name);
+ return -ENXIO;
+ }
+ if (macio_irq_count(mdev) < 2) {
+ printk(KERN_WARNING "fd%d: no intrs for device %s\n",
+ index, swim->full_name);
+ }
+ if (macio_request_resource(mdev, 0, "swim3 (mmio)")) {
+ printk(KERN_ERR "fd%d: can't request mmio resource for %s\n",
+ index, swim->full_name);
+ return -EBUSY;
+ }
+ if (macio_request_resource(mdev, 1, "swim3 (dma)")) {
+ printk(KERN_ERR "fd%d: can't request dma resource for %s\n",
+ index, swim->full_name);
+ macio_release_resource(mdev, 0);
+ return -EBUSY;
+ }
+ dev_set_drvdata(&mdev->ofdev.dev, fs);
+
+ mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ?
+ swim->parent : NULL;
+ if (mediabay == NULL)
+ pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1);
+
+ memset(fs, 0, sizeof(*fs));
+ spin_lock_init(&fs->lock);
+ fs->state = idle;
+ fs->swim3 = (struct swim3 __iomem *)
+ ioremap(macio_resource_start(mdev, 0), 0x200);
+ if (fs->swim3 == NULL) {
+ printk("fd%d: couldn't map registers for %s\n",
+ index, swim->full_name);
+ rc = -ENOMEM;
+ goto out_release;
+ }
+ fs->dma = (struct dbdma_regs __iomem *)
+ ioremap(macio_resource_start(mdev, 1), 0x200);
+ if (fs->dma == NULL) {
+ printk("fd%d: couldn't map DMA for %s\n",
+ index, swim->full_name);
+ iounmap(fs->swim3);
+ rc = -ENOMEM;
+ goto out_release;
+ }
+ fs->swim3_intr = macio_irq(mdev, 0);
+ fs->dma_intr = macio_irq(mdev, 1);;
+ fs->cur_cyl = -1;
+ fs->cur_sector = -1;
+ fs->secpercyl = 36;
+ fs->secpertrack = 18;
+ fs->total_secs = 2880;
+ fs->media_bay = mediabay;
+ init_waitqueue_head(&fs->wait);
+
+ fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
+ memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
+ st_le16(&fs->dma_cmd[1].command, DBDMA_STOP);
+
+ if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) {
+ printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n",
+ index, fs->swim3_intr, swim->full_name);
+ pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0);
+ goto out_unmap;
+ return -EBUSY;
+ }
+/*
+ if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) {
+ printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA",
+ fs->dma_intr);
+ return -EBUSY;
+ }
+*/
+
+ init_timer(&fs->timeout);
+
+ printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
+ mediabay ? "in media bay" : "");
+
+ return 0;
+
+ out_unmap:
+ iounmap(fs->dma);
+ iounmap(fs->swim3);
+
+ out_release:
+ macio_release_resource(mdev, 0);
+ macio_release_resource(mdev, 1);
+
+ return rc;
+}
+
+static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match)
+{
+ int i, rc;
+ struct gendisk *disk;
+
+ /* Add the drive */
+ rc = swim3_add_device(mdev, floppy_count);
+ if (rc)
+ return rc;
+
+ /* Now create the queue if not there yet */
+ if (swim3_queue == NULL) {
+ /* If we failed, there isn't much we can do as the driver is still
+ * too dumb to remove the device, just bail out
+ */
+ if (register_blkdev(FLOPPY_MAJOR, "fd"))
+ return 0;
+ swim3_queue = blk_init_queue(do_fd_request, &swim3_lock);
+ if (swim3_queue == NULL) {
+ unregister_blkdev(FLOPPY_MAJOR, "fd");
+ return 0;
+ }
+ }
+
+ /* Now register that disk. Same comment about failure handling */
+ i = floppy_count++;
+ disk = disks[i] = alloc_disk(1);
+ if (disk == NULL)
+ return 0;
+
+ disk->major = FLOPPY_MAJOR;
+ disk->first_minor = i;
+ disk->fops = &floppy_fops;
+ disk->private_data = &floppy_states[i];
+ disk->queue = swim3_queue;
+ disk->flags |= GENHD_FL_REMOVABLE;
+ sprintf(disk->disk_name, "fd%d", i);
+ set_capacity(disk, 2880);
+ add_disk(disk);
+
+ return 0;
+}
+
+static struct of_device_id swim3_match[] =
+{
+ {
+ .name = "swim3",
+ },
+ {
+ .compatible = "ohare-swim3"
+ },
+ {
+ .compatible = "swim3"
+ },
+};
+
+static struct macio_driver swim3_driver =
+{
+ .name = "swim3",
+ .match_table = swim3_match,
+ .probe = swim3_attach,
+#if 0
+ .suspend = swim3_suspend,
+ .resume = swim3_resume,
+#endif
+};
+
+
+int swim3_init(void)
+{
+ macio_register_driver(&swim3_driver);
+ return 0;
+}
+
+module_init(swim3_init)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);
diff --git a/src/include/ptree.h b/src/include/ptree.h
new file mode 100755
index 0000000..3fdf70f
--- /dev/null
+++ b/src/include/ptree.h
@@ -0,0 +1,295 @@
+/*
+ *
+ * Copyright (c) 2007-2010,
+ * Lingxiao Jiang
+ * Ghassan Misherghi
+ * Zhendong Su
+ * Stephane Glondu
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _PARSE_TREE_H_
+#define _PARSE_TREE_H_
+
+#include