chris@visionware.co.uk (Chris Davies) (05/01/91)
While writing a makefile I came across the following problem with 'lint' on SysV.3 UNIX (several different flavours of the same). Consider a simple standalone program hello.c, anything reasonably correct will do. $ cc -DFRED="oneword" -O -s c.c -o c $ lint -DFRED="oneword" c.c OK so far. No problems (both commands work as expected). Now try defining FRED as "two words", thus $ cc -DFRED="two words" -O -s c.c -o c $ lint -DFRED="two words" c.c The compiler does its funky stuff quite happily, and the preprocessor defines FRED as the constant "two words". However there is no output from lint on the screen, and what's more, on closer examination it's apparent that the file "words" (the second word of the definition for FRED) contains the preprocessor output... Why? Chris -- VISIONWARE LTD, 57 Cardigan Lane, LEEDS LS4 2LE, England Tel +44 532 788858. Fax +44 532 304676. Email chris@visionware.co.uk -------------- "VisionWare: The home of DOS/UNIX/X integration" -------------
scs@adam.mit.edu (Steve Summit) (05/07/91)
In article <1991May1.145501.1752@visionware.co.uk> chris@visionware.co.uk (Chris Davies) writes: >Now try defining FRED as "two words", thus > > $ lint -DFRED="two words" c.c > >However there is no output from lint on the screen, and what's more, on closer >examination it's apparent that the file "words" (the second word of the >definition for FRED) contains the preprocessor output... lint is typically implemented as a shell script which invokes the preprocessor and the "passes" of lint proper. (Once upon a time, the cc driver was a shell script, too.) The big disadvantage of implementing a command like this as a shell script is that there's another chance for quoting to be stripped off. Somewhere in the lint shell script is an invocation of cpp, something like: $CPP $infile $cppflags | $lint1 The $cppflags variable contains those flags you handed to lint which should he handed to cpp (namely -D, -U, and -I). You can see that without some kind of very special handling, your quoted two-word definition, when re-examined on the cpp invocation line within the lint shell script, will be interpreted as two words. Unfortunately, putting the $cppflags interpolation in quotes: $CPP $infile "$cppflags" | $lint1 would make things worse, because $cppflags may contain several -D's, -U's, and/or -I's, which should be interpreted as several words. (It probably also contains -C and -Dlint .) Anyway, what happens is that "words" ends up looking like a second non-flag argument to cpp, which it treats as an output file. (I have to assume from your reported symptoms that your lint shell script invokes cpp as $CPP $infile $cppflags rather than the more conventional $CPP $cppflags $infile since otherwise "words" would have been assumed to be an input file, and there would have been a risk of overwriting your source file, since it would be treated as the output file. I can't verify any of this, because the lint script on this BSD system is apparently different, as it fails in different ways on your example. However, I do note that cpp, even here, will accept flag arguments after the input file, which is a bit unusual given the simpleminded argv parse most C/Unix programs perform.) It's nearly impossible to write a shell script that does the kind of production-quality argument parse, including quoting, that lint potentially requires to handle cases like this (which aren't unheard of). Somebody gets an "A" for good intentions for having tried, but it would not be out of the question to rewrite the lint driver as a simple C program one of these days. (I've seen a number of other obscure lint argument parsing bugs which resulted from its shell script implementation.) Steve Summit scs@adam.mit.edu