save point

This commit is contained in:
2025-10-04 19:28:26 -04:00
parent 744aaf2bf8
commit c12dbce62c
21 changed files with 546 additions and 489 deletions

96
lib/flag.c Normal file
View File

@@ -0,0 +1,96 @@
/* 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 <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "flag.h"
static char *nextchar;
int getopt_long(int argc, char *const argv[], const char *optstring,
const struct option *longopts, int *longindex)
{
if (nextchar == NULL || *nextchar == '\0') {
if (optind >= argc)
return -1;
if (argv[optind][0] != '-' || argv[optind][1] == '\0')
return -1;
if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
optind++;
return -1;
}
if (argv[optind][1] == '-') {
const char *arg = argv[optind] + 2;
char *eq = strchr(arg, '=');
size_t len = eq ? (size_t)(eq - arg) : strlen(arg);
for (int i = 0; longopts[i].name; i++) {
if (strncmp(arg, longopts[i].name, len) == 0 &&
strlen(longopts[i].name) == len) {
if (longindex)
*longindex = i;
if (longopts[i].has_arg ==
required_argument) {
if (eq)
optarg = (char *)eq + 1;
else if (optind + 1 < argc)
optarg = argv[++optind];
else
return '?';
} else if (longopts[i].has_arg ==
optional_argument)
optarg = eq ? (char *)eq + 1 :
NULL;
else
optarg = NULL;
optind++;
if (longopts[i].flag) {
*longopts[i].flag =
longopts[i].val;
return 0;
}
return longopts[i].val;
}
}
optind++;
return '?';
}
nextchar = argv[optind] + 1;
}
char c = *nextchar++;
const char *pos = strchr(optstring, c);
if (!pos) {
optopt = c;
if (*nextchar == '\0')
optind++;
return '?';
}
if (pos[1] == ':') {
if (*nextchar != '\0') {
optarg = nextchar;
optind++;
nextchar = NULL;
} else if (optind + 1 < argc) {
optarg = argv[++optind];
optind++;
nextchar = NULL;
} else {
optopt = c;
return '?';
}
} else {
optarg = NULL;
if (*nextchar == '\0') {
optind++;
nextchar = NULL;
}
}
return c;
}

15
lib/flag.h Normal file
View File

@@ -0,0 +1,15 @@
/* 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 FLAG_H
#define FLAG_H
int getopt_long(int argc, char *const argv[], const char *optstring,
const struct option *longopts, int *longindex);
#endif

157
lib/fs.c Normal file
View File

@@ -0,0 +1,157 @@
/* 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 <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "err.h"
#include "fs.h"
char *fs_read(const char *path)
{
FILE *fptr = fopen(path, "r");
if (!fptr)
return NULL;
size_t cap = 1024;
size_t len = 0;
char *buf = malloc(cap);
if (!buf) {
fclose(fptr);
return NULL;
}
int c;
while ((c = fgetc(fptr)) != EOF) {
if (len + 1 >= cap) {
cap *= 2;
char *tmp = realloc(buf, cap);
if (!tmp) {
free(buf);
fclose(fptr);
return NULL;
}
buf = tmp;
}
buf[len++] = (char)c;
}
buf[len] = '\0';
fclose(fptr);
return buf;
}
bool fs_exists(const char *path)
{
FILE *fptr;
bool exists;
fptr = fopen(path, "r");
if (fptr) {
exists = true;
} else {
exists = false;
}
return exists;
}
int fs_append(const char *path, const char *format, ...)
{
FILE *fp = fopen(path, "a");
if (!fp)
return -1;
va_list ap;
va_start(ap, format);
int ret = vfprintf(fp, format, ap);
va_end(ap);
if (ret < 0) {
fclose(fp);
return -1;
}
if (fclose(fp) != 0)
return -1;
return ret;
}
int fs_del(const char *path)
{
return remove(path);
}
int fs_new(const char *path)
{
size_t len;
int fd;
if (path == NULL) {
errno = EINVAL;
return -1;
}
len = strlen(path);
if (len == 0) {
errno = EINVAL;
return -1;
}
if (path[len - 1] == '/') {
if (mkdir(path, 0777) == -1)
return -1;
} else {
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd == -1)
return -1;
close(fd);
}
return 0;
}
int fs_write(const char *path, const char *format, ...)
{
FILE *fptr = fopen(path, "w");
if (!fptr)
return -1;
va_list ap;
va_start(ap, format);
int ret = vfprintf(fptr, format, ap);
va_end(ap);
if (ret < 0) {
fclose(fptr);
return -1;
}
if (fclose(fptr) != 0)
return -1;
return ret;
}
FILE *fs_temp()
{
FILE *fptr = tmpfile();
if (!fptr) {
errorf("tmpfile failed");
return NULL;
}
return fptr;
}

26
lib/fs.h Normal file
View File

@@ -0,0 +1,26 @@
/* 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 fs_H
#define fs_H
#include <stdio.h>
#include <sys/types.h>
char *fs_read(const char *path);
bool fs_exists(const char *path);
int fs_append(const char *path, const char *format, ...);
int fs_del(const char *path);
int fs_new(const char *path);
int fs_write(const char *path, const char *format, ...);
FILE *fs_temp();
#endif

View File

@@ -9,15 +9,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../config.h"
#include <libgen.h>
#include <config.h>
#include "proginfo.h"
const char *prog_name = "";
void set_prog_name(const char *name)
void set_prog_name(char *name)
{
prog_name = prog_name ? name : "";
prog_name = prog_name ? basename(name) : "";
}
void emit_try_help()
@@ -36,12 +37,12 @@ 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)())
int parse_standard_options(int argc, char **argv, void (*print_help)(),
void (*print_version)())
{
for (int i = 0; i < argc; ++i) {
if (!strcmp(argv[i], "--help")) {
usage(0);
print_help();
exit(EXIT_SUCCESS);
} else if (!strcmp(argv[i], "--version")) {
emit_version();

View File

@@ -11,12 +11,12 @@
extern const char *prog_name;
void set_prog_name(const char *name);
void set_prog_name(char *name);
void emit_try_help();
void emit_version();
int parse_standard_options(int argc, char **argv, void (*usage)(int),
void (*version)());
int parse_standard_options(int argc, char **argv, void (*print_help)(),
void (*print_version)());
#endif

View File

@@ -1,12 +0,0 @@
#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;
}

View File

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

28
lib/textc.c Normal file
View File

@@ -0,0 +1,28 @@
#include <string.h>
#include <ctype.h>
#include "xmem.h"
#include "textc.h"
char *str_dup(char *s)
{
char *new = xmalloc(strlen(s) + 1);
strcpy(new, s);
return new;
}
char *tostrupr(char *s)
{
char *new = str_dup(s);
for (int i = 0; new[i] != '\0'; ++i)
new[i] = toupper((unsigned char)new[i]);
return new;
}
char *tostrlwr(char *s)
{
char *new = str_dup(s);
for (int i = 0; new[i] != '\0'; ++i)
new[i] = tolower((unsigned char)new[i]);
return new;
}

8
lib/textc.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef TEXTC_H
#define TEXTC_H
char *str_dup(char *s);
char *tostrupr(char *s);
char *tostrlwr(char *s);
#endif