summaryrefslogtreecommitdiff
path: root/Src/Modules/zutil.c
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2021-11-12 20:33:52 +0100
committerOliver Kiddle <opk@zsh.org>2021-11-12 20:33:52 +0100
commitdfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3 (patch)
tree1894d81725e4825c1b1948c0ccf1236b439e3710 /Src/Modules/zutil.c
parent631576de0f7b4e52487175e3e017e5136424b626 (diff)
downloadzsh-dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3.tar.gz
zsh-dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3.zip
49561: add zformat -F option, similar to -f but ternary expressions check for existence instead of doing math evaluation
Diffstat (limited to 'Src/Modules/zutil.c')
-rw-r--r--Src/Modules/zutil.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 691ba6c2f..2f17c03f1 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -776,10 +776,12 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
* ousedp (*outp)[*ousedp] is where to write next
* olenp *olenp is the size allocated for *outp
* endchar Terminator character in addition to `\0' (may be '\0')
+ * presence -F: Ternary expressions test emptyness instead
* skip If 1, don't output, just parse.
*/
static char *zformat_substring(char* instr, char **specs, char **outp,
- int *ousedp, int *olenp, int endchar, int skip)
+ int *ousedp, int *olenp, int endchar,
+ int presence, int skip)
{
char *s;
@@ -813,20 +815,29 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
if (testit && STOUC(*s)) {
int actval, testval, endcharl;
- /*
- * One one number is useful for ternary expressions.
- * Remember to put the sign back.
- */
+ /* Only one number is useful for ternary expressions. */
testval = (min >= 0) ? min : (max >= 0) ? max : 0;
- if (right)
- testval *= -1;
- if (specs[STOUC(*s)])
- actval = (int)mathevali(specs[STOUC(*s)]);
- else
- actval = 0;
- /* zero means values are equal, i.e. true */
- actval -= testval;
+ if (specs[STOUC(*s)] && *specs[STOUC(*s)]) {
+ if (presence) {
+ if (testval)
+#ifdef MULTIBYTE_SUPPORT
+ if (isset(MULTIBYTE))
+ actval = MB_METASTRWIDTH(specs[STOUC(*s)]);
+ else
+#endif
+ actval = strlen(specs[STOUC(*s)]);
+ else
+ actval = 1;
+ actval = right ? (testval < actval) : (testval >= actval);
+ } else {
+ if (right) /* put the sign back */
+ testval *= -1;
+ /* zero means values are equal, i.e. true */
+ actval = (int)mathevali(specs[STOUC(*s)]) - testval;
+ }
+ } else
+ actval = presence ? !right : testval;
/* careful about premature end of string */
if (!(endcharl = *++s))
@@ -837,10 +848,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
* vice versa... unless we are already skipping.
*/
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
- olenp, endcharl, skip || actval)))
+ olenp, endcharl, presence, skip || actval)))
return NULL;
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
- olenp, ')', skip || !actval)))
+ olenp, ')', presence, skip || !actval)))
return NULL;
} else if (skip) {
continue;
@@ -912,6 +923,7 @@ static int
bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
char opt;
+ int presence = 0;
if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) {
zwarnnam(nam, "invalid argument: %s", args[0]);
@@ -920,6 +932,9 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
args++;
switch (opt) {
+ case 'F':
+ presence = 1;
+ /* fall-through */
case 'f':
{
char **ap, *specs[256] = {0}, *out;
@@ -939,7 +954,8 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
}
out = (char *) zhalloc(olen = 128);
- zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0);
+ zformat_substring(args[1], specs, &out, &oused, &olen, '\0',
+ presence, 0);
out[oused] = '\0';
setsparam(args[0], ztrdup(out));