diff options
-rw-r--r-- | doc/execlineb.html | 20 | ||||
-rw-r--r-- | src/execline/execlineb.c | 26 |
2 files changed, 28 insertions, 18 deletions
diff --git a/doc/execlineb.html b/doc/execlineb.html index e865199..96e804f 100644 --- a/doc/execlineb.html +++ b/doc/execlineb.html @@ -25,7 +25,7 @@ <h2> Interface </h2> <pre> - execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> ] -c <em>script</em> [ <em>args...</em> ] + execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> | -s <em>nmin</em> ] -c <em>script</em> [ <em>args...</em> ] </pre> <p> @@ -33,7 +33,7 @@ or </p> <pre> - execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> ] <em>scriptfile</em> [ <em>args...</em> ] + execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> | -s <em>nmin</em> ] <em>scriptfile</em> [ <em>args...</em> ] </pre> <p> @@ -62,15 +62,15 @@ exits 0. </li> </p> <ul> - <li> <em>Pushing the current stack frame.</em> If neither the -<tt>-p</tt> nor the <tt>-P</tt> nor the <tt>-S</tt> option is set: + <li> <em>Pushing the current stack frame.</em> If none of the +<tt>-p</tt>, <tt>-P</tt>, <tt>-S</tt> or <tt>-s</tt> options is set: <tt>execlineb</tt> <a href="el_pushenv.html">pushes</a> the current positional parameters, i.e. environment variables that start with <tt>#</tt>, <tt>0</tt>, <tt>1</tt>, ..., <tt>9</tt>. To get the previous values back, use <a href="emptyenv.html"><tt>emptyenv -P</tt></a>. </li> - <li> <em>Setting the new stack frame.</em> If neither the <tt>-P</tt> -nor the <tt>-S</tt> option is set: + <li> <em>Setting the new stack frame.</em> If none of the <tt>-P</tt>, +<tt>-S</tt> or <tt>-s</tt> options is set: <ul> <li> <tt>execlineb</tt> sets the <tt>#</tt> environment variable to the number <em>n</em> of <em>args</em> it is given. </li> @@ -229,6 +229,10 @@ variables. <tt>execlineb -S3 -c "<em>script</em>"</tt> is equivalent to, but more efficient than, <tt>execlineb -c "elgetpositionals -P3 emptyenv -P <em>script</em>"</tt>. See <a href="el_pushenv.html#integrated">the details</a>. </li> + <li> The <tt>-s <em>nmin</em></tt> option behaves just like the +<tt>-S</tt> option, except that it defines <tt>$@</tt> as the rest of the +command line <strong>after</strong> <em>nmin</em> arguments have been +removed. </li> </ul> <h2> Current limitations </h2> @@ -239,8 +243,8 @@ but more efficient than, <tt>execlineb -c "elgetpositionals -P3 emptyenv limitations such as the kernel buffer size for <em>argv</em> and <em>envp</em> - at least 64 kB on most systems. This means that <tt>execlineb</tt> cannot execute arbitrarily large scripts. Be careful with deeply nested scripts too: -without the <tt>-p</tt>/<tt>-P</tt>/<tt>-S</tt> option, each execlineb -invocation uses up some space in the environment. +without the <tt>-p</tt>/<tt>-P</tt>/<tt>-S</tt>/<tt>-s</tt> option, each +execlineb invocation uses up some space in the environment. </p> </body> diff --git a/src/execline/execlineb.c b/src/execline/execlineb.c index bfe1d7e..fbbaeee 100644 --- a/src/execline/execlineb.c +++ b/src/execline/execlineb.c @@ -15,9 +15,9 @@ #include <execline/execline.h> #include "exlsn.h" -#define USAGE "execlineb [ -p | -P | -S nmin ] [ -q | -w | -W ] [ -c commandline ] script args" +#define USAGE "execlineb [ -p | -P | -S nmin | -s nmin ] [ -q | -w | -W ] [ -c commandline ] script args" -static int myexlp (stralloc *sa, char const *const *argv, unsigned int argc, unsigned int nmin, char const *dollar0) +static int myexlp (stralloc *sa, char const *const *argv, unsigned int argc, unsigned int nmin, char const *dollar0, int doshift) { exlsn_t info = EXLSN_ZERO ; unsigned int n = argc > nmin ? argc : nmin ; @@ -33,17 +33,22 @@ static int myexlp (stralloc *sa, char const *const *argv, unsigned int argc, uns if (!stralloc_catb(&info.values, fmt, uint_fmt(fmt, argc)) || !stralloc_0(&info.values)) goto err ; blah[1].var = 2 ; blah[1].value = info.values.len ; blah[1].n = 1 ; if (!stralloc_catb(&info.values, dollar0, str_len(dollar0) + 1)) goto err ; - blah[2].var = 4 ; blah[2].value = info.values.len ; blah[2].n = argc ; + blah[2].var = 4 ; blah[2].value = info.values.len ; blah[2].n = doshift && n == nmin ? 0 : argc ; genalloc_catb(elsubst_t, &info.data, blah, 3) ; } for (; i < n ; i++) { - elsubst_t blah ; + elsubst_t blah = { .var = info.vars.len, .value = info.values.len, .n = 1 } ; char fmt[UINT_FMT] ; - blah.var = info.vars.len ; blah.value = info.values.len ; blah.n = 1 ; if (!stralloc_catb(&info.vars, fmt, uint_fmt(fmt, i+1)) || !stralloc_0(&info.vars)) goto err ; if (!stralloc_catb(&info.values, i < argc ? argv[i] : "", i < argc ? str_len(argv[i]) + 1 : 1)) goto err ; genalloc_append(elsubst_t, &info.data, &blah) ; + if (i == nmin && doshift) + { + elsubst_t *p = genalloc_s(elsubst_t, &info.data) + 2 ; /* hit $@ in-place */ + p->value = blah.value ; + p->n = argc - nmin ; + } } { stralloc dst = STRALLOC_ZERO ; @@ -75,7 +80,7 @@ int main (int argc, char const *const *argv, char const *const *envp) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - register int opt = subgetopt_r(argc, argv, "pPqwWc:S:", &l) ; + register int opt = subgetopt_r(argc, argv, "pPqwWc:S:s:", &l) ; if (opt == -1) break ; switch (opt) { @@ -86,9 +91,10 @@ int main (int argc, char const *const *argv, char const *const *envp) case 'W' : flagstrict = 2 ; break ; case 'c' : stringarg = l.arg ; break ; case 'S' : + case 's' : { if (!uint0_scan(l.arg, &nmin)) strerr_dieusage(100, USAGE) ; - flagpushenv = 3 ; + flagpushenv = 3 + (opt == 's') ; break ; } default : strerr_dieusage(100, USAGE) ; @@ -130,9 +136,8 @@ int main (int argc, char const *const *argv, char const *const *envp) if (!env_addmodif(&modif, "EXECLINE_STRICT", flagstrict ? fmt : 0)) goto errenv ; } - if (flagpushenv == 3) + if (flagpushenv == 3 || flagpushenv == 4) { - flagpushenv = 0 ; if (flagstrict && ((unsigned int)argc < nmin)) { char fmtn[UINT_FMT] ; @@ -144,8 +149,9 @@ int main (int argc, char const *const *argv, char const *const *envp) else strerr_warnw4x("too few arguments: expecting at least ", fmtn, " but got ", fmta) ; } - nc = myexlp(&sa, argv, argc, nmin, dollar0) ; + nc = myexlp(&sa, argv, argc, nmin, dollar0, flagpushenv == 4) ; if (nc < 0) strerr_diefu1sys(111, "substitute positional parameters") ; + flagpushenv = 0 ; } else if (flagpushenv) { |