CHANGES
=======

since 0.79
----------

there's now a man page.  i believe that it's up to date.

a new hook function, %exec-failure, was added.  if a call to execve(2)
fails, %exec-failure is called with the full path name of the program
that couldn't be run and the full argv array (including argv[0], which
might be identical to the first argument.)  if %exec-failure doesn't
exist or returns, an error message is printed and the child process exits.
for example, to emulate the behavior of old shells, one can use
	fn %exec-failure file argv0 args {
		exec /bin/sh $file $args
	}
a default %exec-failure is provided conditionally for machines which
lack #!-support in their execve; see KERNEL_POUNDBANG for details.

the retry builtin was removed.  the functionality is still there,
just use ``throw retry.''  retrying is not a common enough case
to waste the name of a command.

$apid is not exported by default.

-e and eval seem to work more reliably now.

error exceptions now have an additional piece of information.
the second word (the one after ``error'') is now the name of
the primitive or other routine which caused the error.  there
is no guarantee that this piece of information is correct,
but it may be useful.

i've sprinkled the NOTREACHED macro (see stdenv.h) through the source,
which should shut off some warnings on some systems.

Tconv (the format routine for %T) calls itself recursively less often
than it used to.

\x constants are now interpreted correctly.

the $&background primitive now just backgrounds a process.  printing
of the pid and setting $apid is now done in the function which calls
the primitive, which is defined in initial.es.

a new builtin, %is-interactive, was added.  it returns true if and
only if the enclosing interpreter context is interactive.

the initialization process has changed radically.  the shell script
mkinitial used to turn initial.es into a string that was linked into
the binary.  now, es is built with a two-phase process:  first, a
special version of the interpreter (called esdump), which is lacking
initial.es, is built.  esdump is used to translate initial.es into
initial.c, which creates the same in-memory layout would have been
obtained by running initial.es, except that most of the data is put
into the text segment.  the downside:  the executable is large by
about 10% and building es takes long.  the upside:  it starts up
faster, it uses less memory (because many data structures no longer
live in garbage collector space, which requires 2 copies of all data
when collecting), and garbage collects faster (much less data has to
be scanned).  this code may be less portable than the version that
preceeded it, so let us know, especially if esdump panics.

some definitions from var.c were pulled out into the new var.h header file.

fixed a bug where a line consisting of () alone would cause the interpreter
to raise an assertion failure.

several crashing bugs (a spurious assertion failure in the splitting code
following a control-c and an incorrect use of nprint("%L") in the top-level
error catcher) were fixed.

a new hook fn %cdpathsearch, analagous to %pathsearch, was added for cd.

a new builtin, access, which is similar to test from other shells, was added.
the name is different because the semantics are somewhat different.  access is
now used to implement the default form of path searching built in to the shell.
(the primitive $&pathsearch has been dropped; see initial.es or the forthcoming
manual page for details.)  in addition, whatis now triggers calls to %pathsearch
if need be.

a new builtin, unwind-protect, was added for the most common case of exception
handling:  required cleanup code.  standard use is
	unwind-protect { body } { cleanup }
where cleanup is executed when body finishes, regardless of it is by successful
completion or because an exception was raised.  if body completes successfully,
the exit status of the unwind-protect is the exit status of body; otherwise,
the exception is passed through after the cleanup is run, unless cleanup itself
causes an exception.

a new builtin, result, was added.  effectively, it is the identity function:
all it does is return its argument as its exit status.  result is similar to
return, except it does not affect control flow.  (and does not use the exception
mechanism.)

>{} and <{} (aka %readfrom and %writeto) are now implemented using temporary
files on systems that don't have /dev/fd.  /dev/fd will still work better and
be cleaner on the systems that support it, but this should cover 99% of all
the cases otherwise.

wait is now interruptible by control-c.

the mechanism for declaring a variable not exported has changed.  now, all
the variables on the list $noexport are not exported.  also, a new space for
variables, internal has been added.  internal variables are those defined in
initial.es; they are not exported unless redefined, but do not appear on the
$noexport list.  also, $&vars does not include internal definitions, though they
can be found in $&internals.

. now takes argument -e, -x, -v, and -n just like the shell itself.

a getopt like mechanism, esopt(), was introduced.

a new control-flow builtin ``forever'' was added.  this was not needed for
completeness sake, and i still recommend the use of ``while {} body'' for
most purposes.  however, the read-eval-print loop had the wrong behavior
when the user typed ``break'' at the command line because it was implemented
with a while loop.  forever completely ignores exceptions.  (a similar problem
still exists when you pass a code fragment including a return to a function
rather than to a primitive.  maybe the people who want first-class continuations
or at least lexical scoping for break/return do have a point.)

the use of the default exception handler by main has been cleaned up a bit.

the implementation of dynamic variable binding has changed a bit, but this
should not be a user-visible change.

for loops now correctly catch the ``break'' exception.  they used to catch
``return'' by mistake.

a bug was fixed where slashes in some filenames that used ~ expansion
were replaced with 'r'.

the internal flags parent and exitonfalse were coalesced into
one mask rather than the two separate Booleans, and parent was
replaced by eval_inchild, which has the opposite sense.


0.74 to 0.79
------------

the >{} and <{} constructs are now supported (if your system has /dev/fd)
by the builtins %readfrom and %writeto.  you must define the preprocessor
variable DEVFD to turn on this feature.

the limit builtin (ala csh and rc) and a time builtin were added.  to enable
them, turn on the BSD_LIMITS flag.  for those you opposed to things like
time in a shell, the reason it was included is that we wanted to be able
to time es code fragments without doing the ``time es -c $x'' we used to
do and without the extra overhead for a new invocation of the shell.
see the pipeline timing example in our usenix paper for details.

the bug with control-c from the interactive loop prompt was fixed.

~ expansion now uses the builtin function %home, which is implemented by
default by the primitive $&home but can be replaced.  it takes either zero
(for current user) or one (named user) argument, and returns (not prints) the
home directory, which must be a one element list.  $&home uses getpwnam(),
but those of you who want to do something special here can now.

the builtin command ``apids'' serves the purpose of the rc special variable
$apids: it is a list of the current set of background jobs which have not
yet completed.  note that the list is returned in the exit status not to
standard out, so use
	echo <>apids
for the old rc form
	echo $apids

the builtin ``wait'' was added with similar semantics to the same command in
rc and sh.


0.7 to 0.74
-----------

the function which one must replace for spoofing the path-searching
mechanism is now %pathsearch and not %whatis.  %pathsearch is called
in more limited circumstances than %whatis was, because the old form
was a bit of a performance drag and was too easy to screw up the shell
with.  here's a bit of experimental code which does autoloading of
shell functions:

	autoload = ~/bin/es
	let (search = $fn-%pathsearch)
		fn %pathsearch prog {
			if {/bin/test -f $autoload/$prog} {
				. $autoload/$prog
				if {!~ $#(fn-$prog) 0} {
					return $(fn-$prog)
				}
			}
			$search $prog
		}

the prompt is now '; ' and not ';; '.  rc users beware.

on the suggestion of readers of the list, the meanings of let and local
were switched;  that is, let now introduces a lexical binding and local
a dynamic binding.  this is more consistent with scheme.

the prompt function has been renamed %prompt to be consistent with other
function invoked by es internals.

the input scheme has been completely revised to support user-written
read-eval-print loops.  see the function %read-eval-print in initial.es
for details.

DefineTag() has been redone to avoid some compiler bugs where a forward
declaration for a static was not allowed. 

es now works with editline; it probably works with readline but we haven't
tested that yet. 

we think we've gotten rid of all the problems with spaces around identifiers
for those people with stone age vintage preprocessors. 

redirections, closes, and dups do not automatically fork() now.  they are
deferred until a fork() happens.  the main consequence of this is that
builtins with redirections are now done in the context of the original
shell.  [this change perturbed a lot of code in es, and may have introduced
a lot of bugs.  please let us know right away if you think you've found a
bug that is related to redirection, duping, or closing.]

the makefile for the distribution was cleaned up and renamed Makefile.


0.68 to 0.7
-----------

a bug where the garbage collector was just plain broken when lots of data
was allocated between two collections has been fixed.  (there still may
be a garbage collector bug related to large allocations, but i haven't
been able to reproduce it.)

there's now a trip.es (converted from a subset of trip.rc) which tests
some of the shell's basic mechanisms.  we need a more sophisticated
trip to test the parts of es that aren't in the rc subset.

heredocs are now supported.

following comments to the list, things are now safer if a file descriptor
mentioned in a redirection, dup, close, or pipes is already in used by
es.  the new primitive $&newfd (in es on an experimental basis only) returns
as its exit status a file descriptor that is not currently in use.

in prior versions, strings longer than 512 or 1536 bytes (depending on
the underlying malloc implementation) were exported badly if at all.

there is a new predefined function vars which is similar to rc's whatis
without arguments.  it takes the following arguments:
	-v	print variables other than fn- and set- prefixed ones
	-f	print functions (variables with fn- prefixes)
	-s	print settor functions (variables with set- prefixes)
	-e	print exported variables
	-p	print noexport variables
if none of -v, -f, and -s are specified, -v is assumed.  if neither of
-e or -p is specified, -e is specified.  note that vars does not print
lexically scoped variables.

there is a new predefined function var which prints function names in
a manner suitable for re-entry into the shell, ala rc's whatis.  it is
based on the primitive $&var.  (var does not work with lexically scoped
variables.)

the environment, along with the results of $&vars and $&primitives, are
now sorted.

isnoexport var (primitive $&isnoexport) returns true if the variable
is marked noexport.

the primitive $&vars returns all of the currently defined variables.
(other than those which are lexically scoped.)

the primitive $&primitives (which used to print its output) now returns
as its exit status the names of all of the es primitives.  ($&version
has been modified similarly.)

-e and -x are now implemented, with the usual meanings that one expects
for them in a shell.  (this is one place in the language where it's
going to take some experience to tell if all the nits are out.  if you
use -e or -x regularly with other shells, please start trying them here.)

the old GCDEBUG compile time option has been split into three options.
GCVERBOSE provides information on the operation of the garbage collector.
GCALWAYS does a collection at every allocation.  GCPROTECT invalidates
pages that do not contain live data; this option requires operating system
support beyond what is needed for the rest of the shell.  GCDEBUG still
turns on all three options.

based on a suggestion from the list, %fsplit with '' as a separator
string now splits between each character.

the parser has been cleaned up.  it may be a little bit slower, in order
to make some things clearer.  in particular, the rewriting of redirections
has changed significantly.

there are several new configuration options in config.h.  see that
file and their uses for more details but do
	-DUSE_CONST=0		if you don't have or like const
	-DUSE_VOLATILE=0	if you don't have or like volatile
	-DUSE_STDARG=0		if you want to try <varargs.h>
	-DVOID_SIGNALS=0	if signal handlers should return int

since include files seem to be a major issue with respect to
portability, most includes of system files have moved to stdenv.h.
if you need to rearrange things or add #ifdefs in here, please
send us mail, and we will try to make things work better in the
next release.  we're getting to a point where out-of-the-box
portability is important.

the path searching machinery is now available (and replacable)
through the hook %whatis.  for example,
	path-cache =
	local (whatis = <>{%whatis %whatis})
		fn %whatis prog {
			local (what-it-is = <>{$whatis $prog}) {
				if {!~ $prog (/* $path-cache) && ~ $what-it-is(1) /*} {
					path-cache = $path-cache $prog
					fn-$prog = $what-it-is
				}
				return $what-it-is
			}
		}
	fn recache {
		if {~ $#* 0} {
			* = $path-cache
			path-cache =
		}
		for (i = $*)
			fn-$i =
	}
provides a cache for the search path, similar to that built in
to many shells.  [warning:  if you do replace %whatis, ensure
that the replacement code never calls an external program except
by using an absolute pathname, or you will loop forever calling
whatis.  powerful tools are often sharp.]

signals listed on the variable $signals are now trapped:  when
one is received by the shell it throws an exception of the name
``signal <signame>'' that can be caught by the catch primitive.

closures containing strings with single quotes are now exported
properly.

in earlier versions of es, closures bound variables improperly,
capturing old values:  the first time a closure was turned into a
string was also the last time, which was incorrect.  es now flushes
the string forms all old closures whenever a lexically bound variable
is modified.

internal syntax for exporting closures changed.  the old syntax
was a variation on lambda forms;  the new syntax uses a binding
form %closure which is similar to local.

for loop variables are now exported properly.

~ and ~user are now recognized by the globber, bringing joy and
new purpose into the lives former c-shell users.

the syntax for closing files now works.  also, es is more robust
in the presence of having some of its file descriptors closed.


0.67 to 0.68
------------

verbose gc debugging

conditional use of "sig_atomic_t", for non-ANSI environments

conditional use of Reiser-cpp semantics for token pasting and
string-izing

fix for gc foward() of a vector (this fixes most, if not all,
of the crashes that were reported)

added GCDEBUG support for sun memory protection (via valloc & mprotect)

fixed a couple of omissions in initial.es

fix for a word consing bug in the parser

fix for a redirection node bug in the parser

initial.es now runs after exception handlers have been enabled
