Module Name:    src
Committed By:   rillig
Date:           Sat Mar  9 10:54:12 UTC 2024

Modified Files:
        src/usr.bin/xlint/lint1: func.c lint1.h

Log Message:
lint: internally store case label values in order of appearance


To generate a diff of this commit:
cvs rdiff -u -r1.181 -r1.182 src/usr.bin/xlint/lint1/func.c
cvs rdiff -u -r1.217 -r1.218 src/usr.bin/xlint/lint1/lint1.h

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

Modified files:

Index: src/usr.bin/xlint/lint1/func.c
diff -u src/usr.bin/xlint/lint1/func.c:1.181 src/usr.bin/xlint/lint1/func.c:1.182
--- src/usr.bin/xlint/lint1/func.c:1.181	Thu Feb  8 20:45:20 2024
+++ src/usr.bin/xlint/lint1/func.c	Sat Mar  9 10:54:12 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: func.c,v 1.181 2024/02/08 20:45:20 rillig Exp $	*/
+/*	$NetBSD: func.c,v 1.182 2024/03/09 10:54:12 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: func.c,v 1.181 2024/02/08 20:45:20 rillig Exp $");
+__RCSID("$NetBSD: func.c,v 1.182 2024/03/09 10:54:12 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -162,12 +162,7 @@ end_control_statement(control_statement_
 	control_statement *cs = cstmt;
 	cstmt = cs->c_surrounding;
 
-	case_label_t *cl, *next;
-	for (cl = cs->c_case_labels; cl != NULL; cl = next) {
-		next = cl->cl_next;
-		free(cl);
-	}
-
+	free(cs->c_case_labels.vals);
 	free(cs->c_switch_type);
 	free(cs);
 }
@@ -436,6 +431,34 @@ check_case_label_enum(const tnode_t *tn,
 #endif
 }
 
+static bool
+check_duplicate_case_label(control_statement *cs, const val_t *nv)
+{
+	case_labels *labels = &cs->c_case_labels;
+	size_t i = 0, n = labels->len;
+
+	while (i < n && labels->vals[i].u.integer != nv->u.integer)
+		i++;
+
+	if (i < n) {
+		if (is_uinteger(nv->v_tspec))
+			/* duplicate case '%lu' in switch */
+			error(200, (unsigned long)nv->u.integer);
+		else
+			/* duplicate case '%ld' in switch */
+			error(199, (long)nv->u.integer);
+		return false;
+	}
+
+	if (labels->len >= labels->cap) {
+		labels->cap = 16 + 2 * labels->cap;
+		labels->vals = xrealloc(labels->vals,
+		    sizeof(*labels->vals) * labels->cap);
+	}
+	labels->vals[labels->len++] = *nv;
+	return true;
+}
+
 static void
 check_case_label(tnode_t *tn)
 {
@@ -487,27 +510,8 @@ check_case_label(tnode_t *tn)
 	convert_constant(CASE, 0, cs->c_switch_type, &nv, v);
 	free(v);
 
-	/* look if we had this value already */
-	case_label_t *cl;
-	for (cl = cs->c_case_labels; cl != NULL; cl = cl->cl_next) {
-		if (cl->cl_val.u.integer == nv.u.integer)
-			break;
-	}
-	if (cl != NULL && is_uinteger(nv.v_tspec))
-		/* duplicate case '%lu' in switch */
-		error(200, (unsigned long)nv.u.integer);
-	else if (cl != NULL)
-		/* duplicate case '%ld' in switch */
-		error(199, (long)nv.u.integer);
-	else {
+	if (check_duplicate_case_label(cs, &nv))
 		check_getopt_case_label(nv.u.integer);
-
-		/* Prepend the value to the list of case values. */
-		cl = xcalloc(1, sizeof(*cl));
-		cl->cl_val = nv;
-		cl->cl_next = cs->c_case_labels;
-		cs->c_case_labels = cl;
-	}
 }
 
 void
@@ -660,7 +664,6 @@ stmt_switch_expr_stmt(void)
 {
 	int nenum = 0, nclab = 0;
 	sym_t *esym;
-	case_label_t *cl;
 
 	lint_assert(cstmt->c_switch_type != NULL);
 
@@ -675,8 +678,7 @@ stmt_switch_expr_stmt(void)
 		    esym != NULL; esym = esym->s_next) {
 			nenum++;
 		}
-		for (cl = cstmt->c_case_labels; cl != NULL; cl = cl->cl_next)
-			nclab++;
+		nclab = (int)cstmt->c_case_labels.len;
 		if (hflag && eflag && nclab < nenum && !cstmt->c_default)
 			/* enumeration value(s) not handled in switch */
 			warning(206);

Index: src/usr.bin/xlint/lint1/lint1.h
diff -u src/usr.bin/xlint/lint1/lint1.h:1.217 src/usr.bin/xlint/lint1/lint1.h:1.218
--- src/usr.bin/xlint/lint1/lint1.h:1.217	Sat Mar  9 10:47:16 2024
+++ src/usr.bin/xlint/lint1/lint1.h	Sat Mar  9 10:54:12 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: lint1.h,v 1.217 2024/03/09 10:47:16 rillig Exp $ */
+/* $NetBSD: lint1.h,v 1.218 2024/03/09 10:54:12 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -425,14 +425,12 @@ typedef struct qual_ptr {
 	struct qual_ptr *p_next;
 } qual_ptr;
 
-/*
- * The values of the 'case' labels, linked via cl_next in reverse order of
- * appearance in the code, that is from bottom to top.
- */
-typedef struct case_label {
-	val_t	cl_val;
-	struct case_label *cl_next;
-} case_label_t;
+/* The values of the 'case' labels. */
+typedef struct {
+	val_t	*vals;
+	size_t	len;
+	size_t	cap;
+} case_labels;
 
 typedef enum {
 	CS_DO_WHILE,
@@ -466,7 +464,7 @@ typedef struct control_statement {
 
 	type_t	*c_switch_type;	/* type of switch expression */
 	tnode_t	*c_switch_expr;
-	case_label_t *c_case_labels;	/* list of case values */
+	case_labels c_case_labels;	/* list of case values */
 
 	memory_pool c_for_expr3_mem;	/* saved memory for end of loop
 					 * expression in for() */

Reply via email to