diff options
Diffstat (limited to 'src/execline/shift.c')
-rw-r--r-- | src/execline/shift.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/execline/shift.c b/src/execline/shift.c new file mode 100644 index 0000000..b09ba38 --- /dev/null +++ b/src/execline/shift.c @@ -0,0 +1,121 @@ +/* ISC license. */ + +#include <skalibs/sgetopt.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <execline/execline.h> + +#define USAGE "shift [ -n arg# ] [ -b block# ] prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned int strict = el_getstrict() ; + unsigned int b = 0 ; + unsigned int n = 0 ; + unsigned int sharp ; + unsigned int i = 0 ; + PROG = "shift" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "n:b:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : + if (!uint0_scan(l.arg, &n)) dieusage() ; + i = 1 ; + break ; + case 'b' : + if (!uint0_scan(l.arg, &b)) dieusage() ; + i = 1 ; + break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + if (i) i = 0 ; else n = 1 ; + { + char const *x = env_get2(envp, "#") ; + if (!x) strerr_dienotset(100, "#") ; + if (!uint0_scan(x, &sharp)) strerr_dieinvalid(100, "#") ; + } + + + /* Shift n args */ + + if (n > sharp) + { + if (strict) + { + char fmtn[UINT_FMT] ; + char fmtsharp[UINT_FMT] ; + fmtn[uint_fmt(fmtn, n)] = 0 ; + fmtsharp[uint_fmt(fmtsharp, sharp)] = 0 ; + if (strict == 1) + strerr_warnwu5x("shift", " ", fmtn, " arguments: got ", fmtsharp) ; + else + strerr_diefu5x(100, "shift", " ", fmtn, " arguments: got ", fmtsharp) ; + } + n = sharp ; + } + + + /* Shift b blocks */ + + for (; i < b ; i++) + { + for (;;) + { + char const *x ; + unsigned int base = n ; + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, ++n)] = 0 ; + if (n > sharp) + { + char fmti[UINT_FMT] ; + fmti[uint_fmt(fmt, i)] = 0 ; + strerr_diefu6x(100, "shift", " block ", fmti, ": too few arguments (", fmt, ")") ; + } + x = env_get2(envp, fmt) ; + if (!x) strerr_dienotset(100, fmt) ; + if ((x[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !x[1])) break ; + if ((x[0] != EXECLINE_BLOCK_QUOTE_CHAR) && strict) + { + char fmti[UINT_FMT] ; + char fmtp[UINT_FMT] ; + fmti[uint_fmt(fmti, i)] = 0 ; + fmtp[uint_fmt(fmtp, n - base)] = 0 ; + if (strict == 1) + strerr_warnw6x("unquoted positional ", x, " at block ", fmti, " position ", fmtp) ; + else + strerr_dief6x(100, "unquoted positional ", x, " at block ", fmti, " position ", fmtp) ; + } + } + } + + + /* n = shift value; modify the env */ + + { + register unsigned int i = 1 ; + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, sharp - n)] = 0 ; + if (!pathexec_env("#", fmt)) strerr_diefu1sys(111, "pathexec_env") ; + for (; i <= sharp ; i++) + { + char fmu[UINT_FMT] ; + fmt[uint_fmt(fmt, i)] = 0 ; + fmu[uint_fmt(fmu, i + n)] = 0 ; + if (!pathexec_env(fmt, i <= (sharp - n) ? env_get2(envp, fmu) : 0)) + strerr_diefu1sys(111, "pathexec_env") ; + } + } + pathexec(argv) ; + strerr_dieexec(111, argv[0]) ; +} |