From b139a29e2f5500bf89e8da25b884658155e6c376 Mon Sep 17 00:00:00 2001 From: DTB Date: Sat, 18 Nov 2023 11:56:26 -0700 Subject: [PATCH] refactor psops(1) --- libpsargs/libpsargs.c | 14 +++++---- libpsargs/libpsargs.h | 25 +++++++++------ pscat/Makefile | 14 +++++---- pscat/pscat.c | 71 +++---------------------------------------- pscat/psops.c | 20 ++++++++++++ pscat/pspipe.c | 53 ++++++++++++++++++++++++++++++++ 6 files changed, 109 insertions(+), 88 deletions(-) create mode 100644 pscat/psops.c create mode 100644 pscat/pspipe.c diff --git a/libpsargs/libpsargs.c b/libpsargs/libpsargs.c index 2fcabda..32a2a25 100644 --- a/libpsargs/libpsargs.c +++ b/libpsargs/libpsargs.c @@ -7,7 +7,7 @@ #define SCMPFLAT(a, b) (*(a) != '\0' && *((a)+1) == '\0' && *(a) == (b)) int -check_arg(char **args, char l, char r){ +check_arg(char **args){ enum { UNINITIALIZED = 0, NORMAL = 1, @@ -27,8 +27,10 @@ check_arg(char **args, char l, char r){ /* decrement s if on an rparen, increment if on lparen * increment terms if on an rparen */ if(args[0][1] == '\0'){ - s += (args[0][0] == l) - (args[0][0] == r); - terms += (args[0][0] == r && s == NORMAL); + s += (args[0][0] == L_PAREN) + - (args[0][0] == R_PAREN); + terms += + (args[0][0] == R_PAREN && s == NORMAL); } break; } @@ -38,7 +40,7 @@ check_arg(char **args, char l, char r){ } char ** -corresponding_arg(char **arg, char l, char r){ +corresponding_arg(char **arg){ size_t p; for(p = 1; p > 0;){ @@ -46,9 +48,9 @@ corresponding_arg(char **arg, char l, char r){ /* branching here potentially saves a comparison. * this seems like the most optimal way to do this, * maybe it isn't, i don't care too much */ - if(SCMPFLAT(*arg, l)) + if(SCMPFLAT(*arg, L_PAREN)) ++p; - else if(SCMPFLAT(*arg, r)) + else if(SCMPFLAT(*arg, R_PAREN)) --p; } diff --git a/libpsargs/libpsargs.h b/libpsargs/libpsargs.h index ca4f5ae..e48807e 100644 --- a/libpsargs/libpsargs.h +++ b/libpsargs/libpsargs.h @@ -1,17 +1,22 @@ -/* pscat(1) and pspipe(1) arguments are flanked by { '[', '\0' } and - * { ']', '\0' }. Nesting is allowed to facilitate nesting of pscat(1) and - * pspipe(1). This checks to make sure grouping symbols in args are balanced. - * args is the argv that was passed to main, incremented. l is the left - * grouping character (usually '[') and r is the right grouping character - * (usually ']'). +#ifndef L_PAREN +# define L_PAREN '[' +#endif + +#ifndef R_PAREN +# define R_PAREN ']' +#endif + +/* psops(1) arguments are flanked by { '[', '\0' } and { ']', '\0' }. Nesting + * is allowed to facilitate nesting of psops(1) programs. This checks to make + * sure grouping symbols in args are balanced. + * args is the argv that was passed to main, incremented (so args[1] is "["). * Returns 0 in the events of a syntax error or there being no arguments. * Otherwise, returns the number of top-level right grouping arguments * (i.e. the number of terms). */ -int check_arg(char **args, char l, char r); +int check_arg(char **args); /* arg is the location of the argument with the left grouping symbol within - * argv, l is the left grouping character itself, r is the right grouping - * character itself. + * argv. * Returns the location of the argument with the corresponding left grouping * symbol within argv. */ -char **corresponding_arg(char **arg, char l, char r); +char **corresponding_arg(char **arg); diff --git a/pscat/Makefile b/pscat/Makefile index bc04789..7971c92 100644 --- a/pscat/Makefile +++ b/pscat/Makefile @@ -1,16 +1,18 @@ +CFLAGS += -g -I../libpsargs + all: pscat pscat: pscat.o ../libpsargs/libpsargs.o - $(CC) $(CFLAGS) -g -o pscat ../libpsargs/libpsargs.o pscat.o + $(CC) $(CFLAGS) -o $@ pscat.o ../libpsargs/libpsargs.o -pscat.o: pscat.c - $(CC) $(CFLAGS) -c -DPSCAT=1 -I../libpsargs -o pscat.o pscat.c +pscat.o: pscat.c psops.c + $(CC) $(CFLAGS) -DPSCAT=1 -c -o $@ pscat.c pspipe: pspipe.o ../libpsargs/libpsargs.o - $(CC) $(CFLAGS) -g -o pspipe ../libpsargs/libpsargs.o pspipe.o + $(CC) $(CFLAGS) -o $@ pspipe.o ../libpsargs/libpsargs.o -pspipe.o: pscat.c - $(CC) $(CFLAGS) -c -DPSPIPE=1 -I../libpsargs -o pspipe.o pscat.c +pspipe.o: pscat.c psops.c + $(CC) $(CFLAGS) -DPSPIPE=1 -c -o $@ pscat.c ../libpsargs/libpsargs.o: $(MAKE) -C ../libpsargs diff --git a/pscat/pscat.c b/pscat/pscat.c index 38abb9c..e9653c2 100644 --- a/pscat/pscat.c +++ b/pscat/pscat.c @@ -1,17 +1,13 @@ #include /* errno */ -#include /* fprintf(3), stderr */ +#include /* fprintf(3), stderr, "psops.c" */ #include /* strerror(3) */ -#include /* EX_USAGE */ +#include /* EX_OSERR, "psops.c" */ #include /* execvp(3) */ #include /* */ #include /* wait(2) */ -#include "libpsargs.h" /* check_arg(3), corresponding_arg(3) */ +#include "libpsargs.h" /* corresponding_arg(3), "psops.c" */ -#define L_PAREN '[' -#define R_PAREN ']' - -#if defined(PSCAT) static char *program_name = "pscat"; int @@ -19,7 +15,7 @@ f(char **argv){ int child; char **corr; - *(corr = corresponding_arg(argv, L_PAREN, R_PAREN)) = NULL; + *(corr = corresponding_arg(argv)) = NULL; switch(fork()){ case -1: fprintf(stderr, "%s: %s\n", program_name, strerror(errno)); @@ -34,61 +30,4 @@ f(char **argv){ } } -#elif defined(PSPIPE) -static char *program_name = "pspipe"; - -/* At the start of the loop argv[0] is { '[', '\0' } and file descriptor 0 is - * the intended standard input */ -int -f(char **argv){ - int child; - char **corr; - static int fd[2]; - int r; - - *(corr = corresponding_arg(argv, L_PAREN, R_PAREN)) = NULL; - if(corr[1] != NULL){ - if(pipe(fd) != 0){ - fprintf(stderr, - "%s: %s: %s\n", - program_name, argv[1], strerror(errno) - ); - return EX_OSERR; - } - } - if((r = fork()) == -1){ - printf(stderr, "%s: %s\n", program_name, strerror(errno)); - return EX_OSERR; - } - if(r == 0) - dup2(fd[0], 0); - else - dup2(fd[1], 1); - - close(fd[1]); - close(fd[0]); - - if(r == 1) - execvp(argv[1], argv+1); - else{ - argv = corr; - return *++argv == NULL - ? WIFEXITED(child) * WEXITSTATUS(child) - : f(argv); - } -} - -#endif - -int main(int argc, char *argv[]){ - - if(argc != 0) - program_name = argv[0]; - if(check_arg(++argv, L_PAREN, R_PAREN) == 0){ - fprintf(stderr, - "Usage: %s \"[\" [utility [argument...]] \"]\" ...\n", - program_name - ); - return EX_USAGE; - }else return f(argv); -} +#include "psops.c" diff --git a/pscat/psops.c b/pscat/psops.c new file mode 100644 index 0000000..0bc0a44 --- /dev/null +++ b/pscat/psops.c @@ -0,0 +1,20 @@ +/* #include /* fprintf(3), stderr */ + +#ifndef EX_USAGE +# define EX_USAGE 64 /* NetBSD sysexits(3) compat */ +#endif + +/* #include "libpsargs.h" /* check_arg(3) */ + +int main(int argc, char *argv[]){ + + if(argc != 0) + program_name = argv[0]; + if(check_arg(++argv) == 0){ + fprintf(stderr, + "Usage: %s \"[\" [utility [argument...]] \"]\" ...\n", + program_name + ); + return EX_USAGE; + }else return f(argv); +} diff --git a/pscat/pspipe.c b/pscat/pspipe.c new file mode 100644 index 0000000..ba9a171 --- /dev/null +++ b/pscat/pspipe.c @@ -0,0 +1,53 @@ +#include /* errno */ +#include /* fprintf(3), stderr, "psops.c" */ +#include /* strerror(3) */ +#include /* EX_OSERR */ +#include /* execvp(3) */ +#include /* */ +#include /* wait(2) */ + +#include "libpsargs.h" /* corresponding_arg(3), "psops.c" */ + +static char *program_name = "pspipe"; + +/* At the start of the loop argv[0] is { '[', '\0' } and file descriptor 0 is + * the intended standard input */ +int +f(char **argv){ + static int child; + char **corr; + int fd[2]; + int r; + + *(corr = corresponding_arg(argv)) = NULL; + if(corr[1] != NULL){ + if(pipe(fd) != 0){ + fprintf(stderr, + "%s: %s: %s\n", + program_name, argv[1], strerror(errno) + ); + return EX_OSERR; + } + if((r = fork()) == -1){ + fprintf(stderr, "%s: %s\n", + program_name, strerror(errno) + ); + return EX_OSERR; + } + if(r == 0) + dup2(fd[0], 0); + else + dup2(fd[1], 1); + close(fd[1]); + close(fd[0]); + if(r == 1) + execvp(argv[1], argv+1); + } + + argv = corr; + return *++argv == NULL + ? WEXITSTATUS(child) + : f(corr + 1); +} + +#include "psops.c"