From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19873 invoked from network); 13 Mar 2000 09:51:11 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 13 Mar 2000 09:51:11 -0000 Received: (qmail 18313 invoked by alias); 13 Mar 2000 09:50:59 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 10106 Received: (qmail 18301 invoked from network); 13 Mar 2000 09:50:59 -0000 Date: Mon, 13 Mar 2000 10:50:58 +0100 (MET) Message-Id: <200003130950.KAA17664@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk Subject: 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@informatik.hu-berlin.de