$Header: Changes,v 1.19 93/01/21 16:00:02 vern Exp $

Glish changes
=============

21Jan93:
	- 2.1 release.

	- User documentation is now available in doc/User-Doc.ps.

	- An "ind(x)" function has been added which returns the
	  indicies corresponding to an array value.  For example,

		ind("hello, how are you?")

	  returns [1 2 3 4], since the argument has four elements.


13Jan93:
	- Records can now be indexed in the same manner as arrays, i.e.,
	  with integer or boolean arrays.  For example,

		r := [a=1, b=2]
		r[1] := 5
		r[2] := "hi"
		print r

	  prints "[a=5, b=hi]".  You also can add fields to a record:

		r := [=]	# create an empty array
		r[1] := 5
		r[2] := "hi"
		print r

	  prints "[*1=5, *2=hi]", where "*1" and "*2" are internal names
	  for the new record fields just created.

	  This style of record access allows you to create what are
	  effectively arrays of records, functions, or agents, without
	  the restriction (and type-checking) that every element of the
	  array has the same type.

	- Added BSD-style copyright notice to sources.


01Dec92:
	- PostScript for a 15-page paper describing Glish is now available in
	  glish/doc/USENIX-93.ps.  The paper will appear in the proceedings
	  of the 1993 Winter USENIX conference.

	- Glish now supports "link" and "unlink" directives for creating
	  and suspending point-to-point connections between Glish clients.
	  Events sent point-to-point are *not* seen by the sequencer;
	  they do not trigger "whenever"'s.  The "link" syntax looks like:

		link a->b to c->d

	  This causes all of a's "b" events to go directly to c, which
	  will see them as "d" events.  You can also use:

		link a->b to c->*

	  which passes the event along without changing its name (i.e.,
	  it's still called "b").  The "unlink" directive looks the same:

		unlink a->b to c->d

	  suspends the point-to-point connection, so a's "b" events will
	  now be seen by the sequencer and trigger any corresponding
	  "whenever"'s.  Doing another "link" reactivates the link.

	- The Client library has undergone several user-visible changes:

	  An "void Unrecognized()" member function has been added; it *must*
	  be called by a client that does not recognize a particular event.

	  "int ReadFD()" has been replaced by routines oriented towards
	  use of select().  "void AddInputMask( fd_set* mask )" is passed
	  an fd_set mask used by select() and adds to it those bits
	  corresponding to the Client's input sources.  You then can use
	  "int HasClientInput( fd_set* mask )" to determine whether a
	  mask returned by select() indicates that the client has pending
	  input (i.e., one or more events has arrived).  The function returns
	  true or false.

	  A new version of NextEvent() is available; it is passed an fd_set*
	  mask which it uses to determine from where to read the next event.

	  "int WriteFD()" has been removed.

	- Communication between the sequencer and processes running on
	  the same host is now done using pipes, a substantial performance
	  win.

	- When creating clients or shell tasks an optional input= argument
	  can be used to set up the program's standard input.  For example,

		shell("wc", input=1:10)

	  will run the "wc" command on the numbers from 1 to 10, one on
	  each line.

	- shell clients now write their output to a pty if available, so
	  it is line-buffered.

	- The default "glish.init" file now resides in $(ISTKPLACE)/lib/
	  instead of $(ISTKPLACE)/glish/.

	- The "loop" keyword has been replaced with "next" ("continue" can
	  also be used, for die-hard C hackers).

	- The glish interpreter now prints non-string array values with []'s
	  around them.

	- The predefined family of "relay" functions now treat a "destination
	  event name" of '*' to mean "use the same name as that the source
	  generated".


01Oct92:
	- A number of new predefined functions are available: is_function(),
	  is_agent(), and is_numeric() return true if their argument is
	  a function, and agent, or a numeric type, respectively.  abs()
	  returns the absolute value of its numeric argument.  len() is
	  an alias for length().  rep() takes two arguments, a "value" and
	  a "count", and returns an array of "count" copies of "value".
	  For example, rep(5,3) is [5, 5, 5].

	- Clients can be suspended by including "suspend=<executable>" on
	  the Glish command line.  For example, "glish suspend=myprog foo.g"
	  will run Glish on "foo.g" and whenever a client whose executable
	  is called "myprog" is begun, it will act as though "suspend=T" had
	  been specified in the client() call.

	- When clients are suspended they now announce themselves along
	  with their host and PID.

	- The "await" statement has been modified to by default process
	  all other events until the await'd for event(s) arrives.  A
	  special version of await, using the keyword "only", will not
	  process the events unless they match the "except" list.

	- The Value class's constructors for creating Value's from arrays
	  now take an enumerated type as an optional third argument indicating
	  what degree of control the Value is to assume over the array.
	  A value of TAKE_OVER_ARRAY (default) indicates that the array
	  is now the Value's to manage as it pleases (perhaps dynamically
	  growing it, and definitely deleting it when done with it); a value
	  of COPY_ARRAY indicates that the Value should first make a copy of
	  the array; and a value of PRESERVE_ARRAY indicates that the Value
	  should use the array but not dynamically grow it or delete it.
	  COPY_ARRAY is often appropriate for arrays created on the stack
	  in routines that will exit, and PRESERVE_ARRAY is good for static
	  or global arrays, or arrays that are shared among a number of
	  Value's.  The third argument used to be a boolean, with false
	  corresponding to TAKE_OVER_ARRAY and true to COPY_ARRAY.

	- Any line can now be forcibly continued to the next line by
	  escaping its newline.  For example,

		a := b
		+c

	  is normally interpreted as two statements because a semi-colon
	  is inserted after "b", but

		a := b \
		+ c

	  is interpreted as one statement.

	- The output of shell() commands no longer has a newline at the
	  end of each line; they are stripped off.

	- The Glish "fatal" global has been #define'd to actually be
	  named "glish_fatal" to avoid somewhat frequent name clashes
	  when linking Glish clients to other libraries.

	- A bug has been fixed with accessing $value during an "await".

	- The List class has been modified so that many of BaseList's
	  member functions are now protected.  Before this change it was
	  possible to use the wrong type when inserting into a list and
	  have the compiler fail to catch the problem.

	- The Dictionary class is now implemented using dynamically
	  extended hash tables.  Dictionary's can optionally be specified
	  as "ordered", in which case the elements can be accessed
	  in array-fashion, with index 0 corresponding to the first element
	  inserted into the dictionary, index 1 the second, and so on.
	  If an element is deleted from a dictionary then all the indicies
	  are changed to reflect the deletion; for example, if the first
	  element inserted is deleted, index 0 will then correspond to
	  what originally was the second inserted element.


10Aug92:
	- Changed the paste() predefined function to take an optional
	  argument "sep" which designates the string to be used to glue
	  together the arguments to the call.  For example,

		paste( 3, 5, 7, sep="foo" )

	  results in "3foo5foo7", and

		paste( "Test #", 2 )

	  results in "Test #2".  By default sep is a single blank (' ').
	  Note that to preserve leading or trailing whitespace in the
	  separator it must be enclosed in single quotes instead of
	  double quotes.

	- Fixed bugs in automatic growing of values when elements are
	  assigned beyond the current end of the value's array.

	- Fixed a bug in constructing string arrays.

	- Fixed a bug with boolean array indicies.


05Aug92:
	- Added "FieldVal" member functions to Value class for quick access
	  to the scalar values of record fields.


28Jul92:
	- Fixed some minor bugs related to "glishmon", the Glish event
	  monitor.

	- Fixed some bugs related to read_value()/write_value().


24Jul92:
	- A new set of Value member functions called SetField() have been
	  added for easily adding fields to records from raw C types (such
	  as an array of float's).


22Jul92:
	- A -noglish flag has been added to the Client library.  When
	  run standalone clients by default read stdin to get new events
	  and write generated events to stdout.  -noglish suppresses the
	  reading of events from stdin (but not the writing to stdout;
	  perhaps it should do this too); it's main use is to enable
	  running standalone clients in the background.

	- Numerous new methods are now available for Value objects, primarily
	  to make it easy to use Value's in client applications.  See
	  Glish/Value.h for the latest full list.  The main noteworthy
	  changes are routines for accessing record fields.  Also, in
	  general Value member functions are now a bit more lenient regarding
	  bad calls (for example, requesting a field from a Value that's
	  not a record), typically returning nil pointers instead of
	  exiting with a fatal error.

	- A new create_record() function is available to clients for
	  creating Values of type "record".

	- A bug was fixed in the socket code that could substantially
	  slow down sending events.  In particular, interactive applications
	  should now be much snappier.

	- The "glish.init" file, which must be present in order to run
	  glish, is now found first by checking for the "glish_init"
	  environment variable.  If the variable is not set then a
	  hardwired path is used, much as in the past.

	- A couple of bugs were fixed regarding converting values to
	  strings and from boolean to integer.  These previously
	  caused core dumps in some cases.


05Jun92:
	- The BoolVal()/IntVal()/DoubleVal() member functions of the Value
	  class now take an optional argument specifying which element of
	  the Value to convert and return.

	- Two new predefined functions: all(x) returns true if when interpreted
	  as a boolean value, all the elements of "x" are true; any(x) returns
	  true if at least one of the elements of "x" is true.

	- A "terminate" event may now be sent to a client to tell it to
	  terminate.  The event looks the same to the client as a broken
	  sequencer connection (i.e., NextEvent() returns 0).


04Jun92:
	- A "C" client library has been written.  See glish_client.h or
	  doc/glish-diffs for a description of its interface.

	- A bug has been fixed which would cause remotely executed clients
	  to generate sporadic error messages.

	- A bug in the truncating of long event names has been fixed.


15May92:
	- Glish has undergone major revisions.  See doc/glish-diffs for
	  a summary of differences between the old version of Glish and
	  the new (which is Glish version 2.0).


12Mar92:

	- The C++ "Client" class has been rewritten to be layered on top
	  of the C client/event_lib libraries.  The major benefit of this
	  rewrite is that SDS-valued Glish events are now accessible to
	  C++ Glish clients.  See "Client.h" in glish/conn for a description
	  of the relevant member functions.

	- The C++ "Channel" class has been rewritten to be layered on top
	  of the C ipc_lib library.  This change should be transparent,
	  except that the ReadStatus() member function has been removed.

	- The C event_lib interface has changed in several ways:

		- event_init() now takes argv passed by *value* rather
		  than by reference.  I.e., a typical call to event_init()
		  looks like 

			event_init( &argc, argv );

		  (there used to be a '&' before argv, too).  argv is
		  now modified *in place*.

		- event_terminate() is a new routine that must be called
		  for the client to gracefully exit.

		- all routines which take pointer arguments have been
		  modified to declare those arguments "const" if the
		  pointer's contents are not modified.

	- The C client_lib interface has two new routines: client_channel()
	  returns the ipc_lib channel used for the connection (ipc_lib
	  routines can then be used to read or write from the channel,
	  or to get the corresponding read/write fd's for use in select()
	  operations); client_event_available() returns true if another
	  event is available for processing.
	  
	  client_event_available() does *not* do a select(), so events that
	  have arrived in the local system buffer but that have not yet been
	  read by the ipc_lib routines do *not* cause client_event_available()
	  to return true.  These events must be detected using select() calls.
	  client_event_available() is used to make sure all incoming events
	  have been exhausted after a select() has indicated that there
	  are such events, and client_next_event() has been used to read
	  the first such event.  The typical code fragment looks like:

		  <select is done on several channels; it turns out that the
		   client channel shows data ready.>
		  do
			{
			char event_name[512], event_value[8192];

			if ( ! client_next_event( event_name, event_value ) )
				/* Connection terminated - all done */
				exit( ... );

			<process the event>
			}
		  while ( client_event_available() );

	- ipc_lib, client/event_lib have had "const" modifiers attached
	  to all pointer arguments whose contents are not modified.

	- The basic ipc_lib type has been renamed "IPC_Channel" from
	  "Channel".

	- The ipc_lib library no longer uses blocking I/O; the associated
	  data_is_available() routines have been removed (these routines
	  would check to see whether any IPC data was available in the
	  ipc_lib buffer, and if not would try to read more data and
	  see whether the read call returned EWOULDBLOCK).  Instead, use
	  ipc_{channel_}data_in_buffer(), which returns true if more IPC
	  data is available in the channel's buffer, and false otherwise.
	  If you want to know whether more IPC data is available in the
	  system buffer, you must use select().

	- ipc_lib now provides ipc_channel_write_stream(), which returns
	  the FILE* associated with the IPC output file.

	- Bugs that broke Glish string comparisons have been fixed.

	- The C++ "ClientWorld" class has a new member function,
	  CloseConnection(), which gracefully terminates the program's
	  Glish connection (if any).


05Dec91:

	- The Glish sources can now be compiled using cfront-based
	  C++ compilers, and with Saber-C++ (which requires compiling
	  with -DSABER).

	- Environment variables are available inside Glish sequences
	  as "$varname".  They have string values.  At present they
	  cannot be set to new values.

	- Environment variables can be set for a Glish run by specifying
	  "var=value" on the Glish sequencer command line.

	- Some debugging support has been added in the form of supplying
	  a list of task variables on the Glish sequencer command line:
	  "suspend=foo,bar,bletch" indicates that whenever the tasks
	  associated with the Glish variables "foo", "bar", or "bletch"
	  are fired up, they should be given the "suspend" attribute
	  to allow a debugger to be attached.

	- Glish now supports asynchronous clients (i.e., clients that
	  can asynchronously "join" a Glish sequence).  Such clients
	  are declared using the '&' attribute:

		async-client := client<&>( arg1, arg2, ... );

	  Upon executing such a statement, the event variable ".activate"
	  is created (in the above example, this would be
	  async-client.activate); its value is the arguments to async-client,
	  including the magic Glish arguments that client_lib needs to
	  attach to the sequencer.  Typically these arguments will be
	  printed out (or sent to another client for display or action).
	  Once such a client joins the sequence, a ".established" event is
	  generated as usual.

	- A bug that made Glish constructs such as "when foo & bar -> ..."
	  not work has been fixed (this wasn't a problem for "whenever"
	  constructs).

	- If an environment variable "glish_monitor" is set, it indicates
	  the name of a Glish client (found via $PATH, as usual) to monitor
	  Glish events.  The client is sent "inbound" events indicating
	  each event the sequencer receives, and "outbound" events indicating
	  each event sent out by the sequencer.


    Some changes to the C client library (event_lib.a):

	- When an SDS-valued event is sent to a client, "bindings" may
	  be introduced to bind the names of the elements of the SDS.
	  For example, a Glish statement such as:

		kaspar.send( sid.SDS, "xval=betax" );

	  will send a "send" event to the "kaspar" client whose value
	  is the SDS corresponding to the last "SDS" event generated
	  by "sid".  If "kaspar" looks for an element in that SDS called
	  "xval", it will actually be given the element called "betax".
	  Thus, "xval" is in effect a formal parameter that kaspar is
	  specified to work with, while "betax" corresponds to the actual
	  parameter that it will find.

	- If a client linked with event_lib.a is invoked outside of
	  the sequencing system (i.e., stand-alone), then any input
	  from stdin is treated as though it describes incoming events
	  (of the form "eventname eventvalue", with a blank separating
	  the two); any events generated by the client are simply
	  written to stdout.  Any SDS-valued events the client generates
	  are written to a file with the same name as the generated event.
	  To give the client an SDS-valued event as input, use "SDS sdsfile"
	  as the value of the event (this can be followed by bindings
	  as described above).  For example, to give a client a "compute"
	  event whose value is an SDS residing in the file "myvalues",
	  produce the following on the client's stdin:

		compute SDS myvalues

	- event_init() has been modified to return non-zero if the
	  client is running within the Glish system, and zero if it
	  is running stand-alone.

	- Routines have been added to event_lib.h for supporting arrays
	  of strings; see event_recv_string_ptr() and event_add_string_array().
