Simple C++ function prototype extraction tool?

R

Robbie Hatley

I'm maintaining a software project with 134 C++ files, some of
them huge (as much as 10,000 lines each), and very few prototypes.
The author's attitude towards prototypes was like this:

Prototypes are only good for headers to be included in
other files. For functions which call each other inside
one file, such as A calls B which calls C and D,
just define the functions in order D, C, B, A, and you'll
never need prototypes.

:-(

(All in the global namespace, alas.)

So now a typical file in this project has 9834 lines and 82
functions, with no prototypes anywhere. I don't even know
what functions are there in many cases.

SO... how do I quickly, easily generate lists of function
prototypes for all 134 source files in this project?
Does anyone know of any free Sed, Awk, or perl scripts for
this? Or perhaps a small executable? Something small,
simple, open-source, and free would be especially nice.

I'd write it myself in Perl, but my Perl's weak and this
basically needs to be something like a C++ compiler
front-end, which can recognize the beginning of each
function definition and just parrot the part up to (but
not including) the "{", and type a ";" at the end. Not
exactly trivial to write.
 
P

Phlip

Robbie said:
I'm maintaining a software project with 134 C++ files, some of
them huge (as much as 10,000 lines each), and very few prototypes.
The author's attitude towards prototypes was like this:

Prototypes are only good for headers to be included in
other files. For functions which call each other inside
one file, such as A calls B which calls C and D,
just define the functions in order D, C, B, A, and you'll
never need prototypes.

:-(

That's sometimes the correct style, because if a prototype misses its
actual, the compiler might not warn you.

However, this code should have lots of classes, where prototypes are not
optional and are strictly matched. And it shouldn't have 10,000 line
methods.
(All in the global namespace, alas.)

This is probably C-style C++, if not just C.
So now a typical file in this project has 9834 lines and 82
functions, with no prototypes anywhere. I don't even know
what functions are there in many cases.

Ouch. The functions are also run-on. They should be short and sweet.
SO... how do I quickly, easily generate lists of function
prototypes for all 134 source files in this project?

Download Doxygen and run this source through it. One of Doxygen's outputs is
XML. Whack that, like a database, with an XPath tool, and you have your
prototypes. Oh, and it will also produce a website documenting your code!

Now what will you do with the prototypes? Put them into one collosal .h file
that everyone will import and nobody will respect?

You have a "legacy code" situation. Read /Working Effectively With Legacy
Code/ by Mike Feathers. I just told the SCQAA users group that, last week in
Anaheim/Orange, so you might also get down with them about it!
 
R

Robbie Hatley

Phlip said:
That's sometimes the correct style, because if a prototype misses its
actual, the compiler might not warn you.

However, if one does that, the prototypes should still all be listed
somewhere, even if commented-out. From my point of view, headers aren't
just "syntactic glue that makes stuff compile and link without error";
they are statements from one programmer to another saying "See, look
here! Here's what you got! Here's the data-types and functions and
classes I've made available for your use!"

Ie, programming languages are human languages. (And also, almost
coincidentally, computer languages.)

Otherwise, let's all just program in machine language.

01001011010101010100011010101101111010110001011010101010011001
10101010100101101000100011010101011010010101000111010101001101
10101100110110010010110101010100010101010101110100010101010100
11011110100101010010110010101001010101010011010101010001001101

Wheee! Isn't this fun! :-/
However, this code should have lots of classes, where prototypes are not
optional and are strictly matched. And it shouldn't have 10,000 line
methods.

347,000 lines of code and not one class in the entire thing.
Very few structs, for that matter. No methods. (Well, some
of the structs I wrote myself, I wanted to be able to construct
in different ways, so I wrote parameterized constructors.
Those are the only "methods" in the program.)
This is probably C-style C++, if not just C.

Combo of both. Originally, it was pure C. But the need for containers,
algorithms, iterators, templates, inline functions, std::string, and the
stronger typing of a C++ compiler, was enormous, so coworkers and I
converted it to C++. That way, we could create data structures we needed
(such as a map of structs which contain deques of structs) without writing
thousands of lines of error prone implimentation and leak-prone malloc and
free calls.
Ouch. The functions are also run-on. They should be short and sweet.

:) Personally, I like functions with 25 lines of code, and files
with about a half-dozen such functions. If I need more stuff than
that, I make more files. Each file with it's own logical purpose
and responsibilities, and in it's own namespace. My personal
programming at home, for hobby and utility, is all like that.
(I even use a little OOP, where it seems the best approach.)

The software I'm maintaining at work, though, is NOTHING like that.
The dude who wrote it used 500-line-long functions and 10000-line-long
files. No OOP, no classes, almost no structs. Lots of endlessly
repeated cut-n-paste code. Lots of small fixed-size arrays which keep
overflowing. You get the picture. (And a might ugly picture it is.)

Ideally, this app should have been a strongly OOP project from the
start, but the author hated C++ and OOP, so he locked me into a very
different style. So I have to handle a bewildering hierarchy of
object types and subtypes, without benefit of any common interface
or implimentation between related object types. Everything's just
replicated over and over for each slightly-different type.
Download Doxygen and run this source through it. One of Doxygen's outputs is
XML. Whack that, like a database, with an XPath tool, and you have your
prototypes. Oh, and it will also produce a website documenting your code!

Ok, thanks for the tip. I'll look into that.
Now what will you do with the prototypes? Put them into one collosal
.h file that everyone will import and nobody will respect?

No, I'm going in the opposite direction, putting headers for each
*.cpp file in a like-named *.h file, and only #including headers
where they're needed. Nearly every cpp file includes main.h which
includes the MOST-USED header files from inside and outside the
project; but little-used headers are now included only where needed.

My main purpose for wanting to generate prototypes for EVERYTHING
is just to see what's there. Maybe half the functions in this
project are unprototyped, undocumented, effectively "hidden".

Now, if I had a program that not only listed the prototypes, but
generated charts of what functions call what functions, that would
be even better. That would save me hours of laboriously tracing
execution through the debugger.
You have a "legacy code" situation. Read /Working Effectively
With Legacy Code/ by Mike Feathers. I just told the SCQAA users
group that, last week in Anaheim/Orange, so you might also get
down with them about it!

I've already got that book on my "to-buy" list from when you
recommended it to me last Thursday in response to a post of mine
in which I asked about some weird, idiotic thing my dear departed
ex-boss did in his code. It'll have to wait till Friday (payday),
though; then I'll snarf it from Amazon.

Interesting that you were in the Anaheim/Orange area last week;
I live in Tustin (the next city SE of Orange), and work in
Rancho Santa Margarita (when I'm not telecommuting).


--
Cheers,
Robbie Hatley
Tustin, CA, USA
lonewolfintj atsign pacbell period net
home period pacbell period net slantbar earnur slantbar
 
F

Frederick Gotham

Robbie Hatley posted:
Lots of endlessly repeated cut-n-paste code.


Quite possibly my greatest programming phobia.

I'll resort to macros before I write the same code twice. (unless of course
we're only talking about < 5 lines)
 
F

Frederick Gotham

Robbie Hatley posted:

(Not his own words, but a loose quotation of someone else.)
Prototypes are only good for headers to be included in
other files. For functions which call each other inside
one file, such as A calls B which calls C and D,
just define the functions in order D, C, B, A, and you'll
never need prototypes.


I only ever write a function prototype for two reasons:

(1) I'm writing a header file, and want to grant outside access to a
function which resides in the corresponding source file.


(2) I'm writing a source file, and for some reason want to re-arrange
the order of my functions in the source file, and as such need a forward-
declaration before I can use the function within a function which was
defined prior to it.


Most of the time however, I just do exactly as the other guy did, i.e.
put the functions in sequential order and there's no need for prototypes.
It's also enables you to take one swipe at the code, rather than
scrolling down to see what function it's calling.
 
R

Robbie Hatley

Frederick Gotham said:
Robbie Hatley posted:

(Not his own words, but a loose quotation of someone else.)


I only ever write a function prototype for two reasons:

(1) I'm writing a header file, and want to grant outside access to a
function which resides in the corresponding source file.


(2) I'm writing a source file, and for some reason want to re-arrange
the order of my functions in the source file, and as such need a forward-
declaration before I can use the function within a function which was
defined prior to it.


Most of the time however, I just do exactly as the other guy did, i.e.
put the functions in sequential order and there's no need for prototypes.
It's also enables you to take one swipe at the code, rather than
scrolling down to see what function it's calling.

That approach has it's appeals: It's the most efficient way from
the standpoint of smaller source files, fewer headers, less clutter
at the beginnings of files.

But I don't like it. I usually put prototypes for ALL functions
in a cpp file at the beginning, or in a header. Two big reasons:

1. You can see at a glance what's there.
2. I like to arrange functions in source files in top-down order;
whereas, the no-prototypes approach requires arranging them in
bottom-up order.

Personal preference, I suppose. I use the way that corresponds
with my ways of thinking and working.
 
J

Jerry Coffin

[ ... ]
347,000 lines of code and not one class in the entire thing.
Very few structs, for that matter. No methods. (Well, some
of the structs I wrote myself, I wanted to be able to construct
in different ways, so I wrote parameterized constructors.
Those are the only "methods" in the program.)

Some compilers can produce prototypes for you. FWIW, with VC++ it's
/Zg. With gcc it's -aux-info. I believe in both cases, this really
only works for C code though. Fortunately, it sounds like the code
you're stuck with is pretty close to straight C, so that may not be a
problem.

[ ... ]
Ideally, this app should have been a strongly OOP project from the
start, but the author hated C++ and OOP, so he locked me into a very
different style. So I have to handle a bewildering hierarchy of
object types and subtypes, without benefit of any common interface
or implimentation between related object types. Everything's just
replicated over and over for each slightly-different type.

[ ... ]
My main purpose for wanting to generate prototypes for EVERYTHING
is just to see what's there. Maybe half the functions in this
project are unprototyped, undocumented, effectively "hidden".

Please accept our condolences at this trying time.
Now, if I had a program that not only listed the prototypes, but
generated charts of what functions call what functions, that would
be even better. That would save me hours of laboriously tracing
execution through the debugger.

There are a number of tools around that can create call trees. Years
ago, I made some use of C-DOC from Software Blacksmiths. It was long
enough ago that my memory isn't terribly clear, but to my fuzzy
recollection seems to be that it worked reasonably well. A quick
check indicates that they're still in business, with a web page at
www.swbs.com

Up until VC++ 6, it could also produce fairly nice call graphs, but
AFAIK, this capability is missing from at least most of the newer
versions. It might have been added back into some of their high-end
(and insanely expensive) "Team" editions, but with their prices going
up into the five-digit range, I find it hard to care what they do...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top