[PATCH 08/18] Start to regularise error reporting. The idea is that parse errors and other internal errors are reported back in the exit code, while still reporting the context where needed.

John Levon <[email protected]>
Newsgroups org.kernel.vger.smatch
Message-ID <[email protected]>
A user can specify --fatal-checks to make check-level failures do the same.

Signed-off-by: John Levon <[email protected]>
---
 check_kernel_printf.c        |  2 +-
 check_memcpy_overflow.c      |  2 +-
 check_rosenberg.c            |  2 +-
 check_uninitialized.c        | 10 +++----
 check_wrong_size_arg.c       |  2 +-
 smatch.c                     | 33 +++++++++++++++------
 smatch.h                     | 68 ++++++++++++++++++++++++++++++++++++++++++--
 smatch_auto_copy.c           |  2 +-
 smatch_comparison.c          |  6 ++--
 smatch_db.c                  | 28 +++++++++---------
 smatch_flow.c                | 24 +++++-----------
 smatch_implied.c             |  8 +++---
 smatch_links.c               |  6 ++--
 smatch_modification_hooks.c  | 12 +++-----
 smatch_param_compare_limit.c |  2 +-
 smatch_parse_call_math.c     |  2 +-
 smatch_ranges.c              |  8 +++---
 smatch_slist.c               |  4 +--
 smatch_states.c              | 18 ++++++------
 smatch_struct_assignment.c   |  2 +-
 smatch_sval.c                |  8 +++---
 21 files changed, 156 insertions(+), 93 deletions(-)

diff --git a/check_kernel_printf.c b/check_kernel_printf.c
index daf62648..ecc645e7 100644
--- a/check_kernel_printf.c
+++ b/check_kernel_printf.c
@@ -345,7 +345,7 @@ static void typedef_lookup(struct typedef_lookup *tl)
 		return;
 	tl->sym = _typedef_lookup(tl->name);
 	if (!tl->sym) {
-		sm_msg("internal error: could not find typedef '%s'", tl->name);
+		sm_perror(" could not find typedef '%s'", tl->name);
 		tl->failed = 1;
 	}
 }
diff --git a/check_memcpy_overflow.c b/check_memcpy_overflow.c
index a6cc093a..578c70f6 100644
--- a/check_memcpy_overflow.c
+++ b/check_memcpy_overflow.c
@@ -325,7 +325,7 @@ static void register_funcs_from_file(void)
 		token = token->next;
 	}
 	if (token_type(token) != TOKEN_STREAMEND)
-		printf("internal: error parsing '%s'\n", name);
+		sm_perror("parsing '%s'", name);
 	clear_token_alloc();
 }
 
diff --git a/check_rosenberg.c b/check_rosenberg.c
index 01544cd1..67cf7fee 100644
--- a/check_rosenberg.c
+++ b/check_rosenberg.c
@@ -75,7 +75,7 @@ static int check_struct(struct expression *expr, struct symbol *type)
 		}
 
 		if (!tmp->ctype.alignment) {
-			sm_msg("warn: cannot determine the alignment here\n");
+			sm_perror("cannot determine the alignment here");
 		} else if (align % tmp->ctype.alignment) {
 			print_holey_warning(expr, prev);
 			return 1;
diff --git a/check_uninitialized.c b/check_uninitialized.c
index 97d07919..7d553206 100644
--- a/check_uninitialized.c
+++ b/check_uninitialized.c
@@ -125,7 +125,7 @@ static void match_dereferences(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr->unop);
-	sm_msg("error: potentially dereferencing uninitialized '%s'.", name);
+	sm_error("potentially dereferencing uninitialized '%s'.", name);
 	free_string(name);
 
 	set_state_expr(my_id, expr->unop, &initialized);
@@ -145,7 +145,7 @@ static void match_condition(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr);
-	sm_msg("error: potentially using uninitialized '%s'.", name);
+	sm_error("potentially using uninitialized '%s'.", name);
 	free_string(name);
 
 	set_state_expr(my_id, expr, &initialized);
@@ -167,7 +167,7 @@ static void match_call(struct expression *expr)
 			continue;
 
 		name = expr_to_str(arg);
-		sm_msg("warn: passing uninitialized '%s'", name);
+		sm_warning("warn: passing uninitialized '%s'", name);
 		free_string(name);
 
 		set_state_expr(my_id, arg, &initialized);
@@ -228,7 +228,7 @@ static void match_call_struct_members(struct expression *expr)
 			snprintf(buf, sizeof(buf), "$->%s", sm->name + strlen(arg_name) + 1);
 			if (!member_is_used(expr, param, buf))
 				goto free;
-			sm_msg("warn: struct member %s is uninitialized", sm->name);
+			sm_warning("struct member %s is uninitialized", sm->name);
 		} END_FOR_EACH_SM(sm);
 
 free:
@@ -278,7 +278,7 @@ static void match_symbol(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr);
-	sm_msg("error: uninitialized symbol '%s'.", name);
+	sm_error("uninitialized symbol '%s'.", name);
 	free_string(name);
 
 	set_state_expr(my_id, expr, &initialized);
diff --git a/check_wrong_size_arg.c b/check_wrong_size_arg.c
index 7b0baab1..2a8b8d5f 100644
--- a/check_wrong_size_arg.c
+++ b/check_wrong_size_arg.c
@@ -83,7 +83,7 @@ static void register_funcs_from_file(void)
 
 	}
 	if (token_type(token) != TOKEN_STREAMEND)
-		sm_msg("internal: problem parsing '%s'\n", name);
+		sm_perror("problem parsing '%s'", name);
 	clear_token_alloc();
 }
 
diff --git a/smatch.c b/smatch.c
index 8640defd..2ccf8d76 100644
--- a/smatch.c
+++ b/smatch.c
@@ -27,6 +27,7 @@ static char *option_db_file = (char *)"smatch_db.sqlite";
 enum project_type option_project = PROJ_NONE;
 char *bin_dir;
 char *data_dir;
+const char *progname;
 int option_no_data = 0;
 int option_spammy = 0;
 int option_info = 0;
@@ -41,10 +42,15 @@ int option_file_output;
 int option_time;
 int option_mem;
 char *option_datadir_str;
+int option_fatal_checks;
+
 FILE *sm_outfd;
 FILE *sql_outfd;
 FILE *caller_info_fd;
 
+int sm_nr_errors;
+int sm_nr_checks;
+
 bool __silence_warnings_for_stmt;
 
 typedef void (*reg_func) (int id);
@@ -87,7 +93,7 @@ static void show_checks(void)
 		if (!strncmp(reg_funcs[i].name, "check_", 6))
 			printf("%3d. %s\n", i, reg_funcs[i].name);
 	}
-	exit(1);
+	exit(0);
 }
 
 static void enable_disable_checks(char *s, bool enable)
@@ -117,10 +123,9 @@ static void enable_disable_checks(char *s, bool enable)
 			}
 		}
 
-		if (i == ARRAY_SIZE(reg_funcs)) {
-			printf("error: '%s' not found", s);
-			exit(1);
-		}
+		if (i == ARRAY_SIZE(reg_funcs))
+			sm_fatal("'%s' not found", s);
+
 	} while ((s = next));
 }
 
@@ -139,6 +144,7 @@ static void help(void)
 	printf("--assume-loops:  assume loops always go through at least once.\n");
 	printf("--two-passes:  use a two pass system for each function.\n");
 	printf("--file-output:  instead of printing stdout, print to \"file.c.smatch_out\".\n");
+	printf("--fatal-checks: check output is treated as an error.\n");
 	printf("--help:  print this helpful message.\n");
 	exit(1);
 }
@@ -225,6 +231,7 @@ void parse_args(int *argcp, char ***argvp)
 			found = 1;
 		}
 
+		OPTION(fatal_checks);
 		OPTION(spammy);
 		OPTION(info);
 		OPTION(debug);
@@ -286,7 +293,7 @@ static char *get_data_dir(char *arg0)
 
 	if (option_datadir_str) {
 		if (access(option_datadir_str, R_OK))
-			printf("Warning: %s is not accessible -- ignore.\n",
+			sm_warning("%s is not accessible -- ignored.",
 					option_datadir_str);
 		else
 			return alloc_string(option_datadir_str);
@@ -310,8 +317,8 @@ static char *get_data_dir(char *arg0)
 	if (!access(dir, R_OK))
 		return dir;
 
-	printf("Warning: %s is not accessible.\n", dir);
-	printf("Use --no-data or --data to suppress this message.\n");
+	sm_warning("%s is not accessible.", dir);
+	sm_warning("Use --no-data or --data to suppress this message.");
 	return NULL;
 }
 
@@ -323,8 +330,13 @@ int main(int argc, char **argv)
 	sm_outfd = stdout;
 	sql_outfd = stdout;
 	caller_info_fd = stdout;
+	progname = argv[0];
+
 	parse_args(&argc, &argv);
 
+	if (argc < 2)
+		help();
+
 	/* this gets set back to zero when we parse the first function */
 	final_pass = 1;
 
@@ -346,5 +358,10 @@ int main(int argc, char **argv)
 
 	smatch(argc, argv);
 	free_string(data_dir);
+
+	if (sm_nr_errors > 0)
+		return 1;
+	if (sm_nr_checks > 0 && option_fatal_checks)
+		return 1;
 	return 0;
 }
diff --git a/smatch.h b/smatch.h
index 6dae6934..90120f51 100644
--- a/smatch.h
+++ b/smatch.h
@@ -211,6 +211,23 @@ void set_path_impossible(void);
 extern FILE *sm_outfd;
 extern FILE *sql_outfd;
 extern FILE *caller_info_fd;
+extern const char *progname;
+extern int sm_nr_checks;
+extern int sm_nr_errors;
+
+/*
+ * How to use these routines:
+ *
+ * sm_fatal(): an internal error of some kind that should immediately exit
+ * sm_ierror(): an internal error
+ * sm_perror(): an internal error from parsing input source
+ * sm_error(): an error from input source
+ * sm_warning(): a warning from input source
+ * sm_info(): info message (from option_info)
+ * sm_debug(): debug message
+ * sm_msg(): other message (please avoid using this)
+ */
+
 #define sm_printf(msg...) do { if (final_pass || option_debug || local_debug) fprintf(sm_outfd, msg); } while (0)
 
 static inline void sm_prefix(void)
@@ -222,7 +239,7 @@ static inline void print_implied_debug_msg();
 
 extern bool __silence_warnings_for_stmt;
 
-#define sm_msg(msg...) \
+#define sm_print_msg(type, msg...) \
 do {                                                           \
 	print_implied_debug_msg();                             \
 	if (!final_pass && !option_debug && !local_debug)      \
@@ -232,10 +249,22 @@ do {                                                           \
 	if (!option_info && is_silenced_function())	       \
 		break;					       \
 	sm_prefix();					       \
+	if (type == 1) {				       \
+		sm_printf("warning: ");			       \
+		sm_nr_checks++;			    	       \
+	} else if (type == 2) {				       \
+		sm_printf("error: ");			       \
+		sm_nr_checks++;				       \
+	} else if (type == 3) {				       \
+		sm_printf("parse error: ");		       \
+		sm_nr_errors++;				       \
+	}						       \
         sm_printf(msg);                                        \
         sm_printf("\n");                                       \
 } while (0)
 
+#define sm_msg(msg...) do { sm_print_msg(0, msg); } while (0)
+
 #define local_debug(msg...)					\
 do {								\
 	if (local_debug)					\
@@ -266,6 +295,39 @@ static inline void print_implied_debug_msg(void)
 	}							\
 } while(0)
 
+#define sm_warning(msg...) do { sm_print_msg(1, msg); } while (0)
+#define sm_error(msg...) do { sm_print_msg(2, msg); } while (0)
+#define sm_perror(msg...) do { sm_print_msg(3, msg); } while (0)
+
+static inline void sm_fatal(const char *fmt, ...)
+{
+	va_list args;
+
+	fprintf(sm_outfd, "%s: ", progname);
+
+	va_start(args, fmt);
+	vfprintf(sm_outfd, fmt, args);
+	va_end(args);
+
+	fprintf(sm_outfd, "\n");
+
+	exit(1);
+}
+
+static inline void sm_ierror(const char *fmt, ...)
+{
+	va_list args;
+
+	sm_nr_errors++;
+
+	fprintf(sm_outfd, "%s: internal error: ", progname);
+
+	va_start(args, fmt);
+	vfprintf(sm_outfd, fmt, args);
+	va_end(args);
+
+	fprintf(sm_outfd, "\n");
+}
 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
 
 struct smatch_state *__get_state(int owner, const char *name, struct symbol *sym);
@@ -842,8 +904,8 @@ do {										\
 		sm_debug("mem-db: %s\n", buf);					\
 		rc = sqlite3_exec(_db, buf, NULL, NULL, &err);			\
 		if (rc != SQLITE_OK) {						\
-			fprintf(stderr, "SQL error #2: %s\n", err);		\
-			fprintf(stderr, "SQL: '%s'\n", buf);			\
+			sm_ierror("SQL error #2: %s", err);			\
+			sm_ierror("SQL: '%s'", buf);				\
 			parse_error = 1;					\
 		}								\
 		break;								\
diff --git a/smatch_auto_copy.c b/smatch_auto_copy.c
index 127589f2..098404e6 100644
--- a/smatch_auto_copy.c
+++ b/smatch_auto_copy.c
@@ -25,7 +25,7 @@ static int *auto_copy;
 void set_auto_copy(int owner)
 {
 	if (owner <= 1 || owner > num_checks) {
-		printf("bogus set_auto_copy()\n");
+		sm_ierror("bogus set_auto_copy()");
 		return;
 	}
 	auto_copy[owner] = 1;
diff --git a/smatch_comparison.c b/smatch_comparison.c
index b0aa0ba5..51b4a454 100644
--- a/smatch_comparison.c
+++ b/smatch_comparison.c
@@ -117,7 +117,7 @@ int flip_comparison(int op)
 	case SPECIAL_UNSIGNED_GT:
 		return SPECIAL_UNSIGNED_LT;
 	default:
-		sm_msg("internal smatch bug.  unhandled comparison %d", op);
+		sm_perror("unhandled comparison %d", op);
 		return op;
 	}
 }
@@ -148,7 +148,7 @@ int negate_comparison(int op)
 	case SPECIAL_UNSIGNED_GT:
 		return SPECIAL_UNSIGNED_LTE;
 	default:
-		sm_msg("internal smatch bug.  unhandled comparison %d", op);
+		sm_perror("unhandled comparison %d", op);
 		return op;
 	}
 }
@@ -2311,7 +2311,7 @@ static int parse_comparison(char **value, int *op)
 	}
 
 	if (**value != ' ') {
-		sm_msg("internal error parsing comparison.  %s", *value);
+		sm_perror("parsing comparison.  %s", *value);
 		return 0;
 	}
 
diff --git a/smatch_db.c b/smatch_db.c
index 4f669383..cfbc126b 100644
--- a/smatch_db.c
+++ b/smatch_db.c
@@ -109,8 +109,8 @@ void sql_exec(struct sqlite3 *db, int (*callback)(void*, int, char**, char**), v
 
 	rc = sqlite3_exec(db, sql, callback, data, &err);
 	if (rc != SQLITE_OK && !parse_error) {
-		fprintf(stderr, "SQL error #2: %s\n", err);
-		fprintf(stderr, "SQL: '%s'\n", sql);
+		sm_ierror("SQL error #2: %s", err);
+		sm_ierror("SQL: '%s'", sql);
 		parse_error = 1;
 	}
 }
@@ -2118,7 +2118,7 @@ static void init_memdb(void)
 
 	rc = sqlite3_open(":memory:", &mem_db);
 	if (rc != SQLITE_OK) {
-		printf("Error starting In-Memory database.");
+		sm_ierror("starting In-Memory database.");
 		return;
 	}
 
@@ -2128,20 +2128,20 @@ static void init_memdb(void)
 			continue;
 		ret = read(fd, buf, sizeof(buf));
 		if (ret < 0) {
-			printf("failed to read: %s\n", schema_files[i]);
+			sm_ierror("failed to read: %s", schema_files[i]);
 			continue;
 		}
 		close(fd);
 		if (ret == sizeof(buf)) {
-			printf("Schema file too large:  %s (limit %zd bytes)",
+			sm_ierror("Schema file too large:  %s (limit %zd bytes)",
 			       schema_files[i], sizeof(buf));
 			continue;
 		}
 		buf[ret] = '\0';
 		rc = sqlite3_exec(mem_db, buf, NULL, NULL, &err);
 		if (rc != SQLITE_OK) {
-			fprintf(stderr, "SQL error #2: %s\n", err);
-			fprintf(stderr, "%s\n", buf);
+			sm_ierror("SQL error #2: %s", err);
+			sm_ierror("%s", buf);
 		}
 	}
 }
@@ -2164,7 +2164,7 @@ static void init_cachedb(void)
 
 	rc = sqlite3_open(":memory:", &cache_db);
 	if (rc != SQLITE_OK) {
-		printf("Error starting In-Memory database.");
+		sm_ierror("starting In-Memory database.");
 		return;
 	}
 
@@ -2174,20 +2174,20 @@ static void init_cachedb(void)
 			continue;
 		ret = read(fd, buf, sizeof(buf));
 		if (ret < 0) {
-			printf("failed to read: %s\n", schema_files[i]);
+			sm_ierror("failed to read: %s", schema_files[i]);
 			continue;
 		}
 		close(fd);
 		if (ret == sizeof(buf)) {
-			printf("Schema file too large:  %s (limit %zd bytes)",
+			sm_ierror("Schema file too large:  %s (limit %zd bytes)",
 			       schema_files[i], sizeof(buf));
 			continue;
 		}
 		buf[ret] = '\0';
 		rc = sqlite3_exec(cache_db, buf, NULL, NULL, &err);
 		if (rc != SQLITE_OK) {
-			fprintf(stderr, "SQL error #2: %s\n", err);
-			fprintf(stderr, "%s\n", buf);
+			sm_ierror("SQL error #2: %s", err);
+			sm_ierror("%s", buf);
 		}
 	}
 }
@@ -2296,7 +2296,7 @@ static char *get_next_string(char **str)
 	if (len > 256) {
 		memcpy(string, start, 255);
 		string[255] = '\0';
-		printf("return_fix: '%s' too long", string);
+		sm_ierror("return_fix: '%s' too long", string);
 		**str = '\0';
 		return NULL;
 	}
@@ -2325,7 +2325,7 @@ static void register_return_replacements(void)
 	if (ret < 0)
 		return;
 	if (ret == sizeof(buf)) {
-		printf("file too large:  %s (limit %zd bytes)",
+		sm_ierror("file too large:  %s (limit %zd bytes)",
 		       filename, sizeof(buf));
 		return;
 	}
diff --git a/smatch_flow.c b/smatch_flow.c
index 986160db..31503d56 100644
--- a/smatch_flow.c
+++ b/smatch_flow.c
@@ -1072,7 +1072,7 @@ void __split_stmt(struct statement *stmt)
 
 		__bail_on_rest_of_function = 1;
 		final_pass = 1;
-		sm_msg("Function too hairy.  Giving up. %lu seconds",
+		sm_perror("Function too hairy.  Giving up. %lu seconds",
 		       stop.tv_sec - fn_start_time.tv_sec);
 		fake_a_return();
 		final_pass = 0;  /* turn off sm_msg() from here */
@@ -1891,27 +1891,21 @@ static void open_output_files(char *base_file)
 
 	snprintf(buf, sizeof(buf), "%s.smatch", base_file);
 	sm_outfd = fopen(buf, "w");
-	if (!sm_outfd) {
-		printf("Error:  Cannot open %s\n", buf);
-		exit(1);
-	}
+	if (!sm_outfd)
+		sm_fatal("Cannot open %s", buf);
 
 	if (!option_info)
 		return;
 
 	snprintf(buf, sizeof(buf), "%s.smatch.sql", base_file);
 	sql_outfd = fopen(buf, "w");
-	if (!sql_outfd) {
-		printf("Error:  Cannot open %s\n", buf);
-		exit(1);
-	}
+	if (!sql_outfd)
+		sm_fatal("Error:  Cannot open %s", buf);
 
 	snprintf(buf, sizeof(buf), "%s.smatch.caller_info", base_file);
 	caller_info_fd = fopen(buf, "w");
-	if (!caller_info_fd) {
-		printf("Error:  Cannot open %s\n", buf);
-		exit(1);
-	}
+	if (!caller_info_fd)
+		sm_fatal("Error:  Cannot open %s", buf);
 }
 
 void smatch(int argc, char **argv)
@@ -1924,10 +1918,6 @@ void smatch(int argc, char **argv)
 
 	gettimeofday(&start, NULL);
 
-	if (argc < 2) {
-		printf("Usage:  smatch [--debug] <filename.c>\n");
-		exit(1);
-	}
 	sparse_initialize(argc, argv, &filelist);
 	set_valid_ptr_max();
 	alloc_valid_ptr_rl();
diff --git a/smatch_implied.c b/smatch_implied.c
index fc86de2b..0a137dec 100644
--- a/smatch_implied.c
+++ b/smatch_implied.c
@@ -134,7 +134,7 @@ static int create_fake_history(struct sm_state *sm, int comparison, struct range
 		return 0;
 
 	if (rl_intersection(true_rl, false_rl)) {
-		sm_msg("internal error parsing (%s (%s) %s %s)",
+		sm_perror("parsing (%s (%s) %s %s)",
 			sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 		sm_msg("true_rl = %s false_rl = %s intersection = %s",
 		       show_rl(true_rl), show_rl(false_rl), show_rl(rl_intersection(true_rl, false_rl)));
@@ -142,7 +142,7 @@ static int create_fake_history(struct sm_state *sm, int comparison, struct range
 	}
 
 	if (option_debug)
-		sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
+		sm_info("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
 		       sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
 		       show_rl(true_rl), show_rl(false_rl));
 
@@ -403,7 +403,7 @@ static int taking_too_long(void)
 		return 0;
 
 	if (!__inline_fn && printed != cur_func_sym) {
-		sm_msg("internal: turning off implications after 60 seconds");
+		sm_perror("turning off implications after 60 seconds");
 		printed = cur_func_sym;
 	}
 	return 1;
@@ -596,7 +596,7 @@ static void separate_and_filter(struct sm_state *sm, int comparison, struct rang
 	sec = time_after.tv_sec - time_before.tv_sec;
 	if (sec > 20) {
 		sm->nr_children = 4000;
-		sm_msg("Function too hairy.  Ignoring implications after %d seconds.", sec);
+		sm_perror("Function too hairy.  Ignoring implications after %d seconds.", sec);
 	}
 }
 
diff --git a/smatch_links.c b/smatch_links.c
index 91907b57..c24f0c22 100644
--- a/smatch_links.c
+++ b/smatch_links.c
@@ -99,10 +99,8 @@ static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
 
 void set_up_link_functions(int id, int link_id)
 {
-	if (id + 1 != link_id) {
-		printf("FATAL ERROR: links need to be registered directly after the check");
-		exit(1);
-	}
+	if (id + 1 != link_id)
+		sm_fatal("FATAL ERROR: links need to be registered directly after the check");
 
 	add_merge_hook(link_id, &merge_link_states);
 	add_modification_hook(link_id, &match_link_modify);
diff --git a/smatch_modification_hooks.c b/smatch_modification_hooks.c
index 7eef7a7f..b4f9e62f 100644
--- a/smatch_modification_hooks.c
+++ b/smatch_modification_hooks.c
@@ -68,19 +68,15 @@ static struct smatch_state *alloc_my_state(struct expression *expr, struct smatc
 
 void add_modification_hook(int owner, modification_hook *call_back)
 {
-	if (hooks[owner]) {
-		printf("multiple modification hooks for %s\n", check_name(owner));
-		exit(1);
-	}
+	if (hooks[owner])
+		sm_fatal("multiple modification hooks for %s", check_name(owner));
 	hooks[owner] = call_back;
 }
 
 void add_modification_hook_late(int owner, modification_hook *call_back)
 {
-	if (hooks_late[owner]) {
-		printf("multiple late modification hooks for %s\n", check_name(owner));
-		exit(1);
-	}
+	if (hooks_late[owner])
+		sm_fatal("multiple late modification hooks for %s", check_name(owner));
 	hooks_late[owner] = call_back;
 }
 
diff --git a/smatch_param_compare_limit.c b/smatch_param_compare_limit.c
index acdfed9f..1539e062 100644
--- a/smatch_param_compare_limit.c
+++ b/smatch_param_compare_limit.c
@@ -268,7 +268,7 @@ static int parse_comparison(char **value, int *op)
 	}
 
 	if (**value != ' ') {
-		sm_msg("internal error parsing comparison.  %s", *value);
+		sm_perror("parsing comparison.  %s", *value);
 		return 0;
 	}
 
diff --git a/smatch_parse_call_math.c b/smatch_parse_call_math.c
index 19b9e95f..a84622d9 100644
--- a/smatch_parse_call_math.c
+++ b/smatch_parse_call_math.c
@@ -51,7 +51,7 @@ static char pop_op(void)
 	char c;
 
 	if (!op_list) {
-		sm_msg("internal smatch error %s", __func__);
+		sm_perror("%s: no op_list", __func__);
 		return '\0';
 	}
 
diff --git a/smatch_ranges.c b/smatch_ranges.c
index afae4413..fbc93fec 100644
--- a/smatch_ranges.c
+++ b/smatch_ranges.c
@@ -311,7 +311,7 @@ void filter_by_comparison(struct range_list **rl, int comparison, struct range_l
 			ret_rl = remove_range(left_orig, rl_min(right_orig), rl_min(right_orig));
 		break;
 	default:
-		sm_msg("internal error: unhandled comparison %s", show_special(comparison));
+		sm_perror("unhandled comparison %s", show_special(comparison));
 		return;
 	}
 
@@ -949,7 +949,7 @@ int true_comparison_range(struct data_range *left, int comparison, struct data_r
 			return 1;
 		return 0;
 	default:
-		sm_msg("unhandled comparison %d\n", comparison);
+		sm_perror("unhandled comparison %d", comparison);
 		return 0;
 	}
 	return 0;
@@ -1001,7 +1001,7 @@ static int false_comparison_range_sval(struct data_range *left, int comparison,
 			return 0;
 		return 1;
 	default:
-		sm_msg("unhandled comparison %d\n", comparison);
+		sm_perror("unhandled comparison %d", comparison);
 		return 0;
 	}
 	return 0;
@@ -1829,7 +1829,7 @@ void split_comparison_rl(struct range_list *left_orig, int op, struct range_list
 			right_true = remove_range(right_orig, rl_min(left_orig), rl_min(left_orig));
 		break;
 	default:
-		sm_msg("internal error: unhandled comparison %d", op);
+		sm_perror(" unhandled comparison %d", op);
 		return;
 	}
 
diff --git a/smatch_slist.c b/smatch_slist.c
index 4c74caf7..0a993e99 100644
--- a/smatch_slist.c
+++ b/smatch_slist.c
@@ -757,7 +757,7 @@ static void __merge_stree(struct stree **to, struct stree *stree, int add_pool)
 		if (!one_iter.sm || !two_iter.sm)
 			break;
 		if (cmp_tracker(one_iter.sm, two_iter.sm) < 0) {
-			sm_msg("error:  Internal smatch error.");
+			sm_perror(" in %s", __func__);
 			avl_iter_next(&one_iter);
 		} else if (cmp_tracker(one_iter.sm, two_iter.sm) == 0) {
 			if (add_pool && one_iter.sm != two_iter.sm) {
@@ -775,7 +775,7 @@ static void __merge_stree(struct stree **to, struct stree *stree, int add_pool)
 			avl_iter_next(&one_iter);
 			avl_iter_next(&two_iter);
 		} else {
-			sm_msg("error:  Internal smatch error.");
+			sm_perror(" in %s", __func__);
 			avl_iter_next(&two_iter);
 		}
 	}
diff --git a/smatch_states.c b/smatch_states.c
index 53ed75c1..c7a9c85d 100644
--- a/smatch_states.c
+++ b/smatch_states.c
@@ -88,7 +88,7 @@ struct sm_state *set_state(int owner, const char *name, struct symbol *sym, stru
 		return NULL;
 
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 		struct smatch_state *s;
@@ -145,7 +145,7 @@ void __push_fake_cur_stree(void)
 struct stree *__pop_fake_cur_stree(void)
 {
 	if (!fake_cur_stree_stack)
-		sm_msg("INTERNAL error: popping too many fake cur strees.");
+		sm_perror("popping too many fake cur strees.");
 	__use_pre_cond_states();
 	return pop_stree(&fake_cur_stree_stack);
 }
@@ -190,7 +190,7 @@ void __merge_stree_into_cur(struct stree *stree)
 void __set_sm(struct sm_state *sm)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug ||
 	    strcmp(check_name(sm->owner), option_debug_check) == 0) {
@@ -216,7 +216,7 @@ void __set_sm(struct sm_state *sm)
 void __set_sm_cur_stree(struct sm_state *sm)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug ||
 	    strcmp(check_name(sm->owner), option_debug_check) == 0) {
@@ -239,7 +239,7 @@ void __set_sm_cur_stree(struct sm_state *sm)
 void __set_sm_fake_stree(struct sm_state *sm)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug ||
 	    strcmp(check_name(sm->owner), option_debug_check) == 0) {
@@ -472,7 +472,7 @@ void set_true_false_states(int owner, const char *name, struct symbol *sym,
 			   struct smatch_state *false_state)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 		struct smatch_state *tmp;
@@ -487,7 +487,7 @@ void set_true_false_states(int owner, const char *name, struct symbol *sym,
 		return;
 
 	if (!cond_false_stack || !cond_true_stack) {
-		printf("Error:  missing true/false stacks\n");
+		sm_perror("missing true/false stacks");
 		return;
 	}
 
@@ -539,7 +539,7 @@ void __set_true_false_sm(struct sm_state *true_sm, struct sm_state *false_sm)
 	}
 
 	if (!cond_false_stack || !cond_true_stack) {
-		printf("Error:  missing true/false stacks\n");
+		sm_perror("missing true/false stacks");
 		return;
 	}
 
@@ -586,7 +586,7 @@ int __path_is_null(void)
 static void check_stree_stack_free(struct stree_stack **stack)
 {
 	if (*stack) {
-		sm_msg("smatch internal error:  stack not empty");
+		sm_perror("stack not empty");
 		free_stack_and_strees(stack);
 	}
 }
diff --git a/smatch_struct_assignment.c b/smatch_struct_assignment.c
index 90b666fb..1929c95a 100644
--- a/smatch_struct_assignment.c
+++ b/smatch_struct_assignment.c
@@ -285,7 +285,7 @@ static void __struct_members_copy(int mode, struct expression *faked,
 			break;
 		}
 		if (!right_member) {
-			sm_msg("internal.  No right member");
+			sm_perror("No right member");
 			continue;
 		}
 		assign = assign_expression(left_member, '=', right_member);
diff --git a/smatch_sval.c b/smatch_sval.c
index 9d892a06..725509ae 100644
--- a/smatch_sval.c
+++ b/smatch_sval.c
@@ -339,7 +339,7 @@ static sval_t sval_binop_unsigned(struct symbol *type, sval_t left, int op, sval
 		break;
 	case '%':
 		if (right.uvalue == 0) {
-			sm_msg("internal error: %s: MOD by zero", __func__);
+			sm_perror(" %s: MOD by zero", __func__);
 			ret.uvalue = 123456789;
 		} else {
 			ret.uvalue = left.uvalue % right.uvalue;
@@ -361,7 +361,7 @@ static sval_t sval_binop_unsigned(struct symbol *type, sval_t left, int op, sval
 		ret.uvalue = left.uvalue ^ right.uvalue;
 		break;
 	default:
-		sm_msg("internal error: %s: unhandled binop %s", __func__,
+		sm_perror(" %s: unhandled binop %s", __func__,
 		       show_special(op));
 		ret.uvalue = 1234567;
 	}
@@ -397,7 +397,7 @@ static sval_t sval_binop_signed(struct symbol *type, sval_t left, int op, sval_t
 		break;
 	case '%':
 		if (right.value == 0) {
-			sm_msg("internal error: %s: MOD by zero", __func__);
+			sm_perror(" %s: MOD by zero", __func__);
 			ret.value = 123456789;
 		} else {
 			ret.value = left.value % right.value;
@@ -419,7 +419,7 @@ static sval_t sval_binop_signed(struct symbol *type, sval_t left, int op, sval_t
 		ret.value = left.value ^ right.value;
 		break;
 	default:
-		sm_msg("internal error: %s: unhandled binop %s", __func__,
+		sm_perror(" %s: unhandled binop %s", __func__,
 		       show_special(op));
 		ret.value = 1234567;
 	}
-- 
2.14.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.