2017 24th Asia-Pacific Software Engineering Conference

CCFinderSW: Clone Detection Tool
with Flexible Multilingual Tokenization
Yuichi Semura∗ , Norihiro Yoshida† , Eunjong Choi‡ and Katsuro Inoue∗∗ Osaka University, Japan{y-semura, inoue}@ist.osaka-u.ac.jp† Nagoya University, Japan
yoshida@ertl.jp‡ Nara Institute of Science and Technology, Japanchoi@is.naist.jp
found that CCFinderSW can remove comments from about
92% of program languages. Moreover, it was conﬁrmed that
CCFinderSW is able to detect code clones from all program
languages.

Abstract—So far, many tools have been developed for thedetection of code clones in source code. The existing clone
detection tools support only a limited number of programming
languages and do not provide any easy extension mechanism tohandle additional language. However, from our experience in industry/university collaboration, we found that many practitioners
need to analyze source code written in various languages. In thispaper, we propose a clone detection tool CCFinderSW that has
extension mechanism to handle addition language on demand
from practitioners.

II. OVERVIEW OF CCF INDER X
To introduce the mechanism of a token-based clone detection tool, we brieﬂy explain CCFinderX. It identiﬁes not
only Type-1 clones (i.e. identical code fragments except forvariations in whitespace, layout and comments) but also Type2 clones (i.e. syntactically identical fragments except forvariations in identiﬁers, literals, types, whitespace, layout andcomments.) by replacing identiﬁers related to types, variables,
and constants with a special token.
The code clone detection process of CCFinderX is comprised of the following four steps:
Step1: (Lexical analysis) Input source code is divided into
tokens according to a lexical rule of the programming
language. At this step, the white spaces (includingcomments) between tokens are removed from thesource code.
Step2: (Transformation) The token sequence is transformed
based on the transformation rules and then eachidentiﬁer related to types, variables, and constants
is replaced with a special token. This replacement
makes code fragments with different variable names
to become clone pairs.
Step3: (Detection) From all the substrings on the transformed token sequence, equivalent pairs are detected
as clone pairs using sufﬁx-tree matching algorithm.
Step4: (Formatting) Each location of clone pair is converted
into line numbers on the original source ﬁles.

I. I NTRODUCTION
Programmers often copy and paste code so that they canreuse existing code fragments. This causes code clones, codefragments that are identical or similar code fragments toeach other. Generally, a code clone is regarded as one of
the factors that hinder software maintainability. For instance,
when a cloned code fragment contains a bug, a programmer
should check all of its cloned fragments for the same bug. If
the cloned fragments contain the same bugs, they should be
modiﬁed for the same bug. To that end, he/she should know
locations of all code clones in the source code. However, it
is difﬁcult to for developers to recognize all code clone fromlarge-scale software systems. To alleviate this problem, a multitude of code clone detection tools have been developed. For
example, Kamiya has developed a token-based code detection
tool CCFinderX [2] that is widely used in academic research
as well as industries.
The existing clone detection tools support only a limited
number of programming languages and do not provide any
easy extension mechanism to handle additional language.
From our experience in industry/university collaboration, we
found that many practitioners need to analyze source code
written in various languages.
In this paper, we propose a clone detection tool CCFinderSW that has extension mechanism to handle addition language on demand from practitioners. It enables the user toeasily change the lexical mechanism for comment eliminationand identiﬁer replacement.
In the experiment, we compared source code before andafter comments elimination of multiple program languages
to conﬁrm the ﬂexibility and changeable of lexical analysis mechanism in the CCFinderSW. As a result, it was
978-1-5386-3681-7/17 $31.00 © 2017 IEEE
DOI 10.1109/APSEC.2017.80

III. A C LONE D ETECTION T OOL WITH F LEXIBLEM ULTILINGUAL T OKENIZATIONThis section presents an overview of CCFinderSW, a
new code clone detection tool using a ﬂexible tokenization
mechanism for multilingual program languages.
Figure 1 depicts a clone detection process of CCFinderSW.
As you can see in Figure 1, CCFinderSW adopts the same654

NN®ÞŘ_sǋǢɟǢŸȖǋOs®ÞĶsǣNŸŎŎsŘǼrĶÞŎÞŘǼÞŸŘǻŸĨsŘÞʊǼÞŸŘĵsɮÞOĶŘĶɴǣÞǣNŸŎŎsŘǼǊȖĶsǣ

Ý_sŘǼÞ¯Þsǋ^ÞǣǼÞŘOǼÞŸŘ

Ǌsǣsǋɚs_ɟŸǋ_ǣ

Example of end of line comment

v=v+i; //commentb) Multi-line comment: Multi-line comment comments
out the source code from a start symbol to an end symbol. The
following code fragment illustrates an example of the multiline comment in C and Java programs, wheter a start symbol
is /*, and an end symbol is */ .

Example of multi-line commentsǻŸĨsŘǢsǇȖsŘOs
ǻǋŘǣ¯ŸǋŎǼÞŸŘǻǋŘǣ¯ŸǋŎs_ǻŸĨsŘǢsǇȖsŘOs

v=v+i; /*comment
printf(”Hello world”); comment */printf(”Hello world”); /*comment*/
In several languages, multi-line comments are nested inside
other multi-line comments. The nesting of comment is todescribe more multi-line comment in the multi-line comment.
The following code fragment describes an example of thenested multi-line comment by other multi-line comments.

Example of nested multi-line comments

NŸ_sNĶŸŘs^sǼsOǼÞŸŘ
NĶŸŘsǣŸŘǻǋŘǣ¯ŸǋŎs_ǢsǇȖsŘOs
®ŸǋŎǼǼÞŘ¶NĶŸŘs˚ƻÞǋǣˀNĶŸŘs˚NĶǣǣsǣ
Fig. 1. An Overview of CCFinderSW

1 /*
2 /*
3 comment
4 */5 comment
6 */If nesting is not permitted, the above example can be interpreted as (1) the comment starts with a /* symbol in the 1stline and continues until a */ symbol on the 4th line or (2) thecomment starts with a /* symbol in the 1st line and continues
until a */ symbol on the 6th line and in both cases, a /* inthe second line is ignored. Meanwhile, if nesting is permitted,
the above example can be interpreted as a multi-line comment
starts with the symbol on the 2nd line and ends at the 4th line,
and other comment starts with the symbol on the 1st line andends on the 6th line. It can be seen from this example that
there are big differences in interpreting languages depends onwhether nesting is permitted.
c) Full line comment: Full line comment begins witha start symbol and comments out full lines of code. The
following code fragment describes an example of the full line
comment in Fortran program, where the start symbol is C or
* Note that different from the end of line comment, the startsymbol does not be interpreted as an indicator for the full line
comment, if it appears in the middle of the line.

Example of full line comment

four clone detection process, same as the CCFinderX. Furthermore, it also identiﬁes Type-1 and Type-2 code clones.
CCFinderSW provides options for changing target comments for the elimination and reserved words. The option
for the comment elimination is used in the lexical analysis
process. The option for the reserved words is adopted forﬁnding identiﬁers.
The reminding subsection details the process of CCFinderSW. The details of the lexical analysis and transformation
process of the CCFinderSW are described in Sections III-A
and III-B, respectively. In particular, Section III-A explainscomment elimination and tokenization mechanisms in orderto handle multiple program languages. Next, Section III-C
describes the code clone detection process and, ﬁnally, Section
III-D describes transforming process.
A. Step 1: Lexical analysis
Lexical Analysis process is comprised of three steps namely
comment elimination, tokenization, and identiﬁer distinction.
Comments in a programming language are used to annotate/explain the source code. Therefore, during the comment
elimination step, they are ignored by default.
In this study, we categorize comments into ﬁve comments
styles based on their appearance in the source code in different
program languages. Hereafter, the details of ﬁve comment
styles are described with the examples. Note that the red fontin each example represents a comment that is ignored during
the lexical analysis.
a) End of line comment: End of line comment starts witha symbol (e.g., // in C and Java program) and continues until
the end of the line. The following code fragment demonstrates
an example of the end of line comment in C and Java
programs:c
This is a comment*
This is a commentd) Full multi-line comment: We deﬁned a comment rulethat regards lines from the line where the start symbol exists
ﬁrst to the line where the end symbol exists ﬁrst as a comment.
We named it overall multi-line comment. In Ruby source
codes, lines from =begin to lines starting with =end are655

TABLE I

if(b==c) value=i ;SYNTAX INFORMATION FOR EACH COMMENT STYLE

Comment Style
End of line comment
Multi-line coment
Full line comment
Full multi-line Comment
Character and string literals

Start symbol






End symbol

Nesting








if

(

b

=

=

c

)

value

if

(

$

=

=

$

)

$

=

i

;

= $ ;

Fig. 2. Tokenization and Transformation

the identiﬁers representing variable names and function names
are replaced by the same token. Reserved words are strings
that are reserved by the programming language and cannot
be used for variable and function names. For instance, in Java=begin comment
program, words used for controlling the ﬂow of programs suchputs ”Comment 1” comment
as if and while are reserved words.
puts ”Comment 2” comment
Figure 2 depicts an example of the tokenization of sour
=end commentcode.
In this ﬁgure, green square represents alphabetic strings,
puts ”Hello world”
andbluesquare represents converted variables. As you can see
in this ﬁgure, a variable name is converted to the same tokene) Character and String literals: A character literal andcalled $.
string literal is a type of literal in programming for the
regarded as comments.
Overall multi-line comment

representation of a value single character and string object
C. Step 3: Code Clone Detection
within the source code, respectively. For instance, in Java
Generally, when a clone detection tool identiﬁes code clones
program, characters enclosed in single quotes are identiﬁed asfromlarge-scale software systems, it takes a huge amount ofa character literal, and characters enclosed in double quotes
time or crashed due to lack of memory space [5]. To tackle
are identiﬁed as a string literal. These literal are not concisely
this problem, CCFinderSW adopts n-gram for detecting clone
comment styles, they are necessary to distinguish literals fromdetection with high speed. N-gram is a contiguous sequencecomments. For instance, Therefore, if a character used as aof n words from a given sequence of string or words. It issymbol in the comment style appears in the string literal, it
frequently used to investigate the occurrence frequency ofis not recognized as the start or end point of the comment.
contiguous strings in the statistical ﬁeld of natural linguistics
The following code fragment shows an example of a characteror searching matching string.
literal and string literal in Java program. In this example, theHereafter, the details of the process of code clone detection
characters enclosed in double quotes is the start symbol of aareexplained. At ﬁrst, CCFinderSW extracts n-gram from amulti-line comment, but they are not regarded as an indicator
sequenceof transformed tokens, based on a threshold value
for the multi-line comment.
set by the user. This threshold value represents that textsfCExample of Character and String literals
CFinderSW only detects code clones that are more than nString x = ” Line Comment start = /* ”;
token length.
String y = ” Line Comment end = */ ”;
Suppose that user set up 4 as a threshold value when
executing CCFinderSW and a sequence of transformed tokens
Table I summarizes syntax information of each commentis sethesetheses.
style based on above-mentioned deﬁnitions of comment styles.
Based on this threshold value, CCFinderSW then creates
In this table, necessary information is marked with .
a list of tuples (index, n-gram, hash value), where (1) index
After the comments are eliminated from source code basedis an integer denoting the position of n-gram in the sequenceon the deﬁned comment styles, each line of source code is(2) n-gram is a sequence contiguous of tokens with n token
divided into tokens based on a lexical rule. The following
length based on a value deﬁned by user and (3) hash value
four lexical rules are used for the tokenization. Note that a
is a hash code for the n-gram.
rule with a low number has a higher priority.
The reason for using hash code is that comparison of
1) Each character literal or string literal corresponds to one
numerical values is faster than comparison of strings. To
token, respectively.
calculate hash code, a hashcode() method in a class String2) White spaces and line breaks are delimiters.
was used.
3) Each symbol is one token.
Table III illustrates a created list from sethesetheses with
4) Other consecutive alphabetic or numeric strings are
the 4 threshold value 1 .
identiﬁed as one token.
Next, it selects a unique hash value and its corresponding
index
from the list and then creates a unique list, which
B. Step 2: Transformation
In the transformation process, the token sequence is transformed in order to detect meaningful code clones. In detail, all

1 For the simplicity, this paper explains with character-based n-grams. Notethat token-based n-grams are used in CCFinderSW.

656

or more characters.
Since the threshold is 4, 4-gram is extracted from sethesetheses. Next, 4-grams are listed. The elements of 4-gramlist include appearance, string, and hash value. The index of
appearance is set such that the ﬁrst 4-gram is 0, the next 4gram is 1, and so on. The hash value is a hash of the string.
This hashing is aimed at speeding up based on the fact thatcomparison of numerical values is faster than comparison ofstrings. In this way, a list of elements with a appearance, astring and a hash value is called list in order of appearance.
Table III gives an example of a list in order of appearance.
However, the hash value shown in the ﬁgure is different
from that implemented in CCFinderSW. Hashing in CCFinderSW is implemented using the hashcode method provided
in class String. Also, in this explanation, it is assumed thatcollision of hash values does not occur. In other words, when
the hash values are equal, the original character string isassumed to be equivalent.
From the set of hash value of this list in order of appearance,
all unique hash values are selected. And CCFinderSW selects
all appearance corresponding to each of the selected hashvalues. The correspondence of the appearance from the hashvalue is not only one-to-one, but it may be one-to-many. A
list of elements with a set of hash values and a appearance iscalled a unique list. Table IV gives an example of a uniquelist.
Next, we searches for code clones. {0, 5} of the ﬁrst line of
the created unique list is a set of appearances corresponding
to the hash value (1234). When referring to the list in orderof appearance for each element of this set, the same hashvalue appeared in those occurrence spots. In other words,
values hashed from 4-grams appearing at appearance 0 and
5 are equivalent, so 4-grams are considered to be equivalent.
Therefore, it is considered that the 4 characters from 0 to
3 and 4 characters from the 5th to the 8th in the original
string are equivalent, and are code clone. Also, the set {1, 6}
of appearance corresponding to the hash value (2342) andthe set {2, 7} of appearance corresponding to the hash value(3421) are also the same as in the previous example, so
sethesetheses has a set of clone sets. Hence, a code clone
whose number of tokens is equal to the threshold value isdetected.
Next, an algorithm for searching a code clone whose numberof tokens is larger than the threshold value will be described.
CCFinderSW checks the hash value of the next appearance
for each element of the already detected clone set. For example, the tool adds 1 to each of the elements of clone set {0, 5}
to be {1, 6}, and look at the hash values corresponding to 1
and 6 in the list in order of appearance, so both match (2342).
Since 0th 4-gram and 5th 4-gram match, and 1st 4-gram and6th 4-gram match, strings starting at 0 and strings starting at
5 are code clones of 5-character. Thus the 4-character clone
set {0, 5} is rewritten to a 5-character clone set {0, 5}. In thisway, a new clone set is searched by looking at the hash valuesof the next clone set in order of appearance. If this algorithm
is performed on all the hash values of the unique list, the code

TABLE IIA N E XAMPLE OF 4- GRAMS
order
0
1
2
3
4
5
6
7

4-gram
if($=
($==
$==$
==$)
=$)$
$)$+
)$=$
$=$;

contains unique hash value and its index. Table IV illustrates
a unique list created from the Table III. As can be seen in thetable, the hash value in the unique list contains more than two
index values, because a hash value might appear more than
twice.
Finally, code clones are identiﬁed based on the unique list.
For that end, ﬁrstly, code clones whose token length is equal
to the n threshold value are detected by using hash value andindex value in the unique list. That is, the hash value withmultiple index values implies that the same code appears in
the multiple places, which indicates the existences of code
clones. For example, in the ﬁrst row of the list in the table
IV, the index values of a (1234) hash value are {0, 5}. Thismeans that the same hash value appearing in both 0th and 5th
positions. This means that 4-grams appearing from 0th and5th positions are equivalent. Therefore, 4 characters appearing
from 0th to 3rd and 4 characters from the 5th to the 8th inthe original string are detected as code clones. Furthermore,(2342) and (3421) hash value has 1, 6 and 2, 7 index value,
respectively. This indicates that the code clones exist at 1th
and 6th position and 2nd and 7th position.
Secondly, code clones with a maximum number of tokens
are detected by checking the hash value of the next index
for each element that is already detected clone clones. For
example, code clones, whose hash value is (1234), appearing
at the 0th and 5th position, as can be seen in the ﬁrst row of
the list in the table IV. To identify code clones with maximum
number of tokens, CCFinderSW checks whether code clones
also exist in the next position (1th and 6th) of detected codes.
From table IV, you can see that the same hash value namely(2342) exist. ,Since 4-gram starting at 0th and 5th positions are code
clones and 4-gram starting from 1st and 6th positions are code
clones, strings starting from 0th and 5th positions are detected
as code clones with 5 tokens.
In this way, a new clone clones are identifying by determining hash values of the next index. This process is terminatedby checking all hash values in the unique list.
As a result, Table II is a list of 4-grams.
For the simplicity, character-based N-grams are extracted,
but token-based N-grams are used in the actual algorithm.
We deﬁne the target source code as sethesetheses. The
threshold value of the number of tokens of the code clone isset to 4, and the detection target is a coincidence portion of 4657

TABLE III
A N E XAMPLE OF A L IST IN O RDER OF A PPEARANCE{Appearance}
{0}
{1}
{2}
{3}
{4}
{5}
{6}
{7}
{8}
{9}

[String][seth][ethe][thes][hese][eset][seth][ethe][thes][hese][eses]by lexical analysis but can not be removed by the
proposed method as impossible to remove.
2) We create 26 kinds of options. This option makes it
possible to cover more language comment rules.
In order to make it easier for users to set comment rules,
we created a mechanism that allows comment rules tobe set simply by giving an alphabet string. By limiting
26 types, we hope that it is easier to write comment
rules as arguments when running the tool. For example,
when executing the tool by giving argument adf on thecommand line, comment elimination is performed using
the comment rule set to a, d, and f.
Each option is shown in the Table V, a list of options
for code elimination. The option of z concerns whether
nesting of multi-line comments is allowed or not, so it
is not included in the table. Numbers in the column ofthe category indicate the classiﬁcation of comments, 1
is a line comment, 2 is a multi-line comment, 3 is a fullline comment, 4 is a full multi-line comment, and 5 isa literal rule. The details of the results of applying theoption to each language are described in the literature3 .
Using this option, we performed comment elimination to
the 175 languages that implement Comments. For languages
in which we could not be performed comment elimination, it
was described as impossible in the option column. From thisexperiment, 166 languages out of 175 languages are possibleby the proposed method, and 151 languages showed that it
is possible to remove comments with 26 options. The reason
why the proposed method can not cope with a language is thatcomments of a language can not be removed unless parsing
and that a language had a difﬁcult grammar. Then, the reason
that 26 kinds of options can not support is that a comment
rule is unique and there are too many comment rules.
Table VI is the number of languages used for each option
in 166 languages.

(Hash value)(1234)(2342)(3421)(4212)(2123)(1234)(2342)(3421)(4212)(2121)TABLE IVA N E XAMPLE OF A U NIQUE L IST(Hash value)(1234)(2342)(3421)(4212)(2123)(2121){Appearance}
{0,5}
{1,6}
{2,7}
{3,8}
{4}
{9}

clone detection is over.
D. Step 4: Formatting
In this process, the output ﬁle is gereated by converting
each location of detected code clones into line numbers on
the original source ﬁles. For output ﬁle of CCFinderSW, twokinds of formats are available; One is the same output format
as the CCFinder and others are the same output form as the
CCFinderX.
IV. E VALUATION
We investigated the accuracy of CCFinderSW in terms ofcomment elimination.. We use Rosetta Code, a webpage thatprovides source code implemented in different programming
languages for solving the same task2 . Due to its abundantresources, Rosetta Code has been effectively used to compare
languagesf concise, performance, and failure-proneness. In theevaluation, we extracted source code snapshot of November
18, 2015 from the RosettaCode Git repository3 .
We select a task named Comments2 , which contains programs with comments implemented in multiple program languages, in Rosetta Code. We then apply CCFinderSW toprograms contained at Comments task. The details of theexperiment are as follows.
We manually check programs in the Comments task andthen choose 78 tasks as our studied subjects, because they are
all implemented in the object-oriented manner.
1) We list the comment rules of each language that can bedeleted by the proposed method used in Comments.
Among them, we regarded comments that were possible

V. R ELATED W ORK
So far, various tools have been developed for the detectionof code clones in source code [6], [7], [2]. Most of thetools (e.g., CCFinderX [2]) support only a limited numberof programming languages. Since NiCaD [8] detects code
clones based on a TXL [9] grammar for each languages, it
is able to support new programing language by writing a
TXL grammar for the language. However, according to ourexperience in industry/university collaboration, it is difﬁcult
for most practitoners to write a programming language grammar and the parser for it correctly. Therefore, we developed
CCFinderSW that is able to support a new programming
language by specifying only a few options.
VI. C ONCLUSION AND FUTURE WORKIn this paper, we introduced CCFinderSW, a tool that
detects token-based codes clones for multiple program languages. Regarding token splitting, we did not set options with-

2 http://rosettacode.org/wiki/Rosetta Code3 https://github.com/acmeism/RosettaCode. Data
2 http://rosettacode.org/wiki/Comments

3 https://sites.google.com/site/yoshidaatnu/tableforAPSEC.pdf

658

TABLE V
26 O PTIONS ( EXCLUDE Z )

Opt.
a
b
c

d
e
f
g
h
i
j
k
l
m
n

Cat.
5
5
1
2
2
2
1
1
1
1
1
1
1
1
1
2
2
2
2

Start
’
”
//
/*
/+
<!–
;
#
–
%
!
#!
’
‘
NB.
{
[
(
”

End
”
”
none
*/
+/
–>
none
none
none
none
none
none
none
none
none
}
]
)
”

Opt.
o
p

q
r
s
t

Cat.
2
2
2
2
2
2
2
2
2
2
2
2
1
1
2
1
1
2

Start
(*
(:
(#
#|
#=
#{
###
#cs
#˜
{|
{%{
->
–##
–[[
COMMENTIGNORELINE’COMMENT’

End
*)
:)
#)
|#
=#
}#
###
#ce
˜#
|}
-}
%}
none
none
]]
none
none
;

Opt.
u

Cat.
1
1
1
3
3
3
3
3
3
2
1
1
1
4
4
4
3
3
3
3

v

w

x
y

Start
c

*>
*|
NOTE
*
*
C
c
:
%REM
REM
rem
Rem
==comment=begin
=pod
#;
NIL
###
end.

End
none
none
none
none
none
none
none
none
none
%END REM
none
none
none
=cut
=end
=cut
none
none
none
none

u
2

x
2

TABLE VI
T HE N UMBERS OF L ANGUAGES FOR E ACH O PTIONS
a
1

b
3

c
55

d
25

e
40

f
14

g
10

h
7

i
11

j
1

k
3

l
2

m
1

n
2

o
14

p
8

q
1

r
1

s
2

t
2

v
4

w
9

y
1

z
17

out literals. As a future work, we plan to prepare additional
option for token splitting.

[4] T. Kamiya, “the archive of CCFinder Ofﬁcial Site,” 2005. [Online].
Available: http://www.ccﬁnder.net/

ACKNOWLEDGMENT[5] S. Livieri, D. M. German, and K. Inoue, “A needle in the stack: efﬁcient
clone detection for huge collections of source code,” Osaka University,
Tech. Rep., 2010.

This work was supported by JSPS KAKENHI Grant Numbers JP25220003, JP15H06344 and JP16K16034.

[6] I. D. Baxter, A. Yahin, L. Moura, M. S. Anna, and L. Bier, “Clone
detection using abstract syntax trees,” in Proc. of ICSM 1998, 1998, pp.
368–377.

R EFERENCES[1] S. Nanz and C. A. Furia, “A comparative study of programming languages
in rosetta code,” in Proceedings of the 37th International Conference on
Software Engineering, 2015, pp. 778–788.
[2] T. Kamiya, S. Kusumoto, and K. Inoue, “CCFinder: a multilinguistic
token-based code clone detection system for large scale source code,”IEEE Transactions on Software Engineering, vol. 28, no. 7, pp. 654–670,
2002.
[3] A. Tosun, E. Shihab, and Y. Kamei, “On code reuse from stackoverﬂow:
An exploratory study on android apps,” Information and Software Technology, vol. 88, pp. 148 – 158, 2017.

[7] L. Jiang, G. Misherghi, Z. Su, and S. Glondu, “Deckard: Scalable andaccurate tree-based detection of code clones,” in Proc. of ICSE 2007,
2007, pp. 96–105.
[8] C. K. Roy and J. R. Cordy, “Nicad: Accurate detection of near-missintentional clones using ﬂexible pretty-printing and code normalization,”in Proc. of ICPC 2008, 2008, pp. 172–181.
[9] J. R. Cordy, “The TXL source transformation language,” Science ofComputer Programming, vol. 61, no. 3, pp. 190 – 210, 2006.

659