From f99c1d678f3310a3679b24e518355fbb00211273 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 23 May 2026 06:03:23 -0400 Subject: core: Add pointer box / RAII impl Signed-off-by: Ian Moffett --- core/ptrbox.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ core/state.c | 6 +++ include/cescal/ptrbox.h | 71 ++++++++++++++++++++++++++ include/cescal/state.h | 3 ++ 4 files changed, 212 insertions(+) create mode 100644 core/ptrbox.c create mode 100644 include/cescal/ptrbox.h diff --git a/core/ptrbox.c b/core/ptrbox.c new file mode 100644 index 0000000..2bdaa9c --- /dev/null +++ b/core/ptrbox.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause + */ + +#include +#include +#include +#include +#include +#include "cescal/ptrbox.h" + +/* + * Allocate a pointer box entry to be used + */ +static struct ptrbox_entry * +ptrbox_alloc_entry(void) +{ + struct ptrbox_entry *entry; + + if ((entry = malloc(sizeof(*entry))) == NULL) { + return NULL; + } + + entry->data = NULL; + entry->next = NULL; + return entry; +} + +static int +ptrbox_push_entry(struct ptrbox *ptrbox, struct ptrbox_entry *entry) +{ + if (ptrbox == NULL || entry == NULL) { + errno = EINVAL; + return -1; + } + + if (ptrbox->head == NULL || ptrbox->tail == NULL) { + ptrbox->head = entry; + ptrbox->tail = entry; + } else { + ptrbox->head->next = entry; + ptrbox->head = entry; + } + + return 0; +} + +int +ptrbox_init(struct ptrbox *ptrbox) +{ + if (ptrbox == NULL) { + errno = EINVAL; + return -1; + } + + ptrbox->head = NULL; + ptrbox->tail = NULL; + return 0; +} + +void * +ptrbox_alloc(struct ptrbox *ptrbox, size_t len) +{ + struct ptrbox_entry *entry; + void *p; + + if (ptrbox == NULL || len == 0) { + errno = EINVAL; + return NULL; + } + + if ((p = malloc(len)) == NULL) { + return NULL; + } + + if ((entry = ptrbox_alloc_entry()) == NULL) { + free(p); + return NULL; + } + + entry->data = p; + if (ptrbox_push_entry(ptrbox, entry) < 0) { + free(p); + free(entry); + return NULL; + } + + return 0; +} + +char * +ptrbox_strdup(struct ptrbox *ptrbox, const char *s) +{ + char *sdup; + size_t slen; + + if (ptrbox == NULL || s == NULL) { + errno = EINVAL; + return NULL; + } + + slen = strlen(s) + 1; + if ((sdup = ptrbox_alloc(ptrbox, slen)) == NULL) { + return NULL; + } + + memcpy(sdup, s, slen); + return sdup; +} + +void +ptrbox_destroy(struct ptrbox *ptrbox) +{ + struct ptrbox_entry *entry, *tmp; + + if (ptrbox == NULL) { + return; + } + + if ((entry = ptrbox->tail) == NULL) { + return; + } + + while (entry != NULL) { + tmp = entry; + entry = entry->next; + + free(tmp->data); + free(tmp); + } +} diff --git a/core/state.c b/core/state.c index dce1316..6002957 100644 --- a/core/state.c +++ b/core/state.c @@ -33,6 +33,11 @@ state_init(struct cescal_state *state, const char *pathname) return -1; } + if (ptrbox_init(&state->ptrbox) < 0) { + close(state->in_fd); + return -1; + } + return 0; } @@ -41,4 +46,5 @@ state_close(struct cescal_state *state) { close(state->in_fd); state->in_fd = -1; + ptrbox_destroy(&state->ptrbox); } diff --git a/include/cescal/ptrbox.h b/include/cescal/ptrbox.h new file mode 100644 index 0000000..bde75f1 --- /dev/null +++ b/include/cescal/ptrbox.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause + */ + +#ifndef CESCAL_PTRBOX_H +#define CESCAL_PTRBOX_H 1 + +/* + * Represents a pointer box entry in which allocated data can + * be stored within + * + * @data: Allocated data backed by entry + * @next: Next pointer box entry + */ +struct ptrbox_entry { + void *data; + struct ptrbox_entry *next; +}; + +/* + * Represents a pointer box that enables RAII like behavior + * + * @head: Pointer box head + * @tail: Pointer box tail + */ +struct ptrbox { + struct ptrbox_entry *head; + struct ptrbox_entry *tail; +}; + +/* + * Initialize a pointer box + * + * @ptrbox: Pointer box to initialize + * + * Returns zero on success + */ +int ptrbox_init(struct ptrbox *ptrbox); + +/* + * Allocate memory and save the reference within a pointer box + * + * @ptrbox: Pointer box to save reference within + * @len: Length of memory to allocate + * + * Returns the base of the allocated memory on success, otherwise + * NULL. + */ +void *ptrbox_alloc(struct ptrbox *ptrbox, size_t len); + +/* + * Duplicate a string and store the reference within a + * pointer box + * + * @ptrbox: Pointer box to store reference within + * @s: String to duplicate + * + * Returns the duplicated string on success, otherwise NULL. + */ +char *ptrbox_strdup(struct ptrbox *ptrbox, const char *s); + +/* + * Destroy a pointer box along with all references stored + * within + * + * @ptrbox: Pointer box to destroy + */ +void ptrbox_destroy(struct ptrbox *ptrbox); + +#endif /* !CESCAL_PTRBOX_H */ diff --git a/include/cescal/state.h b/include/cescal/state.h index e832bc9..566b5a2 100644 --- a/include/cescal/state.h +++ b/include/cescal/state.h @@ -9,6 +9,7 @@ #include #include "cescal/readbuf.h" #include "cescal/tokbuf.h" +#include "cescal/ptrbox.h" /* * Compiler state machine @@ -16,11 +17,13 @@ * @in_fd: Input file descriptor * @rb: Read buffer * @tokbuf: Token buffer + * @ptrbox: Global pointer box */ struct cescal_state { int in_fd; struct readbuf rb; struct tokbuf tokbuf; + struct ptrbox ptrbox; }; /* -- cgit v1.2.3