Changes between Initial Version and Version 1 of splint

Show
Ignore:
Timestamp:
11/28/09 03:10:24 (12 years ago)
Author:
coke
Comment:

migrate from  http://www.perlfoundation.org/parrot/index.cgi?splint

Legend:

Unmodified
Added
Removed
Modified
  • splint

    v1 v1  
     1Splint 
     2I'm not really sure how to organize this page; I'm hoping that myself and others can expand it, and eventually, converge on something that actually works. I actually started writing this months ago as docs/splint.pod, which is why it looks an awful lot like POD. Please feel free to expand, correct, and reorganize as you see fit. 
     3 
     4OVERVIEW 
     5I'm writing this to document my experiences (and failures) with getting this to work, in the hopes that it's useful to others who are also working on this. 
     6 
     7"make splint" is a makefile target to run the "splint" tool on the Parrot codebase. 
     8 
     9Splint is a very VERY picky "lint" tool, which analyzes C source code for coding mistakes and portability issues. It parses your C sources and generates a huge number of warnings, assuming you can get it to parse the source at all. 
     10 
     11Unfortunately, splint's parser is just as strict as its warning generator is. Also unfortunately, a parse error causes splint to exit right then and there, preventing it from giving you a nifty summary at the end. And the "parse error" message tells you very little of value in finding and fixing the problem. 
     12 
     13SYNOPSIS 
     14perl Configure.pl --cgoto=0 
     15make splint 
     16 
     17STRATEGY 
     18Splint has internal libraries defining common system headers. There's an "ansi" library, there's a "posix" library (extending the ANSI one), and a "unix" library (extending the POSIX one). If a file includes stdio.h, it checks its library to see if it contains a version of stdio.h, and if it does, it uses the library version instead of the one provided by your system C library headers. 
     19 
     20Parrot does lots of detection for system specifics, during the Configure.pl process. It detects the existence of header files, and of things defined within those header files, so it can make the best use of the system you're building it for. 
     21 
     22I think this is a fundamental difference in philosophy, which we need to overcome. Splint wants things to be as generic as possible, but parrot is trying to be as specific as possible. I don't know what the best strategy to reconcile this is, but there are 2 obvious possibilities: 
     23 
     24Convince splint to use the system headers as much as possible. 
     25Convince splint to use the system headers as little as possible. 
     26Option 1 allows parrot to use whatever platform-specific things it has detected, but required (at least, for me) a lot of work convincing splint to parse my system headers properly. This involves disabling splint's header-libraries as much as possible, and then just trying to run it, seeing what breaks, finding a fix or workaround, and repeating until it passes. The below "Parse error in a system header file" section describes some specific issues I found there, and how I worked around them. 
     27 
     28Option 2 is more intrusive, but hopefully, less time consuming. It would also probably have a more portable result. Rather than trying to convince Splint to work with whatever Parrot's trying to do, we try to convince Parrot to use no headers/features except those you'd find defined in the ANSI spec, so that everything ends up coming from splint's header-libraries and the system headers are never needed. Specifically, override the contents of include/parrot/has_header.h and include/parrot/feature.h with a set of features compatible with splint. (Maybe use an #ifdef S_SPLINT_S for this, so the headers can be used for splint without breaking normal compilation.) 
     29 
     30My personal feeling at the moment is that Option 2 is the way to go. I'm hoping that if we can get the has_header.h and feature.h contents right, all of the problems I've been having with Option 1 will just vanish. 
     31 
     32PROBLEMS I'VE RUN INTO 
     33There are several types of problems which have often cropped up, for me. The end result is usually an uninformative parse error. 
     34 
     35Parse error in a system header file. 
     36Common sources for this problem: 
     37 
     38conflict between splint's "header library" and a system header 
     39 
     40This occurs when a system header is not covered by splint's internal library, but relies on another header that was defined by a splint library, and defined in an incompatible fashion. In my case, "+posixstrictlib" caused splint to use an internal version of netinet/in.h, but not an arpa/inet.h. Unfortunately, my arpa/inet.h relied on netinet/in.h to define an "in_addr_t" typedef, which splint's library version didn't. The solution is to disable +posixstrictlib, or (in my arpa/inet.h case) upgrade to +unixstrictlib. 
     41 
     42build-specific defines required 
     43 
     44This occurs when a system header expects the compiler to define some build-specific stuff. In #parrot, particle mentioned a problem where his winnt.h was relying on MSVC to define something specifying which target the source was being built for. The solution is to figure out what needs to be defined, and define it on the splint command-line, with a -D option. 
     45 
     46__attribute syntax 
     47 
     48This occurs when a system header uses "__attribute" instead of "__attribute__". Note the trailing underscores, in the latter. Apparently, 
     49splint recognises the latter, but not the former. Unfortunately, my system has glibc headers, and glibc's pthread.h uses __attribute all over the place. The solution for this is to define __attribute to __attribute__ on the splint command line, by adding an option like "-D__attribute=__attribute__". 
     50 
     51C library dependence on compiler headers 
     52 
     53Glibc was written with gcc in mind. The headers in /usr/include sometimes depend on compiler-specific stuff, either language parser extensions, or things defined by gcc headers in /usr/lib/gcc-lib/*. From this perspective, splint is essentially just a different compiler (though it doesn't generate any binaries, so we can't just do a "perl Configure.pl --cc=splint" directly). 
     54 
     55Recursive #define in a header file 
     56 
     57My /usr/include/bits/confname.h includes both enums and defines for the same tokens. It looks like this: 
     58 
     59enum 
     60{ 
     61_PC_LINK_MAX, 
     62#define _PC_LINK_MAX _PC_LINK_MAX 
     63_PC_MAX_CANON, 
     64#define _PC_MAX_CANON _PC_MAX_CANON 
     65 
     66etc, etc. I'm guessing they want to use an enum for compile-time typechecking, but retain compatibility with code that uses #ifdef to determine its presence, or something. Anyway, splint barfs on this with an "internal error": 
     67 
     68/usr/include/bits/confname.h:31:27: *** Internal Bug at cscannerHelp.c:2422: Unexpanded macro not function or constant: int _PC_MAX_CANON [errno: 25] 
     69     *** Please report bug to splint-bug@splint.org *** 
     70       (attempting to continue, results may be incorrect) 
     71/usr/include/bits/confname.h:32:1: Parse Error: Non-function declaration: _PC_MAX_CANON : int. (For help on parse errors, see splint -help parseerrors.) 
     72*** Cannot continue. 
     73 
     74The nice thing about this error, of course, is that it waits until after all sourcefile processing to emit this error. Which means you think everything's running great, and yet you're denied your nifty summary at the end. 
     75 
     76For now, I've wrapped my system include with #ifndef S_SPLINT_S. But its another argument in favor of keeping splint as far away from system headers as possible... 
     77 
     78Parse error in a Parrot source (or header) file 
     79This section handles problems on a case by case basis. 
     80 
     81src/ops/core_ops_cg.c and src/ops/core_ops_cgp.c 
     82 
     83These files are an implementation of the "CGoto" runloop. The CGoto runloop implements an array of pointers to goto target symbols, and uses nonstandard (gcc-specific) syntax which splint cannot parse. The solution is to re-run Configure.pl with the "--cgoto=0" option. 
     84 
     85AVAILABLE TOOLS AND REFERENCES 
     86Splint has a reference manual, available at http://www.splint.org/manual/manual.html. 
     87 
     88In addition, splint has a special --help topic, which you can get by typing splint --help parseerrors, with some useful advice for parse errors and how to resolve them. 
     89 
     90Splint also has a "+keep" option, which causes it to tell you where to find its temporary (preprocessed) files, and to not automatically remove them. This flag is very useful to see the preprocessed output that splint actually parses, and thus, see what caused a parse error. 
     91 
     92UPDATED CODE 
     93I've had splint crash on me, and I think it's because negative shifts cause a crash, rather than generating a splint error. This bug has been fixed in the CVS version of the code. The CVS version builds just fine.