Includes - An application to show what was included and how, in you C/C++ source

This application grew out of my need to understand how various files were hung together in a project that I inherited a few years ago. I'd been used to compilers that when they find an error in a header file, tell you not only what header the error was in, but from what file and line the inclusion came from. This is really useful when the response to an error, is "where did that come from, and why am I using it?". Granted, if you wrote the code that may not happen too often, but if someone else did then all bets are off.

What I present here is a small GUI app that takes a specific source file, scans it, and recursively scans all included file building a list of inclusions to then display in a nice little tree.

Includes.exe at work

I hope that some of you may find it useful.

Download source and executable here, [size 143K].

Features:

  • Fast:
    On my PII 266, I can generally scan all of a fairly complex stdafx.h in under 4 seconds.
  • Full Drag and Drop server support:
    You can drag a file from the list in the tree window into another application, e.g. DevStudio.
  • Topmost window support:
    The pushpin on the title bar pins the window to the screen so that it is always the topmost window. This makes browsing in combination with DevStudio much more convenient.
  • INCLUDE path support:
    You can set two include paths, the first is for your system includes, i.e. what DevStudio has in its Options/Directories dialog. The second is for your project specific paths.
  • Find support:
    You can search through the list for a file or part of file name.
  • Source Code:
    You get the source; use it, abuse it, credit who wrote it. Seriously, I may have put this together but a huge amount of the code here has been culled from the work of others.

Usage:

This should be fairly obvious, but regardless, this is what to do.

  1. Set your INCLUDE path. The default is to simply pull in your INCLUDE environment value if you have one. The first time that you run Includes then you may want to check that this is accurate. You will only need to change the per-file INCLUDE value if you are adding /I... options to the compile line.
  2. The include depth defaults to 10, the intent here is more to simply fix any recursion loops than anything else, if you find that the number is too low, then simply increase it.
  3. Open a file. That's it.

Bugs/Limitations:

  • Parsing the source files is a little simplistic. I simply find every #include... entry, get the filename and then open that file and recurse. There is no note taken of any conditional compilation options, this means that the tree can show you headers as being included that simply aren't. As a rule I've not found this to be a problem, but do be aware of it.
  • I only show a file once. The first time that a file is encountered it is logged and ignored from that point on. If you are interested in changing this there is a run time flag in the code (CIncludesDoc::m_once) that if set to true will force a full tree to be built. This is much, much slower and is also subject to recursion loops since there are many circular dependencies in both the MFC and standard headers, this is where the inclusion depth limit comes in to bail from ludicrous recursion. I decided that this wasn't of enough general use to even bother adding a GUI for this option, but it should be simple for anyone who's interested.

On to the Code:

First you'll see that there is a fair mix of styles in this code, sorry. I've been looking at more of the new standard C++ library and fiddling around with using std::string rather than CString, this does mean that both are used in this project, I can't say that I'm completely happy with this, but it's very hard to avoid using CString if you use MFC and I wanted to use std::string to see what it was like.

I'm very happy with the standard container classes, std::vector, std::set etc, you'll see that they crop up quite a bit.

The source has been built and tested on both VC 5 and 6.

The major files:

  • Includes.cpp & Includes.h
    Not too much, the main application object and about box.
  • Includes.dsp
    The ubiquitous project file.
  • IncludesDoc.cpp & IncludesDoc.h
    The main scanning and parsing routines, along with the checks to see if the file has been visited once already.
  • IncludeView.cpp & IncludeView.h
    All of the code for adding the elements to the ListView as well as the grunt work of the drag and drop and find support.
  • item.cpp & item.h
    Storage object for the include file that we've processed.
  • DropHelpers.cpp & DropHelpers.h
    Some very neat code written by Jeffrey Richter for his book "Windows 95: A Developer's Guide", This deals with providing server support for WM_DROPFILES.
  • HyperLink.cpp & HyperLink.h
    Used in the about box to provide a hyperlink control.
  • PaintCap.cpp & PaintCap.h
    Paul DiLascia's Code to support owner draw caption bar painting, mainly used here as a foundation for my CTopCaption Class.
  • Subclass.cpp & Subclass.h
    Again from Paul DiLascia, this class supports the arbitrary subclassing of an MFC CWnd object, very cool.
  • TopCaption.cpp & TopCaption.h
    Derived from CCaptionPainter, this class' purpose is to provide a caption bar with a topmost pushpin.
  • MainFrm.cpp & MainFrm.h
    Responsible for persistent window positioning, and caption painting. If the OS supports drawing a gradient colour on the caption bar (Win98 and Win2K) then we use the system GradientFill routine to make the caption bar fall in with the rest of the OS, if we are in NT 4 or Win95 then we do our own gradient fill.
  • Regexp.cpp & Regexp.h
    My regular expression class, see http://www.codeguru.com/string/regexp.shtml
  • split_string.h
    Convert a string with a sequence of delimited segments into a collection of those segments.
  • SuperGridCtrl.cpp & SuperGridCtrl.h
    Taken from Allan Nielsen's Multi column treelist, this version is slightly modified. I didn't need any of the editing options so this version can be compiled to be read only.
  • TreeGridCtrl.cpp & TreeGridCtrl.h
    Subclassed from CSuperGridCtrl, this class reflects some of the drag 'n' drop related messages up to the parent as well as providing searching support. Note that the searching uses regular expressions.
  • block.h
    block<> is a simple class that provides std library iterator semantics to a block of memory. This can be handy for applying std library algorithms and functions to arbitrary lumps of memory.
  • clock.h
    Very simply routing to assist in function timings, search for _TIME_IT in the code to see an example.
  • DebugStream.cpp &DebugStream.h
    std::stream derived class to provide an interface to OutputDebugString.
  • RTFStream.cpp & RTFStream.h
    std::stream derived class to allow the insertion of formatted text into an RTF control.

Guy Gascoigne - Piggford
Last modified: Wed Jan 20 15:24:46 Pacific Standard Time 1999


Comments

  • Perfect. It would be nice...

    Posted by Legacy on 10/22/2003 12:00am

    Originally posted by: Serguei666

    Good job.
    It would be nice to have a possibility to copy the full path of any include file to Winodws Clipboard

    Reply
  • Nice Works !!

    Posted by Legacy on 09/12/2002 12:00am

    Originally posted by: Stephan Poirier

    Very nice program and very usefull too.
    
    There only a problem, it didn't have a print function to send a report to a printer. It could be very usefull !

    Notice me in the case you do this add-on.

    Nice Works !!
    Stephan

    Reply
  • Cool !! Really cool !!

    Posted by Legacy on 07/02/2002 12:00am

    Originally posted by: William


    Apart from being very handy, it is the type utility program that you begin to wonder after a while, how did you ever get along without it for so long!!!

    I particularly liked the "Find" feature in it that allows you to find a specific #include file IMMEDIATELY (in case you become lost in the list of other names).

    It is a really cool, little utility to have around. I tried it out on several large applications and IT WORKED EVERY TIME, ... EVERY TIME!!!!

    Well done, sir!! Well done!!

    Reply
  • GradientFill

    Posted by Legacy on 11/21/2001 12:00am

    Originally posted by: Scott DeWitt

    Thanks for the example of using a GradientFill. I was missing the bit shift.

    Reply
  • Display repeated includes as ellipsis

    Posted by Legacy on 03/23/2000 12:00am

    Originally posted by: U. Robra

    1st thanks for the nice and helpful tool
    
    

    2nd a little improvement:
    suppressing repeated includes is good for performance and for clearity. However the way it is implemented here hides essntial information, namely that we start into a recursion.

    My proposal:
    Display the name of the repeatedly included file with an elipsis (" ...").

    Solution:

    void CIncludesDoc::scan( const std::string & fname, int level )
    {
    if ( level > GetApp()->Depth() )
    return;

    // if ( m_once && m_FileList.fileProcessed( fname ) )
    // return;

    std::string fullName( findFile( fname ) );

    if ( m_once && m_FileList.fileProcessed( fname ) )
    {
    m_iaData.push_back( CItem( fname + " ...", fullName, level ) );
    return;
    }
    else
    m_iaData.push_back( CItem( fname, fullName, level ) );

    FILE *fp;

    if ( fullName.empty() || ( ( fp = fopen( fullName.c_str(), "r" ) ) == 0 ) )
    return;

    while( !feof( fp ) )
    {
    if ( fgets( LineBuffer().data, LineBuffer().size(), fp ) != LineBuffer().data )
    break;

    check_line( LineBuffer().data, level );
    }
    fclose( fp );
    }


    regards, Udo

    Reply
  • Something wrong with the included exe?

    Posted by Legacy on 02/27/1999 12:00am

    Originally posted by: George

    Everything works fine, but not the zipped exe which is in the Release directory. After I built it by myself, works OK, but the original is not. I tried on Polish version of Windows 95, and English Windows 98.

    BR

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Event Date: April 15, 2014 The ability to effectively set sales goals, assign quotas and territories, bring new people on board and quickly make adjustments to the sales force is often crucial to success--and to the field experience! But for sales operations leaders, managing the administrative processes, systems, data and various departments to get it all right can often be difficult, inefficient and manually intensive. Register for this webinar and learn how you can: Align sales goals, quotas and …

  • Hybrid cloud platforms need to think in terms of sweet spots when it comes to application platform interface (API) integration. Cloud Velocity has taken a unique approach to tight integration with the API sweet spot; enough to support the agility of physical and virtual apps, including multi-tier environments and databases, while reducing capital and operating costs. Read this case study to learn how a global-level Fortune 1000 company was able to deploy an entire 6+ TB Oracle eCommerce stack in Amazon Web …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds