[splint-discuss] string concatenation patch
Ed Beroset
beroset at mindspring.com
Mon Dec 31 06:52:20 PST 2007
Over the weekend I was trying to fix up splint so that it wouldn't die
with a parser error for code like the following:
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
printf("The answer is %" PRIu32 ".\n", 42);
return 0;
}
For those who don't recall, the ISO C 99 standard added printf and scanf
format specifiers to inttypes.h. There are two issues here. The first
is that the inttypes.h that is in splint's standard.h doesn't include
these definitions. I tried a few things, but failed in that attempt so
far. (Maybe somebody can show me how to do this.)
The second issue is that a C compiler, according to section 5.1.1.2 of
the standard, should concatenate adjacent string literals. That means
that even when the statement is written as
printf("The answer is %" "d" ".\n", 42);
splint doesn't understand it. I believe I have solved that issue and
the patch is pasted to the bottom of this email message, but here's the
logic behind it. I looked and the grammar file already accepts multiple
strings like that, but the format specifier checking wasn't able to
handle the multiple strings. What I did was to change the
exprNode_stringLiteral() function in exprNode.c so that it now merges
the strings before creating the node. Since the same function is also
invoked for wide strings, it should work either way if I've done things
correctly. Some confirmation of that would be useful.
Also, I tried running splint on its own source code, but was unable to
get it to parse the original file. I think I have the annotations
correct, but some hint as to how to check at least this file with splint
would also be helpful to me. Thanks for the great tool. I hope the
patch (which was created from the 3.1.2 source tarball) is useful.
Ed
--- src/exprNode.c.orig 2007-12-31 09:02:46.000000000 -0500
+++ src/exprNode.c 2007-12-31 09:14:48.000000000 -0500
@@ -865,10 +865,52 @@
size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2);
char *ts = cstring_toCharsSafe (t);
char *s = cstring_toCharsSafe (cstring_create (len + 1));
+ char *ss = s;
+ bool escape = FALSE;
+ bool betweenStrings = FALSE;
+ int i;
llassert (*ts == '\"' && *(ts + len + 1) == '\"');
- strncpy (s, ts+1, len);
- *(s + len) = '\0';
+ /* from ISO/IEC 9899 5.1.1.2 Translation phases, phase 6,
+ "Adjacent string literal tokens are concatenated."
+
+ This code does the concatenation as part of the copying
+ */
+ ts++;
+ for (i=0; i < len; i++)
+ {
+ switch (*ts)
+ {
+ case '\\':
+ *ss++ = *ts++;
+ escape = TRUE;
+ /*@switchbreak@*/ break;
+ case '\"':
+ betweenStrings = !escape;
+ if (!betweenStrings)
+ {
+ *ss++ = *ts;
+ }
+ ts++;
+ escape = FALSE;
+ /*@switchbreak@*/ break;
+ case ' ':
+ case '\n':
+ case '\t':
+ if (!betweenStrings)
+ {
+ *ss++ = *ts;
+ }
+ ts++;
+ escape = FALSE;
+ /*@switchbreak@*/ break;
+ default:
+ *ss++ = *ts++;
+ escape = FALSE;
+ /*@switchbreak@*/ break;
+ }
+ }
+ *ss = '\0';
cstring_free (t);
return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
}
More information about the splint-discuss
mailing list