summaryrefslogtreecommitdiff
path: root/src/execline/shift.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/execline/shift.c')
-rw-r--r--src/execline/shift.c121
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]) ;
+}