summary refs log tree commit diff
path: root/src/execline/shift.c
blob: b09ba38b9e2f0be53d25b08c67c6f49aab423f2b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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]) ;
}