diff options
author | midipix <writeonce@midipix.org> | 2024-04-29 02:39:30 +0000 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2024-05-07 20:07:25 +0000 |
commit | 02e59c946d51faf976a85610e44d7b0ccf4a6e59 (patch) | |
tree | 660056e01b242e947e27c470b9989c7b1ae6b2b7 /src/internal | |
parent | e9098c5591f439cdf8a923c9298b8fc7ff28a3ac (diff) | |
download | treebnf-02e59c946d51faf976a85610e44d7b0ccf4a6e59.tar.bz2 treebnf-02e59c946d51faf976a85610e44d7b0ccf4a6e59.tar.xz |
driver: created program skeleton.
Diffstat (limited to 'src/internal')
-rw-r--r-- | src/internal/treebnf_dprintf_impl.c | 65 | ||||
-rw-r--r-- | src/internal/treebnf_dprintf_impl.h | 10 | ||||
-rw-r--r-- | src/internal/treebnf_driver_impl.h | 127 | ||||
-rw-r--r-- | src/internal/treebnf_errinfo_impl.c | 43 | ||||
-rw-r--r-- | src/internal/treebnf_errinfo_impl.h | 85 | ||||
-rw-r--r-- | src/internal/treebnf_tmpfile_impl.c | 89 | ||||
-rw-r--r-- | src/internal/treebnf_tmpfile_impl.h | 6 | ||||
-rw-r--r-- | src/internal/treebnf_visibility_impl.h | 26 |
8 files changed, 451 insertions, 0 deletions
diff --git a/src/internal/treebnf_dprintf_impl.c b/src/internal/treebnf_dprintf_impl.c new file mode 100644 index 0000000..8b24a93 --- /dev/null +++ b/src/internal/treebnf_dprintf_impl.c @@ -0,0 +1,65 @@ +/**************************************************************/ +/* treebnf: a tree oriented bnf library */ +/* Copyright (C) 2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */ +/**************************************************************/ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include "treebnf_dprintf_impl.h" +#include "treebnf_visibility_impl.h" + +tbnf_hidden int tbnf_dprintf(int fd, const char * fmt, ...) +{ + int ret; + int cnt; + int size; + va_list ap; + char * ch; + char * buf; + char chbuf[2048]; + + va_start(ap,fmt); + + size = sizeof(chbuf); + buf = ((cnt = vsnprintf(chbuf,size,fmt,ap)) < size) + ? chbuf : malloc(cnt + 1); + + va_end(ap); + + if (buf == chbuf) { + (void)0; + + } else if (buf) { + va_start(ap,fmt); + vsprintf(buf,fmt,ap); + va_end(ap); + + } else { + return -1; + } + + ret = 0; + ch = buf; + + for (; cnt && ret>=0; ) { + ret = write(fd,ch,cnt); + + while ((ret < 0) && (errno == EINTR)) + ret = write(fd,ch,cnt); + + ch += ret; + cnt -= ret; + } + + ret = (ret < 0) ? -1 : ch - buf; + + if (buf != chbuf) + free(buf); + + return ret; +} diff --git a/src/internal/treebnf_dprintf_impl.h b/src/internal/treebnf_dprintf_impl.h new file mode 100644 index 0000000..d00ac0f --- /dev/null +++ b/src/internal/treebnf_dprintf_impl.h @@ -0,0 +1,10 @@ +#ifndef TREEBNF_DPRINTF_IMPL_H +#define TREEBNF_DPRINTF_IMPL_H + +#ifdef ARGV_DRIVER +#define argv_dprintf tbnf_dprintf +#endif + +int tbnf_dprintf(int fd, const char * fmt, ...); + +#endif diff --git a/src/internal/treebnf_driver_impl.h b/src/internal/treebnf_driver_impl.h new file mode 100644 index 0000000..7fcdd43 --- /dev/null +++ b/src/internal/treebnf_driver_impl.h @@ -0,0 +1,127 @@ +/**************************************************************/ +/* treebnf: a tree oriented bnf library */ +/* Copyright (C) 2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */ +/**************************************************************/ + +#ifndef TREEBNF_DRIVER_IMPL_H +#define TREEBNF_DRIVER_IMPL_H + +#include <stdint.h> +#include <dirent.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <treebnf/treebnf.h> +#include "argv/argv.h" + +#define TBNF_OPTV_ELEMENTS 128 + +extern const struct argv_option tbnf_default_options[]; + +enum app_tags { + TAG_HELP, + TAG_VERSION, +}; + +struct tbnf_driver_ctx_impl { + struct tbnf_common_ctx cctx; + struct tbnf_driver_ctx ctx; + struct tbnf_fd_ctx fdctx; + int fdtmpin; + const struct tbnf_unit_ctx * euctx; + const char * eunit; + struct tbnf_error_info ** errinfp; + struct tbnf_error_info ** erricap; + struct tbnf_error_info * erriptr[64]; + struct tbnf_error_info erribuf[64]; +}; + +struct tbnf_unit_ctx_impl { + const char * path; + struct tbnf_unit_ctx uctx; + struct tbnf_raw_input map; + struct stat st; +}; + + +static inline struct tbnf_driver_ctx_impl * tbnf_get_driver_ictx( + const struct tbnf_driver_ctx * dctx) +{ + uintptr_t addr; + + if (dctx) { + addr = (uintptr_t)dctx - offsetof(struct tbnf_driver_ctx_impl,ctx); + return (struct tbnf_driver_ctx_impl *)addr; + } + + return 0; +} + +static inline struct tbnf_unit_ctx_impl * tbnf_get_unit_ictx( + const struct tbnf_unit_ctx * uctx) +{ + struct tbnf_unit_ctx_impl * ictx; + uintptr_t addr; + + addr = (uintptr_t)uctx - offsetof(struct tbnf_unit_ctx_impl,uctx); + ictx = (struct tbnf_unit_ctx_impl *)addr; + return ictx; +} + +static inline void tbnf_driver_set_ectx( + const struct tbnf_driver_ctx * dctx, + const struct tbnf_unit_ctx * uctx, + const char * unit) +{ + struct tbnf_driver_ctx_impl * ictx; + + ictx = tbnf_get_driver_ictx(dctx); + ictx->euctx = uctx; + ictx->eunit = unit; +} + +static inline int tbnf_driver_fdin(const struct tbnf_driver_ctx * dctx) +{ + struct tbnf_fd_ctx fdctx; + tbnf_lib_get_driver_fdctx(dctx,&fdctx); + return fdctx.fdin; +} + +static inline int tbnf_driver_fdout(const struct tbnf_driver_ctx * dctx) +{ + struct tbnf_fd_ctx fdctx; + tbnf_lib_get_driver_fdctx(dctx,&fdctx); + return fdctx.fdout; +} + +static inline int tbnf_driver_fderr(const struct tbnf_driver_ctx * dctx) +{ + struct tbnf_fd_ctx fdctx; + tbnf_lib_get_driver_fdctx(dctx,&fdctx); + return fdctx.fderr; +} + +static inline int tbnf_driver_fdlog(const struct tbnf_driver_ctx * dctx) +{ + struct tbnf_fd_ctx fdctx; + tbnf_lib_get_driver_fdctx(dctx,&fdctx); + return fdctx.fdlog; +} + +static inline int tbnf_driver_fdcwd(const struct tbnf_driver_ctx * dctx) +{ + struct tbnf_fd_ctx fdctx; + tbnf_lib_get_driver_fdctx(dctx,&fdctx); + return fdctx.fdcwd; +} + +static inline int tbnf_driver_fddst(const struct tbnf_driver_ctx * dctx) +{ + struct tbnf_fd_ctx fdctx; + tbnf_lib_get_driver_fdctx(dctx,&fdctx); + return fdctx.fddst; +} + +#endif diff --git a/src/internal/treebnf_errinfo_impl.c b/src/internal/treebnf_errinfo_impl.c new file mode 100644 index 0000000..a639f27 --- /dev/null +++ b/src/internal/treebnf_errinfo_impl.c @@ -0,0 +1,43 @@ +/**************************************************************/ +/* treebnf: a tree oriented bnf library */ +/* Copyright (C) 2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */ +/**************************************************************/ + +#include <treebnf/treebnf.h> +#include "treebnf_driver_impl.h" +#include "treebnf_errinfo_impl.h" +#include "treebnf_visibility_impl.h" + +tbnf_hidden int tbnf_record_error( + const struct tbnf_driver_ctx * dctx, + int esyscode, + int elibcode, + const char * efunction, + int eline, + unsigned eflags, + void * eany) +{ + struct tbnf_driver_ctx_impl * ictx; + struct tbnf_error_info * erri; + + ictx = tbnf_get_driver_ictx(dctx); + + if (ictx->errinfp == ictx->erricap) + return -1; + + *ictx->errinfp = &ictx->erribuf[ictx->errinfp - ictx->erriptr]; + erri = *ictx->errinfp; + + erri->edctx = dctx; + erri->esyscode = esyscode; + erri->elibcode = elibcode; + erri->efunction = efunction; + erri->eline = eline; + erri->eflags = eflags; + erri->eany = (eany && (esyscode == ENOENT)) ? strdup(eany) : eany; + + ictx->errinfp++; + + return -1; +} diff --git a/src/internal/treebnf_errinfo_impl.h b/src/internal/treebnf_errinfo_impl.h new file mode 100644 index 0000000..45a7e14 --- /dev/null +++ b/src/internal/treebnf_errinfo_impl.h @@ -0,0 +1,85 @@ +/**************************************************************/ +/* treebnf: a tree oriented bnf library */ +/* Copyright (C) 2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */ +/**************************************************************/ + +#ifndef TREEBNF_ERRINFO_IMPL_H +#define TREEBNF_ERRINFO_IMPL_H + +#include <errno.h> +#include <treebnf/treebnf.h> + +int tbnf_record_error( + const struct tbnf_driver_ctx *, + int esyscode, + int elibcode, + const char * efunction, + int eline, + unsigned eflags, + void * eany); + +#define TBNF_SYSTEM_ERROR(dctx,eany) \ + tbnf_record_error( \ + dctx, \ + errno, \ + 0, \ + __func__, \ + __LINE__, \ + TBNF_ERROR_TOP_LEVEL, \ + (void *)eany) + +#define TBNF_BUFFER_ERROR(dctx) \ + tbnf_record_error( \ + dctx, \ + ENOBUFS, \ + 0, \ + __func__, \ + __LINE__, \ + TBNF_ERROR_TOP_LEVEL, \ + 0) + +#define TBNF_SPAWN_ERROR(dctx) \ + tbnf_record_error( \ + dctx, \ + errno, \ + 0, \ + __func__, \ + __LINE__, \ + TBNF_ERROR_TOP_LEVEL \ + | (errno ? 0 \ + : TBNF_ERROR_CHILD), \ + 0) + +#define TBNF_FILE_ERROR(dctx) \ + tbnf_record_error( \ + dctx, \ + EIO, \ + 0, \ + __func__, \ + __LINE__, \ + TBNF_ERROR_TOP_LEVEL, \ + 0) + +#define TBNF_CUSTOM_ERROR(dctx,elibcode) \ + tbnf_record_error( \ + dctx, \ + 0, \ + elibcode, \ + __func__, \ + __LINE__, \ + TBNF_ERROR_TOP_LEVEL \ + | TBNF_ERROR_CUSTOM, \ + 0) + +#define TBNF_NESTED_ERROR(dctx) \ + tbnf_record_error( \ + dctx, \ + 0, \ + 0, \ + __func__, \ + __LINE__, \ + TBNF_ERROR_NESTED, \ + 0) + +#endif diff --git a/src/internal/treebnf_tmpfile_impl.c b/src/internal/treebnf_tmpfile_impl.c new file mode 100644 index 0000000..2a5eb45 --- /dev/null +++ b/src/internal/treebnf_tmpfile_impl.c @@ -0,0 +1,89 @@ +/**************************************************************/ +/* treebnf: a tree oriented bnf library */ +/* Copyright (C) 2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */ +/**************************************************************/ + +#define _GNU_SOURCE +#include <time.h> +#include <fcntl.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <inttypes.h> + +#include "treebnf_visibility_impl.h" + +#define PPRIX64 "%"PRIx64 + +/* mkostemp might be guarded by non-standard macros */ +/* unless HAVE_NO_MKOSTEMP, assume it is available */ +extern int mkstemp(char *); +extern int mkostemp(char *, int); + +/* __fs_tmpfile() atomically provides a private tmpfile */ +static int tbnf_tmpfile_by_framework(void) +{ +#ifdef _MIDIPIX_ABI + extern int __fs_tmpfile(int); + return __fs_tmpfile(O_CLOEXEC); +#else + return (-1); +#endif +} + +/* O_TMPFILE atomically provides a private tmpfile */ +static int tbnf_tmpfile_by_kernel(void) +{ +#ifdef O_TMPFILE + return openat(AT_FDCWD,"/tmp",O_RDWR|O_TMPFILE|O_CLOEXEC,0); +#else + return (-1); +#endif +} + +/* mk{o}stemp() provides a non-private tmpfile */ +static int tbnf_mkostemp(char * tmplate) +{ + int fd; +#ifdef HAVE_NO_MKOSTEMP + if ((fd = mkstemp(tmplate)) >= 0) + fcntl(fd,F_SETFD,FD_CLOEXEC); +#else + fd = mkostemp(tmplate,O_CLOEXEC); +#endif + return fd; +} + +tbnf_hidden int tbnf_tmpfile(void) +{ + int fd; + void * addr; + char tmplate[128]; + + /* try with __fs_tmpfile() */ + if ((fd = tbnf_tmpfile_by_framework()) >= 0) + return fd; + + /* try with O_TMPFILE */ + if ((fd = tbnf_tmpfile_by_kernel()) >= 0) + return fd; + + /* fallback to mk{o}stemp */ + addr = tmplate; + memset(tmplate,0,sizeof(tmplate)); + snprintf(tmplate,sizeof(tmplate), + "/tmp/" + ".treebnf.tmpfile" + ".time."PPRIX64 + ".salt.%p" + ".pid.%d" + ".XXXXXXXXXXXX", + time(0), + addr, + getpid()); + + return tbnf_mkostemp(tmplate); +} diff --git a/src/internal/treebnf_tmpfile_impl.h b/src/internal/treebnf_tmpfile_impl.h new file mode 100644 index 0000000..c295072 --- /dev/null +++ b/src/internal/treebnf_tmpfile_impl.h @@ -0,0 +1,6 @@ +#ifndef TREEBNF_TMPFILE_IMPL_H +#define TREEBNF_TMPFILE_IMPL_H + +int tbnf_tmpfile(void); + +#endif diff --git a/src/internal/treebnf_visibility_impl.h b/src/internal/treebnf_visibility_impl.h new file mode 100644 index 0000000..9599010 --- /dev/null +++ b/src/internal/treebnf_visibility_impl.h @@ -0,0 +1,26 @@ +#ifndef TREEBNF_VISIBILITY_IMPL_H +#define TREEBNF_VISIBILITY_IMPL_H + +/**********************************************************************/ +/* PE targets: __dllexport suffices for the purpose of exporting only */ +/* the desired subset of global symbols; this makes the visibility */ +/* attribute not only redundant, but also tricky if not properly */ +/* supported by the toolchain. */ +/* */ +/* When targeting Midipix, __PE__, __dllexport and __dllimport are */ +/* always defined by the toolchain. Otherwise, the absnece of these */ +/* macros has been detected by sofort's ccenv.sh during ./configure, */ +/* and they have accordingly been added to CFLAGS_OS. */ +/**********************************************************************/ + +#ifdef __PE__ +#define tbnf_hidden +#else +#ifdef _ATTR_VISIBILITY_HIDDEN +#define tbnf_hidden _ATTR_VISIBILITY_HIDDEN +#else +#define tbnf_hidden +#endif +#endif + +#endif |