This commit is contained in:
2025-09-28 22:06:39 -04:00
parent 90fadf3980
commit d847c2fcb6
20 changed files with 636 additions and 450 deletions

151
lib/err.c Normal file
View File

@@ -0,0 +1,151 @@
/* Copyright (C) GCK
*
* This file is part of gcklib
*
* This project and file is licensed under the BSD-3-Clause license.
* <https://opensource.org/licenses/BSD-3-Clause>
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "err.h"
#define RESET "\e[0m"
#define ERROR "\e[1;91m"
#define WARN "\e[1;95m"
#define NOTE "\e[1;94m"
#define HINT "\e[38;5;166m"
static bool __check(void)
{
static int done = 0;
static bool cached = false;
if (!done) {
const char *term = getenv("TERM");
cached = isatty(STDOUT_FILENO) && term != NULL &&
(strstr(term, "color") != NULL ||
strstr(term, "ansi") != NULL ||
strstr(term, "xterm") != NULL);
done = 1;
}
return cached;
}
void errorf(const char *format, ...)
{
va_list args;
va_start(args, format);
if (__check()) {
fprintf(stderr, "%serror%s: ", ERROR, RESET);
} else {
fputs("error: ", stderr);
}
vfprintf(stderr, format, args);
fputc('\n', stderr);
va_end(args);
}
void fatalf(const char *format, ...)
{
va_list args;
va_start(args, format);
if (__check()) {
fprintf(stderr, "%sfatal%s: ", ERROR, RESET);
} else {
fputs("fatal: ", stderr);
}
vfprintf(stderr, format, args);
fputc('\n', stderr);
va_end(args);
exit(EXIT_FAILURE);
}
void warnf(const char *format, ...)
{
va_list args;
va_start(args, format);
if (__check()) {
fprintf(stderr, "%swarning%s: ", WARN, RESET);
} else {
fputs("warning: ", stderr);
}
vfprintf(stderr, format, args);
fputc('\n', stderr);
va_end(args);
}
void notef(const char *format, ...)
{
va_list args;
va_start(args, format);
if (__check()) {
fprintf(stderr, "%snote%s: ", NOTE, RESET);
} else {
fputs("note: ", stderr);
}
vfprintf(stderr, format, args);
fputc('\n', stderr);
va_end(args);
}
void hintf(const char *format, ...)
{
va_list args;
va_start(args, format);
if (__check()) {
fprintf(stderr, "%shint: ", HINT);
} else {
fputs("hint: ", stderr);
}
vfprintf(stderr, format, args);
if (__check()) {
fprintf(stderr, "%s\n", RESET);
} else {
fputc('\n', stderr);
}
va_end(args);
}
void errorfa(int code)
{
errorf(strerror(code));
}
void fatalfa(int code)
{
fatalf(strerror(code));
}
void notefa(int code)
{
notef(strerror(code));
}
void warnfa(int code)
{
warnf(strerror(code));
}
void hintfa(int code)
{
hintf(strerror(code));
}

24
lib/err.h Normal file
View File

@@ -0,0 +1,24 @@
/* Copyright (C) GCK
*
* This file is part of gcklib
*
* This project and file is licensed under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#ifndef ERR_H
#define ERR_H
void errorf(const char *format, ...);
void fatalf(const char *format, ...);
void notef(const char *format, ...);
void warnf(const char *format, ...);
void hintf(const char *format, ...);
void errorfa(int code);
void fatalfa(int code);
void notefa(int code);
void warnfa(int code);
void hintfa(int code);
#endif

52
lib/proginfo.c Normal file
View File

@@ -0,0 +1,52 @@
/* Copyright (C) GCK
*
* This file is part of gcklib
*
* This project and file is licensed under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../config.h"
#include "proginfo.h"
const char *prog_name = "";
void set_prog_name(const char *name)
{
prog_name = prog_name ? name : "";
}
void emit_try_help()
{
printf("Try '%s --help' for more information\n", prog_name);
}
void emit_version()
{
printf("\
%s %s %d\n\
Copyright (C) %d GCK.\n\
This is free software: you are free to change and redistribute it.\n\
There is NO WARRNTY, to the extent permitted by law.\n\
",
prog_name, VERSION, COMMIT, YEAR);
}
int parse_standard_options(int argc, char **argv, void (*usage)(int),
void (*version)())
{
for (int i = 0; i < argc; ++i) {
if (!strcmp(argv[i], "--help")) {
usage(0);
exit(EXIT_SUCCESS);
} else if (!strcmp(argv[i], "--version")) {
emit_version();
exit(EXIT_SUCCESS);
}
}
return 0;
}

22
lib/proginfo.h Normal file
View File

@@ -0,0 +1,22 @@
/* Copyright (C) GCK
*
* This file is part of gcklib
*
* This project and file is licensed under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#ifndef proginfo_H
#define proginfo_H
extern const char *prog_name;
void set_prog_name(const char *name);
void emit_try_help();
void emit_version();
int parse_standard_options(int argc, char **argv, void (*usage)(int),
void (*version)());
#endif

12
lib/str_dup.c Normal file
View File

@@ -0,0 +1,12 @@
#include <stdlib.h>
#include <string.h>
#include "xmem.h"
#include "str_dup.h"
char *str_dup(char *s)
{
char *new = xmalloc(strlen(s) + 1);
strcpy(new, s);
return new;
}

6
lib/str_dup.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef STR_DUP_H
#define STR_DUP_H
char *str_dup(char *s);
#endif

36
lib/xmem.c Normal file
View File

@@ -0,0 +1,36 @@
/* Copyright (C) GCK
*
* This file is part of gcklib
*
* This project and file is licensed under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#include <stdio.h>
#include <stdlib.h>
#include "err.h"
#include "xmem.h"
void *ensure_nonnull(void *ptr)
{
if (ptr == NULL)
fatalf("memory exhausted");
return ptr;
}
void *xmalloc(size_t size)
{
return ensure_nonnull(malloc(size));
}
void *xrealloc(void *ptr, size_t size)
{
return ensure_nonnull(realloc(ptr, size));
}
void *xcalloc(size_t nmemb, size_t size)
{
return ensure_nonnull(calloc(nmemb, size));
}

18
lib/xmem.h Normal file
View File

@@ -0,0 +1,18 @@
/* Copyright (C) GCK
*
* This file is part of gcklib
*
* This project and file is licensed under the BSD-3-Clause licence.
* <https://opensource.org/licence/bsd-3-clause>
*/
#ifndef xmem_H
#define xmem_H
#include <stdlib.h>
void *xmalloc(size_t size);
void *xrealloc(void *ptr, size_t size);
void *xcalloc(size_t nmemb, size_t size);
#endif