Source code file content

Revision: 2

import
» Project Revision History

» Checkout URL

web-content / trunk / dev / reviews / opinions_91591.html

Size: 26618 bytes, 1 line
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
    <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
    <title>Discovery feature</title>
    <META NAME="AUTHOR" CONTENT="Alexander Simon">
</head>
<link rel="stylesheet" type="text/css" href="http://www.netbeans.org/netbeans.css">
<BODY LANG="en-US" DIR="LTR">
<h1>Architecture Review Opinion</h1>

<dl>
<dt><b>Issue:</b> <a href="http://www.netbeans.org/issues/show_bug.cgi?id=91591">91591</a></dt>
<dt><b>Submitter:</b> <a href="mailto:alexvsimon@netbeans.org">Alexander Simon</a></dt>
<dt><b>History:</b><a href="http://www.netbeans.org/source/browse/cnd/www/dev/reviews/opinions_91591.html">in CVS</a>
<dt><b>Date:</b> Dec 27, 2006</dt>
<dt><b>Reviewers:</b> </dt>
</dl>
<hr/>
<dl>
<dt><b>Contents</b></dt>
<dd>
<ul>
    <li><a href="#summary">Summary</a></li>
    <li><a href="#ways">Discovery include paths and macros</a></li>
    <li><a href="#use">Use cases</a></li>
    <li><a href="#wizard">Wizard</a></li>
    <li><a href="#accuracy">Accuracy</a></li>
    <li><a href="#opinion">Minority Opinion</a></li>
    <li><a href="#appendices">Appendices</a>
        <ul>
        <li><a href="#api">API</a></li>
        </ul>
    </li>
</ul>
</dd>
</dl>

<hr/>

<!-- ===================================================================================== -->

<h2><a name="summary">Summary</a></h2>
<p>Module design. As we have seen the discovery facility can be invoked from many places.
We don't know all potential includes and macros providers. 
<IMG SRC="91591/discovery.png" NAME="Sybsystem Overview" ALIGN=BOTTOM BORDER=0><BR>
   
<!-- ===================================================================================== -->

<h2><a name="ways">Discovery include paths and macros</a></h2>
<p>
I see following ways to resolve problem with include path and macros:
<ol>
<li>
Run "make" in path of which own redefined compiler. 
Redefined compiler is a script which redirect current folder and compiler parameters to output file.
For example redefiniton of g++:
<pre class="examplecode">
export SUSTITUTE_GCC=${GNU_PATH}/g++
substitute.sh $@
</PRE>
substitute.sh:
<pre class="examplecode">
echo "# Compiler substitition: runnung ${SUSTITUTE_GCC} -g $@" 
echo "g++ `pwd` $@" >> ${SUSTITUTE_GCC_FILE}.gcc
${SUSTITUTE_GCC} -g $@  
echo "****************************************************************"
</PRE>
Discovery facility should analyze output file and discover for each file(folder) include paths and macros. 
Also output file contains information about object files. Relation between source files and 
object files can be saved and used in other tools (may be in symbol table or in cross references table).
</li>
<li>
Analyze file system from project root (may be additional folders that user select). 
This way can be applied after model parsing. Model exactly know all failed include directives and 
source files that contain directives. We can find failed includes and suggest to add includes paths. 
Now there are no way to detect missing macros. 
But we can build at parsing time table of undefined macros and suggest user to add some of this. 
This way not reliable.
</li>
<li>
Analyze binary file (or all object files). Extract from file dwarf information.
This way gets list of object files that contains path to sources and included. 
Source files should be compiled with flags:
<pre class="examplecode">
 -g3 -gdwarf-2
</PRE>
Macros can be extracted too.
</li>
<li>
Analyze make file. It's a very complicated way. We should analyze make and shell commands. 
But in this way we cannot detect result of executing user commands.
</li>
<li>
Run "make -n". It output depend on how make was written. 
It can provide us all needed information but sometimes not. 
It can  have infinite loop. It can  do part of work. And so on.
</li>
<li>
Use .make.state files (use KEEP_STATE feature).
If the project is already built (even if the build was not successful) and
if it has .KEEP_STATE: target in makefiles, dmake (and Solaris make)
will save information about each compilation in .make.state files.
All we need is to search for a source file name in .make.state files, and
we will get a compilation instruction, something like this one:
<pre class="examplecode">
 cc -D_POSIX_ -D_SUN_OS_ -g  -c  915resolution.c
</PRE>
But what is more important, if we use Sun Studio compilers, they will
write a list of include files into .make.state file.
GNU make and compilers also can generate the
list of dependencies, but they use a different mechanism, and we can
use it as well.
</li>
<li>
Use source browser information.
Sun Studio compilers have a special option ("-xsb") to generate data
for the Sun Studio source browser. If the project is built with this
option, we can get all information from the source browser repository.
I don't think it is an easy task, but we can reuse sources of the existing
source browser. Obviously this solution is limited to the projects, that
are built with Sun Studio compilers with "-xsb" option.
</li>
</ol>

<!-- ===================================================================================== -->

<h2><a name="use">Use cases</a></h2>
<p>
Let's take first way. Possible use cases:
<ol>
    <li>an axillary step in create new project from existent make file.
    <p>If user select step we
    <ul>
        <li>run make</li>
        <li>analyze output</li>
        <li>automatically filling user include paths and macros for next steps.
        <p>Additional behavior:</li>
        <li>setup each file that should have individual options.</li>
        <li>exclude source "not compiled" files from project.</li>
    </ul>
    </li>
    <li>an action on failed include directive highlighting. User can select:
    <ul>
        <li>fix only this include.</li>
        <li>fix all failed include directives.
        <p>In this way we:</li>
        <li>run make</li>
        <li>analyze output</li>
        <li>suggest user to update include paths and macros on project/folder/file level.
        <p>Additional behavior:</li>
        <li>exclude source "not compiled" files from project.</li>
    </ul>
    </li>
    <li>an axillary action in "failed include directives" dialog.
    <p>In this way we:
    <ul>
        <li>run make</li>
        <li>analyze output</li>
        <li>suggest user to update include paths and macros on project/folder/file level.
        <p>Additional behavior:</li>
        <li>exclude source "not compiled" files from project.</li>
    </ul>
    </li>
    <li>an additional action in "project properties" dialog (or include directories/preprocessor definitions dialogs)
    <p>In this way we:
    <ul>
        <li>run make</li>
        <li>analyze output</li>
        <li>suggest user to update include paths and macros on project/folder/file level.</li>
    </ul>
    </li>
    <li>run stanalone application that build netbeans project.</li>
</ol>

<!-- ===================================================================================== -->

<h2><a name="wizard">Wizard</a></h2>
<p>Proposal of discovery system work flow.
<p>At first define a subject of proposal.
<p>Restrict consideration of configuration following settings:
<ul>
   <li>user include paths.</li>
   <li>user macros.</li>
</ul>
<p><b>Definition</b>: Object configuration is a set of user include paths and set of user macros.
<p><b>Definition</b>: Resulting file configuration is a configuration that is used in code assistant.
<p><b>Definition</b>: Union of configurations is a configuration where:
<ul>
   <li>user include paths are mathematical union of user include paths from configurations.</li>
   <li>user macros are mathematical union by macros names of user macros from configurations.
   If two configurations have same macros then result contains more specialized macro 
   (file macro override folder and project  macro, folder macro override project macro).</li>
</ul>
<p>What we have now:
<p>Project have configurations divided by languages (C/C++).
<p>File have configuration.
<p>Resulting file configuration is a union of project and file configurations.
<p>What is lack for complicated make based project:
<ul>
   <li>union of file configurations can be wrong for project configuration.</li>
   <li>difficult configure each source file if cannot be extracted common project configuration.</li>
</ul>
<p>What I propose:
<p>Add folder settings divided by languages (C/C++).
<p>Resulting file configuration is a union of project, folders and file configurations.
Tree folder structure is taken account. I.e. if folder has configured parent folder 
then resulting child folder configuration is a union of parent folder configuration and child.
<p>Each folder and file have an boolean property that switch off inheritance
for user include paths and user macros separately.
It means that resulting configuration doesn't include parent configuration.
<p>Reasons of have individual non-inherited folder configuration:
<ul>
   <li>make based project in general have same -I and -D options for all compiled files in a folder.</li>
   <li>make based project can have different -I and -D options for sub folders.</li>
   <li>make based project can have different -I and -D options child and parent folders.</li>
</ul>
<p>Problems of inherited folder configurations:
<ul>
   <li>parent folder configuration can have empty intersection of child folders.
   Hence in most cases parent folder should have empty configuration.</li>
   <li>parent folder can source files. In this case intersection of files configurations cannot be set
   for parent folder because it can damage child folders configuration.</li>
   <li>overhead of counting resulting file configuration.</li>
</ul>
<p>Discovery frame work behavior.
<p>Frame work gets files configurations from discovery provider (see wizard step 1).
The provider gathers object files and extract files configurations.
<p>User has three modes of consolidation level (see wizard step 2):
<ul>
   <li>project level. In this level only project configuration is set.
   Folders and files configurations are empty. All files and folders inheritance properties are switch on.
   Hence resulting files and folder configurations equals project configuration.
   Frame work count project configuration as a union of all file's configurations.
   This level simplify following project support and suitable in most cases.</li>
   <li>folder level. In this level frame work count folder's configurations as a union of child files' configurations.
   Files configurations are empty. All files inheritance properties are switch on.
   If intersection of all folder's configuration is not empty
   then frame work extract common project configuration and clear common part from folder's configurations.</li>
   <li>file level. Each file has configuration. Frame work try to extract files common configuration on folder level and
   extract common folder configuration on project level.</li>
</ul>
<p>According to selected strategy discovery frame work consolidate configurations (see wizard step 3). Page have two presentation modes:
<ul>
   <li>show node configuration. For selected node only node configuration is shown. Inherited configuration isn't included.</li>
   <li>show resulting configuration. For selected node resulting configuration is shown. Inherited configuration is included.</li>
</ul>
<p>At the last step (see wizard step 4) frame work show unused files in checked tree.
<p>Checked node mean: Include any children source file in project.
<p>Result of discovery wizard are:
<ul>
   <li>project configuration divided by languages.</li>
   <li>folder configurations divided by languages.</li>
   <li>files configurations.</li>
   <li>files excluded from project.</li>
</ul>
<p>To apply results project system should accept results or provide interface for set results.
<p>
<IMG SRC="91591/discovery1.png" NAME="Configure Code Assistance" ALIGN=BOTTOM BORDER=0><BR>
<p>
<IMG SRC="91591/discovery2.png" NAME="Select Analyzed File(s)" ALIGN=BOTTOM BORDER=0><BR>
<p>
<IMG SRC="91591/discovery3.png" NAME="Configuration Level" ALIGN=BOTTOM BORDER=0><BR>
<p>
<IMG SRC="91591/discovery4.png" NAME="View Configuration" ALIGN=BOTTOM BORDER=0><BR>
<p>
<IMG SRC="91591/discovery5.png" NAME="Exclude Files" ALIGN=BOTTOM BORDER=0><BR>

<!-- ===================================================================================== -->

<h2><a name="accuracy">Accuracy</a></h2>
<p>Proposal for discovery system accuracy metrics.
<p>Test base is open source project MySQL (mysql-5.0.18).
<p>Create new project from existent sources. Finish wizard on step 4.
<p>
<IMG SRC="91591/make2.png" NAME="Make and Build Actions" ALIGN=BOTTOM BORDER=0><BR>
<p>Note: project location differs from source location. It allows us to have different project based on same sources.
<p>
<IMG SRC="91591/make4.png" NAME="Project Name and Location" ALIGN=BOTTOM BORDER=0><BR>
<p>Wait till the end of parsing. Look at failed include directives.
<p>
<IMG SRC="91591/failed_menu.png" NAME="View Failled Include Directives" ALIGN=BOTTOM BORDER=0><BR>
<p>Dialog shows 6532 failed include directives in 1592 files. 
<p>Dialog can print statistic to console by additional argument of java:
<pre class="examplecode">
-J-Dcnd.highlight.trace.statistic=true
</pre>
<table border="1" cellpadding="2" cellspacing="2">
  <tbody valign="middle" align="middle">
    <tr><td>Amount of #includes</td><td>10581</td></tr>
    <tr><td>Failed #includes</td><td>6532</td></tr>
    <tr><td>Resolve #include Accuracy</td><td>38.27%</td></tr>
    <tr><td/></tr>
    <tr><td>Amount of files</td><td>2642</td></tr>
    <tr><td>Failed files</td><td>1592</td></tr>
    <tr><td>File-based Accuracy</td><td>39.74%</td></tr>
  </tbody>
</table>
<p>where:
<p>Resolve Include Accuracy is rato of resolved #include directives to all #include directives in model source and header files. I.e.
<pre class="examplecode">
Resolve #include Accuracy = (10581 - 6532) / 10581 * 100%
</pre>
<p>File-based Accuracy is rato of not failed files to all files in model source and header files. I.e.
<pre class="examplecode">
File-based Accuracy = (2642 - 1592) / 2642 * 100%
</pre>
<p>This table shows problem of code assistance:
<ul>
   <li>it does not know how to resolve include directives.</li>
   <li>it does not know predefined macros.</li>
   <li>it does not know set of source and header files which are really used in the project.</li>
</ul>
<p>Configure code assistance. At first make sure that project is configured and built.
<p>Configure project by command in folder mysql-5.0.18:
<pre class="examplecode">
./configure --with-ndbcluster CFLAGS="-g3 -gdwarf-2" CXXFLAGS="-g3 -gdwarf-2" 
</pre>
<p>Build project by command:
<pre class="examplecode">
make
</pre>
<p>Configure code assistance.
<p>
<IMG SRC="91591/configure_menu.png" NAME="Configure Code Assistance" ALIGN=BOTTOM BORDER=0><BR>
<p>Steps are shown in the <a href="#wizard">Wizard</a> section.
<p>Note: these steps can be performed in the new project wizard (steps 5...9).
<p>Look at failed include directives.
<table border="1" cellpadding="2" cellspacing="2">
  <tbody valign="middle" align="middle">
    <tr><td>Amount of #includes</td><td>6913</td></tr>
    <tr><td>Failed #includes</td><td>9</td></tr>
    <tr><td>Resolve #include Accuracy</td><td>99.87%</td></tr>
    <tr><td/></tr>
    <tr><td>Amount of files</td><td>1827</td></tr>
    <tr><td>Failed files</td><td>3</td></tr>
    <tr><td>File-based Accuracy</td><td>99.84%</td></tr>
  </tbody>
</table>
<p>This table shows what most problems of code assistance were resolved:
<ul>
   <li>Each source file has include paths and predefined macros.</li>
   <li>Project contains files which were compiled.</li>
   <li>Project contains header files which were included in compiled files.</li>
</ul>
<p>This approach have a flaw:
<ul>
   <li>Project have to be configured with special flags. Not all configure commands allow to set needed flags.</li>
   <li>Project can not contain additional files such as samples or additional tools.</li>
</ul>
<p>Both problems can be resolved.
<p>Let's assume we have a project built with needed flags and we want to see all sources and headers.
<p>Select on step "Configuration Level" "Configure per Folder".
<p>Do not mark folders on step "Exclude Files".
<p>It allows us to have same configuration for all files in a folder.
<p>Look at failed include directives.
<table border="1" cellpadding="2" cellspacing="2">
  <tbody valign="middle" align="middle">
    <tr><td>Amount of #includes</td><td>11088</td></tr>
    <tr><td>Failed #includes</td><td>2435</td></tr>
    <tr><td>Resolve #include Accuracy</td><td>78.04%</td></tr>
    <tr><td/></tr>
    <tr><td>Amount of files</td><td>2719</td></tr>
    <tr><td>Failed files</td><td>598</td></tr>
    <tr><td>File-based Accuracy</td><td>78.01%</td></tr>
  </tbody>
</table>
<p>Another code assistance analyzer can help to resolve certain problems.
<p>Start "Configure Code Assistance" and select analyzer "Explore Code Model".
Analyzer is available after parsing is done.
<p>Select on step "Configuration Level" "Configure per Folder".
<p>Look at failed include directives.
<table border="1" cellpadding="2" cellspacing="2">
  <tbody valign="middle" align="middle">
    <tr><td>Amount of #includes</td><td>10947</td></tr>
    <tr><td>Failed #includes</td><td>122</td></tr>
    <tr><td>Resolve #include Accuracy</td><td>98.89%</td></tr>
    <tr><td/></tr>
    <tr><td>Amount of files</td><td>2796</td></tr>
    <tr><td>Failed files</td><td>81</td></tr>
    <tr><td>File-based Accuracy</td><td>97.10%</td></tr>
  </tbody>
</table>
<p>At last configure code assistance for one executable file.
<p>Start "Configure Code Assistance" and select analyzer "Explore Executable or Library File".
<p>Select on step "Select Analyzed File(s)" mysqld:
<pre class="examplecode">
/export/home/as204739/Projects/sfbay/mysql-5.0.18/sql/.libs/mysqld
</pre>
<p>Select on step "Configuration Level" "Configure per File".
<p>Mark folders on step "Exclude Files".
<p>Look at failed include directives.
<table border="1" cellpadding="2" cellspacing="2">
  <tbody valign="middle" align="middle">
    <tr><td>Amount of #includes</td><td>3993</td></tr>
    <tr><td>Failed #includes</td><td>0</td></tr>
    <tr><td>Resolve #include Accuracy</td><td>100%</td></tr>
    <tr><td/></tr>
    <tr><td>Amount of files</td><td>1159</td></tr>
    <tr><td>Failed files</td><td>0</td></tr>
    <tr><td>File-based Accuracy</td><td>100%</td></tr>
  </tbody>
</table>
<p>Summary of accuracy.
<table border="1" cellpadding="2" cellspacing="2">
  <tbody valign="middle" align="middle">
    <tr>
      <td>Project</td>
      <td>Resolve #include Accuracy</td>
      <td>File-based Accuracy</td>
    </tr>
    <tr>
      <td>Not configured full project</td>
      <td>38.27%</td><td>39.74%</td>
    </tr>
    <tr>
      <td>Configured by object files project</td>
      <td>99.87%</td><td>99.84%</td>
    </tr>
    <tr>
      <td>Configured by object files full project</td>
      <td>78.04%</td><td>78.01%</td>
    </tr>
    <tr>
      <td>Configured by object files and model full project</td>
      <td>98.89%</td><td>97.10%</td>
    </tr>
    <tr>
    <td>Configured by executable file project</td>
      <td>100%</td><td>100%</td>
    </tr>
  </tbody>
</table>


<!-- ===================================================================================== -->

<h2><a name="opinion">Minority Opinion</a></h2>
<p>
Comment about repository from Nik:
<p>I have a few comments about the ways to solve the problem with include
path and macros.
<p>I agree that it is too complicated to analyze makefile,
so the "Way 4" looks like a wrong way. It seems very useful to make
some steps along the "Way 3" (read dwarf from the binary), but it helps
only in case we have a binary (some projects may have several binaries,
or don't have binaries at all).
<p>I agree that the "Way 2" is not very reliable,
but I think it is a very good idea, it is relatively easy to implement, and
it helps a lot if user is familiar with this project, so he/she can choose
the proper include file from a list. Technically it is possible to generate
a preliminary list of macros and give user the ability to specify the values,
but it is also not reliable, and I'm not sure it is very helpful.
<p>I think that the "Way 1" is almost the same as the "Way 5". The difference
is that if we use the "Way 5" we have to parse the log file (make output),
which is actually pretty easy in general case. The main problem with the
"Way 1" is that we have to write a "pseudo" compiler ("own redefined
compiler"), which is not an easy task, because it should understand the
syntax of C and C++ compilers (Sun Studio, GCC, ...) to recognize all
macros and options, and it should save its output somewhere outside
of the project tree, so that IDE will find it, but the project tree will not
be "polluted". If there is a risk to get into infinite loop using "Way 5",
there is the same risk using the "Way 1". Actually it is not a problem -
we can kill this build if we see that it runs an infinite loop, or we can
use a timeout. So I think the "Way 5" is more reliable than the "Way 1".
<p>
There are several other solutions:
<ol>
<li>
Use .make.state files (use KEEP_STATE feature).
If the project is already built (even if the build was not successful) and
if it has .KEEP_STATE: target in makefiles, dmake (and Solaris make)
will save information about each compilation in .make.state files.
All we need is to search for a source file name in .make.state files, and
we will get a compilation instruction, something like this one:
<pre class="examplecode">
 cc -D_POSIX_ -D_SUN_OS_ -g  -c  915resolution.c
</PRE>
But what is more important, if we use Sun Studio compilers, they will
write a list of include files into .make.state file! I attached an example
of a .make.state file. GNU make and compilers also can generate the
list of dependencies, but they use a different mechanism, and we can
use it as well.
</li>
<li>
Use source browser information.
Sun Studio compilers have a special option ("-sb") to generate data
for the Sun Studio source browser. If the project is built with this
option, we can get all information from the source browser repository.
I don't think it is an easy task, but we can reuse sources of the existing
source browser. Obviously this solution is limited to the projects, that
are built with Sun Studio compilers with "-sb" option.
</li>
</ol>

<!-- ===================================================================================== -->

<h2><a name="appendices">Appendices</a></h2>
<h2><a name="api">API</a></h2>

<p><pre class="examplecode">
public interface DiscoveryProvider {

    /**
     * Returns provider name
     */
    String getName();
    
    /**
     * Returns provider description
     */
    String getDescription();
    
    /**
     * Returns property keys of additional information for provider
     */
    List&lt;String> getPropertyKeys();

    /**
     * Returns property of additional information for provider
     */
    ProviderProperty getProperty(String key);
    
    /**
     * Analyze project and returns list of configuration
     */
    List&lt;Configuration> getConfigurations(ProjectProxy project);
}
</PRE>
<p>Discovery provider shold be a sevice.
<p>Discovery framework will be lookup providers by:
<p><pre class="examplecode">
    Lookup.Result res = (Lookup.Result) Lookup.getDefault().lookup(new Lookup.Template(DiscoveryProvider.class));
    res.allInstances();
</PRE>
<p>User can select provaider from list.
Discovery framework build UI, setup provider parameters and launch analyze by calling <tt>getConfigurations()</tt>.
<p><pre class="examplecode">
public interface ProjectProxy {
   
    /**
     * Return true if project can be divided on subprojects
     */
    boolean createSubProjects();
    
    /**
     * Returns native project if provider called for existent project
     */
    Object getProject();
}
</PRE>
<p><pre class="examplecode">
public interface ProviderProperty {
    
    /**
     * Returns property name
     */
    String getName();
    
    /**
     * Returns property description
     */
    String getDescription();
    
    /**
     * Returns property value
     */
    Object getValue();
    
    /**
     * Set property value
     */
    void setValue(Object value);
    
    /**
     * Property kind.
     */
    PropertyKind getKind();

    public enum PropertyKind {
        MakeFile,
        BinaryFile,
        SourceFile,
        Folder,
        Folders,
        String,
        Boolean
    }
}
</PRE>
<p><pre class="examplecode">
public interface Configuration {
    
    /**
     * Returns project configuration.
     * Contains one for one-language project or two items.
     */
    List&lt;ProjectProperties> getProjectConfiguration();
    
    /**
     * Returns configuration dependencies
     */
    List&lt;Configuration> getDependencies();

    /**
     * Returns list of source files properties. 
     */
    List&lt;SourceFileProperties> getSourcesConfiguration();
}
</PRE>
<p><pre class="examplecode">
public interface ProjectProperties extends ItemProperties {

    /**
     * Absolute path of make file
     */
    String getMakePath();

    /**
     * Absolute path of binary file
     */
    String getBinaryPath();

    /**
     * Binary kind
     */
    BinaryKind getBinaryKind();

    public enum BinaryKind {
        Unknown,
        Executable,
        Library
    }
}
</PRE>
<p><pre class="examplecode">
public interface SourceFileProperties extends ItemProperties {
    /**
     * Absolute path to folder where item was compiled
     * Can be defined for source files
     */
    String getCompilePath();

    /**
     * Absolute item path
     */
    String getItemPath();
    
    /**
     * returns true if source file has individual configuration
     */
    boolean overrideProjectConfiguration();
}
</PRE>
<p><pre class="examplecode">
public interface ItemProperties {

    /**
     * List of user include paths
     */
    List&lt;String> getUserInludePaths();

    /**
     * List of system include paths
     */
    List&lt;String> getSystemInludePaths();

    /**
     * List of user macros
     */
    Map&lt;String,String> getUserMacros();

    /**
     * List of system predefined macros
     */
    Map&lt;String,String> getSystemMacros();
    
    /**
     * Language kind
     */
    LanguageKind getLanguageKind();

    public enum LanguageKind {
        Unknown,
        C,
        CPP
    }
}
</PRE>
<p>
</body>
</html>

Project Features

About this Project

CND was started in November 2009, is owned by DimaZh, and has 197 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close