git subrepo commit libmisc

subrepo:
  subdir:   "libmisc"
  merged:   "ad02b40"
upstream:
  origin:   "https://git.sr.ht/~nytpu/libmisc"
  branch:   "master"
  commit:   "815ed88"
git-subrepo:
  version:  "0.4.3"
  origin:   "???"
  commit:   "???"
This commit is contained in:
nytpu 2021-07-29 12:20:35 -06:00
parent 759532b78a
commit 43e82b425a
4 changed files with 3 additions and 442 deletions

View File

@ -38,15 +38,11 @@ PROGNAME = libmisc
CC = cc
AR = ar
## default compilation flags
CFLAGS = -Wall -Wextra -pedantic -Wfatal-errors -std=c99 -O3 -I. \
-Wno-missing-field-initializers -Wno-unused-parameter -Werror=return-type
CFLAGS =
## files & dependencies
LIBS = $(PROGNAME).a
OBJS = arena.o err.o string_util.o
TESTS = arena.t string_util.t
OBJS = arena.o string_util.o
include config.mk
@ -57,7 +53,6 @@ all: $(LIBS)
## dependencies
arena.o: arena.h
err.o: err.h
string_util.o: string_util.h
$(OBJS): config.mk Makefile
@ -76,33 +71,6 @@ $(PROGNAME).a: $(OBJS)
## phonies
# technically .PHONY isn't POSIX, but targets with a leading period aren't
# reserved so it's still valid, it'd just be useless to actually execute
.PHONY: all clean scan test-includes
.PHONY: all clean
clean:
rm -rf $(OBJS) $(LIBS) $(TESTS)
# requires clang's scan-build
# https://clang-analyzer.llvm.org/
scan:
printf 'Cleaning build directory and re-running make with scan-build'
make clean
scan-build make
# requires include-what-you-use
# https://github.com/include-what-you-use/include-what-you-use
test-includes:
find . -type f \( -name "*.c" -o -name "*.h" \) -not -path './.ccls-cache/*'\
-exec include-what-you-use -Xiwyu --quoted_includes_first ${CFLAGS} {} \;
## testing
$(TESTS): testing.h
.PHONY: test
.SUFFIXES: .t .c
.c.t:
printf 'Compiling test\t$<\n'
$(CC) $(CFLAGS) -DTEST $(LDFLAGS) -o $@ $<
test: $(TESTS)
printf 'Running tests:\n'
set -e; $(TESTS:%=./%;)

View File

@ -1,191 +0,0 @@
// VERSION: 1.0.2
/* This file contains functions similar to *BSD's err and warn family of
* functions, but implemented portably. Also includes the {get,set}progname
* extensions to stdlib.h.
* See <https://www.freebsd.org/cgi/man.cgi?query=err&sektion=3> for more
* information on these functions.
* It should be noted that the eval parameter was removed from the err family
* of functions, and they all exit with EXIT_FAILURE for portablilty reasons.
*
*
* Copyright (c) 2021 nytpu <alex [at] nytpu.com>
* SPDX-License-Identifier: BSL-1.0
* The orginal source for this file is available at <https://git.sr.ht/~nytpu/libmisc>.
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer, must
* be included in all copies of the Software, in whole or in part, and all
* derivative works of the Software, unless such copies or derivative works are
* solely in the form of machine-executable object code generated by a source
* language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "err.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *progname = "call setprogname()";
static FILE *err_file;
static void (*err_exit_func)(void);
const char *
getprogname(void)
{
return progname;
}
void
setprogname(const char *name)
{
const char *p = strrchr(name, '/');
if (p != NULL) progname = p + 1;
else progname = name;
}
void
err_set_file(void *file)
{
if (file) err_file = file;
else err_file = stderr;
}
void
err_set_exit(void (*exit_func)(void))
{
err_exit_func = exit_func;
}
void
err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrc(errno, fmt, ap);
va_end(ap);
}
void
errc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrc(code, fmt, ap);
va_end(ap);
}
void
verr(const char *fmt, va_list ap)
{
verrc(errno, fmt, ap);
}
void
verrc(int code, const char *fmt, va_list ap)
{
if (err_file == NULL) err_set_file(NULL);
fprintf(err_file, "%s: ", getprogname());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(code));
if (err_exit_func) err_exit_func();
exit(EXIT_FAILURE);
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(errno, fmt, ap);
va_end(ap);
}
void
warnc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(code, fmt, ap);
va_end(ap);
}
void
vwarn(const char *fmt, va_list ap)
{
vwarnc(errno, fmt, ap);
}
void
vwarnc(int code, const char *fmt, va_list ap)
{
if (err_file == NULL) err_set_file(NULL);
fprintf(err_file, "%s: ", getprogname());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(code));
}
void
errx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrx(fmt, ap);
va_end(ap);
}
void
verrx(const char *fmt, va_list ap)
{
if (err_file == NULL) err_set_file(NULL);
fprintf(err_file, "%s: ", getprogname());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
}
fprintf(err_file, "\n");
if (err_exit_func) err_exit_func();
exit(EXIT_FAILURE);
}
void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(const char *fmt, va_list ap)
{
if (err_file == NULL) err_set_file(NULL);
fprintf(err_file, "%s: ", getprogname());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
}
fprintf(err_file, "\n");
}

View File

@ -1,99 +0,0 @@
// VERSION: 1.0.2
/* This file contains functions similar to *BSD's err and warn family of
* functions, but implemented portably. Also includes the {get,set}progname
* extensions to stdlib.h.
* See <https://www.freebsd.org/cgi/man.cgi?query=err&sektion=3> for more
* information on these functions.
* It should be noted that the eval parameter was removed from the err family
* of functions, and they all exit with EXIT_FAILURE for portablilty reasons.
*
*
* Copyright (c) 2021 nytpu <alex [at] nytpu.com>
* SPDX-License-Identifier: BSL-1.0
* The orginal source for this file is available at <https://git.sr.ht/~nytpu/libmisc>.
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer, must
* be included in all copies of the Software, in whole or in part, and all
* derivative works of the Software, unless such copies or derivative works are
* solely in the form of machine-executable object code generated by a source
* language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
#ifndef ERR_H
#define ERR_H
#include <stdarg.h>
// Return the program name.
const char *getprogname(void);
// Set the program name to be returned with getprogname().
// setprogname(argv[0]) should be called early in the main function, as
// getprogname() is used in error reporting often. setprogname is not
// reentrant, it should be called very very early, prior to binding signal
// handlers.
void setprogname(const char *name);
// Set the file to write errors to. It should be a pointer to an open FILE*,
// or a NULL pointer to reset to stderr. The error file defaults to stderr if
// err_set_file() is never called in a program. err_set_file is not reentrant.
void err_set_file(void *file);
// Specify a function that can perform cleanup prior to exiting. Passing a
// NULL pointer will reset the function to do nothing. The exit function is
// called after all error messages are printed, so it is safe to close the file
// here. err_set_exit is not reentrant.
void err_set_exit(void (*exit_func)(void));
// Print the program name, a colon, then print fmt formatted with arguments and
// another colon (if fmt is not NULL), then an error message obtained from
// errno with strerror. Then call the exit function (see err_set_exit above),
// and exit with code EXIT_FAILURE.
// verr* variants use a pre-existing va_list rather than using varargs.
// *errc variants use a provided code with strerror rather than using errno.
void err(const char *fmt, ...);
void errc(int code, const char *fmt, ...);
void verr(const char *fmt, va_list ap);
void verrc(int code, const char *fmt, va_list ap);
// Print the program name, a colon, then print fmt formatted with arguments and
// another colon (if fmt is not NULL), then an error message obtained from
// errno with strerror.
// vwarn* variants use a pre-existing va_list rather than using varargs.
// *warnc variants use a provided code with strerror rather than using errno.
void warn(const char *fmt, ...);
void warnc(int code, const char *fmt, ...);
void vwarn(const char *fmt, va_list ap);
void vwarnc(int code, const char *fmt, va_list ap);
// Print the program name, a colon, then print fmt formatted with arguments (if
// fmt is not NULL). Then call the exit function (see err_set_exit above), and
// exit with code EXIT_FAILURE.
// verr* variants use a pre-existing va_list rather than using varargs.
void errx(const char *fmt, ...);
void verrx(const char *fmt, va_list ap);
// Print the program name, a colon, then print fmt formatted with arguments (if
// fmt is not NULL).
// vwarn* variants use a pre-existing va_list rather than using varargs.
void warnx(const char *fmt, ...);
void vwarnx(const char *fmt, va_list ap);
#endif // ERR_H

View File

@ -1,117 +0,0 @@
// VERSION: 1.0.2
/* This is inspired by <https://text.causal.agency/005-testing-c.txt> and is
* meant to act as a supplement to make printing messages easier for that setup
*
* To use, first set up your makefile as specified in the aforementioned link.
* Add the file to be tested to the TESTS macro in the makefile to include it
* in testing.
*
* Then, simply add this to the end of the file you want to test:
* #ifdef TEST
* #include "testing.h"
*
* int
* main(void)
* {
* begin_tests("<FILENAME>");
* begin_group("<GROUP>");
* // if you just want the condition printed on assertion failure
* assert(...);
* // if you want a custom message printed on assertion failure
* assert_msg(..., "message");
* end_group();
* end_tests();
* }
*
* #endif // TEST
*
* Add more groups as needed.
* It's best to assert the output of a single function (writing helper
* functions if needed).
*
* Note that the test binaries aren't linked with the rest of the code, so
* you will need to stub functions from other translation units.
*
*
* Copyright (c) 2021 nytpu <alex [at] nytpu.com>
* SPDX-License-Identifier: BSL-1.0
* The orginal source for this file is available at <https://git.sr.ht/~nytpu/libmisc>.
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer, must
* be included in all copies of the Software, in whole or in part, and all
* derivative works of the Software, unless such copies or derivative works are
* solely in the form of machine-executable object code generated by a source
* language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
#ifndef TESTING_H
#define TESTING_H
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static const char *filename = NULL;
static const char *groupname = NULL;
// equivalent to assert() but prints out a custom message rather than the
// provided assertion
#define assert_msg(expr, msg) \
if (!(expr)) { \
fprintf(stderr, "%s\n", msg); \
abort(); \
}
// {begin,end}_tests are meant to be used at a file level, but can also be used
// to declare "supergroups" for files with lots of tests
static inline void
begin_tests(const char *fn)
{
assert_msg(filename == NULL, "You must call end_tests before beginning new tests.");
assert_msg(fn != NULL, "Provide a filename.");
filename = fn;
fprintf(stderr, "---\n%s tests begin.\n", filename);
}
static inline void
end_tests(void)
{
assert_msg(filename != NULL, "begin_tests MUST be called before end_tests");
fprintf(stderr, "all %s tests passed.\n", filename);
filename = NULL;
}
// A testing group is meant to be a small unit of testing, and is the smallest
// unit that will have a success message printed
static inline void
begin_group(const char *gn)
{
assert_msg(groupname == NULL, "You must call end_group before starting a new group.");
assert_msg(gn != NULL, "Provide a group name.");
groupname = gn;
}
static inline void
end_group(void)
{
assert_msg(groupname != NULL, "begin_group MUST be called before end_group.");
fprintf(stderr, "\tall %s tests passed.\n", groupname);
groupname = NULL;
}
#endif // TESTING_H