Module Name:    src
Committed By:   rillig
Date:           Sun Mar  3 10:27:18 UTC 2024

Modified Files:
        src/tests/usr.bin/xlint/lint1: msg_363.c msg_364.c msg_365.c msg_366.c
            msg_367.c msg_374.c msg_377.c
        src/usr.bin/xlint/lint1: cksnprintb.c err.c

Log Message:
lint: fix warning about "empty" single-letter snprintb descriptions


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/msg_363.c \
    src/tests/usr.bin/xlint/lint1/msg_364.c \
    src/tests/usr.bin/xlint/lint1/msg_365.c \
    src/tests/usr.bin/xlint/lint1/msg_367.c \
    src/tests/usr.bin/xlint/lint1/msg_377.c
cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/xlint/lint1/msg_366.c \
    src/tests/usr.bin/xlint/lint1/msg_374.c
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/xlint/lint1/cksnprintb.c
cvs rdiff -u -r1.229 -r1.230 src/usr.bin/xlint/lint1/err.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/usr.bin/xlint/lint1/msg_363.c
diff -u src/tests/usr.bin/xlint/lint1/msg_363.c:1.1 src/tests/usr.bin/xlint/lint1/msg_363.c:1.2
--- src/tests/usr.bin/xlint/lint1/msg_363.c:1.1	Fri Mar  1 19:39:28 2024
+++ src/tests/usr.bin/xlint/lint1/msg_363.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_363.c,v 1.1 2024/03/01 19:39:28 rillig Exp $	*/
+/*	$NetBSD: msg_363.c,v 1.2 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_363.c"
 
 // Test for message: non-printing character '%.*s' in description '%.*s' [363]
@@ -33,7 +33,7 @@ old_style_description(unsigned u32)
 	/* expect+7: warning: bit position '\000' (0) in '\000print' out of range 1..32 [371] */
 	/* expect+6: warning: old-style format contains '\0' [362] */
 	/* expect+5: warning: bit position '\n' in '\nable' should be escaped as octal or hex [369] */
-	/* expect+4: warning: empty description in '\0' [367] */
+	/* expect+4: warning: redundant '\0' at the end of the format [377] */
 	snprintb(buf, sizeof(buf),
 	    "\020"
 	    "\001non\000print\nable\0",
Index: src/tests/usr.bin/xlint/lint1/msg_364.c
diff -u src/tests/usr.bin/xlint/lint1/msg_364.c:1.1 src/tests/usr.bin/xlint/lint1/msg_364.c:1.2
--- src/tests/usr.bin/xlint/lint1/msg_364.c:1.1	Fri Mar  1 19:39:28 2024
+++ src/tests/usr.bin/xlint/lint1/msg_364.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_364.c,v 1.1 2024/03/01 19:39:28 rillig Exp $	*/
+/*	$NetBSD: msg_364.c,v 1.2 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_364.c"
 
 // Test for message: missing bit position after '%.*s' [364]
@@ -26,6 +26,7 @@ example(unsigned u32)
 	    "b",
 	    u32);
 
+	/* expect+5: warning: empty description in 'b\007' [367] */
 	/* expect+4: warning: missing '\0' at the end of 'b\007' [366] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
Index: src/tests/usr.bin/xlint/lint1/msg_365.c
diff -u src/tests/usr.bin/xlint/lint1/msg_365.c:1.1 src/tests/usr.bin/xlint/lint1/msg_365.c:1.2
--- src/tests/usr.bin/xlint/lint1/msg_365.c:1.1	Fri Mar  1 19:39:28 2024
+++ src/tests/usr.bin/xlint/lint1/msg_365.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_365.c,v 1.1 2024/03/01 19:39:28 rillig Exp $	*/
+/*	$NetBSD: msg_365.c,v 1.2 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_365.c"
 
 // Test for message: missing field width after '%.*s' [365]
@@ -25,6 +25,7 @@ example(unsigned u32)
 	    "f\000",
 	    u32);
 
+	/* expect+5: warning: empty description in 'f\007\010' [367] */
 	/* expect+4: warning: missing '\0' at the end of 'f\007\010' [366] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
Index: src/tests/usr.bin/xlint/lint1/msg_367.c
diff -u src/tests/usr.bin/xlint/lint1/msg_367.c:1.1 src/tests/usr.bin/xlint/lint1/msg_367.c:1.2
--- src/tests/usr.bin/xlint/lint1/msg_367.c:1.1	Fri Mar  1 19:39:28 2024
+++ src/tests/usr.bin/xlint/lint1/msg_367.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_367.c,v 1.1 2024/03/01 19:39:28 rillig Exp $	*/
+/*	$NetBSD: msg_367.c,v 1.2 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_367.c"
 
 // Test for message: empty description in '%.*s' [367]
@@ -18,7 +18,46 @@ typedef unsigned long long uint64_t;
 int snprintb(char*, size_t, const char*, uint64_t);
 
 void
-example(unsigned u32)
+old_style(unsigned u32)
+{
+	char buf[64];
+
+	/* expect+10: warning: empty description in '\001' [367] */
+	/* expect+9: warning: empty description in '\002' [367] */
+	/* expect+8: warning: empty description in '\003' [367] */
+	/* expect+7: warning: empty description in '\004' [367] */
+	snprintb(buf, sizeof(buf),
+	    "\020"
+	    "\001"
+	    "\002"
+	    "\003"
+	    "\004",
+	    u32);
+
+	/* expect+10: warning: empty description in '\001' [367] */
+	/* expect+9: warning: empty description in '\002' [367] */
+	/* expect+8: warning: empty description in '\003' [367] */
+	/* expect+7: warning: empty description in '\004' [367] */
+	snprintb(buf, sizeof(buf),
+	    "\020"
+	    "\001" "" ""
+	    "\002" "" ""
+	    "\003" "" ""
+	    "\004" "" "",
+	    u32);
+
+	// Single-letter descriptions are not empty.
+	snprintb(buf, sizeof(buf),
+	    "\020"
+	    "\001a"
+	    "\002b"
+	    "\003c"
+	    "\004d",
+	    u32);
+}
+
+void
+new_style(uint64_t u64)
 {
 	char buf[64];
 
@@ -26,37 +65,55 @@ example(unsigned u32)
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "b\000\0",
-	    u32);
+	    u64);
 
 	/* expect+4: warning: empty description in 'f\000\010\0' [367] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "f\000\010\0",
-	    u32);
+	    u64);
 
 	// No warning, as 'F' does not take a description.
 	// If there were a description, it would simply be skipped.
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "F\000\010\0",
-	    u32);
+	    u64);
 
 	/* expect+4: warning: empty description in '=\000\0' [367] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "=\000\0",
-	    u32);
+	    u64);
 
 	/* expect+4: warning: empty description in ':\000\0' [367] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    ":\000\0",
-	    u32);
+	    u64);
 
 	/* expect+4: warning: empty description in '*\0' [367] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "*\0",
-	    u32);
+	    u64);
 
+	// Single-letter descriptions are not empty.
+	snprintb(buf, sizeof(buf),
+	    "\177\020"
+	    "b\000b\0"
+	    "f\001\001f\0"
+	    "F\002\002F\0"
+		"=\000z\0"
+		":\001o\0"
+		"*d\0",
+	    u64 >> 1);
+
+	/* expect+6: warning: empty description in 'b\001""""""\0' [367] */
+	/* expect+5: warning: empty description in 'b\003""""""\0' [367] */
+	snprintb(buf, sizeof(buf),
+	    "\177\020"
+	    "b\001" "" "" "\0"
+	    "b\003" "" "" "\0",
+	    u64);
 }
Index: src/tests/usr.bin/xlint/lint1/msg_377.c
diff -u src/tests/usr.bin/xlint/lint1/msg_377.c:1.1 src/tests/usr.bin/xlint/lint1/msg_377.c:1.2
--- src/tests/usr.bin/xlint/lint1/msg_377.c:1.1	Sun Mar  3 00:50:41 2024
+++ src/tests/usr.bin/xlint/lint1/msg_377.c	Sun Mar  3 10:27:18 2024
@@ -1,12 +1,14 @@
-/*	$NetBSD: msg_377.c,v 1.1 2024/03/03 00:50:41 rillig Exp $	*/
+/*	$NetBSD: msg_377.c,v 1.2 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_377.c"
 
-// Test for message: redundant '\0' at the end of new-style format [377]
+// Test for message: redundant '\0' at the end of the format [377]
 
 /*
- * Each directive in the new-style format ends with a '\0'. The final '\0'
- * that ends the whole format is provided implicitly by the compiler as part
- * of the string literal.
+ * Each directive in the new-style format ends with a '\0' that needs to be
+ * spelled out.
+ *
+ * In both old-style and new-style formats, the '\0' that ends the whole
+ * format is provided by the compiler as part of the string literal.
  */
 
 /* lint1-extra-flags: -X 351 */
@@ -21,15 +23,18 @@ example(unsigned u32, uint64_t u64)
 {
 	char buf[64];
 
-	/* expect+6: warning: old-style format contains '\0' [362] */
-	/* expect+5: warning: empty description in '\0' [367] */
+	/* expect+9: warning: old-style format contains '\0' [362] */
+	/* expect+8: warning: old-style format contains '\0' [362] */
+	/* expect+7: warning: bit position '\000' (0) in '\000out-of-range' out of range 1..32 [371] */
+	/* expect+6: warning: redundant '\0' at the end of the format [377] */
 	snprintb(buf, sizeof(buf),
 	    "\020"
 	    "\005bit"
+	    "\000out-of-range"
 	    "\0",
 	    u32);
 
-	/* expect+5: warning: redundant '\0' at the end of new-style format [377] */
+	/* expect+5: warning: redundant '\0' at the end of the format [377] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "b\005bit\0"

Index: src/tests/usr.bin/xlint/lint1/msg_366.c
diff -u src/tests/usr.bin/xlint/lint1/msg_366.c:1.2 src/tests/usr.bin/xlint/lint1/msg_366.c:1.3
--- src/tests/usr.bin/xlint/lint1/msg_366.c:1.2	Sun Mar  3 00:50:41 2024
+++ src/tests/usr.bin/xlint/lint1/msg_366.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_366.c,v 1.2 2024/03/03 00:50:41 rillig Exp $	*/
+/*	$NetBSD: msg_366.c,v 1.3 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_366.c"
 
 // Test for message: missing '\0' at the end of '%.*s' [366]
@@ -24,18 +24,20 @@ example(unsigned u32)
 {
 	char buf[64];
 
-	/* expect+4: warning: redundant '\0' at the end of new-style format [377] */
+	/* expect+4: warning: redundant '\0' at the end of the format [377] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "\0",
 	    u32);
 
+	/* expect+5: warning: empty description in 'b\007' [367] */
 	/* expect+4: warning: missing '\0' at the end of 'b\007' [366] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "b\007",
 	    u32);
 
+	/* expect+5: warning: empty description in 'f\007\000' [367] */
 	/* expect+4: warning: missing '\0' at the end of 'f\007\000' [366] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
Index: src/tests/usr.bin/xlint/lint1/msg_374.c
diff -u src/tests/usr.bin/xlint/lint1/msg_374.c:1.2 src/tests/usr.bin/xlint/lint1/msg_374.c:1.3
--- src/tests/usr.bin/xlint/lint1/msg_374.c:1.2	Sun Mar  3 00:50:41 2024
+++ src/tests/usr.bin/xlint/lint1/msg_374.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_374.c,v 1.2 2024/03/03 00:50:41 rillig Exp $	*/
+/*	$NetBSD: msg_374.c,v 1.3 2024/03/03 10:27:18 rillig Exp $	*/
 # 3 "msg_374.c"
 
 // Test for message: unknown directive '%.*s' [374]
@@ -32,7 +32,7 @@ example(uint64_t u64)
 	    "\00012345\0",
 	    u64);
 
-	/* expect+5: warning: redundant '\0' at the end of new-style format [377] */
+	/* expect+5: warning: redundant '\0' at the end of the format [377] */
 	snprintb(buf, sizeof(buf),
 	    "\177\020"
 	    "b\00012345\0"

Index: src/usr.bin/xlint/lint1/cksnprintb.c
diff -u src/usr.bin/xlint/lint1/cksnprintb.c:1.4 src/usr.bin/xlint/lint1/cksnprintb.c:1.5
--- src/usr.bin/xlint/lint1/cksnprintb.c:1.4	Sun Mar  3 00:50:41 2024
+++ src/usr.bin/xlint/lint1/cksnprintb.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: cksnprintb.c,v 1.4 2024/03/03 00:50:41 rillig Exp $	*/
+/*	$NetBSD: cksnprintb.c,v 1.5 2024/03/03 10:27:18 rillig Exp $	*/
 
 /*-
  * Copyright (c) 2024 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: cksnprintb.c,v 1.4 2024/03/03 00:50:41 rillig Exp $");
+__RCSID("$NetBSD: cksnprintb.c,v 1.5 2024/03/03 10:27:18 rillig Exp $");
 #endif
 
 #include <stdbool.h>
@@ -180,6 +180,40 @@ check_reachable(checker *ck, uint64_t di
 	}
 }
 
+static void
+parse_description(const checker *ck, quoted_iterator *it,
+		  bool *seen_null, bool *descr_empty)
+{
+	bool new_style = ck->new_style;
+
+	quoted_iterator first = *it;
+	(void)quoted_next(ck->fmt, &first);
+	size_t descr_start = first.start, descr_end = descr_start;
+
+	for (quoted_iterator peek = *it; quoted_next(ck->fmt, &peek);) {
+		if (new_style && peek.value == 0) {
+			*seen_null = true;
+			*it = peek;
+			break;
+		}
+		if (!new_style && peek.value == 0)
+			/* old-style format contains '\0' */
+			warning(362);
+		if (!new_style && peek.value <= 32)
+			break;
+		*it = peek;
+		descr_end = peek.i;
+		if (peek.escaped && !isprint((unsigned char)peek.value)) {
+			/* non-printing character '%.*s' in description ... */
+			warning(363,
+			    len(*it), start(*it, ck->fmt),
+			    (int)(descr_end - descr_start),
+			    ck->fmt->data + descr_start);
+		}
+	}
+	*descr_empty = descr_start == descr_end;
+}
+
 static bool
 check_directive(const buffer *fmt, quoted_iterator *it, bool new_style,
 		checker *ck)
@@ -218,16 +252,11 @@ check_directive(const buffer *fmt, quote
 	quoted_iterator cmp = *it;
 
 	bool has_default = new_style && dir.value == '*';
-	if (has_default && !quoted_next(fmt, it)) {
-		/* missing '\0' at the end of '%.*s' */
-		warning(366, range(dir, *it), start(dir, fmt));
-		return false;
-	}
 
-	if (new_style && dir.value == '\0') {
+	if (dir.value == '\0') {
 		quoted_iterator end = *it;
 		if (!quoted_next(fmt, &end)) {
-			/* redundant '\0' at the end of new-style format */
+			/* redundant '\0' at the end of the format */
 			warning(377);
 			return false;
 		}
@@ -239,44 +268,9 @@ check_directive(const buffer *fmt, quote
 		return false;
 	}
 
-	if (!quoted_next(fmt, it)) {
-		if (new_style && dir.value != '*')
-			/* missing '\0' at the end of '%.*s' */
-			warning(366, range(dir, *it), start(dir, fmt));
-		else
-			/* empty description in '%.*s' */
-			warning(367, range(dir, *it), start(dir, fmt));
-		return false;
-	}
-	quoted_iterator descr = *it;
-
-	quoted_iterator prev = *it;
-	for (;;) {
-		if (new_style && it->value == 0)
-			break;
-		if (!new_style && it->value == 0)
-			/* old-style format contains '\0' */
-			warning(362);
-		if (!new_style && it->value <= 32) {
-			*it = prev;
-			break;
-		}
-		if (it->escaped && !isprint((unsigned char)it->value)) {
-			/* non-printing character '%.*s' in description ... */
-			warning(363,
-			    len(*it), start(*it, fmt),
-			    range(descr, *it), start(descr, fmt));
-		}
-		prev = *it;
-		if (!quoted_next(fmt, it)) {
-			if (new_style) {
-				/* missing '\0' at the end of '%.*s' */
-				warning(366, range(dir, prev),
-				    start(dir, fmt));
-			}
-			break;
-		}
-	}
+	bool needs_descr = !(new_style && dir.value == 'F');
+	bool seen_null = false, descr_empty = false;
+	parse_description(ck, it, &seen_null, &descr_empty);
 
 	if (has_bit)
 		check_hex_escape(fmt, bit);
@@ -311,8 +305,8 @@ check_directive(const buffer *fmt, quote
 		warning(373, val(bit) + val(width),
 		    range(dir, *it), start(dir, fmt));
 	}
-	if (has_cmp && ck->field_width < 64
-	    && cmp.value & ~(uint64_t)0 << ck->field_width) {
+	if (has_cmp && ck->field_width > 0 && ck->field_width < 64
+	    && cmp.value & ~value_bits((unsigned)ck->field_width)) {
 		/* comparison value '%.*s' (%ju) exceeds maximum field ... */
 		warning(375, len(cmp), start(cmp, fmt), val(cmp),
 		    (uintmax_t)value_bits((unsigned)ck->field_width));
@@ -325,10 +319,14 @@ check_directive(const buffer *fmt, quote
 		uint64_t w = has_width ? width.value : 1;
 		check_reachable(ck, bit.value, w, dir.start, it->i);
 	}
-	if (descr.i == prev.i && dir.value != 'F') {
+	if (needs_descr && descr_empty) {
 		/* empty description in '%.*s' */
 		warning(367, range(dir, *it), start(dir, fmt));
 	}
+	if (new_style && !seen_null) {
+		/* missing '\0' at the end of '%.*s' */
+		warning(366, range(dir, *it), start(dir, fmt));
+	}
 
 	if (has_width)
 		ck->field_width = width.value;

Index: src/usr.bin/xlint/lint1/err.c
diff -u src/usr.bin/xlint/lint1/err.c:1.229 src/usr.bin/xlint/lint1/err.c:1.230
--- src/usr.bin/xlint/lint1/err.c:1.229	Sun Mar  3 00:50:41 2024
+++ src/usr.bin/xlint/lint1/err.c	Sun Mar  3 10:27:18 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: err.c,v 1.229 2024/03/03 00:50:41 rillig Exp $	*/
+/*	$NetBSD: err.c,v 1.230 2024/03/03 10:27:18 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: err.c,v 1.229 2024/03/03 00:50:41 rillig Exp $");
+__RCSID("$NetBSD: err.c,v 1.230 2024/03/03 10:27:18 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -432,7 +432,7 @@ static const char *const msgs[] = {
 	"unknown directive '%.*s'",					// 374
 	"comparison value '%.*s' (%ju) exceeds maximum field value %ju", // 375
 	"'%.*s' overlaps earlier '%.*s' on bit %u",			// 376
-	"redundant '\\0' at the end of new-style format",		// 377
+	"redundant '\\0' at the end of the format",			// 377
 	"directive '%.*s' is unreachable by input value",		// 378
 };
 

Reply via email to