summaryrefslogtreecommitdiff
path: root/src/libexecline/exlp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexecline/exlp.c')
-rw-r--r--src/libexecline/exlp.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/libexecline/exlp.c b/src/libexecline/exlp.c
new file mode 100644
index 0000000..060eb68
--- /dev/null
+++ b/src/libexecline/exlp.c
@@ -0,0 +1,78 @@
+/* ISC license. */
+
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/uint.h>
+#include <execline/execline.h>
+#include "exlsn.h"
+
+int exlp (unsigned int nmin, char const *const *envp, exlsn_t *info)
+{
+ unsigned int varbase = info->vars.len ;
+ unsigned int valbase = info->values.len ;
+ unsigned int datbase = genalloc_len(elsubst_t, &info->data) ;
+ unsigned int i = 0 ;
+ char const *x = env_get2(envp, "#") ;
+ elsubst_t blah ;
+ unsigned int n, ntot, poszero ;
+ if (!x) return -2 ;
+ if (!uint0_scan(x, &n)) return -2 ;
+ if (el_vardupl("#", info->vars.s, info->vars.len)) return -2 ;
+ if (el_vardupl("@", info->vars.s, info->vars.len)) return -2 ;
+ {
+ register unsigned int strict = el_getstrict() ;
+ if (strict && (n < nmin))
+ {
+ char fmta[UINT_FMT] ;
+ char fmtn[UINT_FMT] ;
+ fmta[uint_fmt(fmta, n)] = 0 ;
+ fmtn[uint_fmt(fmtn, nmin)] = 0 ;
+ if (strict > 1)
+ strerr_dief4x(100, "too few arguments: expected at least ", fmtn, " but got ", fmta) ;
+ else
+ strerr_warnw4x("too few arguments: expected at least ", fmtn, " but got ", fmta) ;
+ }
+ }
+ blah.var = varbase ;
+ blah.value = info->values.len ;
+ blah.n = 1 ;
+ if (!stralloc_catb(&info->vars, "#\0@", 4)
+ || !stralloc_catb(&info->values, x, str_len(x) + 1)
+ || !genalloc_append(elsubst_t, &info->data, &blah)) goto err ;
+ ntot = n > nmin ? n : nmin ;
+ poszero = info->values.len ;
+ for (; i <= ntot ; i++)
+ {
+ char fmt[UINT_FMT] ;
+ unsigned int l = uint_fmt(fmt, i) ;
+ fmt[l] = 0 ;
+ if (el_vardupl(fmt, info->vars.s, info->vars.len)) goto err2 ;
+ x = (i <= n) ? env_get2(envp, fmt) : "" ;
+ if (!x) goto err2 ;
+ blah.var = info->vars.len ;
+ blah.value = info->values.len ;
+ blah.n = 1 ;
+ if (!stralloc_catb(&info->vars, fmt, l+1)
+ || !stralloc_catb(&info->values, x, str_len(x) + 1)
+ || !genalloc_append(elsubst_t, &info->data, &blah)) goto err ;
+ }
+ blah.var = varbase + 2 ;
+ blah.value = poszero + str_len(info->values.s + poszero) + 1 ;
+ blah.n = n ;
+ if (!genalloc_append(elsubst_t, &info->data, &blah)) goto err ;
+ return n ;
+
+ err:
+ info->vars.len = varbase ;
+ info->values.len = valbase ;
+ genalloc_setlen(elsubst_t, &info->data, datbase) ;
+ return -1 ;
+ err2:
+ info->vars.len = varbase ;
+ info->values.len = valbase ;
+ genalloc_setlen(elsubst_t, &info->data, datbase) ;
+ return -2 ;
+}