Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: compilation



This adds the Functions/Misc/zrecompile function that (hopefully) can
be used to conviently keep wordcode files up to date. See the comment
at the beginning for a description what it can do.


While playing with it I found a buglet in zcompile (well, in
build_dump() which is called from bin_zcompile()): erflag wasn't
reset. The other hunks in the C-code are the result of me being misled 
by my attempt to fixing the bug. They make the wordcode chunks for
{...} and (...) always be ended by a END code. That turned out to not
really be the problem, but it adds a bit to savety if we ever fiddle
more with the wordcode format.


At least linux seems to have a problem when a wordcode file currently
being mapped is overwritten. Because of that zrecompile renames old
wordcode files before creating new ones. Anyone know of a way to make
this safer?

Bye
 Sven

diff -ru ../z.old/Functions/Misc/zrecompile Functions/Misc/zrecompile
--- ../z.old/Functions/Misc/zrecompile	Mon Mar 13 10:40:04 2000
+++ Functions/Misc/zrecompile	Mon Mar 13 10:47:03 2000
@@ -0,0 +1,226 @@
+# This tries to find wordcode files and automatically re-compile them if
+# at least one of the original files is newer than the wordcode file.
+# This will only work if the original files were added with their full
+# paths or if the names stored in the wordcode files are relative to the
+# directory where the wordcode file is.
+#
+# Arguments are the names of wordcode files and directories containing
+# wordcode files that should be checked. If no arguments are given, the
+# directories and wordcode files in $fpath are used.
+#
+# And then there are two options:
+#   -t: Only check if there are wordcode files that have to be 
+#       re-compiled. The return status is zero if there are files
+#       that need to be re-compiled and non-zero otherwise.
+#   -q: Be quiet, i.e.: only set the return status.
+#   -p: If this is given, the arguments are interpreted differently:
+#       they should form one or more sets of arguments for zcompile,
+#       seperated by `--'. For example:
+#
+#         zrecompile -p \
+#                    -r ~/.zshrc -- \
+#                    -m ~/.zcompdump -- \
+#                    ~/zsh/comp.zwc ~/zsh/Completion/*/_* \
+#
+#       This makes ~/.zshrc be compiled into ~/.zshrc.zwc if that doesn't
+#       exist or if it is older than ~/.zshrc. The wordcode file will be
+#       marked for reading instead of mapping. The same is done for
+#       ~/.zcompdump and ~/.zcompdump.zwc, but the wordcode file is marked
+#       for mapping. The last line re-creates the file ~/zsh/comp.zwc if
+#       any of the files matching the given pattern is newer than it.
+#
+# Without the -t option, the return status is zero if all wordcode files
+# that needed re-compilation could be compiled and non-zero if compilation
+# for at least one of the files failed.
+
+emulate -L zsh
+setopt extendedglob
+
+local opt check quiet zwc files re file pre ret map tmp mesg pats
+
+while getopts "tqp" opt; do
+  case $opt in
+  t) check=yes ;;
+  q) quiet=yes ;;
+  p) pats=yes  ;;
+  esac
+done
+shift OPTIND-1
+
+if [[ -n $check ]]; then
+  ret=1
+else
+  ret=0
+fi
+
+if [[ -n $pats ]]; then
+  local end
+
+  while (( $# )); do
+    end=$argv[(i)--]
+
+    if [[ end -le $# ]]; then
+      files=( $argv[1,end-1] )
+      shift end
+    else
+      files=( $argv )
+      argv=()
+    fi
+
+    files=( ${files:#*(.zwc|~)} )
+    if [[ $files[1] = -[rm] ]]; then
+      map=( $files[1] )
+      shift 1 files
+    else
+      map=()
+    fi
+
+    (( $#files )) || continue
+
+    zwc=${files[1]%.zwc}.zwc
+    shift 1 files
+
+    (( $#files )) || files=( ${zwc%.zwc} )
+
+    if [[ -f $zwc ]]; then
+      re=
+      for file in $files; do
+        if [[ $file -nt $zwc ]]; then
+          re=yes
+	  break
+        fi
+      done
+    else
+      re=yes
+    fi
+
+    if [[ -n $re ]]; then
+      if [[ -n $check ]]; then
+
+        # ... say so.
+
+        [[ -z $quiet ]] && print $zwc needs re-compilation
+        ret=0
+      else
+
+        # ... or do it.
+
+        [[ -z $quiet ]] && print -n "re-compiling ${zwc}: "
+
+        # If the file is mapped, it might be mapped right now, so keep the
+	# old file by renaming it.
+
+	if { [[ ! -f $zwc ]] || mv $zwc ${zwc}.old } &&
+             zcompile "$map[@]" $zwc $files 2> /dev/null; then
+          [[ -z $quiet ]] && print succeeded
+        else
+          [[ -z $quiet ]] && print failed
+          ret=1
+        fi
+      fi
+    fi
+  done
+
+  return ret
+fi
+
+# Get the names of wordcode files.
+
+if (( $# )); then
+  argv=( ${^argv}/*.zwc(ND)  ${^argv}.zwc(ND)  ${(M)argv:#*.zwc}  )
+else
+  argv=( ${^fpath}/*.zwc(ND) ${^fpath}.zwc(ND) ${(M)fpath:#*.zwc} )
+fi
+
+# We only handle *.zwc files. zcompile only handles *.zwc files. Everybody
+# seems to handle only *.zwc files.
+
+argv=( ${^argv%.zwc}.zwc )
+
+for zwc; do
+
+  # Get the files in the wordcode file.
+
+  files=( ${(f)"$(zcompile -t $zwc)"} )
+
+  # See if the wordcode file will be mapped.
+
+  if [[ $files[1] = *\(mapped\)* ]]; then
+    map=-m
+    mesg='succeeded (old saved)'
+  else
+    map=-r
+    mesg=succeeded
+  fi
+
+  # Get the path prefix of the wordcode file to prepend it to names of
+  # original files that are relative pathnames.
+  
+  if [[ $zwc = */* ]]; then
+    pre=${zwc%/*}/
+  else
+    pre=
+  fi
+
+  # Maybe this is even for an older version of the shell?
+
+  if [[ $files[1] != *$ZSH_VERSION ]]; then
+    re=yes
+  else
+    re=
+  fi
+
+  files=( ${pre}${^files[2,-1]:#/*} ${(M)files[2,-1]:#/*} )
+
+  # If the version is correct, compare the age of every original file
+  # to the age of the wordcode file.
+
+  [[ -z $re ]] &&
+    for file in $files; do
+      if [[ $file -nt $zwc ]]; then
+        re=yes
+        break
+      fi
+    done
+
+  if [[ -n $re ]]; then
+
+    # The wordcode files needs re-compilation...
+
+    if [[ -n $check ]]; then
+
+      # ... say so.
+
+      [[ -z $quiet ]] && print $zwc needs re-compilation
+      ret=0
+    else
+
+      # ... or do it.
+
+      [[ -z $quiet ]] && print -n "re-compiling ${zwc}: "
+
+      tmp=( ${^files}(N) )
+
+      # Here is the call to zcompile, but if we can't find all the original
+      # files, we don't try compilation.
+
+      if [[ $#tmp -ne $#files ]]; then
+        [[ -z $quiet ]] && print 'failed (missing files)'
+        ret=1
+      else
+
+        # If the file is mapped, it might be mapped right now, so keep the
+	# old file by renaming it.
+
+	if mv $zwc ${zwc}.old && zcompile $map $zwc $files 2> /dev/null; then
+          [[ -z $quiet ]] && print $mesg
+        else
+          [[ -z $quiet ]] && print failed
+          ret=1
+        fi
+      fi
+    fi
+  fi
+done
+
+return ret
diff -ru ../z.old/Src/exec.c Src/exec.c
--- ../z.old/Src/exec.c	Mon Mar 13 10:34:58 2000
+++ Src/exec.c	Mon Mar 13 10:39:49 2000
@@ -315,11 +315,15 @@
 static int
 execcursh(Estate state, int do_exec)
 {
+    Wordcode end = state->pc + WC_CURSH_SKIP(state->pc[-1]);
+
     if (!list_pipe && thisjob != list_pipe_job)
 	deletejob(jobtab + thisjob);
     cmdpush(CS_CURSH);
     execlist(state, 1, do_exec);
     cmdpop();
+
+    state->pc = end;
 
     return lastval;
 }
diff -ru ../z.old/Src/parse.c Src/parse.c
--- ../z.old/Src/parse.c	Mon Mar 13 10:35:00 2000
+++ Src/parse.c	Mon Mar 13 10:39:49 2000
@@ -1264,13 +1264,16 @@
 static void
 par_subsh(int *complex)
 {
-    int oecused = ecused, otok = tok;
+    int oecused = ecused, otok = tok, p;
 
-    ecadd(tok == INPAR ? WCB_SUBSH() : WCB_CURSH());
+    p = ecadd(0);
     yylex();
-    par_save_list(complex);
+    par_list(complex);
+    ecadd(WCB_END());
     if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE))
 	YYERRORV(oecused);
+    ecbuf[p] = (otok == INPAR ? WCB_SUBSH(ecused - 1 - p) :
+		WCB_CURSH(ecused - 1 - p));
     incmdpos = 1;
     yylex();
 }
@@ -2422,6 +2425,7 @@
 	    zfree(file, flen);
 	    zerrnam(nam, "can't read file: %s", *files, 0);
 	    noaliases = ona;
+	    errflag  = 0;
 	    return 1;
 	}
 	zfree(file, flen);
diff -ru ../z.old/Src/zsh.h Src/zsh.h
--- ../z.old/Src/zsh.h	Mon Mar 13 10:35:01 2000
+++ Src/zsh.h	Mon Mar 13 10:39:49 2000
@@ -596,9 +596,11 @@
 #define WC_SIMPLE_ARGC(C)   wc_data(C)
 #define WCB_SIMPLE(N)       wc_bld(WC_SIMPLE, (N))
 
-#define WCB_SUBSH()         wc_bld(WC_SUBSH, 0)
+#define WC_SUBSH_SKIP(C)    wc_data(C)
+#define WCB_SUBSH(O)        wc_bld(WC_SUBSH, (O))
 
-#define WCB_CURSH()         wc_bld(WC_CURSH, 0)
+#define WC_CURSH_SKIP(C)    wc_data(C)
+#define WCB_CURSH(O)        wc_bld(WC_CURSH, (O))
 
 #define WC_TIMED_TYPE(C)    wc_data(C)
 #define WC_TIMED_EMPTY      0

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author