From 2abba7243a736a2fc626f3cc917d8a67014d4d20 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 5 Jun 2015 11:21:22 +0100 Subject: 35386: expand tabs where useful in builtins outputing function. Also add to zed -f. Option is -x . --- Src/builtin.c | 50 ++++++++++++++++++++++++++++---------- Src/hashtable.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++------- Src/pattern.c | 13 ++++------ Src/text.c | 46 +++++++++++++++++++++++++++++++++-- Src/utils.c | 43 +++++++++++++++++++++++++++++---- Src/zsh.h | 9 ++++--- 6 files changed, 196 insertions(+), 39 deletions(-) (limited to 'Src') diff --git a/Src/builtin.c b/Src/builtin.c index 4b081468d..0d1d00ec3 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -72,7 +72,7 @@ static struct builtin builtins[] = BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "aAdDe:EfiIlLmnpPrRt:W", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%Z:%ghlprtux", "E"), - BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmMtTuUz", NULL), + BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmMtTuUx:z", NULL), BUILTIN("getln", 0, bin_read, 0, -1, 0, "ecnAlE", "zr"), BUILTIN("getopts", 0, bin_getopts, 2, -1, 0, NULL, NULL), BUILTIN("hash", BINF_MAGICEQUALS, bin_hash, 0, -1, 0, "Ldfmrv", NULL), @@ -128,9 +128,9 @@ static struct builtin builtins[] = BUILTIN("unset", BINF_PSPECIAL, bin_unset, 1, -1, 0, "fmv", NULL), BUILTIN("unsetopt", 0, bin_setopt, 0, -1, BIN_UNSETOPT, NULL, NULL), BUILTIN("wait", 0, bin_fg, 0, -1, BIN_WAIT, NULL, NULL), - BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsSw", NULL), - BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsSw", "ca"), - BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsSw", "c"), + BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsSwx:", NULL), + BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsSwx:", "ca"), + BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsSwx:", "c"), BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "AFRILP:abcfdilmpue", NULL), BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUMRcmzka", NULL), }; @@ -2749,7 +2749,7 @@ bin_functions(char *name, char **argv, Options ops, int func) Patprog pprog; Shfunc shf; int i, returnval = 0; - int on = 0, off = 0, pflags = 0, roff; + int on = 0, off = 0, pflags = 0, roff, expand = 0; /* Do we have any flags defined? */ if (OPT_PLUS(ops,'u')) @@ -2785,11 +2785,23 @@ bin_functions(char *name, char **argv, Options ops, int func) } if ((off & PM_UNDEFINED) || (OPT_ISSET(ops,'k') && OPT_ISSET(ops,'z')) || + (OPT_ISSET(ops,'x') && !OPT_HASARG(ops,'x')) || (OPT_MINUS(ops,'X') && (OPT_ISSET(ops,'m') || *argv || !scriptname))) { zwarnnam(name, "invalid option(s)"); return 1; } + if (OPT_ISSET(ops,'x')) { + char *eptr; + expand = (int)zstrtol(OPT_ARG(ops,'x'), &eptr, 10); + if (*eptr) { + zwarnnam(name, "number expected after -x"); + return 1; + } + if (expand == 0) /* no indentation at all */ + expand = -1; + } + if (OPT_PLUS(ops,'f') || roff || OPT_ISSET(ops,'+')) pflags |= PRINT_NAMEONLY; @@ -2948,8 +2960,8 @@ bin_functions(char *name, char **argv, Options ops, int func) } else { if (OPT_ISSET(ops,'U') && !OPT_ISSET(ops,'u')) on &= ~PM_UNDEFINED; - scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode, - pflags); + scanshfunc(1, on|off, DISABLED, shfunctab->printnode, + pflags, expand); } unqueue_signals(); return ret; @@ -2965,8 +2977,8 @@ bin_functions(char *name, char **argv, Options ops, int func) /* with no options, just print all functions matching the glob pattern */ queue_signals(); if (!(on|off) && !OPT_ISSET(ops,'X')) { - scanmatchtable(shfunctab, pprog, 1, 0, DISABLED, - shfunctab->printnode, pflags); + scanmatchshfunc(pprog, 1, 0, DISABLED, + shfunctab->printnode, pflags, expand); } else { /* apply the options to all functions matching the glob pattern */ for (i = 0; i < shfunctab->hsize; i++) { @@ -3008,7 +3020,7 @@ bin_functions(char *name, char **argv, Options ops, int func) returnval = 1; } else /* no flags, so just print */ - shfunctab->printnode(&shf->node, pflags); + printshfuncexpand(&shf->node, pflags, expand); } else if (on & PM_UNDEFINED) { int signum = -1, ok = 1; @@ -3222,6 +3234,7 @@ bin_whence(char *nam, char **argv, Options ops, int func) int aliasflags; int csh, all, v, wd; int informed = 0; + int expand = 0; char *cnam, **allmatched = 0; /* Check some option information */ @@ -3230,6 +3243,17 @@ bin_whence(char *nam, char **argv, Options ops, int func) all = OPT_ISSET(ops,'a'); wd = OPT_ISSET(ops,'w'); + if (OPT_ISSET(ops,'x')) { + char *eptr; + expand = (int)zstrtol(OPT_ARG(ops,'x'), &eptr, 10); + if (*eptr) { + zwarnnam(nam, "number expected after -x"); + return 1; + } + if (expand == 0) /* no indentation at all */ + expand = -1; + } + if (OPT_ISSET(ops,'w')) printflags |= PRINT_WHENCE_WORD; else if (OPT_ISSET(ops,'c')) @@ -3286,8 +3310,8 @@ bin_whence(char *nam, char **argv, Options ops, int func) /* and shell functions... */ informed += - scanmatchtable(shfunctab, pprog, 1, 0, DISABLED, - shfunctab->printnode, printflags); + scanmatchshfunc(pprog, 1, 0, DISABLED, + shfunctab->printnode, printflags, expand); /* and builtins. */ informed += @@ -3342,7 +3366,7 @@ bin_whence(char *nam, char **argv, Options ops, int func) } /* Look for shell function */ if ((hn = shfunctab->getnode(shfunctab, *argv))) { - shfunctab->printnode(hn, printflags); + printshfuncexpand(hn, printflags, expand); informed = 1; if (!all) continue; diff --git a/Src/hashtable.c b/Src/hashtable.c index ab381cc6a..2b5524999 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -937,13 +937,17 @@ printshfuncnode(HashNode hn, int printflags) quotedzputs(f->node.nam, stdout); if (f->funcdef || f->node.flags & PM_UNDEFINED) { - printf(" () {\n\t"); - if (f->node.flags & PM_UNDEFINED) - printf("%c undefined\n\t", hashchar); - else + printf(" () {\n"); + zoutputtab(stdout); + if (f->node.flags & PM_UNDEFINED) { + printf("%c undefined\n", hashchar); + zoutputtab(stdout); + } else t = getpermtext(f->funcdef, NULL, 1); - if (f->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL)) - printf("%c traced\n\t", hashchar); + if (f->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL)) { + printf("%c traced\n", hashchar); + zoutputtab(stdout); + } if (!t) { char *fopt = "UtTkz"; int flgs[] = { @@ -959,11 +963,12 @@ printshfuncnode(HashNode hn, int printflags) zputs(t, stdout); zsfree(t); if (f->funcdef->flags & EF_RUN) { - printf("\n\t"); + printf("\n"); + zoutputtab(stdout); quotedzputs(f->node.nam, stdout); printf(" \"$@\""); } - } + } printf("\n}"); } else { printf(" () { }"); @@ -979,6 +984,59 @@ printshfuncnode(HashNode hn, int printflags) putchar('\n'); } +/* + * Wrap scanmatchtable for shell functions with optional + * expansion of leading tabs. + * expand = 0 is standard: use hard tabs. + * expand > 0 uses that many spaces. + * expand < 0 uses no identation. + * + * Note this function and the following two are called with + * interrupts queued, so saving and restoring text_expand_tabs + * is safe. + */ + +/**/ +mod_export int +scanmatchshfunc(Patprog pprog, int sorted, int flags1, int flags2, + ScanFunc scanfunc, int scanflags, int expand) +{ + int ret, save_expand; + + save_expand = text_expand_tabs; + text_expand_tabs = expand; + ret = scanmatchtable(shfunctab, pprog, sorted, flags1, flags2, + scanfunc, scanflags); + text_expand_tabs = save_expand; + + return ret; +} + +/* Wrap scanhashtable to expand tabs for shell functions */ + +/**/ +mod_export int +scanshfunc(int sorted, int flags1, int flags2, + ScanFunc scanfunc, int scanflags, int expand) +{ + return scanmatchshfunc(NULL, sorted, flags1, flags2, + scanfunc, scanflags, expand); +} + +/* Wrap shfunctab->printnode to expand tabs */ + +/**/ +mod_export void +printshfuncexpand(HashNode hn, int printflags, int expand) +{ + int save_expand; + + save_expand = text_expand_tabs; + text_expand_tabs = expand; + shfunctab->printnode(hn, printflags); + text_expand_tabs = save_expand; +} + /**************************************/ /* Reserved Word Hash Table Functions */ /**************************************/ diff --git a/Src/pattern.c b/Src/pattern.c index 4e5e8a110..7e07548f9 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -2202,20 +2202,15 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, if ((patglobflags & GF_MATCHREF) && !(patflags & PAT_FILE)) { char *str = ztrduppfx(patinstart, patinlen); - char *ptr = patinstart; - int mlen = 0; + int mlen; /* * Count the characters. We're not using CHARSUB() - * because the string is still metafied. We're - * not using mb_metastrlen() because that expects - * the string to be null terminated. + * because the string is still metafied. */ MB_METACHARINIT(); - while (ptr < patinstart + patinlen) { - mlen++; - ptr += MB_METACHARLEN(ptr); - } + mlen = MB_METASTRLEN2END(patinstart, 0, + patinstart + patinlen); setsparam("MATCH", str); setiparam("MBEGIN", diff --git a/Src/text.c b/Src/text.c index 958303c68..850879699 100644 --- a/Src/text.c +++ b/Src/text.c @@ -30,6 +30,16 @@ #include "zsh.mdh" #include "text.pro" +/* + * If non-zero, expand syntactically significant leading tabs in text + * to this number of spaces. + * + * If negative, don't output leading whitespace at all. + */ + +/**/ +int text_expand_tabs; + static char *tptr, *tbuf, *tlim, *tpending; static int tsiz, tindent, tnewlins, tjob; @@ -156,8 +166,16 @@ taddnl(int no_semicolon) if (tnewlins) { tdopending(); taddchr('\n'); - for (t0 = 0; t0 != tindent; t0++) - taddchr('\t'); + for (t0 = 0; t0 != tindent; t0++) { + if (text_expand_tabs >= 0) { + if (text_expand_tabs) { + int t1; + for (t1 = 0; t1 < text_expand_tabs; t1++) + taddchr(' '); + } else + taddchr('\t'); + } + } } else if (no_semicolon) { taddstr(" "); } else { @@ -165,6 +183,30 @@ taddnl(int no_semicolon) } } +/* + * Output a tab that may be expanded as part of a leading set. + * Note this is not part of the text framework; it's for + * code that needs to output its own tabs that are to be + * consistent with those from getpermtext(). + * + * Note these tabs are only expected to be useful at the + * start of the line, so we make no attempt to count columns. + */ + +/**/ +void +zoutputtab(FILE *outf) +{ + if (text_expand_tabs < 0) + return; + if (text_expand_tabs) { + int i; + for (i = 0; i < text_expand_tabs; i++) + fputc(' ', outf); + } else + fputc('\t', outf); +} + /* get a permanent textual representation of n */ /**/ diff --git a/Src/utils.c b/Src/utils.c index 7409dc876..c33c16d5a 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -4471,9 +4471,37 @@ ztrlen(char const *s) for (l = 0; *s; l++) { if (*s++ == Meta) { #ifdef DEBUG - if (! *s) + if (! *s) { fprintf(stderr, "BUG: unexpected end of string in ztrlen()\n"); - else + break; + } else +#endif + s++; + } + } + return l; +} + +#ifndef MULTIBYTE_SUPPORT +/* + * ztrlen() but with explicit end point for non-null-terminated + * segments. eptr may not be NULL. + */ + +/**/ +mod_export int +ztrlenend(char const *s, char const *eptr) +{ + int l; + + for (l = 0; s < eptr; l++) { + if (*s++ == Meta) { +#ifdef DEBUG + if (! *s) { + fprintf(stderr, + "BUG: unexpected end of string in ztrlenend()\n"); + break; + } else #endif s++; } @@ -4481,6 +4509,8 @@ ztrlen(char const *s) return l; } +#endif /* MULTIBYTE_SUPPORT */ + /* Subtract two pointers in a metafied string. */ /**/ @@ -4879,11 +4909,16 @@ mb_metacharlenconv(const char *s, wint_t *wcp) * If width is 1, return total character width rather than number. * If width is greater than 1, return 1 if character has non-zero width, * else 0. + * + * Ends if either *ptr is '\0', the normal case (eptr may be NULL for + * this), or ptr is eptr (i.e. *eptr is where the null would be if null + * terminated) for strings not delimited by nulls --- note these are + * still metafied. */ /**/ mod_export int -mb_metastrlen(char *ptr, int width) +mb_metastrlenend(char *ptr, int width, char *eptr) { char inchar, *laststart; size_t ret; @@ -4898,7 +4933,7 @@ mb_metastrlen(char *ptr, int width) num = num_in_char = 0; memset(&mb_shiftstate, 0, sizeof(mb_shiftstate)); - while (*ptr) { + while (*ptr && !(eptr && ptr >= eptr)) { if (*ptr == Meta) inchar = *++ptr ^ 32; else diff --git a/Src/zsh.h b/Src/zsh.h index f6e08e28d..c88c2e739 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2926,9 +2926,11 @@ enum { typedef wint_t convchar_t; #define MB_METACHARLENCONV(str, cp) mb_metacharlenconv((str), (cp)) #define MB_METACHARLEN(str) mb_metacharlenconv(str, NULL) -#define MB_METASTRLEN(str) mb_metastrlen(str, 0) -#define MB_METASTRWIDTH(str) mb_metastrlen(str, 1) -#define MB_METASTRLEN2(str, widthp) mb_metastrlen(str, widthp) +#define MB_METASTRLEN(str) mb_metastrlenend(str, 0, NULL) +#define MB_METASTRWIDTH(str) mb_metastrlenend(str, 1, NULL) +#define MB_METASTRLEN2(str, widthp) mb_metastrlenend(str, widthp, NULL) +#define MB_METASTRLEN2END(str, widthp, eptr) \ + mb_metastrlenend(str, widthp, eptr) /* * We replace broken implementations with one that uses Unicode @@ -3011,6 +3013,7 @@ typedef int convchar_t; #define MB_METASTRLEN(str) ztrlen(str) #define MB_METASTRWIDTH(str) ztrlen(str) #define MB_METASTRLEN2(str, widthp) ztrlen(str) +#define MB_METASTRLEN2END(str, widthp, eptr) ztrlenend(str, eptr) #define WCWIDTH_WINT(c) (1) -- cgit 1.4.1