mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-11-27 15:01:00 +01:00
zsh-workers/9947
This commit is contained in:
parent
76d90bd564
commit
137c94144c
16 changed files with 766 additions and 141 deletions
|
|
@ -14,13 +14,14 @@
|
|||
# to see if auto-dump should re-dump the dump-file.
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
typeset _d_file _d_f _d_bks _d_line _d_als
|
||||
|
||||
_d_file=${_comp_dumpfile-${0:h}/compinit.dump}.$HOST.$$
|
||||
|
||||
typeset -U _d_files
|
||||
_d_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
_d_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
|
||||
|
||||
print "#files: $#_d_files" > $_d_file
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
# default dumpfile) is now the default; to turn off dumping use -D.
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
typeset _i_dumpfile _i_files _i_line _i_done _i_dir _i_autodump=1
|
||||
typeset _i_tag _i_file _i_addfiles
|
||||
|
|
@ -419,7 +420,7 @@ zstyle ':completion:*:options' prefix-hidden yes"
|
|||
# Now we automatically make the definition files autoloaded.
|
||||
|
||||
typeset -U _i_files
|
||||
_i_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
|
||||
if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
|
||||
# Too few files: we need some more directories,
|
||||
# or we need to check that all directories (not just Core) are present.
|
||||
|
|
@ -438,7 +439,7 @@ if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
|
|||
_i_addfiles[$_i_line]=
|
||||
done
|
||||
fpath=($fpath $_i_addfiles)
|
||||
_i_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -468,7 +469,7 @@ fi
|
|||
if [[ -z "$_i_done" ]]; then
|
||||
for _i_dir in $fpath; do
|
||||
[[ $_i_dir = . ]] && continue
|
||||
for _i_file in $_i_dir/_(|*[^~])(N); do
|
||||
for _i_file in $_i_dir/^([^_]*|*~|*.zwc)(N); do
|
||||
read -rA _i_line < $_i_file
|
||||
_i_tag=$_i_line[1]
|
||||
shift _i_line
|
||||
|
|
|
|||
|
|
@ -1283,6 +1283,55 @@ findex(which)
|
|||
item(tt(which) [ tt(-wpams) ] var(name) ...)(
|
||||
Equivalent to tt(whence -c).
|
||||
)
|
||||
findex(zcompile)
|
||||
cindex(wordcode, creation)
|
||||
cindex(compilation)
|
||||
xitem(tt(zcompile) [ tt(-U) ] [ tt(-r) | tt(-m) ] var(file) [ var(function) ... ])
|
||||
item(tt(zcompile -t) var(file) [ var(name) ... ])(
|
||||
This builtin command can be used to create and display files
|
||||
containing the wordcode for functions. In the first form, a wordcode
|
||||
file is created. If called with only the var(file) argument, the
|
||||
wordcode file has the name `var(file)tt(.zwc)' and will be placed in
|
||||
the same directory as the var(file). This will make the wordcode file
|
||||
be loaded instead of the normal function file when the function is
|
||||
autoloaded (see
|
||||
ifzman(\
|
||||
the section `Autoloading Functions' in zmanref(zshfunc)
|
||||
)\
|
||||
ifnzman(\
|
||||
noderef(Functions)
|
||||
)
|
||||
for a description of how autoloaded functions are searched).
|
||||
|
||||
If there is at least one var(function) argument, the wordcode for all
|
||||
these functions will be put in the created wordcode var(file). Such
|
||||
files containing the code for multiple functions are intended to be
|
||||
used as elements of the tt(FPATH)/tt(fpath) special array.
|
||||
|
||||
If the tt(-U) option is given, aliases in the var(function)s will not
|
||||
be expanded. If the tt(-r) option is given, the function(s) in the
|
||||
file will be read and copied into the shell's memory when they are
|
||||
autoloaded. If the tt(-m) option is given instead, the wordcode file
|
||||
will be mapped into the shell's memory. This is done in such a way
|
||||
that multiple instances of the shell running on the same host will
|
||||
share this mapped function. If neither tt(-r) nor tt(-m) are given,
|
||||
the tt(zcompile) builtin decides which style is used based on the size
|
||||
of the resulting wordcode file.
|
||||
|
||||
In every case, the created file contains two versions of the wordcode,
|
||||
one for big-endian machines and one for small-endian machines. The
|
||||
upshot of this is that the wordcode file is machine independent and if
|
||||
it is read or mapped, only one half of the file will really be used
|
||||
(and mapped).
|
||||
|
||||
In the second form, with the tt(-t) option, an existing wordcode file is
|
||||
tested. Without further arguments, the names of the function files
|
||||
used for it are listed. The first line tells the version of the shell
|
||||
the file was created with and how the file will be used (mapping or
|
||||
reading the file). With arguments, only the return value is set
|
||||
to zero if all var(name)s name functiones defined in the file and
|
||||
non-zero if at least one var(name) is not contained in the wordcode file.
|
||||
)
|
||||
findex(zmodload)
|
||||
cindex(modules, loading)
|
||||
cindex(loading modules)
|
||||
|
|
|
|||
|
|
@ -33,10 +33,17 @@ cindex(autoloading functions)
|
|||
cindex(functions, autoloading)
|
||||
A function can be marked as em(undefined) using the tt(autoload) builtin
|
||||
(or `tt(functions -u)' or `tt(typeset -fu)'). Such a function has no
|
||||
body. When the function is first executed, the tt(fpath)
|
||||
variable will be searched for a file with the same name as the
|
||||
function. The usual alias expansion during reading will be suppressed if
|
||||
the tt(autoload) builtin or its equivalent is given the option tt(-U);
|
||||
body. When the function is first executed, each element of the tt(fpath)
|
||||
variable will first be searched for a file with the same name as the
|
||||
function plus the extension tt(.zwc) and then with the name of the
|
||||
function. The first file will only be used if it was created with the
|
||||
tt(zcompile) builtin command, if it contains the wordcode for the
|
||||
function and it is either older than the file with the name of the
|
||||
function in the same directory or if such a file does not exist. The
|
||||
usual alias expansion during reading will be suppressed
|
||||
if the tt(autoload) builtin or its equivalent is given the option
|
||||
tt(-U), for wordcode files this has to be decided when creating the
|
||||
file with the tt(-U) option of the tt(zcompile) builtin command;
|
||||
this is recommended for the use of functions supplied with the zsh
|
||||
distribution. Thus to define functions for autoloading, a typical sequence
|
||||
is:
|
||||
|
|
@ -44,6 +51,12 @@ is:
|
|||
example(fpath=(~/myfuncs $fpath)
|
||||
autoload myfunc1 myfunc2 ...)
|
||||
|
||||
The elements of the tt(fpath) array may also name wordcode files
|
||||
directly. This is mostly useful for wordcode files containing multiple
|
||||
functions, in which case the file is treated like a directory
|
||||
containing files for functions and will be searched for the definition
|
||||
of the function.
|
||||
|
||||
pindex(KSH_AUTOLOAD, use of)
|
||||
If the tt(KSH_AUTOLOAD) option is set, or the file contains only a simple
|
||||
definition of the function, the file's contents will be
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"),
|
||||
BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcfdipue", NULL),
|
||||
BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUmr", NULL),
|
||||
};
|
||||
|
||||
/****************************************/
|
||||
|
|
@ -2151,7 +2152,8 @@ mkautofn(Shfunc shf)
|
|||
p->shf = shf;
|
||||
p->npats = 0;
|
||||
p->pats = NULL;
|
||||
p->heap = 0;
|
||||
p->alloc = EA_REAL;
|
||||
p->dump = NULL;
|
||||
|
||||
p->prog[0] = WCB_LIST((Z_SYNC | Z_END), 0);
|
||||
p->prog[1] = WCB_SUBLIST(WC_SUBLIST_END, 0, 3);
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ evalcond(Estate state)
|
|||
&htok));
|
||||
if (htok)
|
||||
singsub(&right);
|
||||
save = (!state->prog->heap &&
|
||||
save = (state->prog->alloc != EA_HEAP &&
|
||||
!strcmp(opat, right) && pprog != dummy_patprog2);
|
||||
|
||||
if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC),
|
||||
|
|
|
|||
96
Src/exec.c
96
Src/exec.c
|
|
@ -1265,16 +1265,25 @@ mod_export void
|
|||
untokenize(char *s)
|
||||
{
|
||||
if (*s) {
|
||||
char *p = s;
|
||||
int c;
|
||||
|
||||
while ((c = *s++))
|
||||
if (itok(c)) {
|
||||
char *p = s - 1;
|
||||
|
||||
if (c != Nularg)
|
||||
*p++ = ztokens[c - Pound];
|
||||
} else
|
||||
*p++ = c;
|
||||
*p = '\0';
|
||||
|
||||
while ((c = *s++)) {
|
||||
if (itok(c)) {
|
||||
if (c != Nularg)
|
||||
*p++ = ztokens[c - Pound];
|
||||
} else
|
||||
*p++ = c;
|
||||
}
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3010,7 +3019,7 @@ execfuncdef(Estate state, int do_exec)
|
|||
{
|
||||
Shfunc shf;
|
||||
char *s;
|
||||
int signum, nprg, npats, len, plen, i, htok = 0;
|
||||
int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0;
|
||||
Wordcode beg = state->pc, end;
|
||||
Eprog prog;
|
||||
Patprog *pp;
|
||||
|
|
@ -3018,26 +3027,40 @@ execfuncdef(Estate state, int do_exec)
|
|||
|
||||
end = beg + WC_FUNCDEF_SKIP(state->pc[-1]);
|
||||
names = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok);
|
||||
nprg = *state->pc++ - 4;
|
||||
nprg = end - beg;
|
||||
sbeg = *state->pc++;
|
||||
nstrs = *state->pc++;
|
||||
npats = *state->pc++;
|
||||
|
||||
plen = (end - state->pc) * sizeof(wordcode);
|
||||
len = plen + (npats * sizeof(Patprog));
|
||||
nprg = (end - state->pc);
|
||||
plen = nprg * sizeof(wordcode);
|
||||
len = plen + (npats * sizeof(Patprog)) + nstrs;
|
||||
|
||||
if (htok)
|
||||
execsubst(names);
|
||||
|
||||
while ((s = (char *) ugetnode(names))) {
|
||||
prog = (Eprog) zalloc(sizeof(*prog));
|
||||
prog->heap = 0;
|
||||
prog->len = len;
|
||||
prog->npats = npats;
|
||||
prog->pats = pp = (Patprog *) zalloc(len);
|
||||
prog->prog = (Wordcode) (prog->pats + npats);
|
||||
prog->len = len;
|
||||
if (state->prog->dump) {
|
||||
prog->alloc = EA_MAP;
|
||||
incrdumpcount(state->prog->dump);
|
||||
prog->pats = pp = (Patprog *) zalloc(npats * sizeof(Patprog));
|
||||
prog->prog = state->pc;
|
||||
prog->strs = state->strs + sbeg;
|
||||
prog->dump = state->prog->dump;
|
||||
} else {
|
||||
prog->alloc = EA_REAL;
|
||||
prog->pats = pp = (Patprog *) zalloc(len);
|
||||
prog->prog = (Wordcode) (prog->pats + npats);
|
||||
prog->strs = (char *) (prog->prog + nprg);
|
||||
prog->dump = NULL;
|
||||
memcpy(prog->prog, state->pc, plen);
|
||||
memcpy(prog->strs, state->strs + sbeg, nstrs);
|
||||
}
|
||||
for (i = npats; i--; pp++)
|
||||
*pp = dummy_patprog1;
|
||||
memcpy(prog->prog, state->pc, plen);
|
||||
prog->strs = (char *) (prog->prog + nprg);
|
||||
prog->shf = NULL;
|
||||
|
||||
shf = (Shfunc) zalloc(sizeof(*shf));
|
||||
|
|
@ -3150,7 +3173,10 @@ execautofn(Estate state, int do_exec)
|
|||
}
|
||||
} else {
|
||||
freeeprog(shf->funcdef);
|
||||
shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
|
||||
if (prog->alloc == EA_MAP)
|
||||
shf->funcdef = stripkshdef(prog, shf->nam);
|
||||
else
|
||||
shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
|
||||
shf->flags &= ~PM_UNDEFINED;
|
||||
}
|
||||
popheap();
|
||||
|
|
@ -3180,7 +3206,10 @@ loadautofn(Shfunc shf)
|
|||
}
|
||||
if (!prog)
|
||||
prog = &dummy_eprog;
|
||||
shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
|
||||
if (prog->alloc == EA_MAP)
|
||||
shf->funcdef = stripkshdef(prog, shf->nam);
|
||||
else
|
||||
shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
|
||||
shf->flags &= ~PM_UNDEFINED;
|
||||
|
||||
popheap();
|
||||
|
|
@ -3339,6 +3368,8 @@ getfpfunc(char *s)
|
|||
sprintf(buf, "%s/%s", *pp, s);
|
||||
else
|
||||
strcpy(buf, s);
|
||||
if ((r = try_dump_file(*pp, s, buf)))
|
||||
return r;
|
||||
unmetafy(buf, NULL);
|
||||
if (!access(buf, R_OK) && (fd = open(buf, O_RDONLY | O_NOCTTY)) != -1) {
|
||||
if ((len = lseek(fd, 0, 2)) != -1) {
|
||||
|
|
@ -3372,7 +3403,7 @@ getfpfunc(char *s)
|
|||
* contents of that definition. Otherwise, use the entire file. */
|
||||
|
||||
/**/
|
||||
static Eprog
|
||||
Eprog
|
||||
stripkshdef(Eprog prog, char *name)
|
||||
{
|
||||
Wordcode pc = prog->prog;
|
||||
|
|
@ -3399,25 +3430,34 @@ stripkshdef(Eprog prog, char *name)
|
|||
{
|
||||
Eprog ret;
|
||||
Wordcode end = pc + WC_FUNCDEF_SKIP(code);
|
||||
int nprg = pc[2] - 4;
|
||||
int npats = pc[3];
|
||||
int plen, len, i;
|
||||
int sbeg = pc[2], nstrs = pc[3], nprg, npats = pc[4], plen, len, i;
|
||||
Patprog *pp;
|
||||
|
||||
pc += 4;
|
||||
pc += 5;
|
||||
|
||||
plen = (end - pc) * sizeof(wordcode);
|
||||
len = plen + (npats * sizeof(Patprog));
|
||||
nprg = end - pc;
|
||||
plen = nprg * sizeof(wordcode);
|
||||
len = plen + (npats * sizeof(Patprog)) + nstrs;
|
||||
|
||||
ret = (Eprog) zhalloc(sizeof(*ret));
|
||||
ret->heap = 1;
|
||||
if (prog->alloc == EA_MAP) {
|
||||
ret = prog;
|
||||
free(prog->pats);
|
||||
ret->pats = pp = (Patprog *) zalloc(npats * sizeof(Patprog));
|
||||
ret->prog = pc;
|
||||
ret->strs = prog->strs + sbeg;
|
||||
} else {
|
||||
ret = (Eprog) zhalloc(sizeof(*ret));
|
||||
ret->alloc = EA_HEAP;
|
||||
ret->pats = pp = (Patprog *) zhalloc(len);
|
||||
ret->prog = (Wordcode) (ret->pats + npats);
|
||||
memcpy(ret->prog, pc, plen);
|
||||
memcpy(ret->strs, prog->strs + sbeg, nstrs);
|
||||
ret->dump = NULL;
|
||||
}
|
||||
ret->len = len;
|
||||
ret->npats = npats;
|
||||
ret->pats = pp = (Patprog *) zhalloc(len);
|
||||
ret->prog = (Wordcode) (ret->pats + npats);
|
||||
for (i = npats; i--; pp++)
|
||||
*pp = dummy_patprog1;
|
||||
memcpy(ret->prog, pc, plen);
|
||||
ret->strs = (char *) (ret->prog + nprg);
|
||||
ret->shf = NULL;
|
||||
|
||||
|
|
|
|||
22
Src/glob.c
22
Src/glob.c
|
|
@ -2327,16 +2327,22 @@ mod_export void
|
|||
remnulargs(char *s)
|
||||
{
|
||||
if (*s) {
|
||||
char *t = s, *p = s, c;
|
||||
char *o = s, c;
|
||||
|
||||
while ((c = *s++))
|
||||
if (!INULL(c))
|
||||
*p++ = c;
|
||||
*p = '\0';
|
||||
if (!*t) {
|
||||
t[0] = Nularg;
|
||||
t[1] = '\0';
|
||||
}
|
||||
if (INULL(c)) {
|
||||
char *t = s - 1;
|
||||
|
||||
while ((c = *s++))
|
||||
if (!INULL(c))
|
||||
*t++ = c;
|
||||
*t = '\0';
|
||||
if (!*o) {
|
||||
o[0] = Nularg;
|
||||
o[1] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ struct lexstack {
|
|||
int eclen, ecused, ecfree, ecnpats;
|
||||
Wordcode ecbuf;
|
||||
Eccstr ecstrs;
|
||||
int ecsoffs;
|
||||
int ecsoffs, ecssub, ecnfunc;
|
||||
|
||||
unsigned char *cstack;
|
||||
int csp;
|
||||
|
|
@ -255,6 +255,8 @@ lexsave(void)
|
|||
ls->ecbuf = ecbuf;
|
||||
ls->ecstrs = ecstrs;
|
||||
ls->ecsoffs = ecsoffs;
|
||||
ls->ecssub = ecssub;
|
||||
ls->ecnfunc = ecnfunc;
|
||||
cmdsp = 0;
|
||||
inredir = 0;
|
||||
hdocs = NULL;
|
||||
|
|
@ -314,6 +316,8 @@ lexrestore(void)
|
|||
ecbuf = lstack->ecbuf;
|
||||
ecstrs = lstack->ecstrs;
|
||||
ecsoffs = lstack->ecsoffs;
|
||||
ecssub = lstack->ecssub;
|
||||
ecnfunc = lstack->ecnfunc;
|
||||
hlinesz = lstack->hlinesz;
|
||||
errflag = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ execcase(Estate state, int do_exec)
|
|||
|
||||
opat = pat = ecgetstr(state, EC_DUP, NULL);
|
||||
singsub(&pat);
|
||||
save = (!state->prog->heap &&
|
||||
save = (state->prog->alloc != EA_HEAP &&
|
||||
!strcmp(pat, opat) && *spprog != dummy_patprog2);
|
||||
|
||||
pat2 = dupstring(pat);
|
||||
|
|
@ -548,7 +548,7 @@ execcase(Estate state, int do_exec)
|
|||
state->pc - 2, &htok));
|
||||
if (htok)
|
||||
singsub(&pat);
|
||||
save = (!state->prog->heap &&
|
||||
save = (state->prog->alloc != EA_HEAP &&
|
||||
!strcmp(pat, opat) && *spprog != dummy_patprog2);
|
||||
}
|
||||
if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ zzlex(void)
|
|||
}
|
||||
if (iident(*ptr)) {
|
||||
int func = 0;
|
||||
char *p, q;
|
||||
char *p;
|
||||
|
||||
p = ptr;
|
||||
while (iident(*++ptr));
|
||||
|
|
@ -413,10 +413,7 @@ zzlex(void)
|
|||
ptr++;
|
||||
}
|
||||
}
|
||||
q = *ptr;
|
||||
*ptr = '\0';
|
||||
yylval = dupstring(p);
|
||||
*ptr = q;
|
||||
yylval = dupstrpfx(p, ptr - p);
|
||||
return (func ? FUNC : (cct ? CID : ID));
|
||||
}
|
||||
else if (cct) {
|
||||
|
|
|
|||
|
|
@ -1272,7 +1272,7 @@ bin_mem(char *name, char **argv, char *ops, int func)
|
|||
printf("blocks is shown. For otherwise used blocks the first few\n");
|
||||
printf("bytes are shown as an ASCII dump.\n");
|
||||
}
|
||||
printf("\nblock list:\nnum\ttnum\taddr\tlen\tstate\tcum\n");
|
||||
printf("\nblock list:\nnum\ttnum\taddr\t\tlen\tstate\tcum\n");
|
||||
for (m = m_l, mf = m_free, ii = fi = ui = 1; ((char *)m) < m_high;
|
||||
m = (struct m_hdr *)(((char *)m) + M_ISIZE + m->len), ii++) {
|
||||
for (j = 0, ms = NULL; j < M_NSMALL && !ms; j++)
|
||||
|
|
|
|||
657
Src/parse.c
657
Src/parse.c
|
|
@ -131,10 +131,11 @@ struct heredocs *hdocs;
|
|||
* - if (type == PIPE), followed by pipe
|
||||
*
|
||||
* WC_FUNCDEF
|
||||
* - data contains offset to after body-strings
|
||||
* - data contains offset to after body
|
||||
* - followed by number of names
|
||||
* - followed by names
|
||||
* - followed by number of codes for body
|
||||
* - followed by offset to first string
|
||||
* - followed by length of string table
|
||||
* - followed by number of patterns for body
|
||||
* - follwoed by codes for body
|
||||
* - followed by strings for body
|
||||
|
|
@ -230,28 +231,7 @@ Wordcode ecbuf;
|
|||
/**/
|
||||
Eccstr ecstrs;
|
||||
/**/
|
||||
int ecsoffs;
|
||||
|
||||
/* Make at least n bytes free (aligned to sizeof(wordcode)). */
|
||||
|
||||
static int
|
||||
ecspace(int n)
|
||||
{
|
||||
n = (n + sizeof(wordcode) - 1) / sizeof(wordcode);
|
||||
|
||||
if (ecfree < n) {
|
||||
int a = (n > 256 ? n : 256);
|
||||
|
||||
ecbuf = (Wordcode) hrealloc((char *) ecbuf, eclen * sizeof(wordcode),
|
||||
(eclen + a) * sizeof(wordcode));
|
||||
eclen += a;
|
||||
ecfree += a;
|
||||
}
|
||||
ecused += n;
|
||||
ecfree -= n;
|
||||
|
||||
return ecused - 1;
|
||||
}
|
||||
int ecsoffs, ecssub, ecnfunc;
|
||||
|
||||
/* Insert n free code-slots at position p. */
|
||||
|
||||
|
|
@ -323,7 +303,7 @@ ecstrcode(char *s)
|
|||
Eccstr p, q = NULL;
|
||||
|
||||
for (p = ecstrs; p; q = p, p = p->next)
|
||||
if (!strcmp(s, p->str))
|
||||
if (p->nfunc == ecnfunc && !strcmp(s, p->str))
|
||||
return p->offs;
|
||||
|
||||
p = (Eccstr) zhalloc(sizeof(*p));
|
||||
|
|
@ -332,8 +312,9 @@ ecstrcode(char *s)
|
|||
q->next = p;
|
||||
else
|
||||
ecstrs = p;
|
||||
p->offs = (ecsoffs << 2) | (t ? 1 : 0);
|
||||
p->offs = ((ecsoffs - ecssub) << 2) | (t ? 1 : 0);
|
||||
p->str = s;
|
||||
p->nfunc = ecnfunc;
|
||||
ecsoffs += l;
|
||||
|
||||
return p->offs;
|
||||
|
|
@ -370,6 +351,8 @@ init_parse(void)
|
|||
ecused = 0;
|
||||
ecstrs = NULL;
|
||||
ecsoffs = ecnpats = 0;
|
||||
ecssub = 0;
|
||||
ecnfunc = 0;
|
||||
}
|
||||
|
||||
/* Build eprog. */
|
||||
|
|
@ -393,7 +376,8 @@ bld_eprog(void)
|
|||
ret->prog = (Wordcode) (ret->pats + ecnpats);
|
||||
ret->strs = (char *) (ret->prog + ecused);
|
||||
ret->shf = NULL;
|
||||
ret->heap = 1;
|
||||
ret->alloc = EA_HEAP;
|
||||
ret->dump = NULL;
|
||||
for (l = 0; l < ecnpats; l++)
|
||||
ret->pats[l] = dummy_patprog1;
|
||||
memcpy(ret->prog, ecbuf, ecused * sizeof(wordcode));
|
||||
|
|
@ -1288,8 +1272,8 @@ par_subsh(int *complex)
|
|||
static void
|
||||
par_funcdef(void)
|
||||
{
|
||||
int oecused = ecused, oldlineno = lineno, num = 0, sbeg, onp, p, c = 0;
|
||||
Eccstr ostrs;
|
||||
int oecused = ecused, oldlineno = lineno, num = 0, onp, p, c = 0;
|
||||
int so, oecssub = ecssub;
|
||||
|
||||
lineno = 0;
|
||||
nocorrect = 1;
|
||||
|
|
@ -1311,6 +1295,7 @@ par_funcdef(void)
|
|||
}
|
||||
ecadd(0);
|
||||
ecadd(0);
|
||||
ecadd(0);
|
||||
|
||||
nocorrect = 0;
|
||||
if (tok == INOUTPAR)
|
||||
|
|
@ -1318,10 +1303,8 @@ par_funcdef(void)
|
|||
while (tok == SEPER)
|
||||
yylex();
|
||||
|
||||
sbeg = ecsoffs;
|
||||
ecsoffs = 0;
|
||||
ostrs = ecstrs;
|
||||
ecstrs = NULL;
|
||||
ecnfunc++;
|
||||
ecssub = so = ecsoffs;
|
||||
onp = ecnpats;
|
||||
ecnpats = 0;
|
||||
|
||||
|
|
@ -1330,43 +1313,28 @@ par_funcdef(void)
|
|||
par_list(&c);
|
||||
if (tok != OUTBRACE) {
|
||||
lineno += oldlineno;
|
||||
ecsoffs = sbeg;
|
||||
ecstrs = ostrs;
|
||||
ecnpats = onp;
|
||||
ecssub = oecssub;
|
||||
YYERRORV(oecused);
|
||||
}
|
||||
yylex();
|
||||
} else if (unset(SHORTLOOPS)) {
|
||||
lineno += oldlineno;
|
||||
ecsoffs = sbeg;
|
||||
ecstrs = ostrs;
|
||||
ecnpats = onp;
|
||||
ecssub = oecssub;
|
||||
YYERRORV(oecused);
|
||||
} else
|
||||
par_list1(&c);
|
||||
|
||||
ecadd(WCB_END());
|
||||
ecbuf[p + num + 2] = ecused - num - p;
|
||||
ecbuf[p + num + 3] = ecnpats;
|
||||
ecbuf[p + num + 2] = so - oecssub;
|
||||
ecbuf[p + num + 3] = ecsoffs - so;
|
||||
ecbuf[p + num + 4] = ecnpats;
|
||||
ecbuf[p + 1] = num;
|
||||
|
||||
if (ecsoffs) {
|
||||
int beg = ecused, l;
|
||||
Eccstr sp;
|
||||
char *sq;
|
||||
|
||||
ecspace(ecsoffs);
|
||||
|
||||
for (sp = ecstrs, sq = (char *) (ecbuf + beg); sp;
|
||||
sp = sp->next, sq += l) {
|
||||
l = strlen(sp->str) + 1;
|
||||
memcpy(sq, sp->str, l);
|
||||
}
|
||||
}
|
||||
lineno += oldlineno;
|
||||
ecsoffs = sbeg;
|
||||
ecstrs = ostrs;
|
||||
ecnpats = onp;
|
||||
ecssub = oecssub;
|
||||
|
||||
ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
|
||||
}
|
||||
|
|
@ -1481,8 +1449,7 @@ par_simple(int *complex, int nr)
|
|||
p += 3; /* 3 codes per redirection */
|
||||
sr++;
|
||||
} else if (tok == INOUTPAR) {
|
||||
int oldlineno = lineno, sbeg, onp;
|
||||
Eccstr ostrs;
|
||||
int oldlineno = lineno, onp, so, oecssub = ecssub;
|
||||
|
||||
*complex = c;
|
||||
lineno = 0;
|
||||
|
|
@ -1496,11 +1463,10 @@ par_simple(int *complex, int nr)
|
|||
ecbuf[p + 1] = argc;
|
||||
ecadd(0);
|
||||
ecadd(0);
|
||||
ecadd(0);
|
||||
|
||||
sbeg = ecsoffs;
|
||||
ecsoffs = 0;
|
||||
ostrs = ecstrs;
|
||||
ecstrs = NULL;
|
||||
ecnfunc++;
|
||||
ecssub = so = ecsoffs;
|
||||
onp = ecnpats;
|
||||
ecnpats = 0;
|
||||
|
||||
|
|
@ -1512,9 +1478,8 @@ par_simple(int *complex, int nr)
|
|||
if (tok != OUTBRACE) {
|
||||
cmdpop();
|
||||
lineno += oldlineno;
|
||||
ecsoffs = sbeg;
|
||||
ecstrs = ostrs;
|
||||
ecnpats = onp;
|
||||
ecssub = oecssub;
|
||||
YYERROR(oecused);
|
||||
}
|
||||
yylex();
|
||||
|
|
@ -1532,26 +1497,13 @@ par_simple(int *complex, int nr)
|
|||
cmdpop();
|
||||
|
||||
ecadd(WCB_END());
|
||||
ecbuf[p + argc + 2] = ecused - argc - p;
|
||||
ecbuf[p + argc + 3] = ecnpats;
|
||||
ecbuf[p + argc + 2] = so - oecssub;
|
||||
ecbuf[p + argc + 3] = ecsoffs - so;
|
||||
ecbuf[p + argc + 4] = ecnpats;
|
||||
|
||||
if (ecsoffs) {
|
||||
int beg = ecused, l;
|
||||
Eccstr sp;
|
||||
char *sq;
|
||||
|
||||
ecspace(ecsoffs);
|
||||
|
||||
for (sp = ecstrs, sq = (char *) (ecbuf + beg); sp;
|
||||
sp = sp->next, sq += l) {
|
||||
l = strlen(sp->str) + 1;
|
||||
memcpy(sq, sp->str, l);
|
||||
}
|
||||
}
|
||||
lineno += oldlineno;
|
||||
ecsoffs = sbeg;
|
||||
ecstrs = ostrs;
|
||||
ecnpats = onp;
|
||||
ecssub = oecssub;
|
||||
|
||||
ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
|
||||
|
||||
|
|
@ -2020,7 +1972,8 @@ zdupeprog(Eprog p)
|
|||
return p;
|
||||
|
||||
r = (Eprog) zalloc(sizeof(*r));
|
||||
r->heap = 0;
|
||||
r->alloc = EA_REAL;
|
||||
r->dump = NULL;
|
||||
r->len = p->len;
|
||||
r->npats = p->npats;
|
||||
pp = r->pats = (Patprog *) zcalloc(r->len);
|
||||
|
|
@ -2056,7 +2009,11 @@ freeeprogs(void)
|
|||
while ((p = (Eprog) getlinknode(eprog_free))) {
|
||||
for (i = p->npats, pp = p->pats; i--; pp++)
|
||||
freepatprog(*pp);
|
||||
zfree(p->pats, p->len);
|
||||
if (p->dump) {
|
||||
decrdumpcount(p->dump);
|
||||
zfree(p->pats, p->npats * sizeof(Patprog));
|
||||
} else
|
||||
zfree(p->pats, p->len);
|
||||
zfree(p, sizeof(*p));
|
||||
}
|
||||
}
|
||||
|
|
@ -2083,6 +2040,17 @@ ecgetstr(Estate s, int dup, int *tok)
|
|||
}
|
||||
if (tok)
|
||||
*tok = (c & 1);
|
||||
|
||||
/*** Since function dump files are mapped read-only, avoiding to
|
||||
* to duplicate strings when they don't contain tokens may fail
|
||||
* when one of the many utility functions happens to write to
|
||||
* one of the strings (without really modifying it).
|
||||
* If that happens to you and you don't feel like debugging it,
|
||||
* just change the line below to:
|
||||
*
|
||||
* return (dup ? dupstring(r) : r);
|
||||
*/
|
||||
|
||||
return ((dup == EC_DUP || (dup && (c & 1))) ? dupstring(r) : r);
|
||||
}
|
||||
|
||||
|
|
@ -2193,3 +2161,530 @@ init_eprog(void)
|
|||
|
||||
eprog_free = znewlinklist();
|
||||
}
|
||||
|
||||
/* Code for function dump files.
|
||||
*
|
||||
* Dump files consist of a header and the function bodies (the wordcode
|
||||
* plus the string table) and that twice: once for the byte-order of the
|
||||
* host the file was created on and once for the other byte-order. The
|
||||
* header describes where the beginning of the `other' version is and it
|
||||
* is up to the shell reading the file to decide which version it needs.
|
||||
* This is done by checking if the first word is FD_MAGIC (then the
|
||||
* shell reading the file has the same byte order as the one that created
|
||||
* the file) or if it is FD_OMAGIC, then the `other' version has to be
|
||||
* read.
|
||||
* The header is the magic number, a word containing the flags (if the
|
||||
* file should be mapped or read and if this header is the `other' one),
|
||||
* the version string in a field of 40 characters and the descriptions
|
||||
* for the functions in the dump file.
|
||||
* Each description consists of a struct fdhead followed by the name,
|
||||
* aligned to sizeof(wordcode) (i.e. 4 bytes).
|
||||
*/
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#define FD_EXT ".zwc"
|
||||
#define FD_MINMAP 4096
|
||||
|
||||
#define FD_PRELEN 12
|
||||
#define FD_MAGIC 0x01020304
|
||||
#define FD_OMAGIC 0x04030201
|
||||
|
||||
#define FDF_MAP 1
|
||||
#define FDF_OTHER 2
|
||||
|
||||
typedef struct fdhead *FDHead;
|
||||
|
||||
struct fdhead {
|
||||
wordcode start; /* offset to function definition */
|
||||
wordcode len; /* length of wordcode/strings */
|
||||
wordcode npats; /* number of patterns needed */
|
||||
wordcode strs; /* offset to strings */
|
||||
wordcode hlen; /* header length (incl. name) */
|
||||
wordcode tail; /* offset to name tail */
|
||||
};
|
||||
|
||||
#define fdheaderlen(f) (((Wordcode) (f))[FD_PRELEN])
|
||||
|
||||
#define fdmagic(f) (((Wordcode) (f))[0])
|
||||
#define fdbyte(f, i) ((wordcode) (((unsigned char *) (((Wordcode) (f)) + 1))[i]))
|
||||
#define fdflags(f) fdbyte(f, 0)
|
||||
#define fdother(f) (fdbyte(f, 1) + (fdbyte(f, 2) << 8) + (fdbyte(f, 3) << 16))
|
||||
#define fdsetother(f, o) \
|
||||
do { \
|
||||
fdbyte(f, 1) = (o & 0xff); \
|
||||
fdbyte(f, 2) = (o >> 8) & 0xff; \
|
||||
fdbyte(f, 3) = (o >> 16) & 0xff; \
|
||||
} while (0)
|
||||
#define fdversion(f) ((char *) ((f) + 2))
|
||||
|
||||
#define firstfdhead(f) ((FDHead) (((Wordcode) (f)) + FD_PRELEN))
|
||||
#define nextfdhead(f) ((FDHead) (((Wordcode) (f)) + (f)->hlen))
|
||||
|
||||
#define fdname(f) ((char *) (((FDHead) (f)) + 1))
|
||||
|
||||
/* Try to find the description for the given function name. */
|
||||
|
||||
static FDHead
|
||||
dump_find_func(Wordcode h, char *name)
|
||||
{
|
||||
FDHead n, e = (FDHead) (h + fdheaderlen(h));
|
||||
|
||||
for (n = firstfdhead(h); n < e; n = nextfdhead(n))
|
||||
if (!strcmp(name, fdname(n) + n->tail))
|
||||
return n;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
bin_zcompile(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
int map;
|
||||
|
||||
if (ops['t']) {
|
||||
Wordcode f;
|
||||
|
||||
if (!*args) {
|
||||
zerrnam(nam, "too few arguments", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (!(f = load_dump_header(*args))) {
|
||||
zerrnam(nam, "invalid dump file: %s", *args, 0);
|
||||
return 1;
|
||||
}
|
||||
if (args[1]) {
|
||||
for (args++; *args; args++)
|
||||
if (!dump_find_func(f, *args))
|
||||
return 1;
|
||||
return 0;
|
||||
} else {
|
||||
FDHead h, e = (FDHead) (f + fdheaderlen(f));
|
||||
|
||||
printf("function dump file (%s) for zsh-%s\n",
|
||||
((fdflags(f) & FDF_MAP) ? "mapped" : "read"), fdversion(f));
|
||||
for (h = firstfdhead(f); h < e; h = nextfdhead(h))
|
||||
printf("%s\n", fdname(h));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!*args) {
|
||||
zerrnam(nam, "too few arguments", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
map = (ops['m'] ? 2 : (ops['r'] ? 0 : 1));
|
||||
|
||||
if (!args[1])
|
||||
return build_dump(nam, dyncat(*args, FD_EXT), args, ops['U'], map);
|
||||
|
||||
return build_dump(nam, *args, args + 1, ops['U'], map);
|
||||
}
|
||||
|
||||
/* Load the header of a dump file. Returns NULL if the file isn't a
|
||||
* valid dump file. */
|
||||
|
||||
/**/
|
||||
static Wordcode
|
||||
load_dump_header(char *name)
|
||||
{
|
||||
int fd;
|
||||
wordcode buf[FD_PRELEN + 1];
|
||||
|
||||
if ((fd = open(name, O_RDONLY)) < 0)
|
||||
return NULL;
|
||||
|
||||
if (read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
|
||||
((FD_PRELEN + 1) * sizeof(wordcode)) ||
|
||||
strcmp(ZSH_VERSION, fdversion(buf))) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
} else {
|
||||
int len;
|
||||
Wordcode head;
|
||||
|
||||
if (fdmagic(buf) == FD_MAGIC) {
|
||||
len = fdheaderlen(buf) * sizeof(wordcode);
|
||||
head = (Wordcode) zhalloc(len);
|
||||
}
|
||||
else {
|
||||
int o = fdother(buf);
|
||||
|
||||
if (lseek(fd, o, 0) == -1 ||
|
||||
read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
|
||||
((FD_PRELEN + 1) * sizeof(wordcode))) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
len = fdheaderlen(buf) * sizeof(wordcode);
|
||||
head = (Wordcode) zhalloc(len);
|
||||
}
|
||||
memcpy(head, buf, (FD_PRELEN + 1) * sizeof(wordcode));
|
||||
|
||||
if (read(fd, head + (FD_PRELEN + 1),
|
||||
len - ((FD_PRELEN + 1) * sizeof(wordcode))) !=
|
||||
len - ((FD_PRELEN + 1) * sizeof(wordcode))) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
close(fd);
|
||||
return head;
|
||||
}
|
||||
}
|
||||
|
||||
/* Swap the bytes in a wordcode. */
|
||||
|
||||
static void
|
||||
fdswap(Wordcode p, int n)
|
||||
{
|
||||
wordcode c;
|
||||
|
||||
for (; n--; p++) {
|
||||
c = *p;
|
||||
*p = (((c & 0xff) << 24) |
|
||||
((c & 0xff00) << 8) |
|
||||
((c & 0xff0000) >> 8) |
|
||||
((c & 0xff000000) >> 24));
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a dump file. */
|
||||
|
||||
/**/
|
||||
static int
|
||||
build_dump(char *nam, char *dump, char **files, int ali, int map)
|
||||
{
|
||||
int dfd, fd, hlen, tlen, flen, tmp, ona = noaliases, other = 0, ohlen;
|
||||
LinkList progs;
|
||||
LinkNode node;
|
||||
struct fdhead head;
|
||||
wordcode pre[FD_PRELEN];
|
||||
char *file, **ofiles = files, **oofiles = files, *name, *tail;
|
||||
Eprog prog;
|
||||
|
||||
if ((dfd = open(dump, O_WRONLY|O_CREAT, 0600)) < 0) {
|
||||
zerrnam(nam, "can't write dump file: %s", dump, 0);
|
||||
return 1;
|
||||
}
|
||||
progs = newlinklist();
|
||||
noaliases = ali;
|
||||
|
||||
for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
|
||||
if ((fd = open(*files, O_RDONLY)) < 0 ||
|
||||
(flen = lseek(fd, 0, 2)) == -1) {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
close(dfd);
|
||||
zerrnam(nam, "can't open file: %s", *files, 0);
|
||||
noaliases = ona;
|
||||
return 1;
|
||||
}
|
||||
file = (char *) zalloc(flen + 1);
|
||||
file[flen] = '\0';
|
||||
lseek(fd, 0, 0);
|
||||
if (read(fd, file, flen) != flen) {
|
||||
close(fd);
|
||||
close(dfd);
|
||||
zfree(file, flen);
|
||||
zerrnam(nam, "can't read file: %s", *files, 0);
|
||||
noaliases = ona;
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
file = metafy(file, flen, META_REALLOC);
|
||||
|
||||
if (!(prog = parse_string(file, 1)) || errflag) {
|
||||
close(dfd);
|
||||
zfree(file, flen);
|
||||
zerrnam(nam, "can't read file: %s", *files, 0);
|
||||
noaliases = ona;
|
||||
return 1;
|
||||
}
|
||||
zfree(file, flen);
|
||||
|
||||
addlinknode(progs, prog);
|
||||
|
||||
flen = (strlen(*files) + sizeof(wordcode)) / sizeof(wordcode);
|
||||
hlen += (sizeof(head) / sizeof(wordcode)) + flen;
|
||||
|
||||
tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
|
||||
sizeof(wordcode) - 1) / sizeof(wordcode);
|
||||
}
|
||||
noaliases = ona;
|
||||
|
||||
tlen = (tlen + hlen) * sizeof(wordcode);
|
||||
if (map == 1)
|
||||
map = (tlen >= FD_MINMAP);
|
||||
|
||||
for (ohlen = hlen; ; hlen = ohlen) {
|
||||
fdmagic(pre) = (other ? FD_OMAGIC : FD_MAGIC);
|
||||
fdflags(pre) = (map ? FDF_MAP : 0) | other;
|
||||
fdsetother(pre, tlen);
|
||||
strcpy(fdversion(pre), ZSH_VERSION);
|
||||
write(dfd, pre, FD_PRELEN * sizeof(wordcode));
|
||||
|
||||
for (node = firstnode(progs), ofiles = oofiles; node;
|
||||
ofiles++, incnode(node)) {
|
||||
prog = (Eprog) getdata(node);
|
||||
head.start = hlen;
|
||||
hlen += (prog->len - (prog->npats * sizeof(Patprog)) +
|
||||
sizeof(wordcode) - 1) / sizeof(wordcode);
|
||||
head.len = prog->len - (prog->npats * sizeof(Patprog));
|
||||
head.npats = prog->npats;
|
||||
head.strs = prog->strs - ((char *) prog->prog);
|
||||
head.hlen = (sizeof(struct fdhead) / sizeof(wordcode)) +
|
||||
(strlen(*ofiles) + sizeof(wordcode)) / sizeof(wordcode);
|
||||
for (name = tail = *ofiles; *name; name++)
|
||||
if (*name == '/')
|
||||
tail = name + 1;
|
||||
head.tail = tail - *ofiles;
|
||||
if (other)
|
||||
fdswap((Wordcode) &head, sizeof(head) / sizeof(wordcode));
|
||||
write(dfd, &head, sizeof(head));
|
||||
tmp = strlen(*ofiles) + 1;
|
||||
write(dfd, *ofiles, tmp);
|
||||
if ((tmp &= (sizeof(wordcode) - 1)))
|
||||
write(dfd, &head, sizeof(wordcode) - tmp);
|
||||
}
|
||||
for (node = firstnode(progs); node; incnode(node)) {
|
||||
prog = (Eprog) getdata(node);
|
||||
tmp = (prog->len - (prog->npats * sizeof(Patprog)) +
|
||||
sizeof(wordcode) - 1) / sizeof(wordcode);
|
||||
if (other)
|
||||
fdswap(prog->prog, (((Wordcode) prog->strs) - prog->prog));
|
||||
write(dfd, prog->prog, tmp * sizeof(wordcode));
|
||||
}
|
||||
if (other)
|
||||
break;
|
||||
other = FDF_OTHER;
|
||||
}
|
||||
close(dfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if defined(MAP_SHARED) && defined(PROT_READ)
|
||||
|
||||
#define USE_MMAP 1
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_MMAP
|
||||
|
||||
/* List of dump files mapped. */
|
||||
|
||||
static FuncDump dumps;
|
||||
|
||||
/* Load a dump file (i.e. map it). */
|
||||
|
||||
static void
|
||||
load_dump_file(char *dump, int other, int len)
|
||||
{
|
||||
FuncDump d;
|
||||
Wordcode addr;
|
||||
int fd, off;
|
||||
|
||||
if (other) {
|
||||
static size_t pgsz = 0;
|
||||
|
||||
if (!pgsz) {
|
||||
|
||||
#ifdef _SC_PAGESIZE
|
||||
pgsz = sysconf(_SC_PAGESIZE); /* SVR4 */
|
||||
#else
|
||||
# ifdef _SC_PAGE_SIZE
|
||||
pgsz = sysconf(_SC_PAGE_SIZE); /* HPUX */
|
||||
# else
|
||||
pgsz = getpagesize();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
pgsz--;
|
||||
}
|
||||
off = len & ~pgsz;
|
||||
} else
|
||||
off = 0;
|
||||
|
||||
if ((fd = open(dump, O_RDONLY)) < 0)
|
||||
return;
|
||||
|
||||
fd = movefd(fd);
|
||||
|
||||
if ((addr = (Wordcode) mmap(NULL, len, PROT_READ, MAP_SHARED, fd, off)) ==
|
||||
((Wordcode) -1)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
d = (FuncDump) zalloc(sizeof(*d));
|
||||
d->next = dumps;
|
||||
dumps = d;
|
||||
d->name = ztrdup(dump);
|
||||
d->fd = fd;
|
||||
d->map = addr + (other ? (len - off) / sizeof(wordcode) : 0);
|
||||
d->addr = addr;
|
||||
d->len = len;
|
||||
d->count = 0;
|
||||
}
|
||||
|
||||
/* See if `dump' is the name of a dump file and it has the definition
|
||||
* for the function `name'. If so, return an eprog for it. */
|
||||
|
||||
/**/
|
||||
Eprog
|
||||
try_dump_file(char *dump, char *name, char *func)
|
||||
{
|
||||
int isrec = 0;
|
||||
Wordcode d;
|
||||
FDHead h;
|
||||
FuncDump f;
|
||||
|
||||
rec:
|
||||
|
||||
d = NULL;
|
||||
for (f = dumps; f; f = f->next)
|
||||
if (!strcmp(dump, f->name)) {
|
||||
d = f->map;
|
||||
break;
|
||||
}
|
||||
if (!f && (isrec || !(d = load_dump_header(dump)))) {
|
||||
if (!isrec) {
|
||||
struct stat stc, stn;
|
||||
char *p = (char *) zhalloc(strlen(dump) + strlen(name) +
|
||||
strlen(FD_EXT) + 2);
|
||||
|
||||
sprintf(p, "%s/%s%s", dump, name, FD_EXT);
|
||||
|
||||
/* Ignore the dump file if it is older than the normal one. */
|
||||
if (stat(p, &stc) || stat(func, &stn) || stn.st_mtime > stc.st_mtime)
|
||||
return NULL;
|
||||
|
||||
if (!(d = load_dump_header(dump = p)))
|
||||
return NULL;
|
||||
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
if ((h = dump_find_func(d, name))) {
|
||||
/* Found the name. If the file is already mapped, return the eprog,
|
||||
* otherwise map it and just go up. */
|
||||
if (f) {
|
||||
Eprog prog = (Eprog) zalloc(sizeof(*prog));
|
||||
Patprog *pp;
|
||||
int np;
|
||||
|
||||
prog->alloc = EA_MAP;
|
||||
prog->len = h->len;
|
||||
prog->npats = np = h->npats;
|
||||
prog->pats = pp = (Patprog *) zalloc(np * sizeof(Patprog));
|
||||
prog->prog = f->map + h->start;
|
||||
prog->strs = ((char *) prog->prog) + h->strs;
|
||||
prog->shf = NULL;
|
||||
prog->dump = f;
|
||||
|
||||
incrdumpcount(f);
|
||||
|
||||
while (np--)
|
||||
*pp++ = dummy_patprog1;
|
||||
|
||||
return prog;
|
||||
} else if (fdflags(d) & FDF_MAP) {
|
||||
load_dump_file(dump, (fdflags(d) & FDF_OTHER), fdother(d));
|
||||
isrec = 1;
|
||||
goto rec;
|
||||
} else {
|
||||
Eprog prog;
|
||||
Patprog *pp;
|
||||
int np, fd, po = h->npats * sizeof(Patprog);
|
||||
|
||||
if ((fd = open(dump, O_RDONLY)) < 0 ||
|
||||
lseek(fd, ((h->start * sizeof(wordcode)) +
|
||||
((fdflags(d) & FDF_OTHER) ? fdother(d) : 0)), 0) < 0) {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
d = (Wordcode) zalloc(h->len + po);
|
||||
|
||||
if (read(fd, ((char *) d) + po, h->len) != h->len) {
|
||||
close(fd);
|
||||
zfree(d, h->len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
prog = (Eprog) zalloc(sizeof(*prog));
|
||||
|
||||
prog->alloc = EA_MAP;
|
||||
prog->len = h->len + po;
|
||||
prog->npats = np = h->npats;
|
||||
prog->pats = pp = (Patprog *) d;
|
||||
prog->prog = (Wordcode) (((char *) d) + po);
|
||||
prog->strs = ((char *) prog->prog) + h->strs;
|
||||
prog->shf = NULL;
|
||||
prog->dump = f;
|
||||
|
||||
while (np--)
|
||||
*pp++ = dummy_patprog1;
|
||||
|
||||
return prog;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Increment the reference counter for a dump file. */
|
||||
|
||||
/**/
|
||||
void
|
||||
incrdumpcount(FuncDump f)
|
||||
{
|
||||
f->count++;
|
||||
}
|
||||
|
||||
/* Decrement the reference counter for a dump file. If zero, unmap the file. */
|
||||
|
||||
/**/
|
||||
void
|
||||
decrdumpcount(FuncDump f)
|
||||
{
|
||||
f->count--;
|
||||
if (!f->count) {
|
||||
FuncDump p, q;
|
||||
|
||||
for (q = NULL, p = dumps; p && p != f; q = p, p = p->next);
|
||||
if (p) {
|
||||
if (q)
|
||||
q->next = p->next;
|
||||
else
|
||||
dumps = p->next;
|
||||
munmap((void *) f->addr, f->len);
|
||||
zclose(f->fd);
|
||||
zfree(f, sizeof(*f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Eprog
|
||||
try_dump_file(char *dump, char *name, char *func)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
incrdumpcount(FuncDump f)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
decrdumpcount(FuncDump f)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ gettext2(Estate state)
|
|||
n = tpush(code, 1);
|
||||
n->u._funcdef.strs = state->strs;
|
||||
n->u._funcdef.end = end;
|
||||
state->strs = (char *) (p + (*state->pc));
|
||||
state->pc += 2;
|
||||
state->strs += *state->pc;
|
||||
state->pc += 3;
|
||||
}
|
||||
} else {
|
||||
state->strs = s->u._funcdef.strs;
|
||||
|
|
|
|||
|
|
@ -1704,7 +1704,7 @@ spacesplit(char *s, int allownull, int heap)
|
|||
{
|
||||
char *t, **ret, **ptr;
|
||||
int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
|
||||
char *(*dup)(char *) = (heap ? dupstring : ztrdup);
|
||||
char *(*dup)(const char *) = (heap ? dupstring : ztrdup);
|
||||
|
||||
ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zcalloc(l));
|
||||
|
||||
|
|
|
|||
21
Src/zsh.h
21
Src/zsh.h
|
|
@ -476,24 +476,40 @@ struct value {
|
|||
#define MAX_ARRLEN 262144
|
||||
|
||||
/********************************************/
|
||||
/* Defintions for byte code */
|
||||
/* Defintions for word code */
|
||||
/********************************************/
|
||||
|
||||
typedef unsigned int wordcode;
|
||||
typedef wordcode *Wordcode;
|
||||
|
||||
typedef struct funcdump *FuncDump;
|
||||
typedef struct eprog *Eprog;
|
||||
|
||||
struct funcdump {
|
||||
FuncDump next; /* next in list */
|
||||
char *name; /* path name */
|
||||
int fd; /* file descriptor */
|
||||
Wordcode map; /* pointer to header */
|
||||
Wordcode addr; /* mapped region */
|
||||
int len; /* length */
|
||||
int count; /* reference count */
|
||||
};
|
||||
|
||||
struct eprog {
|
||||
int heap; /* != 0 if in heap memory */
|
||||
int alloc; /* EA_* below */
|
||||
int len; /* total block length */
|
||||
int npats; /* Patprog cache size */
|
||||
Patprog *pats; /* the memory block, the patterns */
|
||||
Wordcode prog; /* memory block ctd, the code */
|
||||
char *strs; /* memory block ctd, the strings */
|
||||
Shfunc shf; /* shell function for autoload */
|
||||
FuncDump dump; /* dump file this is in */
|
||||
};
|
||||
|
||||
#define EA_REAL 0
|
||||
#define EA_HEAP 1
|
||||
#define EA_MAP 2
|
||||
|
||||
typedef struct estate *Estate;
|
||||
|
||||
struct estate {
|
||||
|
|
@ -508,6 +524,7 @@ struct eccstr {
|
|||
Eccstr next;
|
||||
char *str;
|
||||
wordcode offs;
|
||||
int nfunc;
|
||||
};
|
||||
|
||||
#define EC_NODUP 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue