From a73c705b0c864a9ce042fca6e72e0c92d4ad8237 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 16 Dec 2022 23:22:33 +0100 Subject: 51212: remove STOUC() macro This served as a workaround for ancient compilers where casts to unsigned char were broken. --- Src/Modules/zftp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Src/Modules/zftp.c') diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index e8e239e76..49b3ffa89 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -944,9 +944,9 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep) return 1; } for (i = 0; i < 4; i++) - iaddr[i] = STOUC(nums[i]); - iport[0] = STOUC(nums[4]); - iport[1] = STOUC(nums[5]); + iaddr[i] = (unsigned char) nums[i]; + iport[0] = (unsigned char) nums[4]; + iport[1] = (unsigned char) nums[5]; memcpy(&zdsockp->in.sin_addr, iaddr, sizeof(iaddr)); memcpy(&zdsockp->in.sin_port, iport, sizeof(iport)); @@ -2438,7 +2438,7 @@ zftp_type(char *name, char **args, int flags) fflush(stdout); return 0; } else { - nt = toupper(STOUC(*str)); + nt = toupper((unsigned char) *str); /* * RFC959 specifies other types, but these are the only * ones we know what to do with. @@ -2472,7 +2472,7 @@ zftp_mode(char *name, char **args, UNUSED(int flags)) fflush(stdout); return 0; } - nt = str[0] = toupper(STOUC(*str)); + nt = str[0] = toupper((unsigned char) *str); if (str[1] || (nt != 'S' && nt != 'B')) { zwarnnam(name, "transfer mode %s not recognised", str); return 1; @@ -3075,7 +3075,7 @@ bin_zftp(char *name, char **args, UNUSED(Options ops), UNUSED(int func)) if ((prefs = getsparam_u("ZFTP_PREFS"))) { zfprefs = 0; for (ptr = prefs; *ptr; ptr++) { - switch (toupper(STOUC(*ptr))) { + switch (toupper((unsigned char) *ptr)) { case 'S': /* sendport */ zfprefs |= ZFPF_SNDP; -- cgit v1.2.3 From a84fdd7c8f77935ecce99ff2b0bdba738821ed79 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Mon, 26 Jun 2023 17:13:04 +0900 Subject: 51889: fix module loading problem with full RELRO If full RELRO (relocation read-only, one of the security enhancement methods for ELF-based systems) is used when building zsh (as in binary packages of most Linuxes), loading a module (e.g. zsh/zftp) fails unless all the modules it depends on are already loaded. With this patch the necessary modules are automatically loaded. --- ChangeLog | 4 ++++ Src/Modules/zftp.c | 2 +- Src/mkbltnmlst.sh | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'Src/Modules/zftp.c') diff --git a/ChangeLog b/ChangeLog index 51a091aff..6a2801e9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2023-06-26 Jun-ichi Takimoto + * 51889: Src/Modules/zftp.c, Src/mkbltnmlst.sh: enable loading a + module (e.g. zftp) that depends on other modules even if zsh is + built with the full RELRO + * 51884: Doc/Zsh/params.yo, Src/params.c, Src/utils.c, Test/D04parameter.ztst: if MULTIBYTE option is on and IFS contains invalid bytes in curret locale then reset it to default diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 49b3ffa89..47a5e9de9 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -3172,7 +3172,7 @@ static struct features module_features = { int setup_(UNUSED(Module m)) { - return (require_module("zsh/net/tcp", NULL, 0) == 1); + return 0; } /**/ diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh index c4611d8b3..067ecdaf9 100644 --- a/Src/mkbltnmlst.sh +++ b/Src/mkbltnmlst.sh @@ -76,6 +76,30 @@ for x_mod in $x_mods; do test "x$linked" = xno && echo "#endif" done +# if dynamic module 'mod' with load=no has moddeps in its .mdd, +# then output add_dep(mod, dep) for each 'dep' in moddeps. +dyn_mods="`grep ' link=dynamic .* load=no ' $CFMOD | \ + sed -e '/^#/d' -e 's/ .*/ /' -e 's/^name=/ /'`" + +for mod in $dyn_mods; do + modfile="`grep '^name='$mod' ' $CFMOD | \ + sed -e 's/^.* modfile=//' -e 's/ .*//'`" + if test "x$modfile" = x; then + echo >&2 "WARNING: no name for \`$mod' in $CFMOD (ignored)" + continue + fi + unset moddeps + . $srcdir/../$modfile + if test -n "$moddeps"; then + echo '#ifdef DYNAMIC' + echo "/* non-linked-in known module \`$mod' */" + for dep in $moddeps; do + echo " add_dep(\"$mod\", \"$dep\");" + done + echo '#endif' + fi +done + echo done_mods=" " for bin_mod in $bin_mods; do -- cgit v1.2.3 From 57248b88830ce56adc243a40c7773fb3825cab34 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Mon, 18 Mar 2024 20:02:34 +0100 Subject: 52750: remove ansi2knr support for old pre-ansi K&R compilers --- ChangeLog | 11 ++++++ Config/defs.mk.in | 3 +- Etc/zsh-development-guide | 2 +- Src/Makemod.in.in | 23 +++--------- Src/Modules/files.c | 4 +-- Src/Modules/watch.c | 2 +- Src/Modules/zftp.c | 2 +- Src/Modules/zprof.c | 6 ++-- Src/Zle/compcore.c | 4 +-- Src/Zle/zle.h | 4 +-- Src/Zle/zle_keymap.c | 2 +- Src/Zle/zle_thingy.c | 2 +- Src/exec.c | 2 +- Src/glob.c | 8 ++--- Src/hist.c | 14 ++++---- Src/makepro.awk | 4 +-- Src/mem.c | 8 ++--- Src/mkbltnmlst.sh | 12 +++---- Src/modentry.c | 10 +++--- Src/parse.c | 2 +- Src/prototypes.h | 54 ++++++++++++++-------------- Src/signals.h | 6 ++-- Src/utils.c | 7 +++- Src/zsh.h | 92 +++++++++++++++++++++++------------------------ Src/zsh_system.h | 8 +---- aclocal.m4 | 50 -------------------------- configure.ac | 41 +-------------------- 27 files changed, 144 insertions(+), 239 deletions(-) (limited to 'Src/Modules/zftp.c') diff --git a/ChangeLog b/ChangeLog index 7e5f68059..290b1f1b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2024-03-18 Oliver Kiddle + + * 52750: Config/defs.mk.in, Etc/zsh-development-guide, + Src/Makemod.in.in, Src/Modules/files.c, Src/Modules/watch.c, + Src/Modules/zftp.c, Src/Modules/zprof.c, Src/Zle/compcore.c, + Src/Zle/zle.h, Src/Zle/zle_keymap.c, Src/Zle/zle_thingy.c, + Src/exec.c, Src/glob.c, Src/hist.c, Src/makepro.awk, Src/mem.c, + Src/mkbltnmlst.sh, Src/modentry.c, Src/parse.c, Src/prototypes.h, + Src/signals.h, Src/utils.c, Src/zsh.h, Src/zsh_system.h, aclocal.m4, + configure.ac: remove ansi2knr support for old pre-ansi K&R compilers + 2024-03-14 Bart Schaefer * 52759: Doc/Zsh/expn.yo, Etc/FAQ.yo, Src/subst.c, diff --git a/Config/defs.mk.in b/Config/defs.mk.in index 2bc17482a..116875fb9 100644 --- a/Config/defs.mk.in +++ b/Config/defs.mk.in @@ -75,7 +75,6 @@ IMPOPT = @IMPOPT@ # utilities AWK = @AWK@ -ANSI2KNR = @ANSI2KNR@ YODL = @YODL@ @YODL_OPTIONS@ YODL2TXT = @YODL@2txt YODL2HTML = @YODL@2html @@ -100,7 +99,7 @@ LDFLAGS='$(LDFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \ DLCFLAGS='$(DLCFLAGS)' DLLDFLAGS='$(DLLDFLAGS)' \ LIBLDFLAGS='$(LIBLDFLAGS)' EXELDFLAGS='$(EXELDFLAGS)' \ LIBS='$(LIBS)' DL_EXT='$(DL_EXT)' DLLD='$(DLLD)' \ -AWK='$(AWK)' ANSI2KNR='$(ANSI2KNR)' \ +AWK='$(AWK)' \ YODL='$(YODL)' YODL2TXT='$(YODL2TXT)' YODL2HTML='$(YODL2HTML)' \ FUNCTIONS_INSTALL='$(FUNCTIONS_INSTALL)' tzsh='$(tzsh)' diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide index 5cb542709..bdabe17d8 100644 --- a/Etc/zsh-development-guide +++ b/Etc/zsh-development-guide @@ -240,7 +240,7 @@ C coding style There must be an empty line, a line with "/**/", a line with the type of the function, and finally the name of the function with typed arguments. These lines must not be indented. The script generating - function prototypes and the ansi2knr program depend on this format. + function prototypes depends on this format. * Variable declarations must similarly be preceded by a line containing only "/**/", for the prototype generation script. diff --git a/Src/Makemod.in.in b/Src/Makemod.in.in index ea0cdc3a4..3343ae1d0 100644 --- a/Src/Makemod.in.in +++ b/Src/Makemod.in.in @@ -52,32 +52,17 @@ DLCOMPILE = $(CC) -c -I. -I$(dir_top)/Src -I$(sdir_top)/Src -I$(sdir_top)/Src/ LINK = $(CC) $(LDFLAGS) $(EXELDFLAGS) $(EXTRA_LDFLAGS) -o $@ DLLINK = $(DLLD) $(LDFLAGS) $(LIBLDFLAGS) $(DLLDFLAGS) -o $@ -KNR_OBJ=.o -KNROBJ=._foo_ +OBJ=.o -ANSIOBJ=.o -ANSI_OBJ=._foo_ +.SUFFIXES: .c .$(DL_EXT) ..o .o .syms .pro .epro -.SUFFIXES: .c .$(DL_EXT) ..o .._foo_ .o ._foo_ .syms .pro .epro - -.c$(ANSI@U@OBJ): +.c$(OBJ): $(COMPILE) -o $@ $< @rm -f $(dir_src)/stamp-modobjs -.c$(KNR@U@OBJ): - @ANSI2KNR@ $< > $@.c - $(COMPILE) -o $@ $@.c - rm -f $@.c - @rm -f $(dir_src)/stamp-modobjs - -.c.$(ANSI@U@OBJ): +.c.$(OBJ): $(DLCOMPILE) -o $@ $< -.c.$(KNR@U@OBJ): - @ANSI2KNR@ $< > $@.c - $(DLCOMPILE) -o $@ $@.c - rm -f $@.c - .c.syms: $(AWK) -f $(sdir_src)/makepro.awk $< $(subdir) > $@ diff --git a/Src/Modules/files.c b/Src/Modules/files.c index bf0e8f8a8..a3fec1daa 100644 --- a/Src/Modules/files.c +++ b/Src/Modules/files.c @@ -29,8 +29,8 @@ #include "files.mdh" -typedef int (*MoveFunc) _((char const *, char const *)); -typedef int (*RecurseFunc) _((char *, char *, struct stat const *, void *)); +typedef int (*MoveFunc) (char const *, char const *); +typedef int (*RecurseFunc) (char *, char *, struct stat const *, void *); struct recursivecmd; diff --git a/Src/Modules/watch.c b/Src/Modules/watch.c index ba17cf940..acc499518 100644 --- a/Src/Modules/watch.c +++ b/Src/Modules/watch.c @@ -584,7 +584,7 @@ readwtab(WATCH_STRUCT_UTMP **head, int initial_sz) if (sz) qsort((void *) *head, sz, sizeof(WATCH_STRUCT_UTMP), - (int (*) _((const void *, const void *)))ucmp); + (int (*) (const void *, const void *))ucmp); return sz; } diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 47a5e9de9..0c26828fd 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -127,7 +127,7 @@ typedef int (*readwrite_t)(int, char *, off_t, int); struct zftpcmd { const char *nam; - int (*fun) _((char *, char **, int)); + int (*fun) (char *, char **, int); int min, max, flags; }; diff --git a/Src/Modules/zprof.c b/Src/Modules/zprof.c index 56cdab888..171a15b90 100644 --- a/Src/Modules/zprof.c +++ b/Src/Modules/zprof.c @@ -163,9 +163,9 @@ bin_zprof(UNUSED(char *nam), UNUSED(char **args), Options ops, UNUSED(int func)) *ap = NULL; qsort(fs, ncalls, sizeof(f), - (int (*) _((const void *, const void *))) cmpsfuncs); + (int (*) (const void *, const void *)) cmpsfuncs); qsort(as, narcs, sizeof(a), - (int (*) _((const void *, const void *))) cmpparcs); + (int (*) (const void *, const void *)) cmpparcs); printf("num calls time self name\n-----------------------------------------------------------------------------------\n"); for (fp = fs, i = 1; *fp; fp++, i++) { @@ -179,7 +179,7 @@ bin_zprof(UNUSED(char *nam), UNUSED(char **args), Options ops, UNUSED(int func)) (*fp)->name); } qsort(fs, ncalls, sizeof(f), - (int (*) _((const void *, const void *))) cmptfuncs); + (int (*) (const void *, const void *)) cmptfuncs); for (fp = fs; *fp; fp++) { printf("\n-----------------------------------------------------------------------------------\n\n"); diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 9b87cad93..09282d42d 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -3253,7 +3253,7 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) /* Now sort the array (it contains matches). */ matchorder = flags; qsort((void *) rp, n, sizeof(Cmatch), - (int (*) _((const void *, const void *)))matchcmp); + (int (*) (const void *, const void *))matchcmp); /* since the matches are sorted and the default is to remove * all duplicates, -1 (remove only consecutive dupes) is a no-op, @@ -3295,7 +3295,7 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) sp = (Cmatch *) zhalloc((n + 1) * sizeof(Cmatch)); memcpy(sp, rp, (n + 1) * sizeof(Cmatch)); qsort((void *) sp, n, sizeof(Cmatch), - (int (*) _((const void *, const void *)))matchcmp); + (int (*) (const void *, const void *))matchcmp); for (asp = sp + 1; *asp; asp++) { Cmatch *ap = asp - 1, *bp = asp; if (matcheq(*ap, *bp)) { diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 010ead3d2..5bb9e7a5e 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -186,7 +186,7 @@ typedef struct thingy *Thingy; /* widgets (ZLE functions) */ -typedef int (*ZleIntFunc) _((char **)); +typedef int (*ZleIntFunc) (char **); struct widget { int flags; /* flags (see below) */ @@ -319,7 +319,7 @@ struct vichange { typedef struct keymap *Keymap; -typedef void (*KeyScanFunc) _((char *, Thingy, char *, void *)); +typedef void (*KeyScanFunc) (char *, Thingy, char *, void *); #define invicmdmode() (!strcmp(curkeymapname, "vicmd")) diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 041682ee9..5012917f5 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -745,7 +745,7 @@ bin_bindkey(char *name, char **argv, Options ops, UNUSED(int func)) static struct opn { char o; char selp; - int (*func) _((char *, char *, Keymap, char **, Options, char)); + int (*func) (char *, char *, Keymap, char **, Options, char); int min, max; } const opns[] = { { 'l', 0, bin_bindkey_lsmaps, 0, -1 }, diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 1b036a8a0..f71435b01 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -344,7 +344,7 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func)) { static struct opn { char o; - int (*func) _((char *, char **, Options, char)); + int (*func) (char *, char **, Options, char); int min, max; } const opns[] = { { 'l', bin_zle_list, 0, -1 }, diff --git a/Src/exec.c b/Src/exec.c index 0231bc361..e955e85df 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -267,7 +267,7 @@ static char *blank_env[] = { NULL }; /* Execution functions. */ -static int (*execfuncs[WC_COUNT-WC_CURSH]) _((Estate, int)) = { +static int (*execfuncs[WC_COUNT-WC_CURSH]) (Estate, int) = { execcursh, exectime, NULL /* execfuncdef handled specially */, execfor, execselect, execwhile, execrepeat, execcase, execif, execcond, diff --git a/Src/glob.c b/Src/glob.c index bd199ace3..3e34f708e 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -133,7 +133,7 @@ typedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figu #define TT_TERABYTES 5 -typedef int (*TestMatchFunc) _((char *, struct stat *, off_t, char *)); +typedef int (*TestMatchFunc) (char *, struct stat *, off_t, char *); struct qual { struct qual *next; /* Next qualifier, must match */ @@ -1264,7 +1264,7 @@ zglob(LinkList list, LinkNode np, int nountok) int sense, qualsfound; off_t data; char *sdata, *newcolonmod, *ptr; - int (*func) _((char *, Statptr, off_t, char *)); + int (*func) (char *, Statptr, off_t, char *); /* * Initialise state variables for current file pattern. @@ -1310,7 +1310,7 @@ zglob(LinkList list, LinkNode np, int nountok) if (*ptr == Dash) *ptr = '-'; while (*s && !newcolonmod) { - func = (int (*) _((char *, Statptr, off_t, char *)))0; + func = (int (*) (char *, Statptr, off_t, char *)) 0; if (*s == ',') { /* A comma separates alternative sets of qualifiers */ s++; @@ -1961,7 +1961,7 @@ zglob(LinkList list, LinkNode np, int nountok) /* Sort arguments in to lexical (and possibly numeric) order. * * This is reversed to facilitate insertion into the list. */ qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch), - (int (*) _((const void *, const void *)))gmatchcmp); + (int (*) (const void *, const void *)) gmatchcmp); } if (first < 0) { diff --git a/Src/hist.c b/Src/hist.c index 448dfddbc..1a00c30ed 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -34,25 +34,25 @@ * word control. */ /**/ -mod_export int (*hgetc) _((void)); +mod_export int (*hgetc) (void); /**/ -void (*hungetc) _((int)); +void (*hungetc) (int); /**/ -void (*hwaddc) _((int)); +void (*hwaddc) (int); /**/ -void (*hwbegin) _((int)); +void (*hwbegin) (int); /**/ -void (*hwabort) _((void)); +void (*hwabort) (void); /**/ -void (*hwend) _((void)); +void (*hwend) (void); /**/ -void (*addtoline) _((int)); +void (*addtoline) (int); /* != 0 means history substitution is turned off */ diff --git a/Src/makepro.awk b/Src/makepro.awk index 0d53c5850..56c4f4595 100644 --- a/Src/makepro.awk +++ b/Src/makepro.awk @@ -131,8 +131,8 @@ BEGIN { sub(/@-.*$/, "", dnam) # Put parens etc. back - gsub(/@[{]/, " _((", dcltor) - gsub(/@}/, "))", dcltor) + gsub(/@[{]/, " (", dcltor) + gsub(/@}/, ")", dcltor) gsub(/@/, ")", dcltor) gsub(/@!/, ",", dcltor) diff --git a/Src/mem.c b/Src/mem.c index fb4be47bf..0b6f76e46 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -1057,17 +1057,17 @@ zrealloc(void *ptr, size_t size) #if !defined(__hpux) && !defined(DGUX) && !defined(__osf__) # if defined(_BSD) # ifndef HAVE_BRK_PROTO - extern int brk _((caddr_t)); + extern int brk (caddr_t); # endif # ifndef HAVE_SBRK_PROTO - extern caddr_t sbrk _((int)); + extern caddr_t sbrk (int); # endif # else # ifndef HAVE_BRK_PROTO - extern int brk _((void *)); + extern int brk (void *); # endif # ifndef HAVE_SBRK_PROTO - extern void *sbrk _((int)); + extern void *sbrk (int); # endif # endif #endif diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh index 067ecdaf9..1994ace60 100644 --- a/Src/mkbltnmlst.sh +++ b/Src/mkbltnmlst.sh @@ -122,12 +122,12 @@ for bin_mod in $bin_mods; do esac done echo " {" - echo " extern int setup_${q_bin_mod} _((Module));" - echo " extern int boot_${q_bin_mod} _((Module));" - echo " extern int features_${q_bin_mod} _((Module,char***));" - echo " extern int enables_${q_bin_mod} _((Module,int**));" - echo " extern int cleanup_${q_bin_mod} _((Module));" - echo " extern int finish_${q_bin_mod} _((Module));" + echo " extern int setup_${q_bin_mod} (Module);" + echo " extern int boot_${q_bin_mod} (Module);" + echo " extern int features_${q_bin_mod} (Module,char***);" + echo " extern int enables_${q_bin_mod} (Module,int**);" + echo " extern int cleanup_${q_bin_mod} (Module);" + echo " extern int finish_${q_bin_mod} (Module);" echo echo " register_module(\"$bin_mod\"," echo " setup_${q_bin_mod}," diff --git a/Src/modentry.c b/Src/modentry.c index 4d8217f43..23c499d94 100644 --- a/Src/modentry.c +++ b/Src/modentry.c @@ -1,10 +1,10 @@ #include "zsh.mdh" -int setup_ _((Module)); -int boot_ _((Module)); -int cleanup_ _((Module)); -int finish_ _((Module)); -int modentry _((int boot, Module m, void *ptr)); +int setup_ (Module); +int boot_ (Module); +int cleanup_ (Module); +int finish_ (Module); +int modentry (int boot, Module m, void *ptr); /**/ int diff --git a/Src/parse.c b/Src/parse.c index 40eb0ee0b..334365649 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2392,7 +2392,7 @@ par_nl_wordlist(void) */ /**/ -void (*condlex) _((void)) = zshlex; +void (*condlex) (void) = zshlex; /* * cond : cond_1 { SEPER } [ DBAR { SEPER } cond ] diff --git a/Src/prototypes.h b/Src/prototypes.h index e3db4f5ee..3578482d0 100644 --- a/Src/prototypes.h +++ b/Src/prototypes.h @@ -28,9 +28,9 @@ */ #ifndef HAVE_STDLIB_H -char *malloc _((size_t)); -char *realloc _((void *, size_t)); -char *calloc _((size_t, size_t)); +char *malloc (size_t); +char *realloc (void *, size_t); +char *calloc (size_t, size_t); #endif #if !(defined(USES_TERMCAP_H) || defined(USES_TERM_H)) @@ -45,11 +45,11 @@ char *calloc _((size_t, size_t)); #else #define TC_CONST #endif -extern int tgetent _((char *bp, TC_CONST char *name)); -extern int tgetnum _((char *id)); -extern int tgetflag _((char *id)); -extern char *tgetstr _((char *id, char **area)); -extern int tputs _((TC_CONST char *cp, int affcnt, int (*outc) (int))); +extern int tgetent (char *bp, TC_CONST char *name); +extern int tgetnum (char *id); +extern int tgetflag (char *id); +extern char *tgetstr (char *id, char **area); +extern int tputs (TC_CONST char *cp, int affcnt, int (*outc) (int)); #undef TC_CONST #endif @@ -70,30 +70,30 @@ char *tgoto(const char *cap, int col, int row); #endif #ifdef __osf__ -char *mktemp _((char *)); +char *mktemp (char *); #endif #if defined(__osf__) && defined(__alpha) && defined(__GNUC__) /* Digital cc does not need these prototypes, gcc does need them */ # ifndef HAVE_IOCTL_PROTO -int ioctl _((int d, unsigned long request, void *argp)); +int ioctl (int d, unsigned long request, void *argp); # endif # ifndef HAVE_MKNOD_PROTO -int mknod _((const char *pathname, int mode, dev_t device)); +int mknod (const char *pathname, int mode, dev_t device); # endif -int nice _((int increment)); -int select _((int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)); +int nice (int increment); +int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout); #endif #if defined(DGUX) && defined(__STDC__) /* Just plain missing. */ -extern int getrlimit _((int resource, struct rlimit *rlp)); -extern int setrlimit _((int resource, const struct rlimit *rlp)); -extern int getrusage _((int who, struct rusage *rusage)); -extern int gettimeofday _((struct timeval *tv, struct timezone *tz)); -extern int wait3 _((union wait *wait_status, int options, struct rusage *rusage)); -extern int getdomainname _((char *name, int maxlength)); -extern int select _((int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)); +extern int getrlimit (int resource, struct rlimit *rlp); +extern int setrlimit (int resource, const struct rlimit *rlp); +extern int getrusage (int who, struct rusage *rusage); +extern int gettimeofday (struct timeval *tv, struct timezone *tz); +extern int wait3 (union wait *wait_status, int options, struct rusage *rusage); +extern int getdomainname (char *name, int maxlength); +extern int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout); #endif /* DGUX and __STDC__ */ #ifdef __NeXT__ @@ -101,34 +101,34 @@ extern pid_t getppid(void); #endif #if defined(__sun__) && !defined(__SVR4) /* SunOS */ -extern char *strerror _((int errnum)); +extern char *strerror (int errnum); #endif /**************************************************/ /*** prototypes for functions built in compat.c ***/ #ifndef HAVE_STRSTR -extern char *strstr _((const char *s, const char *t)); +extern char *strstr (const char *s, const char *t); #endif #ifndef HAVE_GETHOSTNAME -extern int gethostname _((char *name, size_t namelen)); +extern int gethostname (char *name, size_t namelen); #endif #ifndef HAVE_GETTIMEOFDAY -extern int gettimeofday _((struct timeval *tv, struct timezone *tz)); +extern int gettimeofday (struct timeval *tv, struct timezone *tz); #endif #ifndef HAVE_DIFFTIME -extern double difftime _((time_t t2, time_t t1)); +extern double difftime (time_t t2, time_t t1); #endif #ifndef HAVE_STRERROR -extern char *strerror _((int errnum)); +extern char *strerror (int errnum); #endif /*** end of prototypes for functions in compat.c ***/ /***************************************************/ #ifndef HAVE_MEMMOVE -extern void bcopy _((const void *, void *, size_t)); +extern void bcopy (const void *, void *, size_t); #endif diff --git a/Src/signals.h b/Src/signals.h index 391f11fed..7910f6b79 100644 --- a/Src/signals.h +++ b/Src/signals.h @@ -27,7 +27,7 @@ * */ -#define SIGNAL_HANDTYPE void (*)_((int)) +#define SIGNAL_HANDTYPE void (*)(int) #ifndef HAVE_KILLPG # define killpg(pgrp,sig) kill(-(pgrp),sig) @@ -145,7 +145,7 @@ #ifdef BSD_SIGNALS #define signal_block(S) sigblock(S) #else -extern sigset_t signal_block _((sigset_t)); +extern sigset_t signal_block (sigset_t); #endif /* BSD_SIGNALS */ -extern sigset_t signal_unblock _((sigset_t)); +extern sigset_t signal_unblock (sigset_t); diff --git a/Src/utils.c b/Src/utils.c index c8831c85e..ce4e875fd 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5277,6 +5277,7 @@ nicedupstring(char const *s) } +/**/ #ifndef MULTIBYTE_SUPPORT /* Unmetafy and output a string, displaying special characters readably. */ @@ -5311,8 +5312,9 @@ niceztrlen(char const *s) } return l; } -#endif +/**/ +#endif /**/ #ifdef MULTIBYTE_SUPPORT @@ -7633,6 +7635,7 @@ mode_to_octal(mode_t mode) return m; } +/**/ #ifdef MAILDIR_SUPPORT /* * Stat a file. If it's a maildir, check all messages @@ -7756,4 +7759,6 @@ mailstat(char *path, struct stat *st) *st = st_ret_last = st_ret; return 0; } + +/**/ #endif diff --git a/Src/zsh.h b/Src/zsh.h index fae62b8d0..090abf8f5 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -618,7 +618,7 @@ union linkroot { /* Specific elements of linked lists */ /*************************************/ -typedef void (*voidvoidfnptr_t) _((void)); +typedef void (*voidvoidfnptr_t) (void); /* * Element of the prepromptfns list. @@ -678,7 +678,7 @@ struct timedfn { #define COND_MOD 18 #define COND_MODI 19 -typedef int (*CondHandler) _((char **, int)); +typedef int (*CondHandler) (char **, int); struct conddef { Conddef next; /* next in list */ @@ -1164,28 +1164,28 @@ struct dirsav { /* Definitions for Hash Tables */ /*******************************/ -typedef void *(*VFunc) _((void *)); -typedef void (*FreeFunc) _((void *)); +typedef void *(*VFunc) (void *); +typedef void (*FreeFunc) (void *); -typedef unsigned (*HashFunc) _((const char *)); -typedef void (*TableFunc) _((HashTable)); +typedef unsigned (*HashFunc) (const char *); +typedef void (*TableFunc) (HashTable); /* * Note that this is deliberately "char *", not "const char *", * since the AddNodeFunc is passed a pointer to a string that * will be stored and later freed. */ -typedef void (*AddNodeFunc) _((HashTable, char *, void *)); -typedef HashNode (*GetNodeFunc) _((HashTable, const char *)); -typedef HashNode (*RemoveNodeFunc) _((HashTable, const char *)); -typedef void (*FreeNodeFunc) _((HashNode)); -typedef int (*CompareFunc) _((const char *, const char *)); +typedef void (*AddNodeFunc) (HashTable, char *, void *); +typedef HashNode (*GetNodeFunc) (HashTable, const char *); +typedef HashNode (*RemoveNodeFunc) (HashTable, const char *); +typedef void (*FreeNodeFunc) (HashNode); +typedef int (*CompareFunc) (const char *, const char *); /* type of function that is passed to * * scanhashtable or scanmatchtable */ -typedef void (*ScanFunc) _((HashNode, int)); -typedef void (*ScanTabFunc) _((HashTable, ScanFunc, int)); +typedef void (*ScanFunc) (HashNode, int); +typedef void (*ScanTabFunc) (HashTable, ScanFunc, int); -typedef void (*PrintTableStats) _((HashTable)); +typedef void (*PrintTableStats) (HashTable); /* Hash table for standard open hashing. Instances of struct hashtable can be * * created only by newhashtable(). In fact, this function creates an instance * @@ -1352,7 +1352,7 @@ struct funcstack { /* node in list of function call wrappers */ -typedef int (*WrapFunc) _((Eprog, FuncWrap, char *)); +typedef int (*WrapFunc) (Eprog, FuncWrap, char *); struct funcwrap { FuncWrap next; @@ -1428,8 +1428,8 @@ enum { * builtin structure. */ -typedef int (*HandlerFunc) _((char *, char **, Options, int)); -typedef int (*HandlerFuncAssign) _((char *, char **, LinkList, Options, int)); +typedef int (*HandlerFunc) (char *, char **, Options, int); +typedef int (*HandlerFuncAssign) (char *, char **, LinkList, Options, int); #define NULLBINCMD ((HandlerFunc) 0) struct builtin { @@ -1526,10 +1526,10 @@ struct module { /* Module record is an alias */ #define MOD_ALIAS (1<<6) -typedef int (*Module_generic_func) _((void)); -typedef int (*Module_void_func) _((Module)); -typedef int (*Module_features_func) _((Module, char ***)); -typedef int (*Module_enables_func) _((Module, int **)); +typedef int (*Module_generic_func) (void); +typedef int (*Module_void_func) (Module); +typedef int (*Module_features_func) (Module, char ***); +typedef int (*Module_enables_func) (Module, int **); struct linkedmod { char *name; @@ -1574,7 +1574,7 @@ struct feature_enables { /* C-function hooks */ -typedef int (*Hookfn) _((Hookdef, void *)); +typedef int (*Hookfn) (Hookdef, void *); struct hookdef { Hookdef next; @@ -1789,33 +1789,33 @@ typedef const struct gsu_array *GsuArray; typedef const struct gsu_hash *GsuHash; struct gsu_scalar { - char *(*getfn) _((Param)); - void (*setfn) _((Param, char *)); - void (*unsetfn) _((Param, int)); + char *(*getfn) (Param); + void (*setfn) (Param, char *); + void (*unsetfn) (Param, int); }; struct gsu_integer { - zlong (*getfn) _((Param)); - void (*setfn) _((Param, zlong)); - void (*unsetfn) _((Param, int)); + zlong (*getfn) (Param); + void (*setfn) (Param, zlong); + void (*unsetfn) (Param, int); }; struct gsu_float { - double (*getfn) _((Param)); - void (*setfn) _((Param, double)); - void (*unsetfn) _((Param, int)); + double (*getfn) (Param); + void (*setfn) (Param, double); + void (*unsetfn) (Param, int); }; struct gsu_array { - char **(*getfn) _((Param)); - void (*setfn) _((Param, char **)); - void (*unsetfn) _((Param, int)); + char **(*getfn) (Param); + void (*setfn) (Param, char **); + void (*unsetfn) (Param, int); }; struct gsu_hash { - HashTable (*getfn) _((Param)); - void (*setfn) _((Param, HashTable)); - void (*unsetfn) _((Param, int)); + HashTable (*getfn) (Param); + void (*setfn) (Param, HashTable); + void (*unsetfn) (Param, int); }; @@ -2984,7 +2984,7 @@ enum errflag_bits { /* Sorting */ /***********/ -typedef int (*CompareFn) _((const void *, const void *)); +typedef int (*CompareFn) (const void *, const void *); enum { SORTIT_ANYOLDHOW = 0, /* Defaults */ @@ -3042,13 +3042,13 @@ struct hist_stack { short *chwords; int chwordlen; int chwordpos; - int (*hgetc) _((void)); - void (*hungetc) _((int)); - void (*hwaddc) _((int)); - void (*hwbegin) _((int)); - void (*hwabort) _((void)); - void (*hwend) _((void)); - void (*addtoline) _((int)); + int (*hgetc) (void); + void (*hungetc) (int); + void (*hwaddc) (int); + void (*hwbegin) (int); + void (*hwabort) (void); + void (*hwend) (void); + void (*addtoline) (int); unsigned char *cstack; int csp; int hist_keep_comment; @@ -3218,7 +3218,7 @@ enum { /* compctl entry point pointers */ -typedef int (*CompctlReadFn) _((char *, char **, Options, char *)); +typedef int (*CompctlReadFn) (char *, char **, Options, char *); /* ZLE entry point pointer */ diff --git a/Src/zsh_system.h b/Src/zsh_system.h index 16f724401..5c004d53e 100644 --- a/Src/zsh_system.h +++ b/Src/zsh_system.h @@ -82,12 +82,6 @@ */ #define _STRPTIME_DONTZERO -#ifdef PROTOTYPES -# define _(Args) Args -#else -# define _(Args) () -#endif - #ifndef HAVE_ALLOCA # define alloca zhalloc #else @@ -101,7 +95,7 @@ # pragma alloca # else # ifndef alloca -char *alloca _((size_t)); +char *alloca (size_t); # endif # endif # endif diff --git a/aclocal.m4 b/aclocal.m4 index c26e2d834..792d533f2 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -2,56 +2,6 @@ # Copyright (C) 1992, 1994 Free Software Foundation, Inc. # Francois Pinard , 1992. -# @defmac fp_PROG_CC_STDC -# @maindex PROG_CC_STDC -# @ovindex CC -# If the C compiler in not in ANSI C mode by default, try to add an option -# to output variable @code{CC} to make it so. This macro tries various -# options that select ANSI C on some system or another. It considers the -# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and -# handles function prototypes correctly. -# -# If you use this macro, you should check after calling it whether the C -# compiler has been set to accept ANSI C; if not, the shell variable -# @code{fp_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source -# code in ANSI C, you can make an un-ANSIfied copy of it by using the -# program @code{ansi2knr}, which comes with Ghostscript. -# @end defmac - -define(fp_PROG_CC_STDC, -[AC_CACHE_CHECK(for ${CC-cc} option to accept ANSI C, -fp_cv_prog_cc_stdc, -[fp_cv_prog_cc_stdc=no -ac_save_CFLAGS="$CFLAGS" -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX -Ae or -Aa -D_HPUX_SOURCE -# SVR4 -Xc -# For HP-UX, we try -Ae first; this turns on ANSI but also extensions, -# as well as defining _HPUX_SOURCE, and we can then use long long. -# We keep the old version for backward compatibility. -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" -Xc -do - CFLAGS="$ac_save_CFLAGS $ac_arg" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ -[#ifndef __STDC__ -choke me -#endif -]], [[int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);};]])], -[fp_cv_prog_cc_stdc="$ac_arg"; break],[]) -done -CFLAGS="$ac_save_CFLAGS" -]) -case "x$fp_cv_prog_cc_stdc" in - x|xno) ;; - *) CC="$CC $fp_cv_prog_cc_stdc" ;; -esac -]) - AC_DEFUN(AC_PROG_LN, [AC_MSG_CHECKING(whether ln works) AC_CACHE_VAL(ac_cv_prog_LN, diff --git a/configure.ac b/configure.ac index 175d90433..ba3f2fe90 100644 --- a/configure.ac +++ b/configure.ac @@ -273,11 +273,6 @@ fi], AC_DEFINE(CONFIG_LOCALE) ) -dnl Do you want to compile as K&R C. -AC_ARG_ENABLE(ansi2knr, -AS_HELP_STRING([--enable-ansi2knr],[translate source to K&R C before compiling]), -[ansi2knr="$enableval"], [ansi2knr=default]) - ifdef([runhelpdir],[undefine([runhelpdir])])dnl AC_ARG_ENABLE(runhelpdir, AS_HELP_STRING([--enable-runhelpdir=DIR],[the directory in which to install run-help files]), @@ -483,7 +478,7 @@ fi dnl if the user hasn't specified CFLAGS, then dnl if compiler is gcc, then use -O2 and some warning flags dnl else use -O -if test -n "$auto_cflags" && test ."$ansi2knr" != .yes; then +if test -n "$auto_cflags"; then if test "${enable_zsh_debug}" = yes; then if test -n "$GCC"; then CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -ggdb" @@ -558,28 +553,6 @@ case "$host_os" in esac fp_PROG_CC_STDC -AC_MSG_CHECKING([whether to use prototypes]) -if test ."$ansi2knr" = .yes || test ."$ansi2knr" = .no; then - msg="(overridden) " -else - msg= - if test ."$fp_cv_prog_cc_stdc" = .no; then - ansi2knr=yes - else - ansi2knr=no - fi -fi -AH_TEMPLATE([PROTOTYPES], -[Define to 1 if ANSI function prototypes are usable.]) -if test "$ansi2knr" = yes; then - AC_MSG_RESULT(${msg}no) - U=_ -else - AC_MSG_RESULT(${msg}yes) - AC_DEFINE(PROTOTYPES) - U= -fi -AC_SUBST(U) AC_FUNC_ALLOCA dnl Check how to get `alloca'. @@ -647,18 +620,6 @@ case "$LC_PAPER" in esac AC_SUBST(PAPERSIZE) -AC_CHECK_PROGS([ANSI2KNR], [ansi2knr], [: ansi2knr]) - -if test x"$ansi2knr" = xyes && test x"$ANSI2KNR" = x": ansi2knr"; then - echo "----------" - echo "configure fatal error:" - echo "ansi2knr was specified (--enable-ansi2knr) but the program could not be found." - echo "Either remove the configure option if it is not required or build the ansi2knr" - echo "program before reconfiguring Zsh. The source code for ansi2knr is also" - echo "available in the GPL directory on Zsh distribution sites." - exit 1 -fi - dnl ------------------ dnl CHECK HEADER FILES dnl ------------------ -- cgit v1.2.3 From f6e005a9ef55b1fbc5291729faa2ab46bf3d9e8f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 13 May 2024 11:26:06 +0100 Subject: Ooops, missed the actualy patch from the foregoing... --- Src/Modules/zftp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Src/Modules/zftp.c') diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 0c26828fd..b60e5bf31 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -3147,6 +3147,7 @@ zftp_cleanup(void) lastmsg = NULL; zfunsetparam("ZFTP_SESSION"); freelinklist(zfsessions, (FreeFunc) freesession); + zfsessions = NULL; zfree(zfstatusp, sizeof(int)*zfsesscnt); zfstatusp = NULL; } -- cgit v1.2.3 From 6bb792dba89016c250bc9f2581c9c267dd322254 Mon Sep 17 00:00:00 2001 From: dana Date: Thu, 26 Dec 2024 09:36:45 -0600 Subject: 53257: use monotonic clock where appropriate update the following features to use the monotonic clock for calculating time deltas and intervals: * MAILCHECK parameter * PERIOD parameter * SECONDS parameter * %(nS.t.f) prompt-expansion sequence * time built-in's elapsed time and cpu % values * zsh/zftp ZFTP_TMOUT parameter * zsh/zprof timings also use CLOCK_MONOTONIC_RAW instead of CLOCK_MONOTONIC on macOS --- ChangeLog | 9 ++++++ Doc/Zsh/params.yo | 18 ++++++++---- Doc/Zsh/prompt.yo | 3 +- Src/Modules/zftp.c | 4 +-- Src/Modules/zprof.c | 19 ++++++------ Src/compat.c | 12 ++++++++ Src/exec.c | 21 +++++++------- Src/hist.c | 6 ++-- Src/init.c | 7 ++--- Src/jobs.c | 78 ++++++++++++++++++++++++++++++++++---------------- Src/params.c | 38 ++++++++++++------------ Src/prompt.c | 2 +- Src/signals.c | 3 +- Src/utils.c | 25 ++++++++++++---- Src/zsh.h | 4 +-- Test/A08time.ztst | 39 +++++++++++++++++++++++-- Test/D01prompt.ztst | 7 +++++ Test/D04parameter.ztst | 22 ++++++++++++++ 18 files changed, 225 insertions(+), 92 deletions(-) (limited to 'Src/Modules/zftp.c') diff --git a/ChangeLog b/ChangeLog index a58002d71..989cc0aa3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2024-12-26 dana + + * 53257: Doc/Zsh/params.yo, Doc/Zsh/prompt.yo, + Src/Modules/zftp.c, Src/Modules/zprof.c, Src/compat.c, + Src/exec.c, Src/hist.c, Src/init.c, Src/jobs.c, Src/params.c, + Src/prompt.c, Src/signals.c, Src/utils.c, Src/zsh.h, + Test/A08time.ztst, Test/D01prompt.ztst, Test/D04parameter.ztst: + use monotonic clock where appropriate + 2024-12-16 dana * 53251: Completion/Unix/Command/_man: fix page completion on diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 02ce796a9..69298855f 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -926,7 +926,9 @@ referenced or seeded in the parent shell in between subshell invocations. ) vindex(SECONDS) item(tt(SECONDS) )( -The number of seconds since shell invocation. If this parameter +The number of seconds since shell invocation. On most platforms, this +is a monotonic value, so it is not affected by NTP time jumps or other +clock changes (though it may be affected by slewing). If this parameter is assigned a value, then the value returned upon reference will be the value that was assigned plus the number of seconds since the assignment. @@ -936,8 +938,10 @@ be changed using the tt(typeset) command. The type may be changed only to one of the floating point types or back to integer. For example, `tt(typeset -F SECONDS)' causes the value to be reported as a floating point number. The -value is available to microsecond accuracy, although the shell may -show more or fewer digits depending on the use of tt(typeset). See +value is nominally available to nanosecond precision, although this +varies by platform (and probably isn't accurate to 1 ns regardless), +and the shell may show more or fewer digits depending on the +use of tt(typeset). See the documentation for the builtin tt(typeset) in ifzman(zmanref(zshbuiltins))\ ifnzman(noderef(Shell Builtin Commands)) for more details. @@ -1735,8 +1739,12 @@ A star may be inserted between the percent sign and flags printing time (e.g., `tt(%*E)'); this causes the time to be printed in `var(hh)tt(:)var(mm)tt(:)var(ss)tt(.)var(ttt)' format (hours and minutes are only printed if they are not zero). -Alternatively, `tt(m)' or `tt(u)' may be used (e.g., `tt(%mE)') to produce -time output in milliseconds or microseconds, respectively. +Alternatively, `tt(m)', `tt(u)', or `tt(n)' may be used (e.g., +`tt(%mE)') to produce time output in milliseconds, microseconds, or +nanoseconds, respectively. Note that some timings on some platforms +are not actually nanosecond-precise (nor accurate to 1 ns when +they are); in fact on many systems user and kernel times are not +even microsecond-precise. ) vindex(TMOUT) item(tt(TMOUT))( diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo index de988ab7c..108cb62e5 100644 --- a/Doc/Zsh/prompt.yo +++ b/Doc/Zsh/prompt.yo @@ -195,7 +195,8 @@ sitem(tt(%K))(the hour of the day on the 24-hour clock) sitem(tt(%L))(the hour of the day on the 12-hour clock) endsitem() -In addition, if the system supports the POSIX tt(gettimeofday) system +In addition, if the system supports the POSIX tt(clock_gettime) +or tt(gettimeofday) system call, tt(%.) provides decimal fractions of a second since the epoch with leading zeroes. By default three decimal places are provided, but a number of digits up to 9 may be given following the tt(%); hence tt(%6.) diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index b60e5bf31..230ad86f6 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -397,7 +397,7 @@ zfalarm(int tmout) signal(SIGALRM, zfhandler); oalremain = alarm(tmout); if (oalremain) - oaltime = time(NULL); + oaltime = zmonotime(NULL); /* * We'll leave sigtrapped, sigfuncs and TRAPXXX as they are; since the * shell's handler doesn't get the signal, they don't matter. @@ -431,7 +431,7 @@ zfunalarm(void) * I love the way alarm() uses unsigned int while time_t * is probably something completely different. */ - unsigned int tdiff = time(NULL) - oaltime; + time_t tdiff = zmonotime(NULL) - oaltime; alarm(oalremain < tdiff ? 1 : oalremain - tdiff); } else alarm(0); diff --git a/Src/Modules/zprof.c b/Src/Modules/zprof.c index 171a15b90..f5a50effc 100644 --- a/Src/Modules/zprof.c +++ b/Src/Modules/zprof.c @@ -239,8 +239,7 @@ zprof_wrapper(Eprog prog, FuncWrap w, char *name) struct sfunc sf, *sp; Pfunc f = NULL; Parc a = NULL; - struct timeval tv; - struct timezone dummy; + struct timespec ts; double prev = 0, now; char *name_for_lookups; @@ -278,19 +277,19 @@ zprof_wrapper(Eprog prog, FuncWrap w, char *name) stack = &sf; f->calls++; - tv.tv_sec = tv.tv_usec = 0; - gettimeofday(&tv, &dummy); - sf.beg = prev = ((((double) tv.tv_sec) * 1000.0) + - (((double) tv.tv_usec) / 1000.0)); + ts.tv_sec = ts.tv_nsec = 0; + zgettime_monotonic_if_available(&ts); + sf.beg = prev = ((((double) ts.tv_sec) * 1000.0) + + (((double) ts.tv_nsec) / 1000000.0)); } runshfunc(prog, w, name); if (active) { if (zprof_module && !(zprof_module->node.flags & MOD_UNLOAD)) { - tv.tv_sec = tv.tv_usec = 0; - gettimeofday(&tv, &dummy); + ts.tv_sec = ts.tv_nsec = 0; + zgettime_monotonic_if_available(&ts); - now = ((((double) tv.tv_sec) * 1000.0) + - (((double) tv.tv_usec) / 1000.0)); + now = ((((double) ts.tv_sec) * 1000.0) + + (((double) ts.tv_nsec) / 1000000.0)); f->self += now - sf.beg; for (sp = sf.prev; sp && sp->p != f; sp = sp->prev); if (!sp) diff --git a/Src/compat.c b/Src/compat.c index 8b31ad9f4..918d98e69 100644 --- a/Src/compat.c +++ b/Src/compat.c @@ -136,7 +136,19 @@ zgettime_monotonic_if_available(struct timespec *ts) #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) struct timespec dts; + +/* + * On at least some versions of macOS it appears that CLOCK_MONOTONIC is not + * actually monotonic -- there are reports that it can go backwards. + * CLOCK_MONOTONIC_RAW does not have this problem. On top of that, it is faster + * to read and it has nanosecond precision. We could use it on other systems + * too, but on Linux at least it seems that CLOCK_MONOTONIC is preferred + */ +#if defined(__APPLE__) && defined(CLOCK_MONOTONIC_RAW) + if (clock_gettime(CLOCK_MONOTONIC_RAW, &dts) < 0) { +#else if (clock_gettime(CLOCK_MONOTONIC, &dts) < 0) { +#endif zwarn("unable to retrieve CLOCK_MONOTONIC time: %e", errno); ret--; } else { diff --git a/Src/exec.c b/Src/exec.c index bc07e8c39..874ff41f7 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -348,10 +348,9 @@ setlimits(char *nam) /**/ static pid_t -zfork(struct timeval *tv) +zfork(struct timespec *ts) { pid_t pid; - struct timezone dummy_tz; /* * Is anybody willing to explain this test? @@ -360,8 +359,8 @@ zfork(struct timeval *tv) zerr("job table full"); return -1; } - if (tv) - gettimeofday(tv, &dummy_tz); + if (ts) + zgettime_monotonic_if_available(ts); /* * Queueing signals is necessary on Linux because fork() * manipulates mutexes, leading to deadlock in memory @@ -460,7 +459,7 @@ zfork(struct timeval *tv) int list_pipe = 0, simple_pline = 0; static pid_t list_pipe_pid; -static struct timeval list_pipe_start; +static struct timespec list_pipe_start; static int nowait, pline_level = 0; static int list_pipe_child = 0, list_pipe_job; static char list_pipe_text[JOBTEXTSIZE]; @@ -1863,7 +1862,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) (jobtab[list_pipe_job].stat & STAT_STOPPED)))) { pid_t pid = 0; int synch[2]; - struct timeval bgtime; + struct timespec bgtime; /* * A pipeline with the shell handling the right @@ -2284,7 +2283,7 @@ closemn(struct multio **mfds, int fd, int type) char buf[TCBUFSIZE]; int len, i; pid_t pid; - struct timeval bgtime; + struct timespec bgtime; /* * We need to block SIGCHLD in case the process @@ -2829,7 +2828,7 @@ execcmd_fork(Estate state, int how, int type, Wordcode varspc, pid_t pid; int synch[2], flags; struct entersubsh_ret esret; - struct timeval bgtime; + struct timespec bgtime; child_block(); esret.gleader = -1; @@ -2947,7 +2946,7 @@ execcmd_exec(Estate state, Execcmd_params eparams, * for the "time" keyword */ child_times_t shti, chti; - struct timeval then; + struct timespec then; if (how & Z_TIMED) shelltime(&shti, &chti, &then, 0); @@ -5060,7 +5059,7 @@ getproc(char *cmd, char **eptr) int out = *cmd == Inang; char *pnam; pid_t pid; - struct timeval bgtime; + struct timespec bgtime; #ifndef PATH_DEV_FD int fd; @@ -5149,7 +5148,7 @@ getpipe(char *cmd, int nullexec) Eprog prog; int pipes[2], out = *cmd == Inang; pid_t pid; - struct timeval bgtime; + struct timespec bgtime; char *ends; if (!(prog = parsecmd(cmd, &ends))) diff --git a/Src/hist.c b/Src/hist.c index 1a00c30ed..d0960a284 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -2891,9 +2891,9 @@ flockhistfile(char *fn, int keep_trying) /* * Timeout is ten seconds. */ - end_time = time(NULL) + (time_t)10; + end_time = zmonotime(NULL) + (time_t)10; while (fcntl(flock_fd, F_SETLKW, &lck) == -1) { - if (!keep_trying || time(NULL) >= end_time || + if (!keep_trying || zmonotime(NULL) >= end_time || /* * Randomise wait to minimise clashes with shells exiting at * the same time. @@ -3137,7 +3137,7 @@ static int lockhistct; static int checklocktime(char *lockfile, long *sleep_usp, time_t then) { - time_t now = time(NULL); + time_t now = zmonotime(NULL); if (now + 10 < then) { /* File is more than 10 seconds in the future? */ diff --git a/Src/init.c b/Src/init.c index 61f759ded..378aee348 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1022,7 +1022,6 @@ setupvals(char *cmd, char *runscript, char *zsh_name) #ifdef USE_GETPWUID struct passwd *pswd; #endif - struct timezone dummy_tz; char *ptr; int i, j; #if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH) || defined(FIXED_FPATH_DIR) @@ -1109,8 +1108,8 @@ setupvals(char *cmd, char *runscript, char *zsh_name) hatchar = '^'; termflags = TERM_UNKNOWN; curjob = prevjob = coprocin = coprocout = -1; - gettimeofday(&shtimer, &dummy_tz); /* init $SECONDS */ - srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */ + zgettime_monotonic_if_available(&shtimer); /* init $SECONDS */ + srand((unsigned int)(shtimer.tv_sec + shtimer.tv_nsec)); /* seed $RANDOM */ /* Set default path */ path = (char **) zalloc(sizeof(*path) * 5); @@ -1297,7 +1296,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name) #endif breaks = loops = 0; - lastmailcheck = time(NULL); + lastmailcheck = zmonotime(NULL); locallevel = sourcelevel = 0; sfcontext = SFC_NONE; trap_return = 0; diff --git a/Src/jobs.c b/Src/jobs.c index 39c664388..ad14f6312 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -136,7 +136,7 @@ int numpipestats, pipestats[MAX_PIPESTATS]; /**/ static struct timeval * -dtime(struct timeval *dt, struct timeval *t1, struct timeval *t2) +dtime_tv(struct timeval *dt, struct timeval *t1, struct timeval *t2) { dt->tv_sec = t2->tv_sec - t1->tv_sec; dt->tv_usec = t2->tv_usec - t1->tv_usec; @@ -147,6 +147,21 @@ dtime(struct timeval *dt, struct timeval *t1, struct timeval *t2) return dt; } +/* As above, but with timespecs */ + +/**/ +static struct timespec * +dtime_ts(struct timespec *dt, struct timespec *t1, struct timespec *t2) +{ + dt->tv_sec = t2->tv_sec - t1->tv_sec; + dt->tv_nsec = t2->tv_nsec - t1->tv_nsec; + if (dt->tv_nsec < 0) { + dt->tv_nsec += 1000000000.0; + dt->tv_sec -= 1.0; + } + return dt; +} + /* change job table entry from stopped to running */ /**/ @@ -349,7 +364,6 @@ get_usage(void) void update_process(Process pn, int status) { - struct timezone dummy_tz; #ifdef HAVE_GETRUSAGE struct timeval childs = child_usage.ru_stime; struct timeval childu = child_usage.ru_utime; @@ -360,12 +374,12 @@ update_process(Process pn, int status) /* get time-accounting info */ get_usage(); - gettimeofday(&pn->endtime, &dummy_tz); /* record time process exited */ + zgettime_monotonic_if_available(&pn->endtime); /* record time process exited */ pn->status = status; /* save the status returned by WAIT */ #ifdef HAVE_GETRUSAGE - dtime(&pn->ti.ru_stime, &childs, &child_usage.ru_stime); - dtime(&pn->ti.ru_utime, &childu, &child_usage.ru_utime); + dtime_tv(&pn->ti.ru_stime, &childs, &child_usage.ru_stime); + dtime_tv(&pn->ti.ru_utime, &childu, &child_usage.ru_utime); #else pn->ti.st = shtms.tms_cstime - childs; /* compute process system space time */ pn->ti.ut = shtms.tms_cutime - childu; /* compute process user space time */ @@ -753,7 +767,7 @@ printhhmmss(double secs) } static void -printtime(struct timeval *real, child_times_t *ti, char *desc) +printtime(struct timespec *real, child_times_t *ti, char *desc) { char *s; double elapsed_time, user_time, system_time; @@ -774,21 +788,21 @@ printtime(struct timeval *real, child_times_t *ti, char *desc) } /* go ahead and compute these, since almost every TIMEFMT will have them */ - elapsed_time = real->tv_sec + real->tv_usec / 1000000.0; + elapsed_time = real->tv_sec + real->tv_nsec / 1000000000.0; #ifdef HAVE_GETRUSAGE user_time = ti->ru_utime.tv_sec + ti->ru_utime.tv_usec / 1000000.0; system_time = ti->ru_stime.tv_sec + ti->ru_stime.tv_usec / 1000000.0; total_time = user_time + system_time; percent = 100.0 * total_time - / (real->tv_sec + real->tv_usec / 1000000.0); + / (real->tv_sec + real->tv_nsec / 1000000000.0); #else { long clktck = get_clktck(); user_time = ti->ut / (double) clktck; system_time = ti->st / (double) clktck; percent = 100.0 * (ti->ut + ti->st) - / (clktck * real->tv_sec + clktck * real->tv_usec / 1000000.0); + / (clktck * real->tv_sec + clktck * real->tv_nsec / 1000000000.0); } #endif @@ -844,6 +858,23 @@ printtime(struct timeval *real, child_times_t *ti, char *desc) break; } break; + case 'n': + switch (*++s) { + case 'E': + fprintf(stderr, "%0.fns", elapsed_time * 1000000000.0); + break; + case 'U': + fprintf(stderr, "%0.fns", user_time * 1000000000.0); + break; + case 'S': + fprintf(stderr, "%0.fns", system_time * 1000000000.0); + break; + default: + fprintf(stderr, "%%n"); + s--; + break; + } + break; case '*': switch (*++s) { case 'E': @@ -991,12 +1022,12 @@ static void dumptime(Job jn) { Process pn; - struct timeval dtimeval; + struct timespec dtimespec; if (!jn->procs) return; for (pn = jn->procs; pn; pn = pn->next) - printtime(dtime(&dtimeval, &pn->bgtime, &pn->endtime), &pn->ti, + printtime(dtime_ts(&dtimespec, &pn->bgtime, &pn->endtime), &pn->ti, pn->text); } @@ -1506,7 +1537,7 @@ deletejob(Job jn, int disowning) /**/ void -addproc(pid_t pid, char *text, int aux, struct timeval *bgtime, +addproc(pid_t pid, char *text, int aux, struct timespec *bgtime, int gleader, int list_pipe_job_used) { Process pn, *pnlist; @@ -1894,16 +1925,15 @@ spawnjob(void) /**/ void -shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int delta) +shelltime(child_times_t *shell, child_times_t *kids, struct timespec *then, int delta) { - struct timezone dummy_tz; - struct timeval dtimeval, now; + struct timespec dtimespec, now; child_times_t ti; #ifndef HAVE_GETRUSAGE struct tms buf; #endif - gettimeofday(&now, &dummy_tz); + zgettime_monotonic_if_available(&now); #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_SELF, &ti); @@ -1916,8 +1946,8 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d if (shell) { if (delta) { #ifdef HAVE_GETRUSAGE - dtime(&ti.ru_utime, &shell->ru_utime, &ti.ru_utime); - dtime(&ti.ru_stime, &shell->ru_stime, &ti.ru_stime); + dtime_tv(&ti.ru_utime, &shell->ru_utime, &ti.ru_utime); + dtime_tv(&ti.ru_stime, &shell->ru_stime, &ti.ru_stime); #else ti.ut -= shell->ut; ti.st -= shell->st; @@ -1926,15 +1956,15 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d *shell = ti; } if (delta) - dtime(&dtimeval, then, &now); + dtime_ts(&dtimespec, then, &now); else { if (then) *then = now; - dtime(&dtimeval, &shtimer, &now); + dtime_ts(&dtimespec, &shtimer, &now); } if (!delta == !shell) - printtime(&dtimeval, &ti, "shell"); + printtime(&dtimespec, &ti, "shell"); #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_CHILDREN, &ti); @@ -1945,8 +1975,8 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d if (kids) { if (delta) { #ifdef HAVE_GETRUSAGE - dtime(&ti.ru_utime, &kids->ru_utime, &ti.ru_utime); - dtime(&ti.ru_stime, &kids->ru_stime, &ti.ru_stime); + dtime_tv(&ti.ru_utime, &kids->ru_utime, &ti.ru_utime); + dtime_tv(&ti.ru_stime, &kids->ru_stime, &ti.ru_stime); #else ti.ut -= shell->ut; ti.st -= shell->st; @@ -1955,7 +1985,7 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d *kids = ti; } if (!delta == !kids) - printtime(&dtimeval, &ti, "children"); + printtime(&dtimespec, &ti, "children"); } /* see if jobs need printing */ diff --git a/Src/params.c b/Src/params.c index 6f137585b..d1c06b893 100644 --- a/Src/params.c +++ b/Src/params.c @@ -137,11 +137,11 @@ unsigned char hatchar, hashchar; unsigned char keyboardhackchar = '\0'; /* $SECONDS = now.tv_sec - shtimer.tv_sec - * + (now.tv_usec - shtimer.tv_usec) / 1000000.0 + * + (now.tv_nsec - shtimer.tv_nsec) / 1000000000.0 * (rounded to an integer if the parameter is not set to float) */ /**/ -struct timeval shtimer; +struct timespec shtimer; /* 0 if this $TERM setup is usable, otherwise it contains TERM_* flags */ @@ -4496,13 +4496,12 @@ randomsetfn(UNUSED(Param pm), zlong v) zlong intsecondsgetfn(UNUSED(Param pm)) { - struct timeval now; - struct timezone dummy_tz; + struct timespec now; - gettimeofday(&now, &dummy_tz); + zgettime_monotonic_if_available(&now); return (zlong)(now.tv_sec - shtimer.tv_sec - - (now.tv_usec < shtimer.tv_usec ? 1 : 0)); + (now.tv_nsec < shtimer.tv_nsec ? 1 : 0)); } /* Function to set value of special parameter `SECONDS' */ @@ -4511,48 +4510,47 @@ intsecondsgetfn(UNUSED(Param pm)) void intsecondssetfn(UNUSED(Param pm), zlong x) { - struct timeval now; - struct timezone dummy_tz; + struct timespec now; zlong diff; - gettimeofday(&now, &dummy_tz); + zgettime_monotonic_if_available(&now); + diff = (zlong)now.tv_sec - x; shtimer.tv_sec = diff; if ((zlong)shtimer.tv_sec != diff) zwarn("SECONDS truncated on assignment"); - shtimer.tv_usec = now.tv_usec; + shtimer.tv_nsec = now.tv_nsec; } /**/ double floatsecondsgetfn(UNUSED(Param pm)) { - struct timeval now; - struct timezone dummy_tz; + struct timespec now; - gettimeofday(&now, &dummy_tz); + zgettime_monotonic_if_available(&now); return (double)(now.tv_sec - shtimer.tv_sec) + - (double)(now.tv_usec - shtimer.tv_usec) / 1000000.0; + (double)(now.tv_nsec - shtimer.tv_nsec) / 1000000000.0; } /**/ void floatsecondssetfn(UNUSED(Param pm), double x) { - struct timeval now; - struct timezone dummy_tz; + struct timespec now; + + zgettime_monotonic_if_available(&now); - gettimeofday(&now, &dummy_tz); shtimer.tv_sec = now.tv_sec - (zlong)x; - shtimer.tv_usec = now.tv_usec - (zlong)((x - (zlong)x) * 1000000.0); + shtimer.tv_nsec = now.tv_nsec - (zlong)((x - (zlong)x) * 1000000000.0); } /**/ double getrawseconds(void) { - return (double)shtimer.tv_sec + (double)shtimer.tv_usec / 1000000.0; + return (double)shtimer.tv_sec + (double)shtimer.tv_nsec / 1000000000.0; } /**/ @@ -4560,7 +4558,7 @@ void setrawseconds(double x) { shtimer.tv_sec = (zlong)x; - shtimer.tv_usec = (zlong)((x - (zlong)x) * 1000000.0); + shtimer.tv_nsec = (zlong)((x - (zlong)x) * 1000000000.0); } /**/ diff --git a/Src/prompt.c b/Src/prompt.c index e10b05215..f36aba9d3 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -469,7 +469,7 @@ putpromptchar(int doprint, int endchar) test = 1; break; case 'S': - if (time(NULL) - shtimer.tv_sec >= arg) + if (zmonotime(NULL) - shtimer.tv_sec >= arg) test = 1; break; case 'v': diff --git a/Src/signals.c b/Src/signals.c index 86f1a49f6..de42f302d 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -342,8 +342,7 @@ wait_for_processes(void) zwarn("job can't be suspended"); } else { #if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE) - struct timezone dummy_tz; - gettimeofday(&pn->endtime, &dummy_tz); + zgettime_monotonic_if_available(&pn->endtime); #ifdef WIFCONTINUED if (WIFCONTINUED(status)) pn->status = SP_RUNNING; diff --git a/Src/utils.c b/Src/utils.c index ce4e875fd..5c91dfcda 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1570,14 +1570,14 @@ preprompt(void) /* If 1) the parameter PERIOD exists, 2) a hook function for * * "periodic" exists, 3) it's been greater than PERIOD since we * * executed any such hook, then execute it now. */ - if (period && ((zlong)time(NULL) > (zlong)lastperiodic + period) && + if (period && ((zlong)zmonotime(NULL) > (zlong)lastperiodic + period) && !callhookfunc("periodic", NULL, 1, NULL)) - lastperiodic = time(NULL); + lastperiodic = zmonotime(NULL); if (errflag) return; /* Check mail */ - currentmailcheck = time(NULL); + currentmailcheck = zmonotime(NULL); if (mailcheck && (zlong) difftime(currentmailcheck, lastmailcheck) > mailcheck) { char *mailfile; @@ -2761,6 +2761,19 @@ timespec_diff_us(const struct timespec *t1, const struct timespec *t2) return (reverse ? LONG_MIN : LONG_MAX); } +/* Like time(), but uses the monotonic clock */ + +/**/ +mod_export int +zmonotime(time_t *tloc) +{ + struct timespec ts; + zgettime_monotonic_if_available(&ts); + if (tloc) + *tloc = ts.tv_sec; + return ts.tv_sec; +} + /* * Sleep for the given number of microseconds --- must be within * range of a long at the moment, but this is only used for @@ -2794,7 +2807,9 @@ zsleep(long us) /** * Sleep for time (fairly) randomly up to max_us microseconds. - * Don't let the wallclock time extend beyond end_time. + * Don't let the time extend beyond end_time. end_time is compared to + * the current *monotonic* clock time, so do NOT base it on e.g. time(2); + * use zmonotime() or zgettime_monotonic_if_available(). * Return 1 if that seemed to work, else 0. * * For best results max_us should be a multiple of 2**16 or large @@ -2806,7 +2821,7 @@ int zsleep_random(long max_us, time_t end_time) { long r; - time_t now = time(NULL); + time_t now = zmonotime(NULL); /* * Randomish backoff. Doesn't need to be fundamentally diff --git a/Src/zsh.h b/Src/zsh.h index 090abf8f5..85b5c9bdc 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1115,8 +1115,8 @@ struct process { char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */ int status; /* return code from waitpid/wait3() */ child_times_t ti; - struct timeval bgtime; /* time job was spawned */ - struct timeval endtime; /* time job exited */ + struct timespec bgtime; /* time job was spawned */ + struct timespec endtime; /* time job exited */ }; struct execstack { diff --git a/Test/A08time.ztst b/Test/A08time.ztst index 22a460f5e..4a41cc76a 100644 --- a/Test/A08time.ztst +++ b/Test/A08time.ztst @@ -11,9 +11,44 @@ (time cat) >&/dev/null 0:`time' keyword (status only) - ( TIMEFMT='%E %mE %uE %* %m%mm %u%uu'; time (:) ) + ( TIMEFMT='%E %mE %uE %nE %* %m%mm %u%uu %n%nn'; time (:) ) 0:`time' keyword with custom TIMEFMT -*?[0-9]##.[0-9](#c2)s [0-9]##ms [0-9]##us %\* %m%mm %u%uu +*?[0-9]##.[0-9](#c2)s [0-9]##ms [0-9]##us [0-9]##ns %\* %m%mm %u%uu %n%nn + + ( TIMEFMT='x %U %S %E'; time (:) ) +0:TIMEFMT %[USE] use centisecond precision +*?x( <0-9>.<00-99>s)(#c3) + + ( TIMEFMT='x %*U %*S %*E'; time (:) ) +0:TIMEFMT %*[USE] use millisecond precision +*?x( <0-9>.<000-999>)(#c3) + + ( TIMEFMT='%nU %nS'; time (read -k3 -t0.1) ) +1:TIMEFMT %nU and %nS are limited to microsecond precision +*?[1-9][0-9]#000ns [1-9][0-9]#000ns + +# SECONDS (after - before) must be greater than the elapsed time, but not much +# greater. 25% was picked arbitrarily as something that hopefully will prevent +# the test from failing on slow machines + ( + typeset -F SECONDS + TIMEFMT=%nE + a=$SECONDS + t=$( (time (read -k3 -t0.1)) 2>&1 ) + b=$SECONDS + s=$(( b - a )) + t=$(( ${t%ns}.0 / 10**9 )) + echo $s $t $(( s > t )) $(( t > s - (s * 0.25) )) + ) +0:`time' elapsed time matches SECONDS +*>[0-9.]## [0-9.]## 1 1 + +# Again, the wide range here is an attempt to prevent this test from failing on +# slow machines. We don't care about the exact time, just that it's vaguely sane +# and that each representation has the same basis + ( TIMEFMT='%E %mE %uE %nE %*E'; time (read -k3 -t0.1) ) +1:TIMEFMT elapsed time values +*?0.<10-50>s <10-500>ms <100000-500000>us <100000000-500000000>ns 0.<100-500> time x=1 0:`time' simple assignment diff --git a/Test/D01prompt.ztst b/Test/D01prompt.ztst index 55861cca1..f42e19714 100644 --- a/Test/D01prompt.ztst +++ b/Test/D01prompt.ztst @@ -68,6 +68,13 @@ print -P '%(?.true.false)' 0:ternary prompt escapes >true +>false + + sec=$SECONDS + eval "print -P '%(${sec}S.true.false)'" + eval "print -P '%($((sec+30))S.true.false)'" +0:ternary prompt escape with test character S +>true >false print -P 'start %10<...1 >1 + # Integer + a=$SECONDS + sleep 1 + b=$SECONDS + print -r - $a $b $(( b > a )) + # Float + typeset -F SECONDS + a=$SECONDS + repeat 10 : + b=$SECONDS + print -r - $a $b $(( b > a )) + # Assignment + a=$SECONDS + SECONDS=8888 + repeat 10 : + b=$SECONDS + print -r - $(( a < 8888 )) $(( b > 8888 )) +0:SECONDS +*>[0-9]## [0-9]## 1 +*>[0-9]##.[0-9]## [0-9]##.[0-9]## 1 +*>1 1 + foo=("|" "?") [[ "|" = ${(j.|.)foo} ]] && print yes || print no [[ "|" = ${(j.|.)~foo} ]] && print yes || print no -- cgit v1.2.3