VA Linux Systems and SourceForge are trademarks of VA Linux Systems, Inc.
Linux is a registered trademark of Linus Torvalds. All other trademarks and
copyrights on this page are property of their respective owners.
For information about other site Content ownership and sitewide
terms of service, please see the
SourceForge.net Terms of Service.
For privacy
policy information, please see the SourceForge.net Privacy Policy.
Content owned by VA Linux Systems is copyright
1999, 2000, 2001 VA Linux Systems, Inc. All rights reserved.
cccc-3.1.4/bug_reports/prn11.html 0000644 0000000 0000000 00000067345 07401205477 015317 0 ustar root root
SourceForge: Modify: 233585 - Does not handle namespace declarations
VA Linux Systems and SourceForge are trademarks of VA Linux Systems, Inc.
Linux is a registered trademark of Linus Torvalds. All other trademarks and
copyrights on this page are property of their respective owners.
For information about other site Content ownership and sitewide
terms of service, please see the
SourceForge.net Terms of Service.
For privacy
policy information, please see the SourceForge.net Privacy Policy.
Content owned by VA Linux Systems is copyright
1999, 2000, 2001 VA Linux Systems, Inc. All rights reserved.
cccc-3.1.4/bug_reports/prn12.html 0000644 0000000 0000000 00000070051 07401205477 015304 0 ustar root root
SourceForge: Modify: 233587 - Does not handle negative numbers in member initializers
VA Linux Systems and SourceForge are trademarks of VA Linux Systems, Inc.
Linux is a registered trademark of Linus Torvalds. All other trademarks and
copyrights on this page are property of their respective owners.
For information about other site Content ownership and sitewide
terms of service, please see the
SourceForge.net Terms of Service.
For privacy
policy information, please see the SourceForge.net Privacy Policy.
Content owned by VA Linux Systems is copyright
1999, 2000, 2001 VA Linux Systems, Inc. All rights reserved.
cccc-3.1.4/bug_reports/prn8.html 0000644 0000000 0000000 00000070042 07401205477 015231 0 ustar root root
VA Linux Systems and SourceForge are trademarks of VA Linux Systems, Inc.
Linux is a registered trademark of Linus Torvalds. All other trademarks and
copyrights on this page are property of their respective owners.
For information about other site Content ownership and sitewide
terms of service, please see the
SourceForge.net Terms of Service.
For privacy
policy information, please see the SourceForge.net Privacy Policy.
Content owned by VA Linux Systems is copyright
1999, 2000, 2001 VA Linux Systems, Inc. All rights reserved.
cccc-3.1.4/bug_reports/prn9.html 0000644 0000000 0000000 00000073252 07401205477 015240 0 ustar root root
SourceForge: Modify: 233548 - Doesn't accept "public virtual" base classes
CCCC is a tool for the analysis of source code in various
languages (primarily C++), which generates a report in HTML format on
various measurements of the code processed. Although the tool was
originally implemented to process C++ and ANSI C, the present version
is also able to process Java source files, and support has been
present in earlier versions for Ada95. The name CCCC stands for 'C
and C++ Code Counter'.
Measurements of source code of this kind are generally referred to
as 'software metrics', or more precisely 'software product metrics'
(as the term 'software metrics` also covers measurements of the
software process, which are called 'software process metrics'). There
is a reasonable consensus among modern opinion leaders in the
software engineering field that measurement of some kind is probably
a Good Thing, although there is less consensus on what is worth
measuring and what the measurements mean.
CCCC has been developed as freeware, and is released in source
code form. Users are encouraged to compile the program themselves,
and to modify the source to reflect their preferences and interests.
The simplest way of using CCCC is just to run it with the names of
a selection of files on the command line like this:
cccc my_types.h big.h small.h *.cc
Alternatively, the for a complex hierarchy, the user could enter a
command like this:
find . | cccc - (on Unix family platforms)
or
dir /b/s | cccc - (on DOS/Windows family platforms)
CCCC will process each of the files specified on the command line
(using standard wildcard processing were appropriate), or, if the '-'
option is specified in the standard input stream. For each file,
named, CCCC will examine the extension of the filename, and if the
extension is recognized as indicating a supported language, the
appropriate parser will run on the file. As each file is parsed,
recognition of certain constructs will cause records to be written
into an internal database. When all files have been processed, a
report on the contents of the internal database will be generated in
HTML format. By default the main summary HTML report is generated to
the file cccc.htm in a subdirectory called .cccc of the the current
working directory, with detailed reports on each module (i.e. C++ or
Java class) identified by the analysis run.
In addition to the summary and detailed HTML reports, the run will
cause generation of corresponding summary and detailed reports in XML
format, and a further file called cccc.db to be created. cccc.db will
contain a dump of the internal database of the program in a format
delimited with the character '@' (chosen because it is one of the few
characters which cannot legally appear in C/C++ non-comment source
code).
The report contains a number of tables identifying the modules in
the files submitted and covering:
measures of the procedural volume
and complexity of each module and its functions;
measures of the number and type of
the relationships each module is a party to either as a client or a
supplier;
identification of any parts of the
source code submitted which the program failed to parse; and
a summary report over the whole body of code processed of the
measures identified above.
Some of the data presented in the report may be displayed in an
emphasized form (either with a bold or italic font, or with a red or
yellow background). These are items which have been identified as
lying outside ranges which have been laid down as desirable for the
particular items. A bold font or red background indicates a value
which exceeds a threshold defined as being dangerous for that
measure, while italic fonts and yellow backgrounds indicate values
below the danger threshold but still above a second lower threshold
which has been laid down to indicate cause for concern. The two
thresholds are configurable by the user of the tool: see the section
below on configuring metric treatment
for more details.
Report Contents
The report generated by CCCC normally consists of six tables plus
a table of contents at the beginning and some informational material
about CCCC itself at the end.
Tables generated
Table name
Description
Project Summary
This table presents summary values of various measures over the
body of source code submitted.
Procedural Summary
This table presents values of procedural measures summed for
each module identified in the code submitted.
Procedural Details
This table presents values of the same procedural measures
covered in the procedural summary report, but this time broken
down within each module into the contributions of each member
function of the module.
Structural Summary
This table presents counts of fan-in and fan-out relationships
to each module identified, and a derived metric called the
Henry/Kafura/Shepperd measure, which is calculated as the square
of the product of the fan-in and fan-out counts.
Structural Details
This table presents lists of the modules contributing to the
relationship counts reported in the structural summary.
Rejected Extents
This table presents a list of code regions which the analyser
was unable to parse.
Metrics displayed
Tag
Metric Name
Description
LOC
Lines of Code
This metric counts the lines of non-blank, non-comment source
code in a function (LOCf), module (LOCm), or project (LOCp). LOC
was one of the earliest metrics to come into use (principally
because it is straightforward to measure).
It has an obvious relation to the size or complexity of a piece
of code, and
can be calibrated for use in prediction of maintenance effort,
although concern has been expressed that use of this metric as a
measure of programmer productivity may tend to encourage verbose
programming practises and discourage desirable simplification.
MVG
McCabe's Cyclomatic Complexity
A measure of a body of code based on analysis of the cyclomatic
complexity of the directed acyclic graph which represents the flow
of control within each function. First proposed as a measure of
the minimum number of test cases to ensure all parts of each
function are exercised, it is now widely accepted as a measure for
the detection of code which is likely to be error-prone and/or
difficult to maintain.
COM
Comment Lines
A crude measure comparable to LOC of the extent of commenting
within a region of code. Not very meaningful in isolation, but
sometimes used in ratio with LOC or MVG to ensure that comments
are distributed proportionately to the bulk or complexity of a
region of code.
L_C,M_C
LOC/COM, MVG/COM
See above
FO,FOc,FOv FI,FIc,FIc
Fan-out, Fan-in
For a given module A, the fan-out is the number of other
modules which the module A uses, while the fan-in is the number of
other modules which use A. See the section below on counting
methods for a discussion of the distinction between the variants
on each of these measures. these figures.
HKS, HKSv, HKSc
Henry-Kafura/Shepperd measure
This metric is derived by squaring the product of the fan-in
and fan-out of each module. The original Henry-Kafura measure,
which has been described as a measure of 'information flow
complexity' includes a term for the length of the module under
consideration, but CCCC uses the measure as modified by Shepperd,
which omits this term on the basis that it debases the measure by
combining two attributes which can and should be separately
measured. Corresponding to the variants on the fan-in and
fan-out measures described above, similar variants are calculated
on this metric.
NOM
Number of modules
Number of modules identified in the project. See discussion
below about what constitutes a module.
WMC
Weighted methods per class
This measure, proposed by Chidamber and Kemerer, is a count of
the number of functions defined in a module multiplied by a
weighting factor. The only weighting algorithm suggested in the
original formulation is a uniform weighting of one unit per
function.
REJ
Rejected lines
This is a measure of the number of non-blank non-comment lines
of code which was not successfully analysed by the parser. This is
more of a validity check on the report generated than a metric of
the code submitted: if the amount of code rejected was more than a
small fraction (say 10%) of the total code processed, the
meaningfulness of the numbers generated by the run must be in
doubt.
Counting methods
CCCC implements simple algorithms to calculate each of the
measures presented. The algorithms are intended to present a useful
approximation to the underlying quantities, rather than meticulously
exact counting: in general agreement with manual counts based on the
same definitions should agree with CCCC to within 2-3%. If larger
discrepancies are discovered, or if this level of agreement is not
considered adequate, users are welcome to modify the source code to
implement closer agreement, or to change the counting behaviour to
reflect a desired basis of calculation. The basic definitions of each
count are as follows:
Number of Modules (NOM) CCCC
defines modules in terms of a grouping of member functions: C++
classes and namespaces, Java classes and interfaces and Ada packages
are all defined as modules. In addition to this, functions which are
not members of one of these structures are treated as belonging to
an anonymous module, which is counted if it has member functions.
Lines of Code (LOC) This count
follows the industry standard of counting non-blank, non-comment
lines of source code. Preprocessor lines are treated as blank. Class
and function declarations are counted, but declarations of global
data are ignored. There may be some double counting of lines in
class definitions as the algorithm treats the total over a module as
the sum of lines belonging to the module itself and lines belonging
to its member functions (the declarations and definitions of member
functions in the body of the class definition will contribute to
both counts).
Comment Lines (COM) Any line
which contains any part of a comment for the language concerned is
treated as a comment by CCCC, and is allocated to the module and
member of the next following 'real' token. This ensures that leading
comments are treated as part of the function or class definition
which follows them. There is one exception to this rule: the
Rational Rose design tool is known to insert directives into source
files disguised as C++ comments with the prefix '//##'. These are
not counted as comments, however all other comment structures are,
even if there is no content within the comment delimiters, or the
content is commented-out source code.
McCabe's Cyclomatic Complexity(MVG) The formal definition
of cyclomatic complexity is that it is the count of linearly
independent paths through a flow of control graph derived from a
subprogram. A pragmatic approximation to this can be found by
counting language keywords and operators which introduce extra
decision outcomes. This can be shown to be quite accurate in most
cases. In the case of C++, the count is incremented for each of the
following tokens: 'if','while','for','switch','break','&&','||'
Note that the boolean operations introduce extra paths through
the code because the second operand may or may not be evaluated
according to the value of the first operand. Note also that the
treatment of switch statements is problematic: it is quite common
for multiple 'case' labels to be attached to the same block of
code, so counting these might overstate the value. Counting the
'break' tokens instead is better so long as their are no case
labels in the middle of the block of code which the break
terminates. The motive for counting the 'switch' token is to
provide for the default case, which gives rise to a path whether or
not the programmer defines a default label. Counting the break
token in this way may distort the count where it is used in other
contexts (i.e. to exit from a block).
Weighted methods per class
(WMC) This is a count of the member functions known to exist in a
class. Knowledge of existence of a function is only gained from
declarations or definitions directly contained in files processed by
CCCC: files included by a preprocessor are ignored, and CCCC does
not at present identify invocations of member or non-member
functions within procedural code.
Fan-In, Fan-Out (FI,FIc,FIv,FO,FOc,FOv) Traditionally, use
relationships between modules were identified by counting function
invocations or access to module data in procedural code. CCCC
identifies relationships only through structures apparent in the
definitions of the interfaces of C++ classes or Java classes or
interfaces. The specific relationships which can be detected are
inheritance of a supplier class by a client, containment of an
instance of a supplier class in a client, and the existence of
member functions of the client class which accept or return an
instance of the supplier.
While these relationships may seem unrelated to the invocation
and module data counts, they are likely to show a strong corelation
because of the fact that in an object oriented environment, it is
likely (but not inevitable) that the low-level use relationships of
invocation and direct access to data structures require an object
of the class of the supplier module to be available. This
availability can be through instantiation of an instance of the
supplier class within procedural code, but will often be due to the
existence of one of the higher level relationships described above.
The counts of Fan-In and Fan-Out are regarded as a measure of
the structural quality of a program, with high values of either
(and particularly high values of both within the same module)
indicating increased risk of changes required in one module
requiring changes across other modules. CCCC chooses to define the
relationship counts in such a way that each supplier or client
module is counted only once, however many separate ways the
relationship is detected. CCCC applies filtering to the
relationships identified to distinguish between different kinds of
uses which may carry with them different levels of structural risk.
There are two filters: visibility and concreteness.
The visibility filter removes from consideration relationships
which are known to be only accessible from the private interface of
a module. Relationships which are defined in the visible part of
the interface can be exploited by clients of the current module,
thus forcing those clients also to be clients of the current
module's supplier. Visible relationships also increase the range of
operations available on an object, thus increasing the cognitive
complexity of the interface from the point of view of a programmer
required to use a module.
The concreteness filter removes from consideration relationships
which do not create a dependency of the implementation of the
client module on the implementation of the supplier class.
Dependency-creating relationships increase risk because they may
not be cyclical, and thus inhibit the creation of other
relationships. They also inhibit the ability of modules to be built
separately, requiring recompilation of the client module when the
supplier changes. The test for this filter in C++ is whether a
forward declaration of the supplier class is adequate to allow the
client module definition to be compiled: containment and parameter
passing where the client module is modified by a referential
operator are allowed in this case, containment or passing by value
or inheritance are all dependency-creating. In Java, relationships
except inheritance are treated as non-dependency creating.
Number of Modules (NOM) All instances of the following
syntactic constructs are treated as modules: C++ classes and
namespaces; Java classes and interfaces, Ada packages. There are
contexts where the analyser detects something which may belong to
one of these categories but may not. In this case, the name is
treated as a module name if and only if member functions are
identified for it. Functions which do not belong to a module of one
of the categories defined above are treated as belonging to a single
anonymous module: if any members are identified for this module it
is also counted.
Command-line syntax
The command line flags supported by CCCC are defined in the file
ccccmain.cc. A brief usage message can be generated on standard
output by entering the command 'cccc --help'. The same message will
be generated on standard error if an invalid command line is entered.
As of version 3.pre57 the text generated by this command is as
follows:
Usage:
cccc [options] file1.c ...
Process files listed on command line.
If the filenames include '-', read a list of files from standard input.
This program is work in progress and is not well documented.
Please be prepared to refer to the source code for the
meaning of some options.
Options:
--help * generate this help message
--outdir=<dname> * directory for generated files
(default=.cccc)
--html_outfile=<fname> * name of primary HTML report generated
(default=<outdir>/cccc.html)
--xml_outfile=<fname> * name of primary XML report generated
(default=<outdir>/cccc.xml)
--db_infile=<fname> * preload internal database from named file
(default=no initial content)
--db_outfile=<fname> * save internal database to named file
(default=<outdir>/cccc.db)
--opt_infile=<fname> * load options from named file
(default=use compiled-in option values,
refer to cccc_opt.cc for option information)
--opt_outfile=<fname> * save options to named file
(default=<outdir>/cccc.opt)
--lang=<string> * use language specified for files specified
after this option
languages supported are c,c++,ada,java
(default=use language/extension mapping
controlled by options)
--report_mask=<hex> * control report content
(refer to ccccmain.cc for mask values)
--debug_mask=<hex> * control debug output content
(refer to ccccmain.cc for mask values)
Configuration
Much of the behaviour of CCCC can be controlled by a stream of
configuration data. The file cccc_opt.cc contains the default value
for this stream, which can be dumped using the --opt_outfile
qualifier. The resulting file can then be edited to customize
behaviour and loaded into a later run of cccc using the --opt_infile
qualifier. As of version 3.pre57, the contents of the file dumped by
the command cccc --opt_outfile=cccc.opt are as follows:
CCCC_FileExt@.ADA@ada.95@
CCCC_FileExt@.ADB@ada.95@
CCCC_FileExt@.ADS@ada.95@
CCCC_FileExt@.C@c++.ansi@
CCCC_FileExt@.CC@c++.ansi@
CCCC_FileExt@.CPP@c++.ansi@
CCCC_FileExt@.CXX@c++.ansi@
CCCC_FileExt@.H@c++.ansi@
CCCC_FileExt@.H++@c++.ansi@
CCCC_FileExt@.HH@c++.ansi@
CCCC_FileExt@.HPP@c++.ansi@
CCCC_FileExt@.HXX@c++.ansi@
CCCC_FileExt@.J@java@
CCCC_FileExt@.JAV@java@
CCCC_FileExt@.JAVA@java@
CCCC_FileExt@.ada@ada.95@
CCCC_FileExt@.adb@ada.95@
CCCC_FileExt@.ads@ada.95@
CCCC_FileExt@.c@c.ansi@
CCCC_FileExt@.c++@c++.ansi@
CCCC_FileExt@.cc@c++.ansi@
CCCC_FileExt@.cpp@c++.ansi@
CCCC_FileExt@.cxx@c++.ansi@
CCCC_FileExt@.h@c++.ansi@
CCCC_FileExt@.h++@c++.ansi@
CCCC_FileExt@.hh@c++.ansi@
CCCC_FileExt@.hpp@c++.ansi@
CCCC_FileExt@.hxx@c++.ansi@
CCCC_FileExt@.j@java@
CCCC_FileExt@.jav@java@
CCCC_FileExt@.java@java@
CCCC_MetTmnt@8.3@999999.000000@999999.000000@0@8@3@General format for fixed precision 3 d.p.@
CCCC_MetTmnt@CBO@12.000000@30.000000@0@6@0@Coupling between objects@
CCCC_MetTmnt@COM@999999.000000@999999.000000@0@6@0@Comment lines@
CCCC_MetTmnt@COMper@999999.000000@999999.000000@0@6@3@Comment lines (averaged)@
CCCC_MetTmnt@DIT@3.000000@6.000000@0@6@0@Depth of Inheritance Tree@
CCCC_MetTmnt@FI@12.000000@20.000000@0@6@0@Fan in (overall)@
CCCC_MetTmnt@FIc@6.000000@12.000000@0@6@0@Fan in (concrete uses only)@
CCCC_MetTmnt@FIv@6.000000@12.000000@0@6@0@Fan in (visible uses only)@
CCCC_MetTmnt@FO@12.000000@20.000000@0@6@0@Fan out (overall)@
CCCC_MetTmnt@FOc@6.000000@12.000000@0@6@0@Fan out (concrete uses only)@
CCCC_MetTmnt@FOv@6.000000@12.000000@0@6@0@Fan out (visible uses only)@
CCCC_MetTmnt@IF4@100.000000@1000.000000@0@6@0@Henry-Kafura/Shepperd measure (overall)@
CCCC_MetTmnt@IF4c@30.000000@100.000000@0@6@0@Henry-Kafura/Shepperd measure (concrete)@
CCCC_MetTmnt@IF4v@30.000000@100.000000@0@6@0@Henry-Kafura/Shepperd measure (visible)@
CCCC_MetTmnt@LOCf@30.000000@100.000000@0@6@0@Lines of code/function@
CCCC_MetTmnt@LOCm@500.000000@2000.000000@0@6@0@Lines of code/single module@
CCCC_MetTmnt@LOCp@999999.000000@999999.000000@0@6@0@Lines of code/project@
CCCC_MetTmnt@LOCper@500.000000@2000.000000@0@6@3@Lines of code/average module@
CCCC_MetTmnt@L_C@7.000000@30.000000@20@6@3@LOC/COM Lines of code/comment line@
CCCC_MetTmnt@MVGf@10.000000@30.000000@0@6@0@Cyclomatic complexity/function@
CCCC_MetTmnt@MVGm@200.000000@1000.000000@0@6@0@Cyclomatic complexity/single module@
CCCC_MetTmnt@MVGp@999999.000000@999999.000000@0@6@0@Cyclomatic complexity/project@
CCCC_MetTmnt@MVGper@200.000000@1000.000000@0@6@3@Cyclomatic complexity/average module@
CCCC_MetTmnt@M_C@5.000000@10.000000@5@6@3@MVG/COM McCabe/comment line@
CCCC_MetTmnt@NOC@4.000000@15.000000@0@6@0@Number of children@
CCCC_MetTmnt@WMC1@30.000000@100.000000@0@6@0@Weighting function=1 unit per method@
CCCC_MetTmnt@WMCv@10.000000@30.000000@0@6@0@Weighting function=1 unit per visible method@
CCCC_Dialect@c++.mfc@BEGIN_MESSAGE_MAP@start_skipping@
CCCC_Dialect@c++.mfc@END_MESSAGE_MAP@stop_skipping@
CCCC_Dialect@c++.stl@__STL_BEGIN_NAMESPACE@ignore@
CCCC_Dialect@c++.stl@__STL_END_NAMESPACE@ignore@
Configuration of the extension/language
mapping
Records in the configuration stream of type CCCC_FileExt control
the mapping of file extensions to languages.
Treatment of metric values
Records in the configuration stream of type CCCC_MetTmnt control
the treatment of values for each of the metrics defined by CCCC.
Ignoring compiler-specific keywords
Records in the configuration stream of type CCCC_Dialect control
the handling of dialect-specific pseudo keywords by the CCCC parsers.
Disclaimers
CCCC was produced as an artifact of an academic research project.
The primary motivation was to provide a platform for the exploration
of issues related to metrics. The program is not now, and will never
become, a commercial standard supported product. While CCCC attempts
to recover from parse failures, there are some language constructs
which cause crashes, and others which result in code going
unanalyzed. If CCCC does not report syntax errors and terminates
normally, it is likely that all files have been analyzed, otherwise
it is strongly recommended that the user does some kind of
independent check on the quantity of code ignored, rather than
relying on CCCC's own report on 'Rejected Extents'.
There is one further important disclaimer. As noted above, the
primary motivation for the development of CCCC was to aid an academic
project to investigate the use of metrics. Over the five years or so
the project was running various research activities were conducted,
culminating in a practical experiment into the value of metric
analysis data in a simulated software engineering task. The aim of
this final experiment was to attempt to demonstrate a benefit from
the use of such data, its conclusion was that, at best, the presence
of a benefit was "not proven". The research project,
including the design and outcomes of the final experiment is
described at http://www.fchs.ecu.edu.au/~tlittlef, which includes a
link to download a PDF of the final PhD thesis arising from the
project.
The CCCC project is now dormant. There are no plans for new
releases, either to add new features to the program or to fix
existing defects. The current version of the program is released
under the GNU Public License, giving users the right to work on the
source code to address any specific issues they have. The project is
hosted on sourceforge.net, the primary developer, Tim Littlefair, can
be contacted by email and will be happy to provide advice and
encouragement. Contact details appear on the sourceforge website.
CCCC downloads are accessible via the standard SourceForge project
hierarchy starting at http://sourceforge.net/projects/cccc.
SourceForge also hosts mailing lists where new versions are announced
and a bug tracker database for the project.
The CCCC distribution includes a version of the Purdue Compiler
Construction Toolset (PCCTS) originally created by Terence Parr and
coworkers at Purdue University, later maintained by Tom Moog. Many
thanks to Terence, his colleagues and Tom for developing this
excellent tool, and for releasing it under terms which make it
possible for it to be included in the CCCC distribution.
The Win32 installer package for CCCC is created using
version 2.0.18 of the "My Inno Setup Extensions"
package by Jordan Russell, based on "Inno Setup"
by Martjin Laan. This package can be downloaded from
http://www.wintax.nl/isx
The program will also require a C++ compiler to build. Past
versions have been buildable with various versions of the GNU C++
compiler and/or Microsoft Visual C++, although the code is intended
to be portable to a range of modern C++ compilers (with a bit of work
in some cases, as the original code base dates back to times before
the ANSI standardisation of the C++ language). The reference build
tools for the current version are GCC version 3.3 and the freely
distributed Microsoft Visual C++ Toolkit 2003.
See
http://msdn.microsoft.com/visualc/vctoolkit2003/ for details.
cccc-3.1.4/cccc/COPYING 0000644 0000000 0000000 00000043105 10357232456 013050 0 ustar root root GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
cccc-3.1.4/cccc/Cccc.dsp 0000644 0000000 0000000 00000011576 07272040214 013356 0 ustar root root # Microsoft Developer Studio Project File - Name="cccc" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) External Target" 0x0106
CFG=cccc - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Cccc.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Cccc.mak" CFG="cccc - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "cccc - Win32 Release" (based on "Win32 (x86) External Target")
!MESSAGE "cccc - Win32 Debug" (based on "Win32 (x86) External Target")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
!IF "$(CFG)" == "cccc - Win32 Release"
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Cmd_Line "NMAKE /f cccc.mak"
# PROP BASE Rebuild_Opt "/a"
# PROP BASE Target_File "cccc.exe"
# PROP BASE Bsc_Name "cccc.bsc"
# PROP BASE Target_Dir ""
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Cmd_Line "nmake -f w32vc.mak DEBUG=false"
# PROP Rebuild_Opt ""
# PROP Target_File "\ccccprod\bin\cccc.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""
!ELSEIF "$(CFG)" == "cccc - Win32 Debug"
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Cmd_Line "NMAKE /f cccc.mak"
# PROP BASE Rebuild_Opt "/a"
# PROP BASE Target_File "cccc.exe"
# PROP BASE Bsc_Name "cccc.bsc"
# PROP BASE Target_Dir ""
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Cmd_Line "nmake -f w32vc.mak DEBUG=true"
# PROP Rebuild_Opt "clean all"
# PROP Target_File "cccc.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""
!ENDIF
# Begin Target
# Name "cccc - Win32 Release"
# Name "cccc - Win32 Debug"
!IF "$(CFG)" == "cccc - Win32 Release"
!ELSEIF "$(CFG)" == "cccc - Win32 Debug"
!ENDIF
# Begin Group "PCCTS grammars"
# PROP Default_Filter "g"
# Begin Source File
SOURCE=.\ada.g
# End Source File
# Begin Source File
SOURCE=.\cccc.g
# End Source File
# Begin Source File
SOURCE=.\java.g
# End Source File
# End Group
# Begin Group "C++ header files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\cccc.h
# End Source File
# Begin Source File
SOURCE=.\cccc_db.h
# End Source File
# Begin Source File
SOURCE=.\cccc_ext.h
# End Source File
# Begin Source File
SOURCE=.\cccc_htm.h
# End Source File
# Begin Source File
SOURCE=.\cccc_itm.h
# End Source File
# Begin Source File
SOURCE=.\cccc_mem.h
# End Source File
# Begin Source File
SOURCE=.\cccc_met.h
# End Source File
# Begin Source File
SOURCE=.\cccc_mod.h
# End Source File
# Begin Source File
SOURCE=.\cccc_opt.h
# End Source File
# Begin Source File
SOURCE=.\cccc_prj.h
# End Source File
# Begin Source File
SOURCE=.\cccc_rec.h
# End Source File
# Begin Source File
SOURCE=.\cccc_tbl.h
# End Source File
# Begin Source File
SOURCE=.\cccc_tok.h
# End Source File
# Begin Source File
SOURCE=.\cccc_use.h
# End Source File
# Begin Source File
SOURCE=.\cccc_utl.h
# End Source File
# End Group
# Begin Group "C++ implementation files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\cccc_db.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_ext.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_htm.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_itm.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_mem.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_met.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_mod.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_new.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_opt.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_prj.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_rec.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_tbl.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_tok.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_tpl.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_use.cc
# End Source File
# Begin Source File
SOURCE=.\cccc_utl.cc
# End Source File
# Begin Source File
SOURCE=.\ccccmain.cc
# End Source File
# End Group
# Begin Group "makefiles"
# PROP Default_Filter "*.mak"
# Begin Source File
SOURCE=.\posixgcc.mak
# End Source File
# Begin Source File
SOURCE=.\rules.mak
# End Source File
# Begin Source File
SOURCE=.\w32bcb.mak
# End Source File
# Begin Source File
SOURCE=.\w32cygnus.mak
# End Source File
# Begin Source File
SOURCE=.\w32cygnus_gmake.mak
# End Source File
# Begin Source File
SOURCE=.\w32cygnus_nmake.mak
# End Source File
# Begin Source File
SOURCE=.\w32vc.mak
# End Source File
# End Group
# End Target
# End Project
cccc-3.1.4/cccc/ada.g 0000644 0000000 0000000 00000075174 10357241712 012720 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// ada95.g
// derived from the publicly available files grammar9x.y and lexer9x.l
// from Intermetrics, available from:
// somewhere on the internet
// the Intermetrics notices:
/******* A YACC grammar for Ada 9X *********************************/
/* Copyright (C) Intermetrics, Inc. 1994 Cambridge, MA USA */
/* Copying permitted if accompanied by this statement. */
/* Derivative works are permitted if accompanied by this statement.*/
/* This grammar is thought to be correct as of May 1, 1994 */
/* but as usual there is *no warranty* to that effect. */
/*******************************************************************/
/******* A "lex"-style lexer for Ada 9X ****************************/
/* Copyright (C) Intermetrics, Inc. 1994 Cambridge, MA USA */
/* Copying permitted if accompanied by this statement. */
/* Derivative works are permitted if accompanied by this statement.*/
/* This lexer is known to be only approximately correct, but it is */
/* more than adequate for most uses (the lexing of apostrophe is */
/* not as sophisticated as it needs to be to be "perfect"). */
/* As usual there is *no warranty* but we hope it is useful. */
/*******************************************************************/
#header <<
#include "cccc.h"
#include "cccc_ast.h"
#include "cccc_utl.h"
// the objects which PCCTS creates for ASTs as the #0 variable etc
// have type "pointer to ASTBase", which means they need to be cast
// to a pointer to my variant of AST if I want to call my AST
// methods on them
#define MY_AST(X) ( (AST*) X)
>>
#lexaction
<<
void lex_error(int tok)
{
cerr << "Accepting lexical error token " << tok << endl;
}
>>
#token Eof "@" <");>>
#token ADA_COMMENT "\-\- ~[\n]* \n"
<<
IncrementCount(tcCOMLINES);
newline();
skip();
>>
#token WHITESPACE "[\ \r\t\f]" << skip(); >>
#token NEWLINE "\n" <<
if(ANTLRToken::bCodeLine!=0)
{
IncrementCount(tcCODELINES);
}
newline();
skip();
>>
#token LPAREN "\(" <<;>>
#token RPAREN "\)" <<;>>
#token LBRACK "\[" <<;>>
#token RBRACK "\]" <<;>>
#token LBRACE "\{" <<;>>
#token RBRACE "\}" <<;>>
#token PIPE "\|" <<;>>
#token PLUS "\+" <<;>>
#token MINUS "\-" <<;>>
#token TIMES "\*" <<;>>
#token DIVIDE "\/" <<;>>
// Ada provides support for explicitly requesting short circuit evaluation
// on AND THEN and OR ELSE boolean expressions.
// We need to count these as increments to the McCabe value, as they introduce
// new paths through the code.
// To do this we need to trick the lexer into doing lookahead for us
#token AND "and" << mode(AND_RECOGNIZED); >>
#lexclass AND_RECOGNIZED
#token AND_WS "[\ \t\r\f]" << skip(); >>
#token AND_NL "\n" << newline(); skip(); >>
#token THEN_AFTER_AND "then"
<<
IncrementCount(tcMCCABES_VG);
mode(START);
>>
#token AND_OTHER1 "~[]" << _endexpr-=1; mode(START); skip(); >>
#token AND_OTHER2 "t~[]" << _endexpr-=2; mode(START); skip(); >>
#token AND_OTHER3 "th~[]" << _endexpr-=3; mode(START); skip(); >>
#token AND_OTHER4 "the~[]"
<< _endexpr-=4; mode(START); skip(); >>
#lexclass START
#token OR "or" << mode(OR_RECOGNIZED); >>
#lexclass OR_RECOGNIZED
#token OR_WS "[\ \t\r\f]" << skip(); >>
#token OR_NL "\n" << newline(); skip(); >>
#token ELSE_AFTER_OR "else"
<<
IncrementCount(tcMCCABES_VG);
mode(START);
>>
#token OR_OTHER1 "~[]" << _endexpr-=1; mode(START); skip(); >>
#token OR_OTHER2 "e~[]" << _endexpr-=2; mode(START); skip(); >>
#token OR_OTHER3 "el~[]" << _endexpr-=3; mode(START); skip(); >>
#token OR_OTHER4 "els~[]"
<< _endexpr-=4; mode(START); skip(); >>
#lexclass START
// We want to use nesting levels to control resynchronisation strategies after
// unrecognized text.
// in C, C++ and Java, the useful nesting relation is simple:
// depth=number of "{" seen - number of "}" seen
// (this assumes that people do not use the preprocessor to hide or create
// more of one kind of brace than the other)
// in Ada, the useful nesting is BEGIN ... END, but there are some
// complications as END tokens are used to match with tokens other than the
// BEGIN, including IS, DO, LOOP, SELECT, RECORD, IF and CASE.
// Of these:
// IF, SELECT, LOOP and DO stand in positions similar to an opening
// BEGIN, before groups of statements, so we treat them as an alternate
// forms of nesting depth increase,
// IS before a block of statements or declarations matches an END at the
// end
// RECORD at the start of a group of declarations matches an END RECORD
// at the end.
// Unfortunately, IS is used quite widely, sometimes in contexts where
// it does not need a matching END, sometimes where it does. Detecting this
// in the lexer is not trivial
#token PERIOD "." <<;>>
#token DOT_DOT ".." <<;>>
#token LT_LT "\<\<" <<;>>
#token BOX "\<\>" <<;>>
#token LT_EQ "\<=" <<;>>
#token EXPON "\*\*" <<;>>
#token NE "\/=" <<;>>
#token GT_GT "/>/>" <<;>>
#token GE "\>=" <<;>>
#token IS_ASSIGNED ":=" <<;>>
#token RIGHT_SHAFT "=\>" <<;>>
#token ABORT "abort" <<;>>
#token ABS "abs" <<;>>
#token ABSTRACT "abstract" <<;>>
#token ACCEPT "accept" <<;>>
#token ACCESS "access" <<;>>
#token ALIASED "aliased" <<;>>
#token ALL "all" <<;>>
#token ARRAY "array" <<;>>
#token AT "at" <<;>>
#token BEGiN "begin" <<;>>
#token BODY "body" <<;>>
#token CASE "case"
<<
IncrementCount(tcMCCABES_VG);
>>
#token CONSTANT "constant" <<;>>
#token DECLARE "declare" <<;>>
#token DELAY "delay" <<;>>
#token DELTA "delta" <<;>>
#token DIGITS "digits" <<;>>
#token DO "do" <<;>>
#token ELSE "else" <<;>>
#token ELSIF "elsif"
<<
IncrementCount(tcMCCABES_VG);
>>
#token END "end" <<;>>
#token ENTRY "entry" <<;>>
#token EXCEPTION "exception" <<;>>
#token EXIT "exit" <<;>>
#token FOR "for"
<<
IncrementCount(tcMCCABES_VG);
>>
#token FUNCTION "function" <<;>>
#token GENERIC "generic" <<;>>
#token GOTO "goto" <<;>>
#token IF "if"
<<
IncrementCount(tcMCCABES_VG);
>>
#token IN "in" <<;>>
#token IS "is" <<;>>
#token LIMITED "limited" <<;>>
#token LOOP "loop" <<;>>
#token MOD "mod" <<;>>
#token NEW "new" <<;>>
#token NOT "not" <<;>>
#token NuLL "null" <<;>>
#token OF "of" <<;>>
#token OTHERS "others" <<;>>
#token OUT "out" <<;>>
#token PACKAGE "package" <<;>>
#token PRAGMA "pragma" <<;>>
#token PRIVATE "private" <<;>>
#token PROCEDURE "procedure" <<;>>
#token PROTECTED "protected" <<;>>
#token RAISE "raise" <<;>>
#token RANGE "range" <<;>>
#token RECORD "record" <<;>>
#token REM "rem" <<;>>
#token RENAMES "renames" <<;>>
#token REQUEUE "requeue" <<;>>
#token RETURN "return" <<;>>
#token REVERSE "reverse" <<;>>
#token SELECT "select" <<;>>
#token SEPARATE "separate" <<;>>
#token SUBTYPE "subtype" <<;>>
#token TAGGED "tagged" <<;>>
#token TASK "task" <<;>>
#token TERMINATE "terminate" <<;>>
#token THEN "then" <<;>>
#token TYPE "type" <<;>>
#token UNTIL "until" <<;>>
#token USE "use" <<;>>
#token WHEN "when" <<;>>
#token WHILE "while"
<<
IncrementCount(tcMCCABES_VG);
>>
#token WITH "with" <<;>>
#token XOR "xor" <<;>>
#token IDENTIFIER "[a-zA-Z][_a-zA-Z0-9]*" <<;>>
#token CHAR_STRING "\"~[\"]*\"" <<;>>
// there is a very nasty lexer ambiguity between single quote as the start of
// a character literal, and single quote as the modifier for an attribute
// to resolve this, we use the lexclass processing below
#token TIC "'" << mode(TIC_SEEN); >>
#lexclass TIC_SEEN
#token TIC_CHAR_TIC "~[]'" << mode(START); >>
#token TIC_LPAREN "\(" << mode(START); return LPAREN; >>
#token TIC_IDENTIFIER "[a-zA-Z][_a-zA-Z0-9]+"
<< mode(START); return IDENTIFIER; >>
#token TIC_SHORT_ID "[a-zA-Z]" << mode(START); return IDENTIFIER; >>
#token TIC_ERROR "~[]" << mode(START); lex_error(TIC_ERROR); >>
#lexclass START
/*
these are the lex patterns which build up into DECIMAL_LITERAL and
BASED_LITERAL which are the two forms of numeric literal used in the
original lex/yacc grammar
I've implemented them as rules, based on component token patterns as below
EXTENDED_DIGIT [0-9a-zA-Z]
INTEGER ({DIGIT}(_?{DIGIT})*)
EXPONENT ([eE](\+?|-){INTEGER})
DECIMAL_LITERAL {INTEGER}(\.?{INTEGER})?{EXPONENT}?
BASE {INTEGER}
BASED_INTEGER {EXTENDED_DIGIT}(_?{EXTENDED_DIGIT})*
BASED_LITERAL {BASE}#{BASED_INTEGER}(\.{BASED_INTEGER})?#{EXPONENT}?
*/
#token DECIMAL_STRING "[0-9_]+" << ; >>
#token DECIMAL_EXPON "[Ee]{[\+\-]}" << ; >>
#token BASED_INDIC_BEG "#" << mode(BASED); >>
#lexclass BASED
#token BASED_STRING "[_0-9A-Za-z]+" << ; >>
#token BASED_POINT "." << ; >>
#token BASED_INDIC_END "#" << mode(START); >>
// we don't expect to see anything except the tokens above while in
// this mode, but just in case...
#token BASED_ERROR "~[]" << mode(START); lex_error(BASED_ERROR); >>
#lexclass START
#tokclass RESYNCHRONISATION { ";" }
class AdaPrser {
<<
ParseUtility ps;
#define TOKEN_INFO "\t" << LT(1)->getText() << " on line " << LT(1)->getLine()
void tracein(char *rulename) { ps.tracein(rulename,guessing,LT(1)); }
void traceout(char *rulename) { ps.traceout(rulename,guessing,LT(1)); }
void syn(
_ANTLRTokenPtr tok, ANTLRChar *egroup, SetWordType *eset,
ANTLRTokenType etok, int k
)
{
if(DebugMask&PARSER) { ps.syn(tok); }
}
/* Parser Members */
string parse_language;
public:
void init(const string& filename, const string& language)
{
ps.reset(this);
ps.set_string(pssFILE, filename);
parse_language=language;
ANTLRParser::init();
}
>>
goal_symbol : compilation Eof
;
// numeric literal handling
numeric_literal :
decimal_literal
| based_literal
;
decimal_literal :
DECIMAL_STRING { decimal_fractional_part } { decimal_exponent }
| decimal_fractional_part { decimal_exponent }
;
decimal_fractional_part :
PERIOD DECIMAL_STRING
;
decimal_exponent :
DECIMAL_EXPON DECIMAL_STRING
;
based_literal :
DECIMAL_STRING based_number { decimal_exponent }
;
based_number :
BASED_INDIC_BEG based_float BASED_INDIC_END
;
based_float :
BASED_STRING { BASED_POINT BASED_STRING }
| BASED_POINT BASED_STRING
;
error :
<< (LT(1)->getType() == 9999) >>? "!!!!!!" ";"
;
pragma! : PRAGMA simple_name { LPAREN pragma_arg_s RPAREN } ";"
;
pragma_arg_s :
pragma_arg ( "," pragma_arg )*
| /* empty */
;
pragma_arg :
(simple_name RIGHT_SHAFT)? simple_name RIGHT_SHAFT expression
| expression
;
pragma_s :
( pragma )*
;
/* recast for LL parsing */
def_id_s : def_id ( "," def_id )*
;
def_id : IDENTIFIER
;
object_qualifier_opt :
( ALIASED CONSTANT )?
| ALIASED
| CONSTANT
| /* empty */
;
object_subtype_def :
subtype_ind
| array_type
;
init_opt! :
IS_ASSIGNED expression
| /* empty */
;
object_or_number_decl :
def_id_s ":" object_or_number_decl_completion
;
object_or_number_decl_completion :
CONSTANT IS_ASSIGNED expression ";"
| object_qualifier_opt object_subtype_def init_opt ";"
;
type_decl : TYPE IDENTIFIER discrim_part_opt type_completion ";"
;
discrim_part_opt :
discrim_part
| LPAREN BOX RPAREN
| /* empty */
;
type_completion :
IS type_def
| /* empty */
;
type_def :
(private_type)?
| enumeration_type
| integer_type
| real_type
| array_type
| record_type
| access_type
| derived_type
;
subtype_decl : SUBTYPE IDENTIFIER IS subtype_ind ";"
;
subtype_ind :
( name constraint )?
| name
;
constraint :
range_constraint
| decimal_digits_constraint
;
decimal_digits_constraint : DIGITS expression range_constr_opt
;
derived_type :
{ ABSTRACT } NEW subtype_ind subtype_opt_with_extension
;
subtype_opt_with_extension :
WITH PRIVATE
| WITH record_def
| /* empty */
;
range_constraint : RANGE range
;
range :
( name TIC RANGE LPAREN expression RPAREN )?
| ( name TIC RANGE )?
| simple_expression DOT_DOT simple_expression
;
enumeration_type : LPAREN enum_id_s RPAREN
;
enum_id_s : enum_id ( "," enum_id )*
;
enum_id : IDENTIFIER
| char_lit
;
char_lit : TIC TIC_CHAR_TIC
;
integer_type : range_spec
| MOD expression
;
range_spec : range_constraint
;
range_spec_opt :
range_spec
| /* empty */
;
real_type :
float_type
| fixed_type
;
float_type : DIGITS expression range_spec_opt
;
fixed_type : DELTA expression fixed_type_suffix
;
fixed_type_suffix :
range_spec
| DIGITS expression range_spec_opt
;
array_type :
ARRAY LPAREN array_index_spec RPAREN OF component_subtype_def
;
array_index_spec :
( iter_discrete_range_s )?
| index_s
;
component_subtype_def : { ALIASED } subtype_ind
;
index_s : index ( "," index )*
;
index : name RANGE BOX
;
iter_index_constraint : LPAREN iter_discrete_range_s RPAREN
;
iter_discrete_range_s : discrete_range ( "," discrete_range )*
;
discrete_range :
| ( name range_suffix )?
| ( simple_expression DOT_DOT )?
simple_expression DOT_DOT simple_expression
| name
;
range_constr_opt :
| range_constraint
;
record_type : tagged_opt limited_opt record_def
;
record_def : RECORD pragma_s comp_list END RECORD
| NuLL RECORD
;
tagged_opt :
| TAGGED
| ABSTRACT TAGGED
;
comp_list : comp_decl_s variant_part_opt
| variant_part pragma_s
| NuLL ";" pragma_s
;
comp_decl_s :
comp_decl comp_decl_or_pragma_list
;
comp_decl_or_pragma_list :
(comp_decl)? comp_decl comp_decl_s
| (PRAGMA)? pragma comp_decl_s
| empty
;
variant_part_opt : pragma_s (variant_part pragma_s)*
;
comp_decl : def_id_s ":" component_subtype_def init_opt ";"
| error ";"
;
discrim_part : LPAREN discrim_spec_s RPAREN
;
discrim_spec_s : discrim_spec ( ";" discrim_spec )*
;
discrim_spec : def_id_s ":" { ACCESS } mark init_opt
| error
;
variant_part : CASE simple_name IS pragma_s variant_s END CASE ";"
;
variant_s : ( variant )*
;
variant : WHEN choice_s RIGHT_SHAFT pragma_s comp_list
;
choice_s : choice ( PIPE choice )*
;
choice :
( discrete_with_range )?
| expression
| OTHERS
;
discrete_with_range :
( name RANGE)? name range_suffix
| ( name TIC RANGE )? name range_suffix
| simple_expression DOT_DOT simple_expression
;
range_suffix :
range_constraint
| TIC RANGE { LPAREN expression RPAREN }
;
access_type : ACCESS subtype_ind
| ACCESS CONSTANT subtype_ind
| ACCESS ALL subtype_ind
| ACCESS { PROTECTED } proc_func_spec
;
proc_func_spec :
PROCEDURE formal_part_opt
| FUNCTION formal_part_opt RETURN mark
;
decl_part : decl_item_or_body_s1
;
decl_item_s :
(END|PRIVATE)? empty
| decl_item_or_body decl_item_s
;
empty : /* nothing */
;
decl_item_or_body_s1 : decl_item_or_body decl_item_s
;
decl_item_or_body :
<<
// prepare in case we need to resynchronize
ANTLRTokenPtr initial_token=LT(1);
string initial_text=ps.lookahead_text(3);
>>
( generic_decl )?
| ( rename_decl )?
| type_decl
| prot_decl
| subtype_decl
| pkg_decl
| task_decl_or_body
| subprog_decl_or_body
| use_clause
| rep_spec
| pragma
| pkg_body
| prot_body
| (exception_decl)?
| object_or_number_decl
;
<<
{
ANTLRTokenPtr resync_token;
int resync_nesting=mytoken(initial_token)->getNestingLevel();
ps.resynchronize(resync_nesting,RESYNCHRONISATION_set,resync_token);
cerr << "Syntax error: parser failed to handle "
<< initial_text << "..." << resync_token->getText()
<< " on lines " << initial_token->getLine()
<< " to " << resync_token->getLine() << endl;
// now we build an AST representing the rejected area...
initial_token->setText(initial_text.c_str());
AST *rejected_ast=new AST(initial_token);
AST *rejected_ast_end=new AST(resync_token);
rejected_ast->setRight(rejected_ast_end);
ps.record_rejected_extent(rejected_ast);
// we only delete the root tree - it deletes the other one
delete rejected_ast;
}
>>
name :
simple_name name_extension_list
| operator_symbol
;
name_extension_list :
(LPAREN|TIC|PERIOD)? extension_item name_extension_list
| /* empty */
;
extension_item :
index_extension
| selection_extension
| attribute_extension
;
mark : simple_name ( mark_extension )*
;
mark_extension :
TIC! attribute_id!
| PERIOD simple_name
;
simple_name : IDENTIFIER
;
compound_name : simple_name ( PERIOD simple_name )*
;
compound_member_name :
first_name_element extra_name_elements
;
first_name_element :
nm:IDENTIFIER
<< ps.set_string(pssMEMBER,$nm->getText()); >>
;
extra_name_elements :
/* empty */
| PERIOD nm:IDENTIFIER extra_name_elements
<<
ps.set_string(pssMODULE,ps.get_string(pssMEMBER));
ps.set_string(pssMEMBER,$nm->getText());
>>
;
c_name_list : compound_name ( "," compound_name )*
;
used_char : CHAR_LIT
;
operator_symbol : CHAR_STRING
;
index_extension :
LPAREN value_s RPAREN
;
value_s : value ( "," value )*
;
value :
( discrete_with_range )?
| choice_s opt_assoc
| error
;
opt_assoc :
(RIGHT_SHAFT)? RIGHT_SHAFT expression
| /* empty */
;
selection_extension :
PERIOD simple_name
| PERIOD used_char
| PERIOD operator_symbol
| PERIOD ALL
;
attribute_extension :
TIC attribute_id
;
attribute_id : IDENTIFIER
| DIGITS
| DELTA
| ACCESS
;
literal : numeric_literal
| used_char
| NuLL
;
aggregate : LPAREN aggregate_contents RPAREN
;
aggregate_contents :
( value_s_2 )?
| (choice_s RIGHT_SHAFT)? comp_assoc
| expression WITH aggregate_with_operand
| NuLL RECORD
;
aggregate_with_operand :
value_s
| NuLL RECORD
;
value_s_2 : value "," value ( "," value )*
;
comp_assoc : choice_s RIGHT_SHAFT expression
;
expression : relation expression_extension
;
expression_extension :
(logical)? logical expression
| (short_circuit)? short_circuit expression
| /* empty */
;
logical : AND
| OR
| XOR
;
short_circuit : AND THEN_AFTER_AND
| OR ELSE_AFTER_OR
;
relation : simple_expression relation_extension
;
relation_extension :
( membership range )?
| membership name
| ( relational simple_expression )*
;
relational : "="
| NE
| "<"
| LT_EQ
| ">"
| GE
;
membership : IN
| NOT IN
;
simple_expression :
(unary)? unary term
| term ( adding term )*
;
unary : PLUS
| MINUS
;
adding : PLUS
| MINUS
| "&"
;
term : factor ( multiplying factor )*
;
multiplying : TIMES
| DIVIDE
| MOD
| REM
;
factor :
NOT primary
| ABS primary
| primary ( EXPON primary )*
;
primary : literal
| (qualified)?
| name
| allocator
| parenthesized_primary
;
parenthesized_primary : LPAREN paren_primary_contents RPAREN
;
// in the original grammar, the options here are value_s_2 (i.e. at least
// two patterns matching value, separated by commas) or expression
// as expression matches value, this creates an ambiguity, so we relax the
// rule a little...
paren_primary_contents :
value ( "," value )*
;
qualified : name TIC parenthesized_primary
;
allocator :
( NEW qualified )?
| NEW name
;
statement_s :
(statement)? statement statement_s
| /* empty */
;
statement : unlabeled
| label statement
;
unlabeled : simple_stmt
| compound_stmt
| pragma
;
simple_stmt : null_stmt
| (assign_stmt)?
| exit_stmt
| return_stmt
| goto_stmt
| (procedure_call)?
| delay_stmt
| abort_stmt
| raise_stmt
| code_stmt
| requeue_stmt
| error ";"
;
compound_stmt : if_stmt
| case_stmt
| ( loop_stmt )?
| block
| accept_stmt
| select_stmt
;
label : LT_LT IDENTIFIER GT_GT
;
null_stmt : NuLL ";"
;
assign_stmt : name IS_ASSIGNED expression ";"
;
if_stmt : IF cond_clause_s else_opt END IF ";"
;
cond_clause_s : cond_clause ( ELSIF cond_clause )*
;
cond_clause : cond_part statement_s
;
cond_part : condition THEN
;
condition : expression
;
else_opt :
| ELSE statement_s
;
case_stmt : case_hdr pragma_s alternative_s END CASE ";"
;
case_hdr : CASE expression IS
;
alternative_s :
| alternative alternative_s
;
alternative : WHEN choice_s RIGHT_SHAFT statement_s
;
loop_stmt : label_opt iteration basic_loop id_opt ";"
;
label_opt :
| IDENTIFIER ":"
;
iteration :
| WHILE condition
| iter_part reverse_opt discrete_range
;
iter_part : FOR IDENTIFIER IN
;
reverse_opt :
| REVERSE
;
basic_loop : LOOP statement_s END LOOP
;
id_opt :
| func_designator
;
block : label_opt block_decl block_body END id_opt ";"
;
block_decl :
| DECLARE decl_part
;
block_body : BEGiN handled_stmt_s
;
handled_stmt_s : statement_s except_handler_part_opt
;
except_handler_part_opt :
| except_handler_part
;
exit_stmt : EXIT name_opt when_opt ";"
;
name_opt :
| name
;
when_opt :
| WHEN condition
;
return_stmt : RETURN ";"
| RETURN expression ";"
;
goto_stmt : GOTO name ";"
;
subprog_decl_or_body :
<<
string sp_str;
UseType ut;
>>
subprog_spec
subprog_decl_or_body_completion>[ut]
<<
ps.record_function_extent(MY_AST(#0),ut);
>>
;
subprog_decl_or_body_completion > [UseType _retv] :
(
IS SEPARATE ";"
| ";"
)
<<
_retv=utDECLARATION;
ps.set_string(pssDESCRIPTION,"declaration");
>>
|
(
IS ABSTRACT ";"
| IS decl_part block_body END id_opt ";"
| IS generic_inst
)
<<
_retv=utDEFINITION;
ps.set_string(pssDESCRIPTION,"definition");
>>
;
subprog_spec :
PROCEDURE proc_designator formal_part_opt
| FUNCTION func_designator formal_part_opt return_part_opt
;
proc_designator : << string final_name; >>
compound_member_name
;
func_designator : << string final_name; >>
proc_designator
| opname:CHAR_STRING
<<
final_name=$opname->getText();
ps.set_string(pssMEMBER,final_name);
>>
;
formal_part_opt :
| formal_part
;
return_part :
RETURN n:name
<<
ps.set_string(pssUTYPE,MY_AST(#n)->last_token()->getText());
ps.set_string(pssDESCRIPTION,"returns by value");
ps.record_userel_extent(MY_AST(#n),utPARBYVAL);
>>
;
return_part_opt :
return_part
| /* empty */
;
formal_part : LPAREN param_s RPAREN
;
param_s : param ( ";" param )*
;
param : << UseType ut; >>
def_id_s ":" param_mode>[ut] mk:mark init_opt
<<
ps.set_string(pssUTYPE,MY_AST(#mk)->last_token()->getText());
ps.set_string(pssDESCRIPTION,"parameter");
ps.record_userel_extent(MY_AST(#mk),ut);
>>
;
param_mode >[UseType ut]: << $ut=utPARBYVAL; >>
| IN
| OUT
| IN OUT
| ACCESS << $ut=utPARBYREF; >>
;
procedure_call : name ";"
;
pkg_decl :
normal_or_instance_pkg_spec ";"
;
pkg_spec :
normal_or_instance_pkg_spec
;
normal_or_instance_pkg_spec :
PACKAGE cn:compound_name
<<
ps.set_string(
pssMODULE,MY_AST(#cn)->last_token()->getText());
ps.set_string(pssMODTYPE,"Ada package");
>>
normal_or_instance_pkg_spec_completion
;
normal_or_instance_pkg_spec_completion :
RENAMES name
<<
ps.set_string(pssDESCRIPTION,"renames definition");
ps.record_module_extent(MY_AST(#0), utDEFINITION);
>>
| IS generic_inst
<<
ps.set_string(pssDESCRIPTION,"instanced declaration");
ps.record_module_extent(MY_AST(#0), utDECLARATION);
>>
| IS decl_item_s private_part END c_id_opt
<<
ps.set_string(pssDESCRIPTION,"declaration");
ps.record_module_extent(MY_AST(#0), utDECLARATION);
>>
;
private_part :
<< LT(1)->getType() == END >>? /* empty */
| << LT(1)->getType() == PRIVATE >>? PRIVATE decl_item_s
;
c_id_opt :
| compound_name
;
pkg_body :
PACKAGE BODY cn:compound_name
<<
ps.set_string(
pssMODULE,MY_AST(#cn)->last_token()->getText());
ps.set_string(pssMODTYPE,"Ada package");
>>
IS pkg_body_or_separate ";"
;
pkg_body_or_separate :
SEPARATE
| decl_part body_opt END c_id_opt
;
body_opt :
| block_body
;
private_type : tagged_opt limited_opt PRIVATE
;
limited_opt :
| LIMITED
;
use_clause : USE name_s ";"
| USE TYPE name_s ";"
;
name_s : name ( "," name )*
;
rename_decl :
(rename_unit)?
| def_id_s ":" rename_completion
;
rename_completion :
object_qualifier_opt subtype_ind renames ";"
| EXCEPTION renames ";"
;
rename_unit : PACKAGE compound_name renames ";"
| subprog_spec renames ";"
| generic_formal_part generic_renames_completion
;
generic_renames_completion :
PACKAGE compound_name renames ";"
| subprog_spec renames ";"
;
renames : RENAMES name
;
task_decl_or_body : task_spec ";"
;
task_spec :
TASK TYPE simple_name discrim_part_opt task_def
| TASK BODY simple_name IS body_or_separate
| TASK simple_name task_def
;
body_or_separate :
SEPARATE
| decl_part block_body END id_opt ";"
;
task_def :
| IS entry_decl_s rep_spec_s task_private_opt END id_opt
;
task_private_opt :
| PRIVATE entry_decl_s rep_spec_s
;
prot_decl : prot_spec ";"
;
prot_spec : PROTECTED prot_item
;
prot_item :
IDENTIFIER prot_def
| TYPE simple_name discrim_part_opt prot_def
;
prot_def : IS prot_op_decl_s prot_private_opt END id_opt
;
prot_private_opt :
| PRIVATE prot_elem_decl_s
;
prot_op_decl_s :
| prot_op_decl prot_op_decl_s
;
prot_op_decl : entry_decl
| subprog_spec ";"
| rep_spec
| pragma
;
prot_elem_decl_s :
| prot_elem_decl prot_elem_decl_s
;
prot_elem_decl : prot_op_decl | comp_decl
;
prot_body : PROTECTED BODY simple_name IS prot_separate_or_body ";"
;
prot_separate_or_body :
SEPARATE
| prot_op_body_s END id_opt
;
prot_op_body_s : pragma_s ( prot_op_body pragma_s )*
;
prot_op_body : entry_body
| subprog_decl_or_body
;
entry_decl_s : pragma_s ( entry_decl pragma_s )*
;
entry_decl : ENTRY IDENTIFIER entry_decl_completion
;
entry_decl_completion :
( paren_discrete_range )? paren_discrete_range formal_part_opt ";"
| formal_part_opt ";"
;
paren_discrete_range :
LPAREN discrete_range RPAREN
;
entry_body : ENTRY IDENTIFIER { LPAREN iter_part discrete_range RPAREN }
formal_part_opt WHEN condition entry_body_part
;
entry_body_part : ";"
| IS decl_part block_body END id_opt ";"
;
rep_spec_s : ( rep_spec pragma_s )*
;
entry_call : procedure_call
;
accept_stmt : accept_hdr accept_completion
;
accept_completion :
";"
| DO handled_stmt_s END id_opt ";"
;
accept_hdr : ACCEPT entry_name formal_part_opt
;
entry_name : simple_name paren_expression_list
;
paren_expression_list :
( LPAREN )? LPAREN expression RPAREN paren_expression_list
| /* empty */
;
delay_stmt : DELAY expression ";"
| DELAY UNTIL expression ";"
;
select_stmt : SELECT select_completion
;
select_completion :
( select_wait_completion )?
| ( async_select_completion )?
| entry_completion
;
select_wait_completion :
guarded_select_alt or_select else_opt END SELECT ";"
;
guarded_select_alt : select_alt
| WHEN condition RIGHT_SHAFT select_alt
;
or_select : ( OR guarded_select_alt )*
;
select_alt : accept_stmt stmts_opt
| delay_stmt stmts_opt
| TERMINATE ";"
;
delay_or_entry_alt :
delay_stmt stmts_opt
| entry_call stmts_opt
;
async_select_completion :
delay_or_entry_alt THEN ABORT statement_s END SELECT ";"
;
entry_completion : entry_call stmts_opt entry_completion_tail
;
entry_completion_tail :
OR delay_stmt stmts_opt END SELECT ";"
| ELSE statement_s END SELECT ";"
;
stmts_opt :
statement_s | /* empty */
;
abort_stmt : ABORT name_s ";"
;
compilation :
| comp_unit compilation
;
comp_unit :
<<
ParseUtility saved_ps=ps;
>>
pragma_s cs:opt_context_spec private_opt unit
<<
{
ps.set_flag(vPUBLIC);
ps.set_string(pssDESCRIPTION,"with relationship");
while(cs != NULL)
{
if(
(MY_AST(#cs)->token.getType() == IDENTIFIER) &&
(MY_AST(#cs->right())->token.getType() != PERIOD)
)
{
ps.set_string(pssUTYPE,MY_AST(#cs)->token.getText());
ps.record_userel_extent(MY_AST(#cs),utWITH);
ps.set_flag(vPUBLIC);
}
else if(MY_AST(#cs)->token.getType() == PRIVATE)
{
ps.set_flag(vPRIVATE);
}
#cs=MY_AST(#cs->right());
}
ps=saved_ps;
}
>>
;
private_opt :
| PRIVATE
;
opt_context_spec :
{ context_spec }
;
context_spec :
with_clause use_clause_opt pragma_with_list
;
pragma_with_list :
(pragma_with_item)? pragma_with_item pragma_with_list
| /* empty */
;
pragma_with_item :
pragma
| with_clause use_clause_opt
;
with_clause : WITH! c_name_list ";"!
;
use_clause_opt! :
( use_clause )? use_clause use_clause_opt
| /* empty */
;
unit : pkg_decl
| pkg_body
| subprog_decl_or_body
| subunit
| generic_decl
// | rename_unit
;
subunit : SEPARATE LPAREN compound_name RPAREN
subunit_body
;
subunit_body : subprog_decl_or_body
| pkg_body
| task_decl_or_body
| prot_body
;
exception_decl : def_id_s ":" exception_spec
;
exception_spec :
EXCEPTION ";"
| EXCEPTION RENAMES name ";"
;
except_handler_part : EXCEPTION ( exception_handler )*
;
exception_handler :
WHEN { IDENTIFIER ":" } except_choice_s RIGHT_SHAFT statement_s
;
except_choice_s :
except_choice more_except_choices
;
more_except_choices :
(PIPE)? PIPE except_choice_s
| /* empty */
;
except_choice : name
| OTHERS
;
raise_stmt : RAISE name_opt ";"
;
requeue_stmt :
REQUEUE name { WITH ABORT } ";"
;
generic_decl :
generic_formal_part generic_decl_completion
;
generic_decl_completion :
subprog_spec ";"
| pkg_spec ";"
;
/* recast for LL parsing */
generic_formal_part : GENERIC
| generic_formal generic_formal_part
;
generic_formal : param ";"
| TYPE simple_name generic_discrim_part_opt IS generic_type_def ";"
| WITH PROCEDURE simple_name
formal_part_opt subp_default ";"
| WITH FUNCTION func_designator
formal_part_opt return_part subp_default ";"
| WITH PACKAGE simple_name IS NEW name { LPAREN BOX RPAREN } ";"
| use_clause
;
generic_discrim_part_opt :
| discrim_part
| LPAREN BOX RPAREN
;
subp_default :
| IS name
| IS BOX
;
generic_type_def : LPAREN BOX RPAREN
| RANGE BOX
| MOD BOX
| ( DELTA BOX DIGITS BOX )?
| DELTA BOX
| DIGITS BOX
| array_type
| access_type
| private_type
| generic_derived_type
;
generic_derived_type :
NEW subtype_ind { WITH PRIVATE }
| ABSTRACT NEW subtype_ind WITH PRIVATE
;
generic_inst : NEW name
;
rep_spec :
FOR mark USE rep_def
;
rep_def :
expression ";"
| RECORD align_opt comp_loc_s END RECORD ";"
| AT expression ";"
;
align_opt :
| AT MOD expression ";"
;
comp_loc_s :
| mark AT expression RANGE range ";" comp_loc_s
;
code_stmt : qualified ";"
;
}
cccc-3.1.4/cccc/cccc.g 0000644 0000000 0000000 00000102566 10357241712 013062 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
*
* A coarse grammar for C++
* This file is designed to be processed by the PCCTS utilities ANTLR and
* DLG to generate a scanner and parser for the cccc metric analyser project
*
* by Tim Littlefair, 1995-2001
*/
#header<<
#define zzTRACE_RULES
#include "AParser.h"
#include "cccc.h"
#include "cccc_utl.h"
#include "cccc_opt.h"
// the objects which PCCTS creates for ASTs as the #0 variable etc
// have type "pointer to ASTBase", which means they need to be cast
// to a pointer to my variant of AST if I want to call my AST
// methods on them
#define MY_AST(X) ( (AST*) X)
// we have a global variable member for the language of the parse so
// that we can supply the names of dialects (ansi_c, ansi_c++, mfc_c++ etc)
// for contexts where we wish to apply dialect-specific lexing or parsing
// rules
extern string parse_language;
>>
#lexaction
<<
#include
// Need to see definition of CLexer class before defining the
// next actions.
// This will mean this file is included twice in CLexer.cpp. This
// should do no harm...
#include "CLexer.h"
// The lexical analyser passes some information through to
// the parse store to be integrated with parse information before
// recording in the database.
inline void IncrementCount(LexicalCount tc)
{
assert(ParseStore::currentInstance()!=NULL);
ParseStore::currentInstance()->IncrementCount(tc);
}
inline void endOfLine(CLexer &lexer)
{
assert(ParseStore::currentInstance()!=NULL);
ParseStore::currentInstance()->endOfLine(lexer.line());
lexer.newline();
lexer.skip();
}
>>
#token Eof "@" << replstr(""); >>
#token WHITESPACE "[\ \t\r]+" << skip(); >>
// handle newlines
#token DOS_NL "\r\n" << endOfLine(*this); >>
#token MAC_NL "\r" << endOfLine(*this); >>
#token UNIX_NL "\n" << endOfLine(*this); >>
/* preprocessor constructs - comments, #defines etc */
#token HASH "#" << mode(PREPROC); more(); >>
#lexclass PREPROC
#token DOS_P_EOL "\r\n" << mode(START); endOfLine(*this); >>
#token MAC_P_EOL "\r" << mode(START); endOfLine(*this); >>
#token UNIX_P_EOL "\n" << mode(START); endOfLine(*this); >>
#token P_LINECONT "\\\n" << ; skip(); >>
#token P_ANYTHING "~[\n]" << ; more(); >>
#token P_COMMULTI "/\*" << mode(COMMENT_MULTI); more(); skip(); >>
#lexclass START
/*
** The object oriented design editor Rational Rose/C++ generates source
** inserting directives into source files disguised as comments so that
** C++ source contributed by Rational Rose, which Rose is at liberty to
** change or overwrite can be distinguished from source code written by
** the programmer, which Rose will do its best to preserve.
** We do not count these as user comments.
*/
#token RR_DIRECTIVE "//##" << mode(RR); skip(); >>
#lexclass RR
#token RR_ANYTHING "~[\n]" << skip(); >>
#token RR_END "\n" << mode(START); endOfLine(*this); >>
#lexclass START
/*
** for some reason, the string //#define gives an invalid token error
** with //# quoted as the token name, the 'd' lost in space and 'efine'
** quoted as the next token. For the time being we will just try to trap
** this here (NB we _do_ count this as a user comment)
*/
#token COMDEF "//#" << mode(COMMENT_LINE); skip(); >>
#token COMLINE "//" << mode(COMMENT_LINE); skip(); >>
#lexclass COMMENT_LINE
#token COMLINE_END "\n" <<
IncrementCount(tcCOMLINES);
endOfLine(*this);
mode(START);
>>
#token COMLINE_ANYTHING "~[\n]" << skip(); >>
#lexclass START
#token COMMULTI "/\*" << mode(COMMENT_MULTI); skip(); >>
#lexclass COMMENT_MULTI
#token COMMULTI_END "\*/" <<
IncrementCount(tcCOMLINES);
mode(START);
skip();
>>
#token COMMULTI_EOL "\n" << IncrementCount(tcCOMLINES); endOfLine(*this); >>
#token COMMULTI_ANYTHING "~[\n]" << skip(); >>
#lexclass START
#token STRINGSTART "\"" << mode(CONST_STRING); skip(); >>
#lexclass CONST_STRING
#token STRINGCONST "\"" << mode(START); >>
// thanks to Lynn Wilson for pointing out the need for a simple fix
// to handle escaped newlines within string constants
#token LYNNS_FIX "\\\n" << endOfLine(*this); >>
#token ESCAPED_DQUOTE "\\\"" << skip(); >>
#token ESCAPED_OTHER "\\~[\"]" << skip(); >>
#token S_ANYTHING "~[\"]" << skip(); >>
#lexclass START
#token CHARSTART "\'" << mode(CONST_CHAR); skip(); >>
#lexclass CONST_CHAR
#token CHARCONST "'" << replstr("'.'"); mode(START); >>
#token CH_ANYTHING "~[']" << skip(); >>
#lexclass START
#token LBRACE "\{" << ANTLRToken::IncrementNesting(); >>
#token RBRACE "\}" << ANTLRToken::DecrementNesting(); >>
#token LPAREN "\(" << ; >>
#token RPAREN "\)" << ; >>
#token LBRACK "\[" << ; >>
#token RBRACK "\]" << ; >>
/* keywords */
// Some of the keywords below have recently acquired the prefix
// KW_. This is to avoid clashes between items in the token type
// enumeration generated by PCCTS and predefined datatypes in Windows.
// (Problem first seen under Borland C++ Builder v3).
#token ASM "asm" << ; >>
#token AUTO "auto" << ; >>
#token BREAK "break" << IncrementCount(tcMCCABES_VG); >>
#token CASE "case" << ; >>
#token CATCH "catch" << ; >>
#token KW_CHAR "char" << ; >>
#token CLASS "class" << ; >>
#token KW_CONST "const" << ; >>
#token CONTINUE "continue" << ; >>
#token DEFAULT "default" << ; >>
#token DELETE "delete" << ; >>
#token DO "do" << ; >>
#token KW_DOUBLE "double" << ; >>
#token ELSE "else" << ; >>
#token ENUM "enum" << ; >>
#token EXTERN "extern" << ; >>
#token KW_FLOAT "float" << ; >>
#token FOR "for" << IncrementCount(tcMCCABES_VG); >>
#token FRIEND "friend" << ; >>
#token GOTO "goto" << ; >>
#token IF "if" << IncrementCount(tcMCCABES_VG); >>
#token INLINE "inline" << ; >>
#token KW_INT "int" << ; >>
#token KW_LONG "long" << ; >>
#token NEW "new" << ; >>
#token OPERATOR "operator" << ; >>
#token PRIVATE "private" << ; >>
#token PROTECTED "protected" << ; >>
#token PUBLIC "public" << ; >>
#token REGISTER "register" << ; >>
#token RETURN "return" << IncrementCount(tcMCCABES_VG); >>
#token KW_SHORT "short" << ; >>
#token SIGNED "signed" << ; >>
#token SIZEOF "sizeof" << ; >>
#token STATIC "static" << ; >>
#token STRUCT "struct" << ; >>
#token SWITCH "switch" << IncrementCount(tcMCCABES_VG); >>
#token TEMPLATE "template" << ; >>
#token KW_THIS "this" << ; >>
#token THROW "throw" << ; >>
#token TRY "try" << ; >>
#token TYPEDEF "typedef" << ; >>
#token UNION "union" << ; >>
#token UNSIGNED "unsigned" << ; >>
#token VIRTUAL "virtual" << ; >>
#token KW_VOID "void" << ; >>
#token VOLATILE "volatile" << ; >>
#token WHILE "while" << IncrementCount(tcMCCABES_VG); >>
/* operators */
#token "==" << ; >>
#token "!=" << ; >>
#tokclass EQUAL_OP { "==" "!=" }
#token ASSIGN_OP "=" << ; >>
#token "\*=" << ; >>
#token "\/=" << ; >>
#token "%=" << ; >>
#token "\+=" << ; >>
#token "\-=" << ; >>
#token "\>\>=" << ; >>
#token "\<\<=" << ; >>
#token "&=" << ; >>
#token "\^=" << ; >>
#token "\|=" << ; >>
#tokclass OP_ASSIGN_OP
{ "\*=" "\/=" "%=" "\+=" "\-=" "\>\>=" "\<\<=" "&=" "\^=" "\|=" }
#token "\>\>" << ; >>
#token "\<\<" << ; >>
#tokclass SHIFT_OP { "\>\>" "\<\<" }
#token GREATERTHAN "\>" << ; >>
#token LESSTHAN "\<" << ; >>
#token GREATEREQUAL "\>=" << ; >>
#token LESSEQUAL "\<=" << ; >>
#tokclass REL_OP { "\>" "\<" "\>=" "\<=" }
#token ASTERISK "\*" << ; >>
#token "\/" << ; >>
#token "%" << ; >>
#tokclass DIV_OP { "\/" "%" }
#token "\.\*" << ; >>
#token "\-\>\*" << ; >>
#tokclass PM_OP { "\.\*" "\->\*" }
#token "\+\+" << ; >>
#token "\-\-" << ; >>
#tokclass INCR_OP { "\+\+" "\-\-" }
#token "\+" << ; >>
#token "\-" << ; >>
#tokclass ADD_OP { "\+" "\-" }
#token LOGICAL_AND_OP "&&" << IncrementCount(tcMCCABES_VG); >>
#token LOGICAL_OR_OP "\|\|" << IncrementCount(tcMCCABES_VG); >>
#token LOGICAL_NOT_OP "!" << ; >>
#token QUERY_OP "?" << IncrementCount(tcMCCABES_VG); >>
#token AMPERSAND "&" << ; >>
#token PIPE "\|" << ; >>
#token TILDA "\~" << ; >>
#tokclass BITWISE_OP { "&" "\|" "\~" }
#token COLONCOLON "::" << ; >>
#token ARROW "\-\>" << ; >>
#token COLON ":" << ; >>
#token PERIOD "\." << ; >>
#token COMMA "," << ; >>
#token SEMICOLON ";" << ; >>
/*
** draft ANSI C++ keywords
**
** this grammar is intended to look forward to ANSI C++, so we at least
** try to lex up the new keywords (taken from the revised appendix to the
** ARM, which claims to cover decisions up to February 1995)
**
** namespaces will be treated as a kind of module, along with class and struct
**
** most of the other keywords will make little difference except
** that they will not be recognized as identifiers
** in general, anyone who is using these keywords as identifiers today,
** probably shouldn't be
**
** most of the rest of the new keywords occur in contexts where we aren't
** looking too hard (e.g. in procedural code rather than declaration or
** definition signatures)
*/
#token NAMESPACE "namespace" << ; >>
#token USING "using" << ; >>
#token AND "and" << ; >>
#token AND_EQ "and_eq" << ; >>
#token BITAND "bitand" << ; >>
#token BITOR "bitor" << ; >>
#token COMPL "compl" << ; >>
#token NOT "not" << ; >>
#token OR "or" << ; >>
#token OR_EQ "or_eq" << ; >>
#token XOR "xor" << ; >>
#token XOR_EQ "xor_eq" << ; >>
#token KW_BOOL "bool" << ; >>
#token BTRUE "true" << ; >>
#token BFALSE "false" << ; >>
#token STATIC_CAST "static_cast" << ; >>
#token REINTERPRET_CAST "reinterpret_cast" << ; >>
#token CONST_CAST "const_cast" << ; >>
#token DYNAMIC_CAST "dynamic_cast" << ; >>
#token TYPEID "typeid" << ; >>
// The next definition reserves a member of the token type enumeration for
// later use. We do not expect to match the associated regular expression.
#token IMPLEMENTATION_KEYWORD "XXXXXXXXXXXXXXXXXXXXXXXXXX" << ; >>
/* identifiers */
#token IDENTIFIER "[A-Za-z_][A-Za-z_0-9]*"
<<
// Check whether there are any dialect-specific rules
// about the current token.
std::string treatment =
CCCC_Options::dialectKeywordPolicy(parse_language,lextext());
std::string toktext=lextext();
if( treatment == "ignore" )
{
skip();
}
// Ultimately, the next two cases will need to be handled
// using a #lexclass or something similar, for the moment
// we just try to skip the tokens themselves.
else if ( treatment == "start_skipping" )
{
skip();
}
else if ( treatment == "stop_skipping" )
{
skip();
}
>>
/* Literal elements - integer and float numbers and strings */
#lexclass START
#token OCT_NUM "[0][0-7]*"
#token L_OCT_NUM "[0][0-7]*[Ll]"
#token INT_NUM "[1-9][0-9]*"
#token L_INT_NUM "[1-9][0-9]*[Ll]"
#token HEX_NUM "[0][Xx][0-9A-Fa-f]+"
#token L_HEX_NUM "[0][Xx][0-9A-Fa-f]+[Ll]"
//#token FNUM "([1-9][0-9]*{.[0-9]*} | {[0]}.[0-9]+ | 0. ) {[Ee]{[\+\-]}[0-9]+}"
#token FNUM "([0-9]+.[0-9]+ | [0-9]+. | .[0-9]+ ) {[Ee]{[\+\-]}[0-9]+}"
#token ANYTHING "~[\{\}\[\]\(\)@]" << skip(); >>
// it is not obvious from the PCCTS documentation that it a token class
// may contain things already declared as tokens, but it does not appear
// to cause problems
#tokclass RESYNCHRONISATION { "\}" ";" }
class CParser {
<<
ParseStore* ps;
ParseUtility* pu;
void tracein(const char *rulename) { pu->tracein(rulename,guessing,LT(1)); }
void traceout(const char *rulename) { pu->traceout(rulename,guessing,LT(1)); }
void syn(
_ANTLRTokenPtr tok, ANTLRChar *egroup, SetWordType *eset,
ANTLRTokenType etok, int k)
{
pu->syn(tok,egroup,eset,etok,k);
}
string typeCombine(const string& modifiers, const string& name, const string& indir)
{
string retval;
if(modifiers.size()>0)
{
retval=modifiers+" "+name;
}
else
{
retval=name;
}
if(indir.size()>0)
{
retval+=" ";
retval+=indir;
}
return retval;
}
// Many of the rules below accept string parameters to
// allow upward passing of attributes.
// Where the calling context does not need to receive
// the attributes, it can use the dummy values defined
// here to save allocating a string locally to satisfy the
// parameter list.
string d1,d2,d3;
public:
void init(const string& filename, const string& language)
{
pu=ParseUtility::currentInstance();
ps=ParseStore::currentInstance();
ANTLRParser::init();
parse_language=language;
}
>>
/*
** the start symbol for the grammar:
*/
start : << string fileScope; >>
end_of_file
| link_item[fileScope] start
;
link_item[string& scope] :
(EXTERN STRINGCONST LBRACE)?
extern_linkage_block
| namespace_block
| using_statement
| linkage_qualifiers definition_or_declaration[scope]
;
end_of_file : eof:Eof
<<
ps->record_other_extent(1,$eof->getLine(),"");
>>
;
definition_or_declaration[string& scope] :
<<
// get ready in case we need to resynchronize...
ANTLRTokenPtr initial_token=LT(1);
int startLine=LT(1)->getLine();
string initial_text=pu->lookahead_text(3);
>>
typedef_definition
| ( explicit_template_instantiation )?
| ( scoped_member_name SEMICOLON )? // e.g. 'friend CCCC_Project;'
| ( scoped_member_name LPAREN )?
method_declaration_or_definition_with_implicit_type[scope]
| (type[d1,d2,d3] scoped_member_name LPAREN )?
method_declaration_or_definition_with_explicit_type[scope]
| (type[d1,d2,d3] scoped_member_name )?
instance_declaration[scope]
| (type[d1,d2,d3] LPAREN ASTERISK scoped_member_name RPAREN)?
instance_declaration[scope]
| class_declaration_or_definition[scope]
| union_definition
| enum_definition
// suggested by Kenneth H. Cox to deal with coders who put
// a semicolon after the '}' at the end of an inline method
// definition
| SEMICOLON
;
<<
{
ANTLRTokenPtr resync_token;
int resync_nesting=mytoken(initial_token)->getNestingLevel();
pu->resynchronize(resync_nesting,RESYNCHRONISATION_set,resync_token);
cerr << "Syntax error: parser failed to handle "
<< initial_text << "..." << resync_token->getText()
<< " on lines " << initial_token->getLine()
<< " to " << resync_token->getLine() << endl;
// record the rejected extent in the database
int endLine=LT(1)->getLine();
ps->record_other_extent(startLine,endLine,initial_text);
}
>>
// the following rule is included to cause generation of a token class
// which will be passed to the resynchronise() function
// it is not intended to be matched within the grammar
resync_tokens :
RBRACE
| SEMICOLON
;
extern_linkage_block : << string dummy; >>
EXTERN STRINGCONST LBRACE (link_item[dummy])* RBRACE
;
namespace_block : << string dummy; >>
NAMESPACE { IDENTIFIER } LBRACE (link_item[dummy])* RBRACE SEMICOLON
;
using_statement :
USING { NAMESPACE } scoped_member_name SEMICOLON
;
explicit_template_instantiation :
scoped_member_name angle_block SEMICOLON
;
class_declaration_or_definition[string& scope] :
<<
int startLine=LT(1)->getLine();
bool is_definition;
string modname,modtype;
>>
class_prefix[modname,modtype] sfx:class_suffix[is_definition,modname]
<<
int endLine=LT(1)->getLine();
if(is_definition==false)
{
ps->record_module_extent(startLine,endLine,modname,modtype,
"declaration",utDECLARATION);
}
else
{
ps->record_module_extent(startLine,endLine,modname,modtype,
"definition",utDEFINITION);
}
>>
;
class_suffix[bool& is_definition,string& scope] :
SEMICOLON
<< is_definition=false; >>
| { inheritance_list[scope] } class_block[scope] class_suffix_trailer
<< is_definition=true; >>
;
// version 3.pre42
// Attempting to add support for C-style anonymous struct declarations,
// where there is no class name between the keyword (usually 'struct')
// and the start of the definition block, but there are a list of instances
// of the anonymous class declared between the end of the definition block
// and the semicolon.
class_suffix_trailer :
opt_instance_list SEMICOLON
;
opt_instance_list :
IDENTIFIER ( COMMA IDENTIFIER )*
| /* empty */
;
union_definition :
(anonymous_union_definition)?
| named_union_definition
;
anonymous_union_definition :
UNION brace_block opt_instance_list SEMICOLON
;
named_union_definition :
<< int startLine=LT(1)->getLine(); >>
UNION id:IDENTIFIER brace_block SEMICOLON
<<
ps->record_module_extent(startLine,startLine,
$id->getText(),"union",
"definition",utDEFINITION);
>>
;
enum_definition :
( anonymous_enum_definition )?
| named_enum_definition
;
anonymous_enum_definition :
ENUM brace_block opt_instance_list SEMICOLON
;
named_enum_definition :
<getLine(); >>
ENUM id:IDENTIFIER brace_block SEMICOLON
<<
ps->record_module_extent(startLine,startLine,
$id->getText(),"enum",
"definition",utDEFINITION);
>>
;
/*
** instance_declaration embraces declarations which initialise the variable
** as the same declaration may initialise some variables but not others,
** so we do not have a separate instance_definition rule
*/
instance_declaration[string& scopeName] :
<< int startLine=LT(1)->getLine(); string cvQuals,typeName,varName,indir; >>
(cv_qualifier[cvQuals])* { STATIC } type_name[typeName]
instance_item[indir,varName] ( COMMA instance_item[d1,d2] )* SEMICOLON
<<
if(indir.size()!=0)
{
ps->record_userel_extent(startLine,startLine,
scopeName,varName,typeName,
"has by reference",
ps->get_visibility(),
utHASBYREF);
}
else
{
ps->record_userel_extent(startLine,startLine,
scopeName,"",typeName,
"has by value",
ps->get_visibility(),
utHASBYVAL);
}
>>
;
class_block [string& scope]:
<<
int saved_visibility=ps->get_flag(psfVISIBILITY);
>>
LBRACE class_block_item_list[scope] RBRACE
<< ps->set_flag(psfVISIBILITY,saved_visibility); >>
;
class_block_item_list[string& scope] :
(class_block_item[scope])? class_block_item[scope] class_block_item_list[scope]
| /* empty */
;
class_block_item[string& scope] :
( access_modifier )?
| class_item_qualifier_list definition_or_declaration[scope]
;
class_item_qualifier_list! :
(class_item_qualifier)? class_item_qualifier class_item_qualifier_list
| /* empty */
;
class_item_qualifier :
FRIEND
| VIRTUAL << ps->set_flag(psfVIRTUAL,abTRUE); >>
| STATIC << ps->set_flag(psfSTATIC,abTRUE); >>
| INLINE
;
access_modifier! :
access_key COLON
;
method_declaration_or_definition_with_implicit_type[string& implicitScope] :
<<
int startLine=LT(1)->getLine(); bool is_definition;
string returnType,scope=implicitScope,methodName, paramList;
>>
method_signature[scope,methodName,paramList]
method_suffix[is_definition]
<<
int endLine=LT(1)->getLine();
if(is_definition==false)
{
ps->record_function_extent(startLine,endLine,
returnType,scope,
methodName,paramList,
"declaration",
ps->get_visibility(),
utDECLARATION);
}
else
{
ps->record_function_extent(startLine,endLine,
returnType,scope,
methodName,paramList,
"definition",
ps->get_visibility(),
utDEFINITION);
}
>>
;
method_declaration_or_definition_with_explicit_type[string &scope] :
<< string cvQualifiers,typeName,indirMods; >>
type[cvQualifiers,typeName,indirMods]
method_declaration_or_definition_with_implicit_type[scope]
;
// It has become increasingly obvious that one of the major
// reasons for people in the field to use CCCC is to assess
// legacy code, which is often not pure ANSI C.
// One common idiom which has been reported is hybrid
// Kernighan&Ritche/ANSI C with the preprocessor used
// to offer either compiler sight of their appropriate
// kind of signature. CCCC runs on code which has not
// been preprocessed and ignores the preprocessor
// directives, so this idiom looks to it as if the
// function has two signatures, one after another,
// followed by the function's implementation.
// Attempts have been made to support this idiom but
// they are disabled at present.
// Once we have seen the signature of a function, there are a
// number of ways the item can end.
method_suffix[bool& is_definition] :
// a simple declaration
SEMICOLON << is_definition=false; >>
// declaration of a pure virtual function
// NB the value zero may look like a normal integer, but to the
// lexer, it is seen as an octal literal
| ASSIGN_OP OCT_NUM SEMICOLON << is_definition=false; >>
// definition of a constructor with an initializer list
| ctor_init_list brace_block << is_definition=true; >>
// definition of any other kind of method
| brace_block << is_definition=true; >>
;
method_signature[string& scope, string& methodName, string& paramList] :
<<
int startLine=LT(1)->getLine();
>>
scoped_identifier[scope,methodName] param_list[scope,paramList] opt_const_modifier
<<
>>
;
type[string& cvQualifiers, string& typeName, string& indirMods] :
(cv_qualifier[cvQualifiers])* { STATIC }
type_name[typeName]
indirection_modifiers[indirMods]
;
cv_qualifier[string& cvQualifiers] :
<< string nextTokenText=LT(1)->getText(); >>
(
KW_CONST
| MUTABLE
| VOLATILE
| REGISTER
)
<< cvQualifiers=typeCombine(cvQualifiers,nextTokenText,""); >>
;
type_name[string& typeName] :
builtin_type[typeName]
| user_type[typeName]
;
indirection_modifiers[string& indirMods] :
(indirection_modifier[indirMods])?
indirection_modifier[indirMods] indirection_modifiers[indirMods]
| /* empty */
;
indirection_modifier[string& indirMods] :
(KW_CONST ASTERISK)? << indirMods+="const*"; >>
| ASTERISK << indirMods+="*"; >>
| AMPERSAND << indirMods+="&"; >>
;
builtin_type[string& typeName] :
(type_keyword[typeName])+
;
type_keyword[string& typeName] :
<< string tokenText=LT(1)->getText(); >>
(
KW_VOID
| KW_BOOL
| KW_CHAR | KW_INT
| KW_FLOAT | KW_DOUBLE
| KW_SHORT | KW_LONG | UNSIGNED | SIGNED
)
<<
// We only really care about the type name so that we
// can count relationships between classes, so what we store
// here is a bit arbitrary. We choose to represent the type
// of composed builtin types such as 'unsigned char' using
// only the last keyword (i.e. 'char' in this case), so that
// we don't have to have an enormous supression list of different
// variants like 'long long unsigned int'.
typeName=tokenText;
>>
;
user_type[string& typeName] : << string scope,name; >>
{ class_key[d1] } scoped_identifier[scope,name]
<< typeName=pu->scopeCombine(scope,name); >>
;
scoped_member_name: << string dummy1, dummy2; >>
scoped_identifier[dummy1,dummy2]
;
scoped_identifier[string& scope, string& name] :
( explicit_scope_spec[scope] )?
explicit_scope_spec[scope] scoped_identifier[scope,name]
| unscoped_member_name[name]
;
explicit_scope_spec[string& scope] :
cl:IDENTIFIER {angle_block} COLONCOLON
<<
scope=cl->getText();
ps->set_flag(vDONTKNOW);
>>
;
unscoped_member_name[string& name] :
(
(id1:IDENTIFIER angle_block)? << name=$id1->getText(); >>
| id2:IDENTIFIER << name=$id2->getText(); >>
| dtor_member_name[name]
| operator_member_name[name]
)
;
dtor_member_name[string& name] :
TILDA id:IDENTIFIER
<<
name="~";
name+=$id->getText();
>>
;
operator_member_name[string& name] : << string operatorIdentifier; >>
OPERATOR operator_identifier[operatorIdentifier]
<<
name+="operator ";
name+=operatorIdentifier;
>>
;
operator_identifier[string& opname] :
<<
string cv,name,indir;
opname=LT(1)->getText();
>>
(op)?
| (new_or_delete LBRACK RBRACK)? << opname+="[]"; >>
| new_or_delete
| type[cv,name,indir] << opname=name+indir; >>
| LPAREN RPAREN << opname="()"; >>
| LBRACK RBRACK << opname="[]"; >>
;
new_or_delete :
NEW
| DELETE
;
param_list[string& scope, string& params] :
<<
int startLine=LT(1)->getLine();
string param_items;
>>
( LPAREN param_list_items[scope,param_items] RPAREN )?
<<
params="(";
params+=param_items;
params+=")";
>>
| paren_block
<<
params="(...)";
>>
;
param_list_items [string& scope, string& items] :
/* empty */
| param_item[scope,items] more_param_items[scope,items]
;
more_param_items[string& scope, string& items] :
<< string next_item, further_items; >>
/* empty */
| COMMA param_item[scope,next_item] more_param_items[scope,further_items]
<<
items+=",";
items+=next_item;
items+=further_items;
>>
;
param_item[string& scope, string& item] :
param_type[scope,item] param_spec
;
param_type[string& scope, string& typeName] :
<<
string cvmods, name, indir;
int startLine=LT(1)->getLine();
>>
type[cvmods,name,indir]
<<
// we distinguish between value & reference by
// looking at the length of the string of indirection
// operator associated with the last recognised type
if(indir.size()!=0)
{
ps->record_userel_extent(startLine,startLine,
scope,"",name,
"pass by reference",
ps->get_visibility(),
utPARBYREF);
}
else
{
ps->record_userel_extent(startLine,startLine,
scope,"",name,
"pass by value",
ps->get_visibility(),
utPARBYVAL);
}
typeName=typeCombine(cvmods,name,indir);
>>
;
param_spec :
{ IDENTIFIER } { "=" literal }
;
knr_param_decl_list :
/* empty */
| instance_declaration[d1] knr_param_decl_list
;
<<
cerr << "failed knr_param_decl_list for token "
<< static_cast(LT(1)->getType()) << ' '
<< LT(1)->getText() << endl;
>>
opt_const_modifier :
/* empty */
<<
ps->set_flag(psfCONST,abFALSE);
>>
| KW_CONST
<<
ps->set_flag(psfCONST,abTRUE);
>>
;
<<
// fail action for opt_const_modifier
// I can't see how we can fail this, but we seem to manage
cerr << "failed opt_const_modifier for token "
<< static_cast(LT(1)->getType()) << ' '
<< LT(1)->getText() << endl;
>>
typedef_definition : << string dummy; >>
( fptr_typedef_definition )?
| ( TYPEDEF class_key[dummy])? struct_typedef_definition
| simple_typedef_definition
;
fptr_typedef_definition :
TYPEDEF type[d1,d2,d3] fptr_type_alias SEMICOLON
;
// This rule added in response to a report sent by Tennis Smith of
// Cisco.
// It supports the old C-style idiom where a struct is defined within
// a typedef (either with or without a name).
// There's a lot of this code out there...
struct_typedef_definition : << string dummy; >>
TYPEDEF class_key[dummy] identifier_opt brace_block tag_list_opt SEMICOLON
;
simple_typedef_definition :
TYPEDEF type[d1,d2,d3] simple_type_alias SEMICOLON
;
identifier_opt :
IDENTIFIER
| /* empty */
;
tag_list_opt :
tag ( COMMA tag )*
| /* empty */
;
tag :
( ASTERISK )* IDENTIFIER
;
simple_type_alias :
id:IDENTIFIER
;
fptr_type_alias :
LPAREN ASTERISK scoped_identifier[d1,d2] RPAREN paren_block
;
class_or_method_declaration_or_definition[string& scope] : << string dummy; >>
(class_key[dummy])? class_declaration_or_definition[scope]
| (scoped_member_name LPAREN)?
method_declaration_or_definition_with_implicit_type[scope]
| method_declaration_or_definition_with_explicit_type[scope]
;
class_prefix[string& modname, string& modtype] :
class_key[modtype] scoped_identifier[d1,modname] { angle_block }
// or perhaps an anonymous type...
| class_key[modtype]
;
inheritance_list [string& childName] :
<< ps->set_flag(vPRIVATE); >>
COLON inheritance_item_list[childName]
;
inheritance_item_list[string& childName] :
inheritance_item[childName] ( COMMA inheritance_item[childName])*
;
inheritance_access_key :
VIRTUAL { access_key }
| access_key { VIRTUAL }
| /* empty */
;
inheritance_item[string& childName] :
<<
string parent_scope,parent_name;
int startLine=LT(1)->getLine();
>>
inheritance_access_key type_name[parent_name]
<<
int endLine=LT(1)->getLine();
ps->record_userel_extent(startLine,endLine,
childName,"",parent_name,
"inheritance",
ps->get_visibility(),
utINHERITS);
>>
;
class_key[string& modtype] : << modtype=LT(1)->getText(); >>
CLASS << ps->set_flag(vPRIVATE); >>
| STRUCT << ps->set_flag(vPUBLIC); >>
;
access_key :
PUBLIC!
<<
ps->set_flag(vPUBLIC);
>>
| PRIVATE!
<<
ps->set_flag(vPRIVATE);
>>
| PROTECTED!
<<
ps->set_flag(vPROTECTED);
>>
;
ctor_init_list :
COLON ctor_init_item_list
;
ctor_init_item_list :
( ctor_init_item COMMA )? ctor_init_item COMMA ctor_init_item_list
| ctor_init_item
;
ctor_init_item :
instance_item[d1,d2]
;
linkage_qualifiers:
(linkage_qualifier)? linkage_qualifier linkage_qualifiers
| /* empty */
;
linkage_qualifier :
STATIC << ps->set_flag(psfSTATIC,abTRUE); >>
| ( EXTERN STRINGCONST )?
| EXTERN
| INLINE
| TEMPLATE { angle_block }
;
identifier_or_brace_block_or_both :
IDENTIFIER opt_brace_block
;
opt_brace_block :
( brace_block )?
| /* empty */
;
instance_item[string& indir,string& name] :
item_specifier[indir,name] brack_list opt_initializer
;
item_specifier[string& indir,string& name] :
LPAREN ASTERISK scoped_member_name RPAREN paren_block
| (indirection_modifier[indir])* scoped_identifier[d1,name]
;
opt_initializer: << string dummy; >>
"=" init_expr
| ( LPAREN RPAREN )?
| LPAREN init_expr RPAREN
| /* empty */
;
init_expr :
( init_expr_item op )? init_expr_item op init_expr
| init_expr_item
;
init_expr_item :
SIZEOF paren_block
| paren_block
| brace_block
| (IDENTIFIER paren_block)?
| cast_keyword angle_block paren_block
| constant
;
cast_keyword :
STATIC_CAST | CONST_CAST | REINTERPRET_CAST
;
init_value:
constant
| brace_block
| paren_block
;
keyword :
ASM | AUTO | KW_BOOL | BREAK | CASE | CATCH | KW_CHAR | CLASS | KW_CONST
| CONTINUE | DEFAULT | DELETE | KW_DOUBLE | DO | DYNAMIC_CAST | ELSE
| ENUM | EXTERN | EXPLICIT
| BFALSE | KW_FLOAT | FOR | FRIEND | GOTO | IF | INLINE | KW_INT | KW_LONG | NEW
| OPERATOR | PRIVATE | PROTECTED | PUBLIC | REGISTER
| REINTERPRET_CAST | RETURN
| KW_SHORT | SIGNED | SIZEOF | STATIC | STATIC_CAST | STRUCT
| SWITCH | TEMPLATE
| KW_THIS | THROW | BTRUE | TRY | TYPEDEF | UNION | UNSIGNED | VIRTUAL
| KW_VOID | VOLATILE | WHILE
;
op :
EQUAL_OP | ASSIGN_OP | OP_ASSIGN_OP | SHIFT_OP | REL_OP
| ASTERISK | DIV_OP | PM_OP | INCR_OP | ADD_OP | QUERY_OP
| LOGICAL_AND_OP | LOGICAL_OR_OP | LOGICAL_NOT_OP | BITWISE_OP
| COLONCOLON | COLON | PERIOD | ARROW | COMMA
;
constant :
literal
| IDENTIFIER
;
literal :
string_literal
| CHARCONST | FNUM
| OCT_NUM | L_OCT_NUM | HEX_NUM | L_HEX_NUM | INT_NUM | L_INT_NUM
| BTRUE | BFALSE
| ADD_OP literal
;
string_literal :
(STRINGCONST STRINGCONST)? STRINGCONST string_literal
| STRINGCONST
;
block :
brace_block
| brack_block
| paren_block
;
balanced :
scoped
| block
| SEMICOLON
;
balanced_list :
( balanced )? balanced balanced_list
| /* empty */
;
nested_token_list [ int nl ] :
nested_token[nl] nested_token_list[nl]
| /* empty */
;
nested_token [ int nl ] : << ANTLRTokenPtr la_ptr=LT(1); >>
<< (la_ptr!=0) && (mytoken(la_ptr)->getNestingLevel() > nl) >>?
tok:.
;
scoped :
( keyword )?
| (op)?
| IDENTIFIER
| literal
;
brace_block : << int brace_level=MY_TOK(LT(1))->getNestingLevel(); >>
LBRACE skip_until_matching_rbrace[brace_level]
;
skip_until_matching_rbrace [ int brace_level ] :
<<
// this is an init action, so it should be executed unconditionally
// when we try to match this rule
while(MY_TOK(LT(1))->getNestingLevel()>=brace_level)
{
if(LT(1)->getType()==Eof)
{
// We have reached the end of file with unbalanced {} nesting.
// Presumably somebody stuffed up. Maybe a preprocessor problem.
// Anyway, get out of this rule. Expect a syntax error RSN.
break;
}
else
{
consume();
}
}
>>
RBRACE
;
paren_block :
LPAREN balanced_list! RPAREN
;
brack_block :
LBRACK balanced_list! RBRACK
;
brack_list :
( brack_block )? brack_block brack_list
| /* empty */
;
angle_balanced_list :
<< LT(1)->getType() == LESSTHAN >>? angle_block angle_balanced_list
| << LT(1)->getType() == GREATERTHAN >>?
/* empty, the token will be matched in parent rule angle_block */
| ~GREATERTHAN angle_balanced_list /* consume one token & recurse */
;
angle_block :
LESSTHAN! angle_balanced_list! GREATERTHAN!
;
}
#token TOKENTYPE_MAX
// -*-c++-*- (Emacs mode request)
cccc-3.1.4/cccc/cccc.h 0000644 0000000 0000000 00000004434 10020121650 013037 0 ustar root root /*
* cccc.h
* diagnostic and portability facilities for the cccc project
*/
#ifndef _CCCC_H__
#define _CCCC_H__
#ifdef _WIN32
#pragma warning (disable:4786 4503)
#endif
// I am trying to standardise on using the ANSI C++ names
// for the ANSI C header files, and bringing all of
// the includes of these libraries into this file.
// I have not yet attempted to purge includes for these
// files from the other source files.
#include
#include
#include
#include
#include
#include
#include
using std::string;
#include
#include
#include
using std::ostream;
using std::istream;
using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::ostringstream;
using std::stringstream;
using std::endl;
using std::cout;
using std::cerr;
// debugging facilities
extern int DebugMask;
enum DebugFlags {
LEXER=0x01,
PARSER=0x02,
COUNTER=0x04,
MEMORY=0x08,
EXTENT=0x10,
DATABASE=0x20
};
#define DbgMsg(DF,OS,X) if(DebugMask&DF) { OS << X ; }
// the global database to which stuff is added...
class CCCC_Project;
extern CCCC_Project *prj;
// a nasty global array of identifiers we want the lexer to ignore
#define SKIP_IDENTIFIERS_ARRAY_SIZE 256
extern char *skip_identifiers[SKIP_IDENTIFIERS_ARRAY_SIZE];
#if 0
#include "DLGLexer.h"
#endif
// These macros were used to cover differences between the way the
// old strstream classes were used in Win32 and GNU builds.
// The differences are no longer necessary.
#define MAKE_STRSTREAM(X) stringstream X;
#define CONVERT_STRSTREAM(X) (X)
#define RELEASE_STRSTREAM(X)
// The -gd option generates uncompilable code with a missing
// variable called zzTracePrevRuleName if the generated
// files cccc.cpp, java.cpp, ada.cpp don't include a version
// of AParser.h seen with zzTRACE_RULES defined.
// I'm not sure how this is supposed to work, but for the moment
// I am including it here which should make all three files OK.
// Note that this could break again if the header files shift around
// and AParser.h gets read before zzTRACE_RULES is defined.
// Another option is turning -gd off, but its the way we do the
// cccc -dp debug output which is very useful.
#include "cccc_tok.h"
#define zzTRACE_RULES
#include "AParser.h"
#endif
cccc-3.1.4/cccc/cccc_db.cc 0000644 0000000 0000000 00000007670 10357241712 013666 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cccc.h"
#include
#include "cccc_itm.h"
#include "cccc_db.h"
CCCC_Project *current_loading_project=NULL;
CCCC_Module *current_loading_module=NULL;
CCCC_Member *current_loading_extent=NULL;
CCCC_UseRelationship *current_loading_userel=NULL;
#define LINE_BUFFER_SIZE 1000
int ifstr_line;
extern CCCC_Project *prj;
// the file scope variable last_supplier is used to supress repeated
// output of the supplier name in the use relationship section where
// the current record has the same supplier as the previous one
// the indentation makes this reasonably clear
static string last_supplier="";
// persistence facilities
#define SEP '@'
// This function provides the ability for the persistence functions
// defined below to do a quick peek at the first token on the stream
// leaving the get pointer at the start of that token.
// This should be static, but on MSVC++ this gives me an unresolved
// symbol at link.
bool PeekAtNextLinePrefix(ifstream& ifstr, string pfx)
{
bool retval=false;
char prefix_buffer[1024];
size_t initial_stream_pos=ifstr.tellg();
ifstr.getline(prefix_buffer,1023,SEP);
if(pfx==prefix_buffer)
{
retval=true;
}
ifstr.seekg(initial_stream_pos);
return retval;
}
// this is a sort of abstract junkyard function (cf Abstract Factory)
template void DisposeOfImportRecord(T *record_ptr, int fromfile_status)
{
switch(fromfile_status)
{
case RECORD_ADDED:
// the newly created object has been added to the
// database
// we must not delete it
break;
case RECORD_TRANSCRIBED:
// the database already had an object for this item
// the content of the new object was merged in, but the object
// itself is no longer required
delete record_ptr;
break;
default:
// something went wrong, so we mention it
cerr << "Import error " << fromfile_status
<< " at line " << ifstr_line
<< " for " << record_ptr->key()
<< endl;
delete record_ptr;
}
}
// when we add a record to, for example, the extent table for a member of
// a module, we need to merge the information in the new extent
// with what is already known
// there are two kinds of merge:
// 1. ordinary fields like module_type should either be consistent or
// blank for all extents relating to the same module, so where the old
// field is blank, we overwrite with the new field
// 2. the flags field in CCCC_Member contains a variety of single character
// flags giving the visibility, constness, etc. of the member, with '?' being
// used to reflect a state of lack of knowledge: in these cases, any other
// value can overwrite '?', all other values do not change.
void Resolve_Fields(string& field1, string& field2)
{
if(field1.size()==0)
{
field1=field2;
}
}
template
void
DisposeOfImportRecord(CCCC_Module *record_ptr, int fromfile_status);
template
void
DisposeOfImportRecord(CCCC_Member *record_ptr, int fromfile_status);
template
void
DisposeOfImportRecord(CCCC_UseRelationship *record_ptr, int fromfile_status);
template
void
DisposeOfImportRecord(CCCC_Extent *record_ptr, int fromfile_status);
cccc-3.1.4/cccc/cccc_db.h 0000644 0000000 0000000 00000005613 10357241712 013523 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* cccc_db.h
*/
#ifndef CCCC_DB_H
#define CCCC_DB_H
#include "cccc.h"
#include "cccc_ext.h"
#include "cccc_rec.h"
#include "cccc_prj.h"
#include "cccc_mod.h"
#include "cccc_mem.h"
#include "cccc_use.h"
// The various FromFile functions need to indicate to their
// caller their status, particularly because the caller will have
// allocated an instance of the incoming class on the heap, and needs
// to know whether it has to delete it. There are two 'normal' outcomes
// plus a potentially infinite range of possible application error
// conditions. The normal conditions are where the new instance is
// the first encountered of this module/member/relationship/whatever
// and the allocated item has been added to the database and must not
// be deleted, and when the new instance is of a previously encountered
// entity, and the information from the new record has been transcribed
// and merged into the instance in the database, and the locally allocated
// instance must be deleted.
enum GeneralFromFileStatuses
{
RECORD_TRANSCRIBED = 0,
RECORD_ADDED = 1,
RECORD_ERROR = 2
// error conditions may return RECORD_ERROR, or may use a distinctive
// value defined as a literal
};
// This function provides the ability for the persistence functions
// defined below to do a quick peek at the first token on the stream
// leaving the get pointer at the start of that token.
bool PeekAtNextLinePrefix(ifstream& ifstr, string pfx);
// These are global variables because I don't want to have
// to pass the project, module, member, relationship down into all of the
// FromFile methods.
// There is probably a better way for a less lazy programmer than me.
extern CCCC_Project *current_loading_project;
extern CCCC_Module *current_loading_module;
extern CCCC_Member *current_loading_extent;
extern CCCC_UseRelationship *current_loading_userel;
// this one tracks the line number in the input file
extern int ifstr_line;
template void DisposeOfImportRecord(T *record_ptr, int fromfile_status);
void Resolve_Fields(string& field1, string& field2);
#endif // CCCC_DB_H
cccc-3.1.4/cccc/cccc_ext.cc 0000644 0000000 0000000 00000007322 10357241712 014073 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* cccc_ext.cc
*/
#include "cccc_itm.h"
#include "cccc_ext.h"
#include "cccc_db.h"
#include "cccc_utl.h"
unsigned int CCCC_Extent::nextkey=0;
CCCC_Extent::CCCC_Extent()
{
v=vINVALID;
ut=utINVALID;
extkey=++nextkey;
}
CCCC_Extent::CCCC_Extent(CCCC_Item& is)
{
char v_as_char='!', ut_as_char='!';
if(
is.Extract(filename) &&
is.Extract(linenumber) &&
is.Extract(description) &&
is.Extract(flags) &&
is.Extract(count_buffer) &&
is.Extract(v_as_char) &&
is.Extract(ut_as_char)
)
{
v=(Visibility) v_as_char;
ut=(UseType) ut_as_char;
}
else
{
// we can trust the string constructor to give us empty strings,
// but we need to initialise these
v=vDONTKNOW;
ut=utDONTKNOW;
}
extkey=++nextkey;
}
int CCCC_Extent::AddToItem(CCCC_Item& item)
{
int retval=FALSE;
if(
item.Insert(filename) &&
item.Insert(linenumber) &&
item.Insert(description) &&
item.Insert(flags) &&
item.Insert(count_buffer) &&
item.Insert((char) v) &&
item.Insert((char) ut)
)
{
retval=TRUE;
}
return retval;
}
int CCCC_Extent::GetFromItem(CCCC_Item &item)
{
int retval=FALSE;
char v_as_char, ut_as_char;
if(
item.Extract(filename) &&
item.Extract(linenumber) &&
item.Extract(description) &&
item.Extract(flags) &&
item.Extract(count_buffer) &&
item.Extract(v_as_char) &&
item.Extract(ut_as_char)
)
{
v = (Visibility) v_as_char;
ut = (UseType) ut_as_char;
retval=TRUE;
}
return retval;
}
string CCCC_Extent::name(int level) const
{
string rtnbuf;
rtnbuf="";
switch(level)
{
case nlFILENAME:
rtnbuf=filename;
break;
case nlLINENUMBER:
rtnbuf=linenumber;
break;
case nlDESCRIPTION:
rtnbuf=description;
break;
case nlSEARCH:
case nlRANK:
// Extents have no meaningful internal primary key.
// We never want two extents to have the same
// key, so we use the running number extkey
// which is initialized in both constructors.
// This should cause extents to sort in order of
// their creation, which is fine.
char buf[16];
sprintf(buf,"%015d",extkey);
rtnbuf=buf;
break;
default:
rtnbuf+=filename;
rtnbuf+=":";
rtnbuf+=linenumber;
}
return rtnbuf.c_str();
}
string CCCC_Extent::key() const { return name(nlRANK); }
int CCCC_Extent::get_count(const char* count_tag) {
int retval=0;
char local_count_buffer[100], *count_tag_ptr, *count_value_ptr;
strcpy(local_count_buffer,count_buffer.c_str());
count_tag_ptr=strtok(local_count_buffer,":");
while(count_tag_ptr!=NULL)
{
count_value_ptr=strtok(NULL," ");
if(strcmp(count_tag_ptr, count_tag) ==0)
{
retval+=atoi(count_value_ptr);
}
count_tag_ptr=strtok(NULL,":");
}
return retval;
}
cccc-3.1.4/cccc/cccc_ext.h 0000644 0000000 0000000 00000003303 10357241712 013730 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* cccc_ext.h
*/
#ifndef CCCC_EXT_H
#define CCCC_EXT_H
#include
using std::string;
#include "cccc_utl.h"
class CCCC_Item;
enum ExtentNameLevel { nlFILENAME=-1, nlLINENUMBER=-2, nlDESCRIPTION=-3};
class CCCC_Extent
{
friend class CCCC_Record;
friend class CCCC_Project;
string filename;
string linenumber;
string description;
string flags;
string count_buffer;
UseType ut;
Visibility v;
static unsigned int nextkey;
unsigned int extkey;
public:
CCCC_Extent();
CCCC_Extent(CCCC_Item& is);
string name( int index ) const;
string key() const;
int GetFromItem(CCCC_Item& item);
int AddToItem(CCCC_Item& item);
Visibility get_visibility() const { return v; }
int get_count(const char *count_tag);
UseType get_usetype() const { return ut; }
const char* get_description() const { return description.c_str(); }
};
#endif // CCCC_EXT_H
cccc-3.1.4/cccc/cccc_htm.cc 0000644 0000000 0000000 00000126766 10357241712 014101 0 ustar root root /*
CCCC - C and C++ Code Counter
Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// cccc_htm.cc
// this file defines HTML output facilities for the CCCC project
#include "cccc.h"
#include "cccc_itm.h"
#include "cccc_htm.h"
// I would love to use the C++ standard preprocessor
// directive #if here, but I have had reports before now
// of people who are using compilers which only support
// #ifdef.
#ifdef CCCC_CONF_W32VC
#include
#else
#ifdef CCCC_CONF_W32BC
#include
#else
#include
#endif
#endif
#include
#include
#include "cccc_utl.h"
typedef std::map source_anchor_map_t;
source_anchor_map_t source_anchor_map;
// class static data members
CCCC_Project* CCCC_Html_Stream::prjptr;
string CCCC_Html_Stream::outdir;
string CCCC_Html_Stream::libdir;
void CCCC_Html_Stream::GenerateReports(CCCC_Project* prj,
int report_mask,
const string& file,
const string& dir)
{
prjptr=prj;
outdir=dir;
CCCC_Html_Stream main_html_stream(file.c_str(),"Report on software metrics");
if(report_mask & rtCONTENTS)
{
// For testing purposes, we want to be able to disable the inclusion
// of the current time in the report. This enables us to store a
// reference version of the report in RCS and expect the program
// to generate an identical one at regression testing time.
if(report_mask & rtSHOW_GEN_TIME)
{
main_html_stream.Table_Of_Contents(report_mask,true);
}
else
{
main_html_stream.Table_Of_Contents(report_mask,false);
}
}
if(report_mask & rtSUMMARY)
{
main_html_stream.Project_Summary();
}
if(report_mask & rtPROC1)
{
main_html_stream.Procedural_Summary();
}
if(report_mask & rtPROC2)
{
main_html_stream.Procedural_Detail();
}
if(report_mask & rtOODESIGN)
{
main_html_stream.OO_Design();
}
if(report_mask & rtSTRUCT1)
{
main_html_stream.Structural_Summary();
}
if(report_mask & rtSTRUCT2)
{
main_html_stream.Structural_Detail();
}
if(report_mask & rtSEPARATE_MODULES)
{
main_html_stream.Separate_Modules();
}
if(report_mask & rtOTHER)
{
main_html_stream.Other_Extents();
}
if(report_mask & rtSOURCE)
{
main_html_stream.Source_Listing();
}
if(report_mask & rtCCCC)
{
main_html_stream.Put_Section_Heading("About CCCC","infocccc",1);
main_html_stream.fstr
<< "
This report was generated by the program CCCC, which is FREELY "
<< "REDISTRIBUTABLE but carries NO WARRANTY." << endl
<< "
CCCC was developed by Tim Littlefair. " << endl
<< "as part of a PhD research project. "
<< "This project is now completed and descriptions of the "
<< "findings can be accessed at "
<< ""
<< "http://www.chs.ecu.edu.au/~tlittlef. "
<< "