Powered by Linux
[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. — Semantic Matching Tool

[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.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A user can specify --fatal-checks to make check-level failures do the same.

Signed-off-by: John Levon <levon@xxxxxxxxxxxxxxxxx>
---
 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




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux