Write script to detect preprocessor include guard discrepanciesBRL-CAD
Status: ClosedTime to complete: 72 hrs Mentors: SeanTags: code cleanup, header, consistency, perl, python, javascript, ruby, scripting

BRL-CAD source code currently has over 450 C header (include) files. Header files usually include a preprocessor block that ensures the header is only included once. It usually looks something like this:

#ifndef THIS_HEADER
#define THIS_HEADER
... file contents ...

#endif /* THIS_HEADER */

This tasks basically involves writing a script that will detect whether a header file has a header guard and, if it does, whether the name matches our header name convention.

Your job is to write a script that detects any discrepancies, based on the file name, for all of our headers. Our convention should be {SUBPATH_}FILENAME_H where SUBPATH indicates the subdirectory where the header resides minus the first directory; and FILENAME_H is the name of the file with punctuation and spaces converted to underscores.

Some examples:

  • include/bu.h becomes just BU_H
  • src/libbu/anim.h becomes LIBBU_ANIM_H
  • src/conv/iges/iges.h becomes CONV_IGES_IGES_H

Suggest using the VM if you're not on Linux, but this command will locate all of the header files for you from the top of a source tree checkout:

find . \( -not -regex '.*src/other.*' -not -regex '.*svn.*' -not -regex '.*cmake.*' \) -name \*.h

You can use any language you like to write your script. We have numerous POSIX shell scripts that you can reference in our sh/ directory of a source tree.

Obtain our trunk sources from a Subversion checkout or VM from Sourceforge. Submit your script, which should just run with minimal fuss (no external dependencies preferred) on our source tree.

Uploaded Work
File name/URLFile sizeDate submitted
headers.py1.6 KBDecember 14 2013 17:23 UTC
headers.py1.6 KBDecember 15 2013 05:02 UTC
headers.py2.6 KBDecember 15 2013 15:26 UTC
headers.py2.8 KBDecember 15 2013 15:38 UTC
Comments
Peter Amidonon December 14 2013 14:59 UTCTask Claimed

I would like to work on this task.

Harmanpreet on December 14 2013 15:02 UTCTask Assigned

This task has been assigned to Andromeda Galaxy. You have 72 hours to complete this task, good luck!

Peter Amidonon December 14 2013 17:23 UTCReady for review

The work on this task is ready to be reviewed.

Sean on December 15 2013 04:54 UTCTask Needs More Work

One of the mentors has sent this task back for more work. Talk to the mentor(s) assigned to this task to satisfy the requirements needed to complete this task, submit your work again and mark the task as complete once you re-submit your work.

Sean on December 15 2013 04:55 UTCdid you test your file?

$ python headers.py 


  File "headers.py", line 15


    matchState = 0


                 ^


IndentationError: unindent does not match any outer indentation level


 

Peter Amidonon December 15 2013 05:02 UTCReady for review

The work on this task is ready to be reviewed.

Peter Amidonon December 15 2013 05:03 UTCtesting

Sorry about that, I did test it, but apparently somehow the spacing got mangled; if it still doesn't work on your end (I tried to test it again before uploading, and I might have fixed it), I can try uploading an archive to make sure Melange doesn't mangle the spacing.

Sean on December 15 2013 05:56 UTCbetter

Looking much better.  Could you make just a few small adjustments so this can be more easily used with other testing infrastructure?


First up is to make it more robust on the #define match, catching spaces or tabs before and/or after the '#', not just zero or more spaces after


Second, you print a number before the results, which will mess with scripting.


Finally, you print out a python array.  Just printing one filepath (not just the name) per line is easier to integrate into testing infrastructure.


Not necessary, but it'd also be helpful if the script could take either a list of files or a list of directories, instead of just the one current "subtree".  We want all headers except we don't want the ones in src/other and misc , so we need to be able to conveniently specify either our list of files or multiple directories to scan.


 

Sean on December 15 2013 05:56 UTCTask Needs More Work

One of the mentors has sent this task back for more work. Talk to the mentor(s) assigned to this task to satisfy the requirements needed to complete this task, submit your work again and mark the task as complete once you re-submit your work.

Peter Amidonon December 15 2013 15:26 UTCReady for review

The work on this task is ready to be reviewed.

Peter Amidonon December 15 2013 15:49 UTCdocumentation

I just wanted to give you a quick look at how this version should be run (the built-in help is pretty good, but I thought that I would show you the example that you mentioned in your previous comment). In this version, you can print the "good" files instead of the "bad"; the choice is controlled through the -g/--good or -b/--bad options, with -b being the default.


The toplevel directory option (-t,--toplevel) allows you to specify a directory that the header guard names will be computed relative to: "python headers.py -t src/ src/other" will look inside the src/other directory, but compute the paths for the guards relative to the src/ directory; without the -t option it uses the name of each directory passed in for that directory's subtree: "python headers.py src/other" would compute src/other/dom2dox/dom2dox.h's proper header string as DOM2DOX_DOM2DOX_H instead of OTHER_DOM2DOX_DOM2DOX_H.


Any number of -e options can be specified; they specify directories that should not be examined, so your example would probaby be best run as "python headers.py -e src/other src/ include/".

Sean on December 15 2013 17:31 UTCTask Closed

Congratulations, this task has been completed successfully.

Sean on December 15 2013 17:33 UTCneeds testing

We still need to test this out more thoroughly, but you're done more than enough work to call this task complete.  Very nicely done.  We'll have to sort out the details of how to hook this into our build system (a little tricky to do for all our platforms).