Commit b9944858 authored by jklowden's avatar jklowden
Browse files

ye olde documentation

parent 6c696202
cscan reports the use of a cast as an error message. It can be used
in place of a C compiler in familiar tools that let you jump to the
line in a source file where the "error" occurs. It is intended as an
aid to review C source code for unnecessary (or perhaps harmful)
casts.
cscan is a Python script. More than a fancy **grep**(1), it uses
the [pycparser](https://github.com/eliben/pycparser) module by Eli
Bendersky, based on [Ply](http://www.dabeaz.com/ply/), David Beazley's
excellent Lex/Yacc implementation. cscan uses pycparser to parse the C
code, and responds to recognized casts.
Example output:
```
$ cscan somefile.c
scanning "../libcob/somefile.c"
../lib/gettext.h:224: FuncCall: (char*) (malloc(msgctxt_len + msgid_len))
../lib/gettext.h:272: FuncCall: (char*) (malloc(msgctxt_len + msgid_len))
somefile.c:48: StructRef: (void*) (ff->fcd->_fnamePtr.ptr_name)
somefile.c:49: StructRef: (void*) (ff->fcd)
somefile.c:51: StructRef: (void*) (ff->f)
somefile.c:53: ID: (void*) (ff)
somefile.c:164: StructRef: (void*) (fcd->_fnamePtr.ptr_name)
somefile.c:214: BinaryOp: (EXTKEY*) ((char*) ((char*) (kdb)) + keypos)
somefile.c:221: StructRef: (unsigned char) (f->keys[idx].char_suppress)
```
Each output line has 3 parts:
1. the filename and source line
2. the type of expression being cast
3. the cast and a rendering of the expression in the form `(cast)(expression)`
The expression approximately matches the source code. Sometimes it's
a little mangled, and sometimes extra type information is included in
an effort to be helpful. Comments and whitespace are obviously
missing, because it is reconstructed from the parse tree.
Prerequisites
=============
- [pycparser](https://github.com/eliben/pycparser)
- [Ply](http://www.dabeaz.com/ply/)
If these aren't supplied by your favorite package manager, both
packages can be downloaded from GitHub. Each includes simple
installation instructions.
Installation
============
Put cscan somewhere on your `PATH` for your convenience.
Invocation
==========
cscan [-E cpp] filename ...
The `-E` option lets you specify the preprocessor you wish to use,
overriding the default.
Environment
===========
- **CSCAN_FLAGS** are passed to the preprocessor.
**PLEASE NOTE**:
Individual options in CSCAN_FLAGS must be separated by at least 2
spaces or tabs. For reasons too tedious to go into, cscan must
break up the string into individual options, and it seemed simplest
to use extra whitespace to delineate them.
It can be handy to keep a script to be "sourced" as needed, along the
lines of:
```
if [ -z "$FAKE_INCLUDES" ]
then
FAKE_INCLUDES=$HOME/projects/3rd/pycparser/utils/fake_libc_include
fi
CSCAN_FLAGS="-undef \
-I$FAKE_INCLUDES -I.. -I. -Ilib \
-I/usr/local/include"
export CSCAN_FLAGS
```
Implementation Notes
====================
Preprocesser
------------
While pycparser recognizes C99 code, it does not include its own C
preprocessor. Instead, it invokes **cpp**(1) and processes the
preprocessor output. Which preprocessor is used can be controlled by
the cscan `-E` option.
cscan (because pycparser) will not parse C extensions, notably GNU gcc
extensions. Consequently it will choke on many system header
files. To avoid problems with files you probably don't want to examine
anyway, pycparser includes a set of fake standard C header files. The
basic trick is to put that directory at the front of the *include
path* by making it the first `-I` option in **CSCAN_FLAGS**. See the
pycparser documentation for details.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment