Improved, cleaner/faster/more flexible return value checks
This commit is contained in:
parent
7456a21ddb
commit
ac2e8f5a15
20
bp.c
20
bp.c
@ -342,8 +342,8 @@ __attribute__((nonnull(2)))
|
||||
static int process_git_files(def_t *defs, pat_t *pattern, int argc, char *argv[])
|
||||
{
|
||||
int fds[2];
|
||||
check_nonnegative(pipe(fds), "Failed to create pipe");
|
||||
pid_t child = check_nonnegative(fork(), "Failed to fork");
|
||||
require(pipe(fds), "Failed to create pipe");
|
||||
pid_t child = require(fork(), "Failed to fork");
|
||||
if (child == 0) {
|
||||
const char **git_args = new(char*[3+argc+1]);
|
||||
int g = 0;
|
||||
@ -351,20 +351,20 @@ static int process_git_files(def_t *defs, pat_t *pattern, int argc, char *argv[]
|
||||
git_args[g++] = "ls-files";
|
||||
git_args[g++] = "-z";
|
||||
while (*argv) git_args[g++] = *(argv++);
|
||||
check_nonnegative(dup2(fds[STDOUT_FILENO], STDOUT_FILENO), "Failed to hook up pipe to stdout");
|
||||
check_nonnegative(close(fds[STDIN_FILENO]), "Failed to close read end of pipe");
|
||||
require(dup2(fds[STDOUT_FILENO], STDOUT_FILENO), "Failed to hook up pipe to stdout");
|
||||
require(close(fds[STDIN_FILENO]), "Failed to close read end of pipe");
|
||||
(void)execvp("git", (char**)git_args);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
check_nonnegative(close(fds[STDOUT_FILENO]), "Failed to close write end of pipe");
|
||||
FILE *fp = check_nonnull(fdopen(fds[STDIN_FILENO], "r"), "Could not open pipe file descriptor");
|
||||
require(close(fds[STDOUT_FILENO]), "Failed to close write end of pipe");
|
||||
FILE *fp = require(fdopen(fds[STDIN_FILENO], "r"), "Could not open pipe file descriptor");
|
||||
char *path = NULL;
|
||||
size_t path_size = 0;
|
||||
int found = 0;
|
||||
while (getdelim(&path, &path_size, '\0', fp) > 0)
|
||||
found += process_file(defs, path, pattern);
|
||||
if (path) delete(&path);
|
||||
check_nonnegative(fclose(fp), "Failed to close read end of pipe");
|
||||
require(fclose(fp), "Failed to close read end of pipe");
|
||||
int status;
|
||||
while (waitpid(child, &status, 0) != child) continue;
|
||||
if (!((WIFEXITED(status) == 1) && (WEXITSTATUS(status) == 0)))
|
||||
@ -450,7 +450,7 @@ int main(int argc, char *argv[])
|
||||
if (after_spaces(p->end, true) < arg_file->end) file_err(arg_file, p->end, arg_file->end, "Failed to compile this part of the argument");
|
||||
pattern = chain_together(arg_file, pattern, p);
|
||||
} else if (FLAG("-w") || FLAG("--word")) {
|
||||
check_nonnegative(asprintf(&flag, "\\|%s\\|", flag), "Could not allocate memory");
|
||||
require(asprintf(&flag, "\\|%s\\|", flag), "Could not allocate memory");
|
||||
file_t *arg_file = spoof_file(&loaded_files, "<word pattern>", flag, -1);
|
||||
delete(&flag);
|
||||
pat_t *p = bp_stringpattern(arg_file, arg_file->start);
|
||||
@ -505,10 +505,10 @@ int main(int argc, char *argv[])
|
||||
int signals[] = {SIGTERM, SIGINT, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGSEGV, SIGTSTP};
|
||||
struct sigaction sa = {.sa_handler = &sig_handler, .sa_flags = (int)(SA_NODEFER | SA_RESETHAND)};
|
||||
for (size_t i = 0; i < sizeof(signals)/sizeof(signals[0]); i++)
|
||||
check_nonnegative(sigaction(signals[i], &sa, NULL), "Failed to set signal handler");
|
||||
require(sigaction(signals[i], &sa, NULL), "Failed to set signal handler");
|
||||
|
||||
// Handle exit() calls gracefully:
|
||||
check_nonnegative(atexit(&cleanup), "Failed to set cleanup handler at exit");
|
||||
require(atexit(&cleanup), "Failed to set cleanup handler at exit");
|
||||
|
||||
// No need for these caches anymore:
|
||||
for (file_t *f = loaded_files; f; f = f->next)
|
||||
|
4
files.c
4
files.c
@ -116,7 +116,7 @@ file_t *load_file(file_t **files, const char *filename)
|
||||
|
||||
finished_loading:
|
||||
if (fd != STDIN_FILENO)
|
||||
check_nonnegative(close(fd), "Failed to close file");
|
||||
require(close(fd), "Failed to close file");
|
||||
|
||||
populate_lines(f);
|
||||
if (files != NULL) {
|
||||
@ -177,7 +177,7 @@ void destroy_file(file_t **at_f)
|
||||
delete(&f->allocated);
|
||||
|
||||
if (f->mmapped) {
|
||||
check_nonnegative(munmap(f->mmapped, (size_t)(f->end - f->mmapped)),
|
||||
require(munmap(f->mmapped, (size_t)(f->end - f->mmapped)),
|
||||
"Failure to un-memory-map some memory");
|
||||
f->mmapped = NULL;
|
||||
}
|
||||
|
30
utils.c
30
utils.c
@ -128,36 +128,6 @@ char unescapechar(const char *escaped, const char **end)
|
||||
return (char)ret;
|
||||
}
|
||||
|
||||
//
|
||||
// If the given argument is NULL, print the error message and exit with
|
||||
// failure. Otherwise return the given argument.
|
||||
//
|
||||
void *check_nonnull(void *p, const char *err_msg, ...)
|
||||
{
|
||||
if (p == NULL) {
|
||||
va_list args;
|
||||
va_start(args, err_msg);
|
||||
verr(EXIT_FAILURE, err_msg, args);
|
||||
va_end(args);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//
|
||||
// If the given argument is negative, print the error message and exit with
|
||||
// failure. Otherwise return the given argument.
|
||||
//
|
||||
int check_nonnegative(int i, const char *err_msg, ...)
|
||||
{
|
||||
if (i < 0) {
|
||||
va_list args;
|
||||
va_start(args, err_msg);
|
||||
verr(EXIT_FAILURE, err_msg, args);
|
||||
va_end(args);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//
|
||||
// Case-insensitive memory comparison
|
||||
//
|
||||
|
35
utils.h
35
utils.h
@ -4,6 +4,8 @@
|
||||
#ifndef UTILS__H
|
||||
#define UTILS__H
|
||||
|
||||
#include <err.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -16,10 +18,34 @@
|
||||
#define S2(x) S1(x)
|
||||
#define __LOCATION__ __FILE__ ":" S2(__LINE__)
|
||||
|
||||
#define DEFINE_CHECK_TYPE(t, name, var, expr) \
|
||||
static inline t _check_##name(t var, const char *fmt, ...) { \
|
||||
if (!(expr)) {\
|
||||
va_list args;\
|
||||
va_start(args, fmt);\
|
||||
verrx(1, fmt, args);\
|
||||
va_end(args);\
|
||||
}\
|
||||
return var;\
|
||||
}
|
||||
DEFINE_CHECK_TYPE(void*, ptr, p, p);
|
||||
DEFINE_CHECK_TYPE(int, int, i, i >= 0);
|
||||
DEFINE_CHECK_TYPE(ssize_t, ssize_t, i, i >= 0);
|
||||
DEFINE_CHECK_TYPE(char, char, c, c);
|
||||
DEFINE_CHECK_TYPE(_Bool, bool, b, b);
|
||||
|
||||
#define PP_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,N,...) N
|
||||
#define PP_NARG(...) PP_ARG_N(__VA_ARGS__,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
|
||||
#define _require_fmt(e, ...) _Generic((e), _Bool: _check_bool, int: _check_int, ssize_t: _check_ssize_t, char: _check_char, void*: _check_ptr, default: _check_ptr)((e), ""__VA_ARGS__)
|
||||
#define require(e, ...) (PP_NARG(e,##__VA_ARGS__) > 1 ? _require_fmt((e), __LOCATION__": "__VA_ARGS__) : _require_fmt((e), __LOCATION__": `%s` failed", #e))
|
||||
#define require_true(e, ...) (PP_NARG(e,##__VA_ARGS__) > 1 ? _require_fmt((_Bool)(e), __LOCATION__": "__VA_ARGS__) : _require_fmt((_Bool)(e), __LOCATION__": `%s` is not true", #e))
|
||||
|
||||
#define new(t) _check_ptr(calloc(1, sizeof(t)), "`new(" #t ")` allocation failure")
|
||||
#define checked_strdup(s) _check_ptr(strdup(s), "`checked_strdup(" #s ")` allocation failure")
|
||||
#define grow(arr,n) _check_ptr(realloc(arr,sizeof(arr[0])*(n)), "`grow(" #arr ", " #n ")` allocation failure")
|
||||
|
||||
#define streq(a, b) (strcmp(a, b) == 0)
|
||||
#define new(t) check_nonnull(calloc(1, sizeof(t)), __LOCATION__ ": `new(" #t ")` allocation failure")
|
||||
#define checked_strdup(s) check_nonnull(strdup(s), __LOCATION__ ": `checked_strdup(" #s ")` allocation failure")
|
||||
#define grow(arr,n) check_nonnull(realloc(arr,sizeof(arr[0])*(n)), __LOCATION__ ": `groaw(" #arr ", " #n ")` allocation failure")
|
||||
|
||||
__attribute__((nonnull(1)))
|
||||
char unescapechar(const char *escaped, const char **end);
|
||||
@ -31,9 +57,6 @@ __attribute__((nonnull))
|
||||
bool matchchar(const char **str, char c, bool skip_nl);
|
||||
__attribute__((nonnull))
|
||||
bool matchstr(const char **str, const char *target, bool skip_nl);
|
||||
__attribute__((returns_nonnull))
|
||||
void *check_nonnull(void *p, const char *err_msg, ...);
|
||||
int check_nonnegative(int i, const char *err_msg, ...);
|
||||
__attribute__((nonnull))
|
||||
int memicmp(const void *s1, const void *s2, size_t n);
|
||||
__attribute__((nonnull))
|
||||
|
Loading…
Reference in New Issue
Block a user