From 4c96d993fab76e46342c244ebf3d6d686c812101 Mon Sep 17 00:00:00 2001 From: Emil Williams Date: Sat, 31 Aug 2024 23:05:09 +0000 Subject: [PATCH] expunge and whatever --- README | 44 +++++++++++++++++++++++++ bake.1 | 14 +++++--- bake.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 138 insertions(+), 36 deletions(-) diff --git a/README b/README index 8d7e8db..e093a41 100644 --- a/README +++ b/README @@ -64,3 +64,47 @@ needs to be tested a bit more to confirm full compatibility. changes - Rewrite of the code; Removal of -x --expunge; Addition of @LINE & @NAME, list, & select. + +24/08/22 - Expunge + +I decided to add expunge back in, after I went back to a project using +it, because I didn't feel like writing a regexp that would prune it. + +It works the same. However it's less tested. Backslashes are reliable. +It doesn't eat characters around itself and returns a reliable string. +It does, however, cover the same space as the origin string. + +Such brutal expressions as '@{\} @{\}@SHORT\}}' -> '} @{}@SHORT}' +successfully, with expunge_me correctly containing only that. + +It's the same, as before. Sadly I didn't generalize the search and +replace code, that's what sed is for, and I didn't want to implement +finite automata for this simple update, so its implementation is primitive. + +The implementation as a whole was meant for simplicity, +extensibility. I, before getting it working, got a gorilla version +that removed contextless @{ } successfully, and a version that +contextually removed each @{ and it's respective } via expand. + +Interesting note: Old Bake's executable is larger than new Bakes. +So, not only do we have constant memory, but I've saved space. + +Note that the only real limitation is that, that we can't make a @BAKE +command the size of THIS file, or a a @BAKE command inlining all of +Bake. If you need such a feature, use the old version of Bake, or +simply extend this version. I may do such things, because the code +here is better. + +This project really was never meant to be optimized, simply memory +confined. if it goes over, it'll SEGV and imply to the diligent user +to shorten his commands. If you just need enough in a simple fashion, +boosting: +#define BUFFER_SIZE (1 << 12) /* 4096 bytes; 4 KiB */ + TO (1 << 20) /* 1048576 bytes; 1 MiB */ + +4 KiB is enough in 99% cases and covers 100% of usage that I am aware +of apart from the case of testing this exact faculty. If it does limit +you, you can use an external script or + +I'm not planning to update Shake with @STOP, @LINE, (-x, --expunge), +or any new bells and wistles. diff --git a/bake.1 b/bake.1 index 613ddac..2420b18 100644 --- a/bake.1 +++ b/bake.1 @@ -4,7 +4,7 @@ \- file embeddable scripts .SH SYNOPSIS .B bake -[\-chln] [\-s ] [ARGS...] +[\-chlnx] [\-s ] [ARGS...] .SH DESCRIPTION bake is a simple tool meant to execute embedded shell commands within @@ -16,10 +16,15 @@ instance of \fB@BAKE\fP appears. It roots the shell execution in the directory of the given file. -Options must always be put first, and short options may be merged together. +Options must always be put first, and short options may be merged together, numerical options must be trailing. .HP - \fB\-c \-\-color\fP, \-h \-\-help, \fB\-n \-\-dry\-run\fP, \fB\-l \-\-list\fP, \fB\-s \-\-select\fP <\fBn\fP> + \fB\-c \-\-color\fP, Disables color + \-h \-\-help, Help message +\fB\-n \-\-dry\-run\fP, don't execute anything +\fB\-l \-\-list\fP, lists available shell commands +\fB\-s \-\-select\fP <\FBn\fP>, selects Nth shell command +\fB\-x \-\-expunge\fP, Removes what's specified in the expunge block .PP Macros @@ -47,7 +52,8 @@ Additional Features And Notes Shell execution may be disabled with the \fB-n\fP or \fB--dry-run\fP option. -Colors may be disabled with the \fB-c\fP or \fB--color\fP option. +Expunge removes exactly one file specified in the @{...} format. You may use +backslashes to remove .SH EXAMPLE .\" SRC BEGIN (example.c) diff --git a/bake.c b/bake.c index f0d8deb..8c8d78e 100644 --- a/bake.c +++ b/bake.c @@ -1,4 +1,7 @@ -// @BAKE cc -std=c99 -O2 -Wall -Wextra -Wpedantic -Wno-implicit-fallthrough -o @SHORT @FILENAME @ARGS @STOP +/* @BAKE cc -std=c99 -O2 -Wall -Wextra -Wpedantic -Wno-implicit-fallthrough -o @SHORT @FILENAME @ARGS @STOP */ +/* @BAKE cc -std=c99 -O2 -Wall -Wextra -Wpedantic -Wno-implicit-fallthrough -o '@{\} @{\}@SHORT\}}' @FILENAME @ARGS @STOP */ +/* @BAKE cc -std=c99 -O2 -Wall -Wextra -Wpedantic -Wno-implicit-fallthrough -o '@{\}}' @FILENAME @ARGS @STOP */ +/* @BAKE cc -std=c99 -O2 -Wall -Wextra -Wpedantic -Wno-implicit-fallthrough -o '@{a}' @FILENAME @ARGS @STOP */ #define _GNU_SOURCE #include @@ -16,8 +19,8 @@ #define BUFFER_SIZE (1 << 12) -#define START ("@" "BAKE" " ") -#define STOP ("@" "STOP") +#define START "@" "BAKE" " " +#define STOP "@" "STOP" #define AUTONOMOUS_COMPILE 0 @@ -45,10 +48,8 @@ #define ARRLEN(x) (sizeof (x) / sizeof (x [0])) -#if AUTONOMOUS_COMPILE -__attribute__((__section__(".text"))) static char autonomous_compile [] = - "@BAKE" " cc -w @FILENAME.c -o @FILENAME @ARGS\n"; -#endif +__attribute__((__section__(".text"))) static volatile char autonomous_compile [] = + "@BAKE cc -std=c99 -O2 -Wall -Wextra -Wpedantic -Wno-implicit-fallthrough -o @SHORT @FILENAME.c @ARGS @STOP"; static void swap (char * a, char * b) { @@ -113,8 +114,7 @@ lines (char * buffer, size_t off) { } static char * -expand (char * buffer, size_t length, char ** pairs, size_t count) { - static char expanded [BUFFER_SIZE] = {0}; +expand_buffer(char * expanded, char * buffer, size_t length, char ** pairs, size_t count) { size_t old, new, i, f, off = 0; /* I need to test the bounds checking here, it'll crash normally if this provision doesn't do anything, though. */ length &= (1 << 12) - 1; @@ -138,6 +138,36 @@ expand (char * buffer, size_t length, char ** pairs, size_t count) { } static char * +expand (char * buffer, size_t length, char ** pairs, size_t count) { + static char expanded [BUFFER_SIZE] = {0}; + return expand_buffer (expanded, buffer, length, pairs, count); +} + +static char * +expunge (char * to, char * from, size_t length, char ** pair, size_t count) { + size_t i, f; + (void)count; /* count isn't actually used... */ + static char expunge_me [FILENAME_MAX] = {0}; + for (i = 0; i < length; ++i) { + if (memcmp(from + i, pair[0], strlen(pair[0])) == 0) { + if (from[i - 1] == '\\') { --i; memmove(from + i, from + i + 1, length - i); i+=1+strlen(pair[0]); --length; continue; } + for (f = i + strlen(pair[0]); f < length; ++f) { + if (memcmp(from + f, pair[1], strlen(pair[1])) == 0) { + if (from[f - 1] == '\\') { --f; memmove(from + f, from + f + 1, length - f); --length; continue; } + memmove(to + i, from + i + strlen(pair[0]), length - i - strlen(pair[0])); + memmove(to + f - strlen(pair[1]), from + f - 1, length - f); + /* memcpy(to + f - 2, " ", strlen(pair[1])); */ + memcpy(expunge_me, to + i, f - i - 1 - strlen(pair[1])); + goto end; + } + } + } + } +end: + return expunge_me; +} + +static char * getmap (char * filename, size_t * length) { char * buffer = NULL; int fd = open (filename, O_RDONLY); @@ -192,21 +222,24 @@ color_fprintf (FILE * fp, char * format, ...) { free (buf); va_end (ap); } + /* -- */ int main (int argc, char ** argv) { void help (void); - int off, run = 1, list = 0, select_input, select = 1; + int off, run = 1, list = 0, ex = 0, select_input, select = 1; size_t length, begin = 0, end = 0; pid_t pid; - char line [10], expanded [BUFFER_SIZE], * buffer, * expandedp, * args, * shortened, * filename = NULL; + char line [10], expanded [BUFFER_SIZE], * buffer, * expandedp, * args, * shortened, * filename = NULL, + * paren [] = { "@{", "}" }, * expunge_me = NULL, * bake_begin = START, * bake_end = STOP; + /* opts */ for (off = 1; off < argc; ++off) { if (argv [off][0] != '-') { filename = argv [off]; ++off; break; } if (argv [off][1] != '-') { while (*(++argv [off])) switch (argv [off][0]) { - case_select: case 's': + select: case 's': select = atoi (argv [off] + 1); if (!select) { ++off; @@ -214,19 +247,23 @@ int main (int argc, char ** argv) { select = atoi (argv [off]); } if (select) { goto next; } - case_help: default: case 'h': help (); - case_list: case 'l': list = 1; - case_dryrun: case 'n': run = 0; break; - case_color: case 'c': color = 0; break; + default: case 'h': help (); + case 'l': list = 1; + case 'n': run = 0; break; + case 'c': color = 0; break; + case 'x': ex = 1; break; + case 'q': fclose(stderr); fclose(stdout); break; } continue; } argv[off] += 2; - if (strcmp(argv[off], "select") == 0) { goto case_select; } - else if (strcmp(argv[off], "list") == 0) { goto case_list; } - else if (strcmp(argv[off], "dry-run") == 0) { goto case_dryrun; } - else if (strcmp(argv[off], "color") == 0) { goto case_color; } - else if (strcmp(argv[off], "help") == 0) { goto case_help; } + if (strcmp(argv[off], "select") == 0) { goto select; } + else if (strcmp(argv[off], "list") == 0) { list = 1; run = 0; } + else if (strcmp(argv[off], "dry-run") == 0) { run = 0; } + else if (strcmp(argv[off], "color") == 0) { color = 0; } + else if (strcmp(argv[off], "expunge") == 0) { ex = 1; } + else if (strcmp(argv[off], "quiet") == 0) { fclose(stderr); fclose(stdout); } + else if (strcmp(argv[off], "help") == 0) { help(); } next:; } if (argc == 1 || !filename) { help (); } @@ -239,14 +276,14 @@ int main (int argc, char ** argv) { color_fprintf (stderr, RED "%s" RESET ": Could not access '" BOLD "%s" RESET "'\n", argv [0], filename); return 1; } - for (begin = 0; (list || select) && begin < length - strlen (START); ++begin) { - if (memcmp (buffer + begin, START, strlen (START)) == 0) { + for (begin = 0; (list || select) && begin < length - strlen (bake_begin); ++begin) { + if (memcmp (buffer + begin, bake_begin, strlen (bake_begin)) == 0) { size_t stop = begin; end = begin; again: while (end < length && buffer[end] != '\n') { ++end; } if (buffer[end - 1] == '\\') { ++end; goto again; } - while (stop < length - strlen(STOP)) { - if (memcmp(buffer + stop, STOP, strlen(STOP)) == 0) { + while (stop < length - strlen(bake_end)) { + if (memcmp(buffer + stop, bake_end, strlen(bake_end)) == 0) { if (stop && buffer[stop - 1] == '\\') { ++stop; continue; } end = stop; break; @@ -259,7 +296,7 @@ int main (int argc, char ** argv) { color_puts (RESET); } else { --select; } }} - begin += strlen (START) - 1; + begin += strlen (bake_begin) - 1; if (list) { return 0; } if (end < begin) { @@ -280,19 +317,33 @@ int main (int argc, char ** argv) { "@ARGS", args, "$+", args, "@LINE", line - }; - size_t count = ARRLEN (pair); + }; snprintf (line, 16, "%lu", lines (buffer, begin)); - expandedp = expand (buffer + begin, end - begin, pair, count); + expandedp = expand (buffer + begin, end - begin, pair, ARRLEN (pair)); memcpy(expanded, expandedp, BUFFER_SIZE); + expunge_me = expunge (expanded, expanded, strlen(expanded), paren, ARRLEN (paren)); munmap (buffer, length); /* print and execute */ - color_printf (GREEN "%s" RESET ": " BOLD "%s" RESET, argv [0], expanded); + color_fprintf (stderr, GREEN "%s" RESET ": " BOLD "%s" RESET, argv [0], expanded); if (expanded[strlen(expanded)] != '\n') { puts(""); } + + if (ex) { + color_fprintf (stderr, GREEN "%s" RESET ": removing '%s'\n", argv [0], expunge_me); + char * jin = ".c"; + if (expunge_me + && run + && /* just in case */ + memcmp(expunge_me + strlen(expunge_me) - strlen(jin), jin, strlen(jin)) != 0) + { remove(expunge_me); } + return 0; + } + if (!run) { return 0; } - fflush(stdout); + color_fprintf (stderr, GREEN "output" RESET ":\n"); + fflush(stdout); + if ((pid = fork ()) == 0) { execl ("/bin/sh", "sh", "-c", expanded, NULL); return 0; /* execl overwrites the process anyways */ @@ -334,7 +385,8 @@ void help (void) { "of the shell command (-n, --dry-run); disable color (-c, --color); list\n" "(-l, --list) and select (-s, --select ) which respectively lists\n" "all " BOLD "@BAKE" RESET " commands and select & run the Nth command.\n\n" - "It roots the shell execution in the directory of the given file.\n\n" + "It roots the shell execution in the directory of the given file.\n" + "Expunge with @{filename...}, using (-x, --expunge), \\@{} or @{\\}}.\n\n" "Licensed under the public domain.\n"; color_printf ("%s", help); exit (1);