RELEASE NOTES for qore

see online release notes for more info:
	http://qore.org/manual/current/lang/html/release_notes.html

*** end of release notes


****************
*** KNOWN ISSUES
****************
Darwin:
  * the fork() function on Darwin does not copy over the state of pthread
    objects to the child process; it's not safe to use any threading
    primitives on Darwin in a child process after a fork().  This is
    a limitation of Darwin's C library and/or kernel and cannot be worked
    around in Qore.  Qore programs using threading will encounter strange
    errors when threading primitives are used after a fork() - note that this
    includes threading primitives needed by the Qore language itself.  This
    was apparently a conscious design decision in Darwin development and is
    not likely to change.
    (tested with Darwin 11.3.0/OSX 10.7.3 - 12.1.0/OSX 10.8.1)
  * Darwin does not seem to have complete support for signaling in threads;
    for example, sigprocmask() has to be called after pthread_sigmask() in
    order to effect changes in the thread signal mask (this is only necessary
    on Darwin and discovered with trial and error).
    Additionally, SIGINFO and SIGWINCH are never delivered to Qore's signal
    handling thread even though the signal mask is set up appropriately (other
    signals are delivered correctly though) - this only happens on Darwin
    (tested with Darwin 11.3.0/OSX 10.7.3 - 12.1.0/OSX 10.8.1)
  * pthread_create() on Darwin (on <= Darwin 10 - however this problem is
    fixed on Darwin 11.3.0+/OSX 10.7.3+) returns 0 (= success) even though
    thread creation fails - the background thread is never started.  Therefore
    on Darwin < 11 the maximum number of threads is set to 2560 which is the
    empirically tested maximum number of threads where pthread_create() still
    works.


***********************
*** LANGUAGE ISSUES ***
***********************

Thread Stacks Overrun
---------------------
*) BUG: on platforms without an assembler "stack guard" implementation
When the thread stack space is exhausted, the program will simply crash.
Qore is heavily threaded and uses the stack often to save thread state, so a
program like: 'sub a() { a(); } a();' will cause a core dump fairly quickly if
the stack guard option is not available for the platform in question.

Note that it is very easy to add a "stack guard" implementation for a new CPU;
there has to be a way to retrieve the value of the current stack pointer
register; this is normally a trivial operation.

The following platforms are *not* vulnerable (because they have assembly stack
guard implementations - also note that "stack guard" support does not depend
on the operating system but rather on the CPU, compiler, and assembler used -
for example on HP-UX pa-risc gcc and aCC can use different, incompatible
assemblers):
  + i386 (gcc, SunPro CC)
  + x86_64 (gcc, SunPro CC)
  + powerpc - 32-bit only (gcc)
  + sparc - 32-bit only (gcc, SunPro CC)
  + itanium - 64-bit only (gcc, aCC)
  + pa-risc - 32-bit only (gcc, aCC)

Out of Memory Errors
--------------------
*) BUG: out of memory conditions are not handled with the c++ new
operator... I need a good solution for that.  Generally the Qore program will
crash if the new operator cannot allocate the memory it needs, however work
has begun on handling out of memory errors starting in v0.5.2.

Object Comparisons
------------------
Note that the comparison operator == (and ===) will only report True if the
two objects are the same object - future versions of Qore will support a
mechanism to allow objects to implement their own handling for operators like
these.

References, Copying, Passing by Value
-------------------------------------
Unlike some other languages requiring garbage collection, Qore uses a
deterministic reference-counted architecture for memory management.  When the
references on a value node reach 0, that object is deleted.  When arguments to
a function or method are passed by value, internally, for all value types
other than an object (instantiation of a Qore class), the reference count is
atomically incremented and the same value node is passed to the function or
method.  In this case, if that value node is changed, then the value is copied
and the changes are made to the copy.  So, for all value node types other than
objects, a copy-on-write approach is used.  However objects are always passed
by reference.  There is always only one copy of each object unless the object
is explicitly copied.  In this sense, Qore acts like Java as far as I am aware
(actually, like Java, a copy of a reference is passed when an object is passed
as the argument to another function).

Parsing
-------
*) Note that there is a parse lock on each program object.  Parsing on a
   single program object is single-threaded.  However, the reentrant parser is
   able to support simultaneous parsing on different program objects.

*) Parsing is atomic; it is executed in 2 stages - 1) parse to pending data
   structures, and 2) resolve references.  References are resolved in the
   second stage, which allows flexible referencing of functions, constants,
   classes, etc before they are declared.
   Stage 2 parsing happens when Program::parseCommit() is called; if any
   errors occur in stage 2 parsing, then the commit fails.
   Any parse errors at any stage will cause all the uncomitted parsing to be
   rolled back.  The Qore Program class allows the programmer control over the
   2 stages of parsing with the Program::parsePending(),
   Program::parseCommit(), and Program::parseRollback() methods.   


*********************
*** SQL Subsystem ***
*********************

*) NOTE that there is a transaction thread lock (mutex) on the Datasource
 class (above the DBI driver level) that is automatically enabled if
 autocommit is off on the Datasource; this transaction thread lock prohibits
 two or more threads from being in a transaction at the same time on the same
 datasource.  To best use this feature when starting a transaction with a
 Datasource::select() (like a "select for update"), call
 Datasource::beginTransaction() before the "select for update"; this will grab
 the transaction lock manually.  You notify qore that the transaction has
 completed by calling Datasource::commit() or Datasource::rollback().  Note
 that this must be done in the same thread that started the transaction.
 Currently there is no way in qore to execute SQL in separate threads
 simultaneously on the same datasource if autocommit is off and one of the
 threads has started a transaction (either by calling
 Datasource::beginTransaction() or Datasource::exec()).  This is because	
 normally a Datasource represents a single socket-based connection to a 
 database server.  
 Also note that transaction locks in the Datasource class and connection 
 allocations in the DatasourcePool class are tracked as thread resources using
 Qore's thread resource management infrastructure (so if the thread exits
 without releasing the resource, an exception is thrown and the resouce is
 automatically released).


**************************************
*** Current and Future Development ***
**************************************

Qore is being continuously developed and is making progress towards the 1.0
release.

There is no defined roadmap for 1.0; this milestone will be declared when the
time feels right (typical of open-source projects).

Version 0.8.4 brings qore a lot closer to the 1.0 release; one main set of
features that may be added before then are hooks for debugging, tracing,
breakpoints, etc.


*********************
*** General Notes ***
*********************

Threading
---------
Qore was designed to favor multithreaded performance over single-threaded
performance.  Due to this reason Qore programs should be very scalable on SMP
systems.

Memory Cleanliness
------------------
Qore has been thoroughly reviewed with valgrind (on Linux) and dbx (on
Solaris) for memory errors.  There are no known static or dynamic memory leaks
in qore at this time.  However, see below on handling out of memory
conditions.

The new features have not been as extensively tested, and there is some danger
of memory leaks with exception handling, as not every code path has been
explicitly tested.

Stability & Bugs
----------------
NOTE that while qore is version 0.8.*, this does not indicate a lack of
stability.  The qore language is in heavy commercial use and must absolutely
remain stable and without memory leaks.

However not all code paths are as well tested as others; there are certainly
unknown bugs out there.


---------------------
RELEASE NOTES HISTORY
---------------------

*****************************
RELEASE NOTES for qore v0.8.4
*****************************

release summary: major new features and changes that can affect backwards-
	         compatibility, plus 40 bug fixes

Release Overview
**************************************************
** Changes That Can Affect Backwards-Compatibility
**************************************************
* Namespace Changes
Qore's internal namespace handling was nearly completely rewritten for Qore
0.8.4.  This is because the old code was inefficient and applied namespaces
inconsistently to Program objects.

The main change that can cause backwards-compatibility issues is that now 
functions are full namespace members.  If no namespace is explicitly given in
a function definition, the function is a member of the unnamed root namespace.

Also the distinction between builtin and user functions was removed.
Internally, there is only one kind of function object, which can contain both
builtin and user function variants (overloaded variants of the same function
with the same name but different arguments).

All Qore builtin functions were moved to the ::Qore namespace.

Other namespace changes:
+ loading namespaces provided by builtin modules into a Program object is now
  an atomic operation that may fail, if, for example, objects have already
  been defined in the target Program with the same name as objects provided by
  the builtin module.  Previously this could cause undefined behavior.
+ namespace looks are now truly breadth-first as documented; previously the
  algorithm was depth-first (contrary to the documentation)
+ namespace lookups are now done (both at parse time and runtime) with the
  help of symbol lookup tables for fast lookups; tables are maintained for
  both committed and temporary uncomitted parse symbols; this leads to up to
  3x faster parsing for Qore code
+ global variables are also now full namespace members, however this does not
  cause problems with backwards-compatibility

***********************
** New Features in Qore
***********************
* User Modules
It is now possible to develop user modules in Qore; several user modules are
now included in the Qore distribution, forming Qore-language components of
Qore's runtime library.

User modules delivered with Qore 0.8.4:
+ HttpServer: a multi-threaded HTTP server implementation
+ SmtpClient: an SMTP client library
+ TelnetClient: a TELNET client implementation
+ Mime: a set of MIME definitions and functions for manipulating MIME data

There are also new example programs for the above modules in the examples/
directory.

User modules are subject to Qore's functional restriction framework; see
Qore's updated documentation for more information.

* Namespace Changes
As listed above:
+ global variables and functions are now full namespace members
+ all builtin functions are now in the Qore namespace
+ real depth-first searches are used for namespace symbols
+ symbols are resolved first in the current namespace when parsing
  declarations/code in a namespace

* The "final" Keyword
classes and methods can now be declared "final" to prevent subclassing or
overriding in a subclass

* Pseudo Methods
Pseudo-methods are class methods that can be implemented on any value; they
are also part of class hierarchy.  The methods that can be executed on the
value depend on the value's type, and all "pseudo-classes" inherit methods
from a common base class.

For example
    "string".strlen()
    <abf05da3>.size()
    500.typeCode()

are examples of pseudo-methods on literal values.

Some expensive operations such as getting the first or last key (or value) of
a hash are now cheap using pseudo-methods, for example:
    $hash.firstKey()
    $hash.lastValue()

See the new doxygen-generated documentation for Qore for more information.

* New Doxygen-Based Documentation
The Qore reference documentation is now generated by Doxygen, and is generated
directly from the Qore sources.  In fact, a new preprocessor known as "qpp"
was developed for Qore 0.8.4 to facilitate and enforce doxygen documentation
on Qore's runtime library (as well as abstract the relatively complex APIs
used to bind C++ code to the Qore runtime library from the C++ programmer).

The documentation is more comprehensive, and corresponds much closer to the
actual internal implementation since the documentation is now also contained
in and directly generated from the internal C++ implementation of Qore.

For example, there is the <value>::val() method.  This method is implemented
in the base pseudo class and is reimplemented in other pseudo-classes for
other runtime data types as necessary.  This method returns True if the value
has a value in the same sense as Perl's boolean context evaluation.  For
example, if the value is a hash with no keys, it returns False; if it is a
hash with keys, it returns True; if it is an empty string, it returns False;
if it is a non-empty string, it returns True, etc.

See Qore's new documentation for more information about pseudo-classes and a
complete technical description of all the methods available, their return
values, etc.

* LValue Handling Changes
lvalue handling was rewritten as the old implementation was ugly and subject
to deadlocks (in rare corner cases).

Furthermore, medium-term, an architectural goal of Qore is to store all 
ints, floats, and bools internally as the basic C++ type instead of using a
class wrapper for each value, which needs dynamic allocation and destruction,
which takes up more memory and negatively affects execution speed.

With Qore 0.8.4, all local and global variables are stored using optimized C++
types when declared with the appropriate type restrictions; for example:
      my int $i0;
      our int $i1;

These declares local and global variables that can only be assigned integer
values; in Qore 0.8.4 the value internally will be stored as an "int64" value
(and not a dynamically-allocated QoreBigIntNode object). 

The same holds for:
    + int
    + softint
    + float
    + softfloat
    + bool
    + softbool

Note that the optimized lvalue handling has not yet been applied to all
lvalues, in particular non-static object members with declared types are not
yet implemented with optimized storage; to do this requires a rewrite of 
Qore's API and ABI (will happen in the next major release of Qore).

This change leads to improved integer and floating-point performance and a
smaller memory footprint.

* Runtime Optimizations
In addition to the up to 3x faster parsing (as decribed in the namespace
changes above), Qore 0.8.4 contains many runtime optimizations designed to
reduce the number of dynamic memory allocations performed at runtime.

The optimizations included in this version of Qore are only a half-measure
compared to future changes that will necessitate a new binary Qore API.

* Per-Thread Initialization
the new set_thread_init() function allows a call reference or closure to be
set which will be automatically executed when new threads are started (or a
new thread accesses a Program object) which can be used to transparently
initialize thread-local data.

* More Control Over Thread Resource Exceptions
new functions:
+ throw_thread_resource_exceptions_to_mark()
+ mark_thread_resources()

Allow for only thread resouces created after a certain point to be processed
(for example only thread resources left after some embedded code was called)

* New Socket Methods
new methods:
+ Socket::upgradeClientToSSL()
+ Socket::upgradeServerToSSL()

allow upgrading an already-existing socket connection to SSL

* Better Socket Error Messages
More information has been added to socket exceptions to provide better
feedback when errors occur.

* New Socket Event Fields
added "type" and "typename" keys to the EVENT_HOSTNAME_RESOLVED event
added "type", "typename", and "address" keys to the EVENT_CONNECTING event

* Support For Blocking Writes in the Queue Class
Queue objects can now be used as a blocking message channel (similar to a Go
channel); if a maximum size is given to the Queue constructor, then trying to
write data to the Queue when it is full will block until the Queue's size goes
below the maximum size; optional timeout parameters have been added to Queue
methods that write to the Queue.

* New Queue::clear() Method
Does just what you think it does :)

* date(string, string) Improvement
added the possibility to specify microseconds when parsing dates against a
mask with the date() function

* New Support For ++ And -- Operators With Floating-Point Lvalues
previously this would either convert the lvalue to an int or throw an
exception if the lvalue could not be converted to an int due to type
restrictions

* Class Recognition/Compatibility Between Program Objects
The problem is that a user class created from the same source code in two
different Program objects would be recognized as a different class with
parameter and variable type restrictions - ie you could not declare a
variable or parameter with a class type restrictions and assign it an object
created from the same class source code but created in another Program object.

This problem is analogous to a similar problem with java in that classes built
from the same source but from different classloaders are also recognized as
different classes.

In Qore 0.8.4 a class signature is created of all public and private objects,
and an SHA1 hash is maintained of the class signature, and if the class names
and signatures match, then the classes are assumed to be identical, even if
they have different internal class IDs (because they were created in different
Program objects, for example).

* New TimeZone::date(string) Method
to support creating arbitrary dates in a given TimeZone

* New GetOpt::parse3() method
This method will display any errors on stderr and exit the program (which is
the most typical way of handling command line errors anyway)

* += Operator Optimization For object += hash
this operation is faster in this release

* New Parse Option PO_NO_MODULES
Using this option disables module loading

* New Parse Option PO_NO_EMBEDDED_LOGIC
Using this option disables all dynamic parsing

* New Parse Directives
+ %assume-global: the opposite of %assume-local
+ %old-style: the opposite of %new-style
+ %require-dollar: the opposite of %allow-bare-refs
+ %push-parse-options: allows parse options to be saved and restored when the
  current file is done parsing; very useful for %include files

* New Context Functions
+ any cx_value(string key): returns the value of the given key
+ bool cx_first(): returns True if iterating the first row
+ bool cx_last(): returns True if iterating the last row
+ int cx_pos(): returns the current row number (starting from 0)
+ int cx_total(): returns the total number of rows in the set

* SOCKET-HTTP-ERROR Exception Enhancement
The invalid header info received is reported in the exception's "arg" key

* Improved Parse Error Messages
Improved some parse error messages dealing with namespace and class
declaration errors

* Added NT_CLOSURE Constant
type code for runtime closure values

************
** Bug Fixes
************
* fixed a race condition with Program objects when a signal handler is left
  active and the Program terminates
* fixed a bug in the File class where the encoding given in the constructor
  was ignored; if no encoding was given in the File::open*() method then the
  File's encoding would always be set to the default encoding, now it's set to
  the encoding given in the constructor (as documented)
* runtime checks have been implemented so that references to local variables
  cannot be passed to a closure; this would cause a runtime crash
* a fix has been made to the delete and remove operators; lists will not be
  extended when trying to remove/delete list elements that do not exist
* fixed some bugs showing the error location with bugs in the second stage of
  parsing (symbol resolution)
* apply type filters to blocks with a designated return type but no return
  statement
* fixed crashing bugs on some 32bit platforms where size_t was assumed to be
  64 bits
* fixed a crashing bug parsing invalid "%requires" directives in the scanner
* fixed a bug in usleep() with relative date/time values (added a new usleep()
  variant to support this)
* fixed a typo in the command-line help for the qore binary with unknown parse
  options	  
* fixed Option::HAVE_SIGNAL_HANDLING to be False if signal handling is
  disabled on platforms where signal handling is otherwise available
* fixed a scanner bug parsing out of line class definitions with a root-
  justified namespace path (ex: "class ::X::ClassName ...")
* merging code from binary modules at parse time and at runtime is now
  transaction-safe (before it would cause memory errors and/or a crash), now
  if errors are detected then an exception is raised and changes are not
  applied.
* fixed a crashing bug in QoreHashNode::setKeyValue() when the value is 0 and
  an exception occurs or is already active before the call is made
* fixed a bug in date parsing with a format string - off by one with integer
  months - added a regression test for this case
* fixed a memory error with the rethrow statement in enclosing but nested
  try-catch blocks
* fixed a crashing bug where qore would try to instantiate a class for a type
  that did not represent a class (ex: 'my int $i();')
* fixed a memory leak in the softlist and *softlist type implementation
* make sure and raise a SOCKET-CLOSED error when reading a HTTP header if no
  data is received
* make sure and convert encodings with index() and rindex() functions if the
  encodings don't match
* build fix: only use a lib64 directory if the directory exists already
* raise a parse exception in the scanner if a numeric overflow occurs in
  literal integer values
* fixed a bug in AbstractSmartLock::lockTID()
* fixed a major crashing error in QoreStringNode::createAndConvertEncoding() -
  this function is used by the xml module when parsing XML-RPC sent in a non-
  UTF-8 character encoding
* fixed File::getchar() to always retrieve 1 character (even for multi-byte
  character encodings)
* fixed string evaluation in a boolean context to return True with floating-
  point numbers between -1.0 and 1.0 exclusive
* printf formatting fix: output YAML-style "null" for NOTHING with %y
* scanner fix: accept \r as whitespace to allow better parsing of sources with
  Windows EOL markers
* fixed parse-time type processing/checks for the keys, + and * operators
* foreach statement fix: unconditionally evaluate the hash when iterating as
  otherwise it could change during iteration which could cause a crash
* fixed another parse-time variant matching bug where the variant-matching
  algorithm was too aggressive and excluded possible matches at parse time
  which could result in a false parse-time definitive match even though a
  better match could be available at runtime
* fixed a static memory leak when signal handlers are left registered when
  the qore library terminates
* fixed static memory leaks and 1 dynamic memory leak in strmul()
* fixed a crashing bug in handling recursive constant references
* fixed a bug in HashIterator::deleteKey() when the node's value is NULL
* fixed time zone/DST calculations for time zone regions with DST with dates
  before the epoch but after the last DST transition before the epoch 
* fixed a memory error where invalid source expressions referenced in a
  regular expression substitution expression would cause a crash (ex:
  str =~ s/public (name)/$2/g
* fixed a memory error in regular expression substitution where the
  unconverted string (if not given in UTF-8 encoding) was used when copying
  source expressions to the target string
* fixed a bug where a recursive class inheritance tree would cause a crash
* fixed a bug where a static class method could not access private members of
  the class


*****************************
RELEASE NOTES for qore v0.8.3
*****************************

release summary: 33 bug fixes and new feature support

* BUG FIX: fixed a bug in parse_url() & parseURL(); parsing urls with
	   IPv6 addresses without ":" - this will only work if a port
	   number is included; otherwise raw IPv6 addresses must be
	   enclosed in square brackets: [ipv6addr]
* BUG FIX: fixed a bug in is_readable() - was returning True for all
	   arguments
* BUG FIX: fixed a file descriptor leak in the FtpClient class related
	   to exception handling
* BUG FIX: fixed some crashing memory bugs in socket handling
	   (particularly related to the internal getPort() call) 
* BUG FIX: fixed split() with quote argument
* BUG FIX: fixed a bug in handling parse errors in switch statements
	   that caused an endless loop
* BUG FIX: fixed 2 memory errors handling parse exceptions with
	   regular expressions
* BUG FIX: fixed an error in system() recognizing "$=" as shell
	   meta-characters
* BUG FIX: fixed a bug in system() where system() caused a deadlock in
	   both child and parent processes if launching the child
	   process launch fails
* BUG FIX: fixed a bug in system() where quotes and backslashes were
	   not being properly quoted
* BUG FIX: fixed typeinfo handling with imported variables in many
	   places - particulary subprograms with imported variables
	   could fail to parse if %require-types is set in the
	   subprogram
* BUG FIX: fixed detected duplicate variables in the same block when
   	   %assume-local is set
* BUG FIX: SQLStatement::commit() and SQLStatement::rollback() no
	   longer throw an exception when called without an active
	   statement; instead, the statement is closed and the
	   operation is executed on the underlying database connection
	   object (Datasource or DatasourcePool object)
* BUG FIX: fixed a memory error looking up scoped constant values at
	   parse time
* BUG FIX: do not issue a "return value ignored" exception if the
	   function/method could throw an exception - the usage
	   without using the return value could be to test if an
	   exception is raised (ie an exception would be considered a
	   side effect)
* BUG FIX: fixed the string output for dates (when date/time values
	   are converted to a string) to not duplicate UTC offset
	   information in case the associated time zone has no region
	   name
* BUG FIX: fixed a bug in the c++ function QoreString::replaceAll()
* BUG FIX: fixed a crash when parsing a class with an
	   unknown/undefined base class
* BUG FIX: fixed a memory leak in the Socket class static
	   initialization
* BUG FIX: fixed issues with passing a reference through different
	   program stacks
* BUG FIX: fixed a bug where some specific type errors in function or
	   method calls were not found at parse time, but rather only
	   at bug time - now these errors are found at parse time
* BUG FIX: added stack overrun check in QoreClass::execConstructor()
	   call to catch the case when a class instantiation is
	   recursively defined
* BUG FIX: fixed a crash due to a memory error in managing reference
	   cycles with closures assigned to constant containers
* BUG FIX: fixed a crash when referencing closure-bound local
	   variables in expressions executed by the background
	   operator
* BUG FIX: fixed function/method variant matching to ensure that
	   variants are matched at run time if there is a variant with
	   fewer parameters than arguments in the call, but the
	   arguments could be NOTHING (count these as ambiguous
	   matches)
* BUG FIX: fixed 2 extremely tricky bugs where deleting a
	   global-thread-local and closure-bound variable that causes
	   an object to go out of scope that in turn references the
	   variable int its destructor caused a crash due to improper
	   thread-local variable stack deletion 
* BUF FIX: fixed a deadlock when deleting the old value of the
	   closure-bound global-thread-local variable while holding
	   the variable's lock (happened when the value was an object
	   that referenced the variable in the destructor)
* BUG FIX: implemented variable finalization to ensure that variables
	   are not assigned after they are destroyed during program
	   and thread termination and destruction - this fixed some
	   possible memory leaks in QoreProgram destruction
* BUG FIX: implemented sleep() and usleep() with nanosleep() (on all
	   platforms with nanosleep(); also no longer mask SIGALRM as
	   it may be used by a library; SIGALRM is also needed for
	   sleep() and usleep() on UNIX and UNIX-like platforms; this
	   eliminated some strange crashes due to unhandled SIGALRM
	   signals when qore is used with some 3rd party libraries
* BUG FIX: added QDOM_FILESYSTEM to all static File class methods (so
	   they cannot be called while "no-filesystem" restrictions
	   are in place for a Program object)
* BUG FIX: added QDOM_TERMINAL_IO to TermIOS::getWindowSize() (so it
	   cannot be called while "no-terminal-io" restrictions are in
	   place for a Program object)
* BUG FIX: added runtime checks for method calls to system File class
	   constants while "no-terminal-io" is in force (so they
	   cannot be called while "no-terminal-io" restrictions are in
	   place for a Program object)
* BUF FIX: fixed a crashing bug where a hash passed to the context statement
	   will cause a crash if one of the keys after the first is not
	   assigned to a list
* new feature: Qore is now supported on Windows with a native DLL and
	   binaries; see README-WINDOWS for more information
* new feature: parse defines are now supported for conditional parsing
	   in a very simple way similar to a very simplified form of
	   the C/C++ pre-processor.  All option (HAVE_*) are now
	   supported as parse defines as well (they are defined only
	   if they are True):
	   new parse directives supporting parse defines:
	   + %define
	   + %ifdef
	   + %ifndef
	   + %else
	   + %endif
	   new Program methods supporting parse defines:
	   + Program::define()
	   + Program::getDefine()
	   + Program::isDefined()
	   + Program::undefine()
* new feature: new softlist and *softlist types
      	   for automatically converting values to a list
* new feature: FtpClient class enhancements:
      	   new methods
	   + FtpClient::mkdir()
	   + FtpClient::rmdir()
  	   + FtpClient::putData()
  	   implemented implicit connection handling for the
 	   FtpClient class 
* new feature: Program class enhancements:
      	   new method: Program::replaceParseOptions()
   	   also expanded the parse option checking logic to allow
	   parse options to be set even when options are locked, if
	   the options make the Program's option environment more
	   restrictive
* new feature: added a new argument to split(string, string); now it's
	   split(string, string, bool = False) - if the 3rd arg is
	   True then the separator pattern string will be included in
	   each element of the output list
* new feature: do not issue "duplicate-local-vars" warning when the
	   other var is a top-level (thread-) local var
* new feature: include "deprecated" in the default warning mask
* new feature: added WARN_DEFAULT constant
* new features: new command-line options for the qore executable:
           + --time-zone,-z (set default time region)
	   + --define, -D   (create a parse define)
* new feature: thread-local variables are now persistent in each
	   Program object; they do not disappear between calls to
	   Program::run() or Program::callFunction(), etc
* new feature: allow SQLStatments to go from state 'defined'
	   (retrieving select after exec) to 'executed' automatically
	   without forcing the user to call SQLStatement::close()
* new feature: new functions:
           + strmul(string, int, *int)
	   + has_key()
* new feature: parser improvements: implemented parser error recovery
	   for syntax errors in argument list declarations
* new feature: added support for removing or deleting a list of keys
	   from a hash in a single atomic operation:
	   + my hash $h = remove $hash.$list_of_keys;
	   + delete $hash.("a", "b", "c")
* new feature: allow parameters to be declared with type "nothing"
* doc updates: documentation updated for new features, documentation
	   corrections


*****************************
RELEASE NOTES for qore v0.8.2
*****************************

release summary: 16 bug fixes, IPv6 support, and other minor
                 improvements

* BUG FIX: fixed a crash when calling exit() right after fork() in the
    parent process by ensuring that the signal thread is stopped
    before exit()ing
* BUG FIX: fixed parse option inheritance with Program objects; when
    PO_NO_CHILD_PO_RESTRICTIONS is set, then take the parse option
    argument to Program::constructor() and apply them literally to the
    new Program object (before the parse options were ignored and the
    parse options applied to the child were applied from unitialized
    memory)
* BUG FIX: fixed a memory/reference leak in the remove operator
* BUG FIX: fixed a bug initializing the internal signal manager
    related to static C++ initialization ordering
* BUG FIX: fixed some bugs with %new-style with variable declaration
    lists
* BUG FIX: fixed typos in statvfs hash output
* BUG FIX: fixed constant resolution when a class constant refers to
    other (unscoped) class constants in the constant's definition
* BUG FIX: fixed catch block parameter parsing when %allow-bare-refs
    is set
* BUG FIX: Dir::openFile() return type corrected to "File"
* BUG FIX: fixed memory errors merging in exception thrown when
    executing code at parse time to the run-time exception sink
* BUG FIX: fixed initializing case expressions requiring parse-time
    evaluation
* BUG FIX: fixed the SQLStatement class to perform an auto-commit if
    necessary when the statement is closed when used with a Datasource
    with auto-commit enabled
* BUG FIX: fixed (with an override) RWLock::lockOwner() to return True
    if the read lock is held
* BUG FIX: the SQLStatement class did not set the "in transaction" flag when
    executing SQL; this could cause the transaction state to be
    silently lost when a driver does a reconnect with a lost
    connection
* BUG FIX: the internal c++ Datasource class did not set the "active
    transaction" flag properly with the first exec
* BUG FIX: added -lthread to sparc8 builds
* new feature: IPv6 support: Socket class updated, parseURL(), and
    parse_url() updated to work with IPv6 addresses and hostnames
* new feature: added Socket::getPeerInfo() and Socket::getSocketInfo()
    methods to get verbose information about local and remote sockets
* new feature: getaddrinfo() function and related constants to get
    network address information for hostnames and services
* new feature: added statvfs() function
* new feature: added normal methods: Dir::hstat(), Dir::stat(),
    Dir::statvfs()
* new feature: added normal methods: File::stat(), File::hstat(),
    File::statvfs(); added static methods: File::stat(),
    File::lstat(), File::hstat(), File::hlstat(), File::statvfs()
* new feature: added the %y printf format specifier to give YAML-like
    output for complex data structures
* new feature: added RWLock::writeLockOwner() and
    RWLock::readLockOwner() methods
* new feature: added date_info() function with 2 variants to get
    broken-down date/time information
* new feature: added FtpClient::rename() method
* new feature: removed restriction assigning function references to
    constants
* new feature: added trunc_str() function for more efficient trimming
    a multi-byte string to a certain maximum byte length
* new feature: added a new DBI method: selectRow() and capability
    (DBI_CAP_HAS_SELECT_ROW); this allows drivers to efficiently
    select only one row from a select statement; if more than one row
    is returned, then an exception should be raised and the data not
    actually returned from the DB server; if the DBI driver does not
    implement this function, then the Qore library will emulate this
    behavior with selectRows()
* new feature: added timestamp to default exception handler output
* new feature: when the debugging compile-time option is enabled, then
    simple backtraces are supported in specific places that will
    assert on Linux and OSX
* doc updates: content was added for new and existing features and
    corrections were made


*****************************
RELEASE NOTES for qore v0.8.1
*****************************

release summary: major bugfixes and major new features including the new
    prepared statement API, vastly improved type system, static class variables
    and class constants

* COMPATIBILITY WARNING: removed all XML and JSON functionality to the new
    "xml" and "json" modules; see README-MODULES for more information
* BUG FIX: fixed a deadlock when calling HTTPClient::setProxyURL() with an
    empty string argument
* BUG FIX: fixed a bug in the return statement to not check return type if an
    exception is active
* BUG FIX: fixed a crashing bug when on_exit, on_success, or on_error
    statement bodies are empty ({})
* BUG FIX: fixed command-line to take modules loaded on the command-line and
    apply them immediately to the program; previously the modules would be
    loaded but only accessible in the parsed program if the program also had a
    %requires declaration for the same module as well
* BUG FIX: fixed a bug in QoreClass initialization from modules that could
    cause a crash
* BUG FIX: updated time zone initialization to parse /etc/TIMEZONE on solaris
    if the TZ variable is not set to set the time zone
* BUG FIX: made all Socket read methods taking a timeout throw a 
    SOCKET-TIMEOUT exception instead of returning NOTHING
* BUG FIX: fixed SSL read timeouts with Socket::recv*()
* BUG FIX: fixed 2-byte bitop swap on MSB platforms (ex sparc)
* BUG FIX: fixed DatasourcePool::constructor(hash), was ignoring "max" option
    and setting to default (20)
* BUG FIX: fixed the setegid() function, was non functional before
* BUG FIX: fixed and improved parse-time variant matching
* BUG FIX: fixed a bug where it was possible to declare a function/method/
    closure with a return type and then not have a return statement as the
    last statement in the block thereby exiting with return value NOTHING,
    which could cause a crash
* BUG FIX: implemented run-time checking when NOTHING is returned from a 
    function, method, or closure that declares a return type
* BUG FIX: fixed a bug in Dir::mkdir()
* BUG FIX: fixed sign error with not found strings with index() and rindex()
    functions
* BUG FIX: fixed a bug with object += hash; member types were not checked
    which could allow for members to be assigned types in violation of their
    declared types
* BUG FIX: fixed a bug where too-lax type checking when executing variants
    resolved at parse time can lead to a crash when a call is made with a
    runtime type error
* BUG FIX: fixed a deadlock where if a global variable contains an object
    which is deleted when the global var is reassigned and the object's
    destructor references the containing global variable, a deadlock could
    result due to incorrectly running the object's destructor while the global
    variable's lock is held
* BUG FIX: fixed incompatibility with string "splice" and "extract" operators;
    they were ignoring the 4th argument if it was not a string
* BUG FIX: fixed invalid memory access after delete error
* BUG FIX: removed internal references to the non-thread-safe localtime()
    function; use thread-safe Qore internal date/time APIs instead
* BUG FIX: fixed %require-types checking with local variable declarations
* BUG FIX: fixed a memory leak/error when a namespace is added to a namespace
    list and a committed namespace of the same name already exists, the
    committed namespace is leaked and replaced with the parsed namespace
    (happened in the parseCommit stage)
* BUG FIX: fixed race condition in ManagedDatasource without connection lock
    when grabbing transaction lock - previously (without the connection lock,
    which was recently removed) the startDBAction function did not guarantee
    exclusive access to the datasource
* BUG FIX: fixed a memory/reference leak with thread resource tracking with
    the Datasource class
* BUG FIX: the Datasource class will no longer allow read-only access to the
    Datasource from other threads when a thread holds the transaction lock
    because access to uncommitted data would be possible
* BUG FIX: fixed DatasourcePool destruction with a transaction open in current
    thread
* BUG FIX: fix in the Dir class for stat()'ing symbolic links
* BUG FIX: bug fix for Socket class to enable the descriptor to be 0 (a valid
    socket descriptor); before this would fail with strange errors
* BUG FIX: fixed constant initialization, parse intiialization order, and
    global thread-local variable access from code parsed and committed to the
    Program object after the first commit
* BUG FIX: fixed connecting to a HTTPS server through a proxy by using the
    HTTP CONNECT method with the proxy
* BUG FIX: fixed bugs in FtpClient class handling invalid responses from buggy
    FTP servers
* BUG FIX: fixed socket read when socket is closed during a read(-1) or
    readBinary(-1) operation; an exception was thrown instead of returning the
    data that was already read
* BUG FIX: added internal C++ API function Datasource::activeTransaction() so
    DBI drivers can see if they need to throw an exception or not when
    automatically reconnecting to a dataource - if
    Datasource::beginTransaction() is called and then the driver finds out the
    connection is down, it is safe to reconnect silently if no DB commands
    have been issued since the beginTransaction() call -
    Datasource::activeTransaction() will only return true if DB commands have
    been issued since the transaction started.  All DBI drivers the support
    auto-reconnect were separately updated as well to use the new API
* BUG FIX: warnings and parse options are now stored on each statement so that
    they are applied in the same way during both parse stages
* new feature: class constants; classes can now declare constants in their
    private and public declaration blocks
* new feature: static class variables; classes can now declare static
    variables in their private and public declaration blocks
* new feature: much better type implementation
  * new type "timeout": accepts either integer or date
  * types prefixed by "*" mean "or nothing" - also allow assignments to
    NOTHING
* new feature: SQLStatement class and internal prepared statement API for DBI
    drivers; the first driver supporting the new prepared statement API is the
    Oracle driver
* new feature: fixed in-object calls (ex: $.call()) to dynamically look up the
    method if the run-time class is not the same as the parse class.  This
    means that it's no longer necessary to use the "$self.method()" syntax to
    make calls when the method may be called by a child class that has
    reimplemented the method
* new feature: new parse options:
  * %assume-local: variables declared with type and without "my" are assumed
    to be local variables
  * %allow-bare-refs: allows all variables, object members, and object
    method calls to be made without using "$" or "$."
  * %new-style: combination of %assume-local and %allow-bare-refs
* new feature: return types for functions, methods, and closures can appear
    before the function signature:
    ex: int sub function() {}
    the new syntax with the return type before the method signature is
    preferred over the olf syntax with the "returns" keyword
* new feature: implemented warning "duplicate-block-vars" enabled by default
    for the case when a variable is declared twice within the same block at
    the exact same lexical scope; this is an error when %assume-local is
    enabled
* new feature: implemented "$#" giving the implicit offset when implicitly
    iterating a list (foreach, map, foldl, foldr, select)
* new feature: added the following methods to the HTTPClient class:
  * HTTPClient::setUserPassword()
  * HTTPClient::clearUserPassword()
  * HTTPClient::setProxyUserPassword()
  * HTTPClient::clearProxyUserPassword()
* new feature: added "perm" key to stat hash output giving the file's symbolic
    permission (i.e. "drwxr-xr-x")
* new feature: implemented %module-cmd(<module-name>) parse directive to allow
    modules to handle commands while parsing; first module using this is the
    gnu-java module for "import" statements allowing java classes (to be
    imported to the current program)
* new feature: implemented "deprecated" method and function tag
* new feature: implemented splice(string, string, string) to split with an
    optional quote character; this can be used, for example, to quickly parse
    CSV files where some fields may be quoted and some not 
* new feature: added the ability to deserialize xml-rpc extension types
  * ex:nil
  * ex:i1
  * ex:i2
  * ex:i8
  * ex:float
  * ex:dateTime 
  note that none of these types can be serialized automatically yet
* new feature: added methods:
  * AbstractSmartLock::lockOwner()
  * AbstractSmartLock::lockTID()
* new feature: updated HTTPClient to accept URLs specifying UNIX domain
    sockets


*****************************
RELEASE NOTES for qore v0.8.0
*****************************

release summary: major Qore release with significant new functionality; see below for compatibility warnings

* hard typing, function and method overloading, and default argument values
declaring a variable with type info:
  ex: our int $i = 1;
      # the following 2 are functionally identical
      my Mutex $m = new Mutex();
      my Mutex $m();

declaring a function with argument types, default argument values and return types:
  ex:
  sub example(int $i = 0, bool $force = False) returns string {
      return "test";
  }

builtin types: int, float, bool, string, hash, object, reference, binary, date, nothing, null

soft types:
softint: converts automatically from string, float, bool, and date
softbool: converts automatically from string, float, int, and date
softstring: converts automatically from int, float, bool, and date
softfloat: converts automatically from string, int, bool, and date

composite types:
data: either string or binary
any: any value (including nothing)
code: either a call reference or a closure

the special type names "callref" and "closure" are synonyms for "code" and cannot be used to restrict a value to one or the other types.

limitations of hard typing:
no complex types are available yet (reference to hash, list of Condition, etc).
many functions and methods can return more than one data type depending on the arguments (values, not types); in this case the return types are tagged as "any" even though only a small number of types can be returned.  In general, whenever an expression can return more than one type, this is currently covered by returning type "any".

Type information has been propagated through the parser; so many more errors can be caught at parse time, sometimes even if types are not declared in code (such as with code written for older versions of qore, for example).  See below for warnings (non-existent-method-call, invalid-operation, call-with-type-errors, return-value-ignored, deprecated, excess-args, duplicate-hash-key) and parse directives (ex %require-types) added, most of them related to typing.

class methods restrictions: the following methods may not be overloaded:
      <class>::copy()
      <class>::destructor()
      <class>::memberNotification(string $member)
      <class>::memberGate(string $member)
      <class>::methodGate(string $method, ...)

* time zone support in absolute date/time values
Qore uses the system's zoneinfo information to determine the UTC offset and daylight saving's time changes
Dates given without a time zone portion are assumed to be in local time

* more flexible time input when parsing:
UTC offset in time east plus hundreths of a second (1-6 digits after the decimal point are accepted):
2001-01-01T11:35:21.53+06:00

date in Zulu time (UTC) (time component = 00:00:00Z)
2001-01-01Z

* date/time values have resolution to the microsecond
previously was to the millisecond; applies to both relative and absolute date/time values

parser accepts a new relative time format: <x>us, ex: 45us = 45 microseconds

* conversion to a date from a string is much more flexible
formats such as the following are now accepted:
2001-01-01T15:35:23         # 2001-01-01 15:35:23 Mon +01:00 (CET)
20010101 15:35:23Z          # 2001-01-01 15:35:23 Mon Z (UTC)
20010101 153523Z            # 2001-01-01 15:35:23 Mon Z (UTC)
20010101 153523-02          # 2001-01-01 15:35:23 Mon -02:00 (-02:00)
20010101 153523-02:00:00    # 2001-01-01 15:35:23 Mon -02:00 (-02:00)
2001-01-01-153523-020000    # 2001-01-01 15:35:23 Mon -02:00 (-02:00)
20010101-153523             # 2001-01-01 15:35:23 Mon +01:00 (CET)
etc

furthermore, it's now possible to directly specify relative date/time values when converting from a string using a subset of ISO-8601 duration formats with an extension for microseconds (<n>u - the 'u' is lower-case as it is not part of the ISO9601 standard) and also an extension where the numeric portion may be negative:
P<n>Y<n>M<n>DT<n>H<n>M<n>S<n>u

for example:
P1Y2MT4H                    # <time: 1 year 2 months 4 hours>
P4DT-2M15u                  # <time: 4 days -2 minutes 15 microseconds>
PT4H30M                     # <time: 4 hours 30 minutes>

note that there must be at least one time component, and the <n>M value is minutes when following the 'T' and months when preceding or in the absense of a 'T'.
unlike ISO-8601 durations, all numbers must be integers (ISO-8601 allows the smallest time unit given to have a fractional component)

The other duration format: PYYYY-MM-DDTHH:MM:SS is also still accepted as well as in previous versions of qore

* class constuctor methods can now be declared private

* new TimeZone class
# creates a TimeZone object based on a zoneinfo region file
TimeZone::constructor(string)

# creates a TimeZone object based on a UTC offset in seconds east of UTC
TimeZone::constructor(softint)

# returns a date marked with this TimeZone from the UTC offset in seconds
TimeZone::date(softint $epoch_seconds, softint $us = 0)

# returns a date marked with this TimeZone
TimeZone::date(date)

# returns a date marked with this TimeZone from the given argument as an epoch offset in milliseconds
TimeZone::dateMs(softint)

# returns a date marked with this TimeZone from the given argument as an epoch offset in microseconds
TimeZone::dateUs(softint)

# returns the time zone for the current execution context
static TimeZone::get() returns TimeZone

# allows the time zone to be set for the current execution context
static TimeZone::set(TimeZone) returns nothing

# sets the time zone according to a UTC offset in seconds east of UTC for the current execution context
static TimeZone::setUTCOffset(softint) returns nothing 

# sets the time zone according to a zoneinfo region file for the current execution context
static TimeZone::setRegion(string) returns nothing

* new Program methods
Program::setTimeZoneRegion(string)
Program::setTimeZoneUTCOffset(softint)
Program::setTimeZone(TimeZone)
Program::getTimeZone() returns TimeZone

* new functions
getpwuid2(softint) returns hash
getpwnam(string) returns any
getpwnam2(string) returns hash
getgrgid(softint) returns any
getgrgid2(softint) returns hash
getgrnam(string) returns any
getgrname2(string) returns hash
readlink(string) returns string
is_date_relative(date) returns bool
is_date_absolute(date) returns bool
get_duration_seconds(date) returns int
get_duration_milliseconds(date) returns int
get_duration_microseconds(date) returns int
now_us() returns date
now_utc() returns date
date_us(softint) returns date
microseconds(softint) returns date
get_microseconds(date) returns int
get_epoch_seconds(date) returns int
setsid() returns int

* new overloaded variants of existing functions
gmtime(date) returns date
localtime(date) returns date

* new Socket methods and variants
Socket::connectINET(string $host, int $port, int $timeout_ms = -1) returns nothing
Socket::connectINET(string $host, int $port, date $timeout_ms) returns nothing
Socket::connectINETSSL(string $host, int $port, int $timeout_ms = -1) returns nothing
Socket::connectINETSSL(string $host, int $port, date $timeout_ms) returns nothing
Socket::connectUNIX(string $path) returns nothing
Socket::connectUNIXSSL(string $path) returns nothing
Socket::setCertificate(binary) returns nothing
Socket::setCertificate(string) returns nothing
Socket::setPrivateKey(binary) returns nothing
Socket::setPrivateKey(string) returns nothing

* new object creation syntax
to create an object without explicitly using the "new" operator, use the "my" or "our" keywords then give the class name followed by the arguments to the constructor in parentheses as in the following example:
   my File $f();

* cast<> operator
This operator can be used to suppress warnings such as the non-existent-method-call warning; for example, if you make a method call from a base class to a method that only exists in a subclass, because qore has no way of defining "pure virtual" methods like in C++, the parser raises a "non-existent-method-call" warning.  You can use the cast<> operator to supress this warning as in the following example:
     cast<ChildClass>($self).methodCall();

* delete statement is now the delete operator
so now the delete operator can be used in "map" expressions, for example

* new remove operator
the remove operator works in a way similar to the delete operator, but does not call the destructor when operating on objects.  It also returns the value removed.
For example:
    my string $str = remove $hash.key;

This would remove "key" from $hash and return the value removed.

* new extract operator
The extract operator is identical to the "splice" operator, except the extract operator returns any values removed from the list or string operated on

* constants may be assigned with any expression that does not have side effects
this includes builtin functions that have been tagged as safe to use in constant expressions

* fixed the ',' operator's precedence in the parser
previously the comma operator's precedence was set far too high which caused problems in certain expressions, for example:
func(1, $a = 2, 3)
would previously be interpreted like this:
func(1, ($a = 2, 3))
contrary to what any reasonable programmer would expect.  From this version on, the comma operator's precedence has been adjusted to be like other programming languages.

* fixed conversion of characters quoted with '\' in JSON strings

* changed output of printf format specifiers %n and %N
double quotes (") and '\' characters are now quoted with '\'

* new warning: non-existent-method-call
raised when a given method name cannot be found in the current class or base classes.  such calls may be valid if the method itself is called from a derived class where the method exists

* new warning: invalid-operation
warns when an expression will produce a constant output due to type errors

* new warning: call-with-type-errors
warns when a variant tagged with RT_NOOP is resolved at parse time

* new warning: return-value-ignored
warns when a function or method that only returns a value and has no side effects has its return value ignored

* new warning: deprecated
warns when deprecated features are accessed

* new warning: excess-args
warns when excess arguments are passed to a variant that does not access the excess arguments

* new warning: duplicate-hash-key
warns when a duplicate hash key is given in an immediate literal hash

* default warning mask updated
the default warning mask includes: unknown-warning, unreachable-code, nonexistent-method-call, invalid-operation, call-with-type-errors, return-value-ignored, duplicate-hash-key

* new parse option PO_REQUIRE_TYPES (%require-types), command-line --require-types
if this option is given, then all parameters, return types, and object members must have a declared type
if no return type for functions and methods is explicitly declared when this option is set, then the return type is assumed to be NOTHING
this option also implies PO_STRICT_ARGS

* new parse option PO_STRICT_ARGS (%strict-args), command-line --strict-args
when this option is set, no variant tagged with RT_NOOP is accessible; any access to variants with this tag at parse-time or at runtime will result in an exception
Additionally, if excess arguments are sent to a function or method that does not access excess arguments, an exception is raised

* new parse option PO_NO_THREAD_INFO (%no-thread-info), command-line --no-thread-info, domain QDOM_THREAD_INFO
the following functions were tagged with QDOM_THREAD_INFO:
gettid(), num_threads(), thread_list(), get_thread_data(), get_all_thread_data(), getAllThreadCallStacks()

* new parse option PO_NO_EXTERNAL_INFO (%no-external-info), command-line --no-external-info, domain QDOM_EXTERNAL_INFO
the following functions were tagged with QDOM_EXTERNAL_INFO:
getuid(), geteuid(), getgid(), getegid(), getpid(), getppid(), gethostname(),
gethostbyname(), gethostbyaddr(), gethostbyname_long(), gethostbyaddr_long(),
getcwd(), getcwd2(), getpwuid(), getpwuid2(), getpwnam(), getpwnam2()

* new parse option PO_NO_LOCALE_CONTROL (%no-locale-control), command-line --no-locale-control, domain QDOM_LOCALE_CONTROL
the following functions were tagged with QDOM_LOCALE_CONTROL:
TimeZone::set()

* parseDatasource() function updated
parseDatasource() will now parse options at the end of a datasource string in curly brackets ('{' '}') such as the following:
oracle:user/pass@db(al32utf8)%localhost:1521{min=5,max=10}

Any option name can be placed there, whitespace is ignored; options must have the form <key>=<value>

Options are placed in a hash under the "options" key in the value returned from parseDatasource().
The example above would produce the following output:
hash: (8 members)
  type : "oracle"
  user : "user"
  pass : "pass"
  charset : "al32utf8"
  db : "db"
  host : "localhost"
  port : 1521
  options : hash: (2 members)
    min : "5"
    max : "10"

Only "min" and "max" options are now currently used - when the DatasourcePool(hash) constructor is used are these options respected if they are present in the hash.

* new Datasource constructor variant:
Datasource::constructor(hash)

expects a hash as produced by parseDatasource()

* new DatasourcePool constructor variant:
DatasourcePool::constructor(hash)

expects a hash as produced by parseDatasource()

* HTTP-CLIENT-RECEIVE-ERROR exception
now returns more information - the exception argument "arg" is a hash with the following keys:
code: the HTTP code received
body: the message body received

* HAVE_TIMEGM is always true
we no longer use the system function timegm(), so this option (and constant) is always true now
timegm() is now an alias for get_epoch_seconds()

* new constants
MACHINE_MSB: boolean, True if the machine is a big-endian machine, False if not
Z_DEFAULT_COMPRESSION: integer; the default compression level for zlib

* module blacklist
qt-core, qt-gui, qt-svn, and qt-opengl are all blacklisted because they were implemented with faulty namespace handling that does not work with qore 0.8.0+; use the 'qt4' module based on libsmoke instead; it's much more complete and supports types, etc

* COMPATIBILITY WARNING: HTTPClient::setSecure(bool $b = True)
before calling this method without an argument would turn off secure connections, which was counter-intuitive

* COMPATIBILITY WARNING: HTTPClient::setProxySecure(bool $b = True)
before calling this method without an argument would turn off secure connections, which was counter-intuitive

* COMPATIBILITY WARNING: HTTPClient::setNoDelay(bool $b = True)
before calling this method without an argument would turn off TCP_NODELAY, which was counter-intuitive

* COMPATIBILITY WARNING: Socket::setNoDelay(bool $b = True)
before calling this method without an argument would turn off TCP_NODELAY, which was counter-intuitive

* COMPATIBILITY WARNING: method return values updated
Datasource::open(), Datasource::close(), Datasource::commit(), Datasource::rollback(), DatasourcePool::commit(), DatasourcePool::rollback(), FtpClient::connect(), FtpClient::disconnect(), FtpClient::cwd(), FtpClient::get(), FtpClient::put(), FtpClient::del(), Socket::shutdownSSL()
no longer return any value.  In previous versions they would return integer 0.  However, they always throw an exception if there is an error, so any return value was meaningless.


*****************************
RELEASE NOTES for qore v0.7.8
*****************************

release summary: 19 bug fixes from 0.7.7 plus a single enhancement

* BUG FIX: fixed a bug processing arguments to in-object method calls in the
           background operator
* BUG FIX: fixed a bug processing arguments to static method calls in the
           background operator
* BUG FIX: fixed a bug where the File class would reset the encoding given in
           the constructor on ::open*()
* BUG FIX: fixed a bug where if local variables were used in a reference 
           expression with the background operator, whenever the reference
           was accessed in the called code a crash would result
* BUG FIX: eliminated string parsing in block comments, fixed a bug where the
           parser was not terminated at EOF in a block comment
* BUG FIX: check for PO_NO_FILESYSTEM in FtpClient::put()
* BUG FIX: fixed a cosmetic bug in exception string in FtpClient::get()
* BUG FIX: fixed a bug in SSLCertificate::getSignature()
* BUG FIX: fixed a bug in SSLCertificate::getInfo()
* BUG FIX: fixed CANNOT-PROVIDE-FEATURE exception text
* BUG FIX: fixed getpwnam() to use q_getgrnam() and correct a thread and
           functional error in QC_Dir.cc
* BUG FIX: fixed non-thread-safe usage of getpwnam() in QC_Dir.cc
* BUG FIX: fixed adding virtual private data to classes with multiple virtual
           base classes
* BUG FIX: fixed Socket::recv() and Socket::recvBinary() when reading all data
           available on the socket when the remote ends closes the connection
           in an orderly way
* BUG FIX: fixed parsing negative numbers in json strings
* BUG FIX: fixed limited XML node size
* BUG FIX: fixed a memory bug in the context statement when an exception
           occurs in the context expression
* BUG FIX: fixed a memory bug in the binary += operation; if the operand for
           BinaryNode::append() is equal to the current buffer, a crash would
           result
* BUG FIX: fixed some bugs processing arguments in the XmlReader class
* enhancement: added a QoreSocket::recvBinary() function to receive all data
               available on the socket (with an optional initial timeout 
               value) and return it as a binary object; if 
               Socket::recvBinary() is called with buffer-size <= 0, then this
               variant is used


*****************************
RELEASE NOTES for qore v0.7.7
*****************************

release summary: 15 bug fixes from 0.7.6

* BUG FIX: fixed a bug where taking a slice from an object could return
           private members when called outside the class (backported from
           trunk)
* BUG FIX: fixed a bug making a hash slice where the character encoding was
           not ensured to be QCS_DEFAULT before trying to match key names
           (backported from trunk)
* BUG FIX: fixed a bug returning the last builtin data type ID; affects qore
           modules that implement new builtin types (ex qt module, qt4 module)
* BUG FIX: fixed a reference counting bug in callObjectMethodArgs() that could
           lead to a crash if a list is passed as the 3rd argument
* BUG FIX: fixed a bug executing builtin functions if an exception is raised
           when evaluating the arguments (the function was erroneously 
           executed)
* BUG FIX: fixed a bug in the FtpClient class that caused the connection to
           never get established
* BUG FIX: fixed a bug when a builtin class tries to access private data of an
           object that's already been deleted; now an appropriate exception is
           thrown; previously it would silently fail
* BUG FIX: fixed examples/WSDL.qc de/serializing "int" and "short" from
           negative numbers
* BUG FIX: removed an extraneous reference and dereference in objects when
           launching new threads in objects (slightly better performance
           launching new threads in objects)
* BUG FIX: fixed a rare race condition in object constructors when an object
           launches threads in the object and then the constructor throws an
           exception afterwards
* BUG FIX: fixed handling in the Datasource and DatasourcePool classes when
           auto-reconnects fail (connection aborted handling) - now the
           Datasource class tags the connection as aborted and closes the
           connection when Datasource::connectionAborted() is called by the 
           DBI drivers, and the DatasourcePool class correctly returns the 
           Datasource to the pool.  Additionally, the Datasource class will
           not execute any action on the Datasource once the connection has
           been aborted.  The flag is cleared when the connection is opened
           again.
* BUG FIX: fixed memory leaks in parse exceptions with static method call
           references (backported from 0.8.0/trunk)
* BUG FIX: detected erroneous variable list declarations like:
           our (my $x, ...) or my (our $x) and throw a parse exception
           (backported from 0.8.0/trunk)
* BUG FIX: fixed a harmless bug in TempEncodingHelper to remove a message from
           valgrind (backported from 0.8.0/trunk)
* BUG FIX: fixed memory bug in CryptoHelper - removed unnecessary and incorrect
           string termination code (backported from 0.8.0/trunk)


*****************************
RELEASE NOTES for qore v0.7.6
*****************************

release summary: 34 bug fixes and major new features over 0.7.5

*) BUG FIX: updated is_writable() and is_readable() to always return True if
       	    called by effective UID 0 (root)
*) BUG FIX: fixed a race condition in deleting objects by marking objects
            atomically as inside destructor
*) BUG FIX: updated sleep() to continue sleeping for the remaining time if
            interrupted by a signal
*) BUG FIX: changed decompression routines to a string to preserve binary 
            data, especially trailing nulls
*) BUG FIX: fixed C++ QoreString constructor when taking ownership of a string
            buffer to ensure that the buffer is null terminated when the
            allocated buffer is exactly equal to the string length
*) BUG FIX: fixed scanner to ignore quoted text in comments (i.e. "*/" will be
       	    ignored)
*) BUG FIX: updated the Socket class implementation to retry connect(), 
       	    accept(), recv(), send(), and select() (Socket::isDataAvailable(),
	    Socket::connect() with timeout, etc) if interrupted by a signal
*) BUG FIX: updated the File class implementation to retry read(), write() and
       	    fcntl() with F_SETLKW (File::lockBlocking()) if interrupted by a
	    signal
*) BUG FIX: fixed set_signal_handler() to accept a closure as per the
       	    documentation
*) BUG FIX: fixed internal C++ library function test_funcref_param() to return
       	    a value for call references and closures
*) BUG FIX: fixed broken access to private members of an object outside the
            class; before it was possible to delete and reassign private
	    members from outside the class which should have been illegal
*) BUG FIX: fixed a crashing bug in the File::open2() method
*) BUG FIX: fixed class method registration so that static method names and
            non-static method names have independent namespaces (i.e. a static
	    method may now have the same name as a non-static method).  Static
	    methods may still be called with normaly method call syntax,
	    however if there is a non-static method with the same name, then it
	    will be called instead.
*) BUG FIX: when an HTTP header is received more than once, return all values
            as a list under the header name in the resulting hash
*) BUG FIX: fixed a potential race condition that could cause a crash in very
            rare circumstances in internal C++ QoreClass::numMethods() and
	    QoreClass::numStaticMethod() functions; to make a crash a program
	    would have to be running and parsing new code into the program in
	    a separate thread as well; this is explicitly supported by Qore,
	    but very rarely done
*) BUG FIX: fixed an XML-RPC parsing bug caused by a side-effect in a 
            debugging statement
*) BUG FIX: fixed a bug setting the character encoding in strings produced 
            with makeXMLFragment() and makeFormattedXMLFragment() when the
	    default character encoding is not UTF8
*) BUG FIX: fixed concatentation of strings with embedded nulls
*) BUG FIX: fixed split() to work on strings with embedded nulls
*) BUG FIX: fixed method resolution for in-object method calls when the target
            method is static
*) BUG FIX: fixed a crash in parsing when a class with no parent classes
            references a base class method of an existing class
*) BUG FIX: fixed static method calls at the top level of a program
*) BUG FIX: fixed type comparisons with new qore types implemented in external
            modules
*) BUG FIX: fixed configure to ensure compiling in 32-bit mode on Darwin/OSX if
            32-bit mode is selected
*) BUG FIX: fixed configure to assume 64-bit mode by default on Darwin 10 (OSX
            Snow Leopard)
*) BUG FIX: fixed $ARGV and $QORE_ARGV variables to always be of type list
            as according to the documentation
*) BUG FIX: fixed Socket::connect() with timeout (affects all classes using
            sockets for communication
*) BUG FIX: fixed DatasourcePool handling when a driver-handled auto-reconnect
            fails (previously would cause a crash)
*) BUG FIX: added QDOM_TERMINAL_IO to TermIOS class (previously this class
            would be available even if PO_NO_TERMINAL_IO was in force)
*) BUG FIX: fixed a bug parsing XML-RPC array data with empty value elements;
       	    i.e.: <value/>
*) BUG FIX: fixed a bug waiting on a Condition variable when thread read lock
            is held by multiple threads (for RWLock)
*) BUG FIX: fixed a bug calculating the time offset for waiting on a Condition
            object
*) BUG FIX: fixed millisecond formatting using "ms" with format_date()
*) BUG FIX: fixed a crashing bug when a Condition object waits on a RWLock with
       	    the read lock held
*) BUG FIX: fixed a bug setting the exception location when throwing thread
       	    resource exceptions when shutting down the qore library
*) NEW FEATURE: added XmlDoc, XmlReader, and XmlNode classes for more robust
       		XML parsing and document iteration
*) NEW FEATURE: added support for validation with RelaxNG schemas: new 
                functions: parseXMLWithRelaxNG() and 
		parseXMLAsDataWithRelaxNG() as well as new method:
		XmlDoc::validateRelaxNG()
*) NEW FEATURE: added a new binary_to_string() function to convert a binary 
                object directly to a string type
*) NEW FEATURE: implemented binary object concatentation with the + and +=
                operators
*) NEW FEATURE: the -= operator now operates on objects (with string and list
                operands) like it does with hashes
*) NEW FEATURE: added static method TermIOS::getWindowSize() to get the 
                current terminal window size (rows and columns)
*) NEW FEATURE: new C++ APIs are available supporting a generic calling
             	convention to facilitate the development of the new Qt4 module
		using libsmoke; the latest module API is now 0.8
*) NEW FEATURE: added the HTTPClient::isConnected() method
*) NEW FEATURE: added the rename() function to rename or move files
*) NEW FEATURE: case expressions now support the == operator for soft 
                comparisons
*) NEW FEATURE: updated split() to work on binary objects just like on 
                strings, but will return a list of binary objects split by the
		marker
*) BUILD CHANGE: minimum libxml2 version required for compiling and linking is
                 now 2.6.0


*****************************
RELEASE NOTES for qore v0.7.5
*****************************

release summary: 4 bug fixes and minor new features over 0.7.4

*) BUG FIX: Datasource::close() would assert() in debug mode and do nothing in
            non-debug mode
*) BUG FIX: fixed a deadlock in running class destructor code when a member is
       	    deleted that is itself an object, and that object's destructor
	    references the parent object
*) BUG FIX: fixed a bug in the "qore" binary reporting the library's latest
       	    module API version (was using the compiled value and not the value
	    from the library)
*) BUG FIX: fixed a bug in the HTTPClient class where the connection was not
            flagged as closed when an error occurred that indicated that the
            client had closed the connection
*) added a ModuleDir key to the hash output of get_qore_library_info()
*) added an optional port number to datasources (i.e.: 
   driver:user/pass@db(encoding)%host:port, updated:
   + Datasource::constructor(): added support for a port argument
   + Datasource::setPort(): new method
   + Datasource::getPort(): new method
   + DatasourcePool::constructor(): added support for a port argument
   + DatasourcePool::getPort(): new method
   + parseDatasource(): modified to parse the port if present
*) updated module API to 0.7 supporting DBI drivers with port as a 
   configuration option
*) updated the %include directive to always search the directory of the
   currently-executing script first if known when looking for files without an
   absolute path
*) added the C++ API function QoerObject::externalDelete() to handle the
   situation when object private data is deleted externally (needed by the QT
   modules)
*) improved error messages in the scanner when trying to %include something
   that's not a regular file


*****************************
RELEASE NOTES for qore v0.7.4
*****************************

release summary: qore 0.7.4 contains minor feature improvements over 0.7.3 and
                 twenty-two bug fixes

*) BUG FIX: fixed localtime() when called with no argument to return the
   current date and time as per documentation
*) BUG FIX: fixed a race condition that could cause a deadlock when calling
   pthread_join() when Qore code calls "exit()" when multiple threads are
   running
*) BUG FIX: fixed the Dir::listFiles() method; the mask used would not filter
   out directories
*) BUG FIX: fixed crashes in the File class due to unsigned data type being
   used and the comparison (< 0) that signaled an error always failed; the
   crash would happen when a non-File object was read
*) BUG FIX: fixed outputting recursive data structures with the %n and %N 
   printf format specifiers (would otherwise result in a crash - for example,
   when an object contains a list that also contains the object, etc)
*) BUG FIX: fixed object access deadlock scenarios
*) BUG FIX: fixed the "-" operator with: hash-string and hash-list (also
   hash-=string and hash-=list) to remove the value(s) from the hash, not call
   the delete operator
*) BUG FIX: NULL values are serialized as "null" JSON values
*) BUG FIX: fixed parsing of a corner case of marginally valid XML-RPC
*) BUG FIX: fixed XML-RPC serialization to handle NOTHING (no value) and NULL
   identically
*) BUG FIX: fixed XML-RPC serialization to never output an empty <param/>
   element, as it could potentially break some implementations (the XML-RPC
   spec is not very clear on this).  Note: we send empty value elements:
   <value/> when serializing NOTHING or NULL, which may not be correct either
*) BUG FIX: do not assume that a trailing null should terminate the string when
   reading string data from files; include the trailing null in the string
*) BUG FIX: fixed a bug parsing base64 strings when newlines and/or linefeeds
   trailed the base64-encoded data
*) BUG FIX: fixed outputting '%%' as '%' in *printf*() functions
*) BUG FIX: fixed a bug parsing hashes where the hash key was given as a
   constant
*) BUG FIX: fixed a bug in the delete operator where shared data was being
   updated in place instead of copied and then updated
*) BUG FIX: fixed some race conditions that could cause deadlocks with the
   getAllThreadCallStacks() function (not normally enabled by default)
*) BUG FIX: ignore '\n' and '\r' when parsing base64-encoded strings
*) BUG FIX: fixed a crashing bug when trying to copy member elements of a 
   deleted object
*) BUG FIX: fixed the foreach statement when used with a reference and the 
   break statement is used
*) BUG FIX: fixed a rare reference dependency bug where system classes were 
   being destroyed while still referenced in user code
*) BUG FIX: fixed %= with a modula operand of 0 to set the lvalue to 0
   (previously the expression was ignored if the modula operand was 0)
*) added the abilty for a Condition variable to wait on RWLock objects as well
   as Mutex objects
*) dereferencing a hash or object with a list will return a slice of the hash
   or object as a hash: ex: $hash.("key1", "key2")
*) allow %include parse directives to quote the file names (ignore leading and
   trailing quotes around the file name)
*) new Socket class methods:
   + Socket::isWriteFinished(<timeout_ms>): for future support for 
     non-blocking writes
   + Socket::setNoDelay(<boolean>): to set the TCP_NODELAY option
   + Socket::getNoDelay(): returns value of the TCP_NODELAY option
*) new functions to allow for explicitly specifying the encoding when
   serializing XML-RPC strings:
   + makeXMLRPCCallStringWithEncoding()
   + makeXMLRPCCallStringArgsWithEncoding()
   + makeXMLRPCResponseStringWithEncoding()
   + makeXMLRPCFaultResponseStringWithEncoding()
   + makeFormattedXMLRPCCallStringWithEncoding()
   + makeFormattedXMLRPCCallStringArgsWithEncoding()
   + makeFormattedXMLRPCResponseStringWithEncoding()
   + makeFormattedXMLRPCFaultResponseStringWithEncoding()
*) added new HTTPClient methods for manipulating the TCP_NODELAY setting:
   + HTTPClient::setNoDelay()
   + HTTPClient::getNoDelay()
*) now the XmlRpcClient and JsonRpcClient constructors accept an optional
   second argument that, when True, will inhibit the immediate connection
   attempt on the socket and instead allow the socket connections to be either
   manually established or established on demand with the first request


*****************************
RELEASE NOTES for qore v0.7.3
*****************************

release summary: qore 0.7.3 contains minor feature improvements over 0.7.2 and
                 five bug fixes

*) Socket::connect() takes an optional timeout value
*) HTTPClient::constructor() options takes a new option: connect_timeout
   (usable with the XmlRpcClient and JsonRpcClient classes as well)
*) SOAP support updated in examples directory: SoapClient.qc, SoapHandler.qc,
   HTTPServer.qc, WSDL.qc
*) added is_writable() function as a correctly-spelled alias for
   is_writeable()
*) fixed and documented getcwd() function
*) added new functions parseXMLAsData() and parseXMLAsDataWithSchema()
*) BUG FIX: fixed a bug in the binary() function when converting binary
   strings to binary type when the strings had embedded nulls
*) BUG FIX: fixed a crashing bug in the handling of GLIBC gethostbyname_r()
   failures; contrary to the documentation, the return value is 0 even when
   the function fails
*) BUG FIX: fixed some erroneous builds on powerpc where processor-specific
   features were not built properly
*) BUG FIX: fixed a bug handling GLIBC gethostbyaddr_r() failures; contrary to
   the documentation, the return value is 0 even when the function fails
*) BUG FIX: fixed a bug doing math on negative units of relative dates;
   invalid dates would be returned


*****************************
RELEASE NOTES for qore v0.7.2
*****************************

release summary: qore 0.7.2 is a bugfix release from 0.7.1

* several bug fixes (including 8 crashing bugs), including packaging fixes
* support for timeouts in Socket::connect*() methods
* terminal attribute support, TermIOS class, new constants
* non-blocking read support for the File class
* event support for File class

------------------------------------------------------------------------------
* several bug fixes (including 8 crashing bugs), including packaging fixes
CRASH FIX: fixed a crashing bug in the map operator when the list operand is
           not a list

CRASH FIX: fixed a crashing bug in the parser with parse errors

CRASH FIX: fixed crash when pthread_create fails in thread.cc, thanks to
           Dmytro Milinevskyy for the info and patch

CRASH FIX: fixed a race condition with getAllThreadCallStacks() (only affected
       	   debugging builds)

CRASH FIX: fixed a bug where thread-local variables (as top-level local
           variables of a Program) were not being instantiated when another
	   Program called a function in a Program with such variables

CRASH FIX: fixed an issue where proper locking was not done to DBI drivers and
           more than one call could be issued to a connection at one time, 
	   causing crashes

CRASH FIX: fixed a crashing bug in the %= operator when the operand is 0

CRASH FIX: fixed a crashing bug in the map with select operator when the map
      	   expression is 0

fix to allow references to be used in closure and call reference calls

implemented an optimization to map to efficiently handle the case when no
return value is used

spec file fixes; 0.7.1 spec file was badly broken

fixed configure.ac to account for linkable libraries in /lib - would cause
configure to fail before

* support for timeouts in Socket::connect*() methods
added optional timeout parameters in ms to:
      Socket::connect()
      Socket::connectINET()
      Socket::connectSSL()
      Socket::connectINETSSL()

see updated documentation for details

* terminal attribute support, TermIOS class, new constants
new methods:
    File::setTerminalAttributes(action, TermIOS);
    File::getTerminalAttributes(TermIOS);

new class:
    TermIOS

* non-blocking read support for the File class
new method:
    File::isDataAvailable()

the following methods now take optional timeout values in milliseconds:
    File::read()
    File::readBinary()

* event support for File class
new method:
    File::setEventQueue()

new events:
    QORE_EVENT_OPEN_FILE
    QORE_EVENT_FILE_OPENED
    QORE_EVENT_DATA_READ
    QORE_EVENT_DATA_WRITTEN

new event source:
    SOURCE_FILE


*******************************
RELEASE SUMMARY for qore v0.7.1
*******************************

release summary: qore 0.7.1 is a bugfix release from 0.7.0

release overview:
*) bug fixes
*) new ABI 5.0, problems were found with ABI 4.0
*) packaging and build updated to support building universal binaries on
   Darwin
*) support for atomic operations in 64bit builds with itanium processors
*) support for stack guard including RSE monitoring in 64-bit builds on
   itanium processors
*) default module dir change, module handling updated
*) network event notification support
*) implemented the ability to specify qore, module, and feature version
   requirements
*) misc additions

------------------------------------------------------------------------------
*) bug fixes
a bug in the != operator for strings was fixed; != would return True for
strings with different encodings but otherwise equal content; this has been
fixed to return False

fixed a bug in QoreString::set()

fixed 2 crashing bugs in the "-" operator: the operator functions were
expecting certain arguments but the operator code was making partial matches
and sending other types to the functions.  Added the abilty for an operator
function to require an exact argument match for both arguments.

fixed evaluation of nonsensical arguments with the "-" and "+" operators; now
this will return NOTHING instead of nonsense.

fixed a crashing bug in the FtpClient class; the FtpClient class was not
usable in Qore 0.7.0

fixed a parsing bug with the switch statement when a case value using a
constant was not resolved caused a crash (affected debug builds only)

fixed parsing XML-RPC arrays when the first element is empty (would previously
generate an exception even though the XML was valid)

mostly fixed signal handling on Darwin, however for some reason it looks like
signal handling after a fork() on Leopard (OS/X 10.5, Darwin 9.5) is broken. I
haven't figured out why.

fixed a setting the URL in the HTTPClient class with only a path if a hostname
is already set

fixed a bug setting the URL in parseURL()

fixed a bug parsing the Content-Type in the HTTPClient class

fixed Queue::copy() to copy the elements in the original Queue instead of
returning an empty object

fixed the problem where exit() caused a random segmentation fault when other
threads were active by doing the following:
   +) all threads started with joinable status PTHREAD_CREATE_JOINABLE,
      threads call pthread_detach() before exiting
   +) implemented a new function, qore_exit_process() to be called instead of
      exit() that calls pthread_cancel() on each thread (except the calling
      thread) and then pthread_join() on that thread
   +) added a call to pthread_testcancel() in AbstractStatement::exec()

fixed a bug in an internal API in QoreHTTPClient where the wrong type was
passed

fixed bugs in JsonRpcClient and XmlRpcClient where a new connection was
established with each request

fixed a bug in the HTTPClient where a new connection was established for each
request even if the connection was already open and Keep-Alive was set

fixed socket handling on HPUX 64/bit builds where the header files declare
socklen_t to be 8 bytes wide, but the libraries expect a pointer to a 32-bit
value

fixed getAllThreadCallStacks() (only enabled with debugging builds and with
the explicit configure option: --enable-runtime-thread-stack-trace because it
has a performance penalty) by requiring all threads to grab a read lock
before updating the thread stack, and getAllThreadCallStacks() to grab a write
lock before reading all threads' call stacks.  This function was not
thread-safe before now.

SOAP improvements in example code in the examples/ directory:
     WSDL.qc, SoapHandler.qc, SoapClient.qc, HTTPServer.qc
soap 1.2 is handled better, namespace handling improvements

*) new ABI 5.0, problems were found with ABI 4.0
The 4.0 ABI was supposed to be fixed for a while; hopefully version 5.0 will
last a little longer :-)

The multi-byte character support was defective; it could lead to reading from
outside the buffer, so functions in QoreEncoding.h were updated.

Also it turns out that an array is not the same as a pointer to the array
type; and the array size of global objects is somehow part of the ABI.

Changing any of these arrays (including character arrays) caused ABI issues,
which was really a bad situation.

The following symbols are now pointers (all except the last are in Qore.h, the
last is in QoreProgram.h):

DLLEXPORT extern const char *qore_version_string;
DLLEXPORT extern const char *qore_target_os;
DLLEXPORT extern const char *qore_target_arch;
DLLEXPORT extern const char *qore_module_dir;
DLLEXPORT extern const char *qore_cplusplus_compiler;
DLLEXPORT extern const char *qore_cflags;
DLLEXPORT extern const char *qore_ldflags;
DLLEXPORT extern const char *qore_build_host;
DLLEXPORT extern const char **qore_warnings;

The old definitions were:
DLLEXPORT extern const char qore_version_string[];
DLLEXPORT extern const char qore_target_os[];
DLLEXPORT extern const char qore_target_arch[];
DLLEXPORT extern const char qore_module_dir[];
DLLEXPORT extern const char qore_cplusplus_compiler[];
DLLEXPORT extern const char qore_cflags[];
DLLEXPORT extern const char qore_ldflags[];
DLLEXPORT extern const char qore_build_host[];
DLLEXPORT extern const char *qore_warnings[];

Note that module API 0.4 (supported by qore 0.7.0) is not supported

*) packaging and build updated to support building universal binaries on
Darwin Qore header files and build were updated to support building Universal
binaries by using cpp macros to select the right inline assembly code or
defines for atomic operation and stack guard support in the macros-*.h header
files.

*) support for atomic operations in 64bit builds with itanium processors
supported with g++ and aCC, 64-bit builds only
Note that if you built qore 0.7.0 for 64bit itanium previously, the ABI now
will be completely incompatible with this version due to atomic operation
support, therefore all modules will have to be rebuilt with the new header
files.

*) support for stack guard including RSE monitoring in 64-bit builds on
   itanium processors
RSE = Register Stack Engine: the itanium has basically 2 stacks, a normal
stack and a register stack; qore now will throw an exception before either
stack will overflow.

*) default module dir change, module handling updated
the default module directory is $libdir/qore-modules; all modules should be
stored in this directory from now on.  Modules are also expected to append the
module api supported to the file name (i.e.: module-api-0.5.qmod).

Qore has been updated to support multiple module APIs; when loading a feature,
the corresponding module name will be searched with the module api tag in
descending order, if not found then the filename without a module api will be
searched.

*) network event notification support
you can now add an event queue (Queue object) to the Socket, HTTPClient,
FtpClient, XmlRpcClient, and JsonRpcClient classes.

Currently the Socket, HTTPClient, and FtpClient classes all post events to the
event queue, if one is set.

The events allow for more detailed reporting of the technical events occurring
during network operations that are abstracted to a relatively high level
through the previously-listed classes.

The events supported are:
  EVENT_PACKET_READ
  EVENT_PACKET_SENT
  EVENT_HTTP_CONTENT_LENGTH
  EVENT_HTTP_CHUNKED_START
  EVENT_HTTP_CHUNKED_END
  EVENT_HTTP_REDIRECT
  EVENT_CHANNEL_CLOSED
  EVENT_DELETED
  EVENT_FTP_SEND_MESSAGE
  EVENT_FTP_MESSAGE_RECEIVED
  EVENT_HOSTNAME_LOOKUP
  EVENT_HOSTNAME_RESOLVED
  EVENT_HTTP_SEND_MESSAGE
  EVENT_HTTP_MESSAGE_RECEIVED
  EVENT_HTTP_FOOTERS_RECEIVED
  EVENT_HTTP_CHUNKED_DATA_RECEIVED
  EVENT_HTTP_CHUNK_SIZE
  EVENT_CONNECTING
  EVENT_CONNECTED
  EVENT_START_SSL
  EVENT_SSL_ESTABLISHED

For most events posted to the event Queue, associated detailed information is
posted to the queue along with the event type a listed above; for example when
the EVENT_HTTP_CONTENT_LENGTH event is posted, the number of bytes given in the
content-length header is also posted.

See the Qore 0.7.1 documentation for more information; see examples/qget for an
example of a qore script using this new functionality (for example, run
examples/qget -v <url> to see all network events as a URL is retrieved).

*) implemented the ability to specify qore, module, and feature version
   requirements

you can now use:

  %requires <module> OP <version>

where OP is one of <, <=, =, >=, >

for example: 

  %requires oracle >= 1.0.1

also a special feature "qore" was implemented to give a requirement for the
qore library, for example: 

  %requires qore >= 0.7.1 

*) misc additions
added AF_UNIX and AF_LOCAL constants (which are actually interchangable)


*******************************
RELEASE SUMMARY for qore v0.7.0
*******************************

NOTE: modules are now delivered separately from the qore library, see the file
      README-MODULES for more information
NOTE: for platform-specific notes and build instructions, please see the file
      BUILD

qore 0.7.0 is a major release with major new features - please see compatibility
warnings beflow.

release overview:
*) COMPATIBILITY WARNING: local variables declared with "my" at the top-level
   are now global thread-local variables
*) COMPATIBILITY WARNING: qore command-line options changed, 3 seldomly-used
   short options removed
*) all modules are delivered separately now from the library, see README-MODULES
   for more information
*) stable ABI and API, cleaned-up public header files, development packages
*) library may be used under the GPL or LGPL (enforced with license tagging on
   library and module initialization)
*) documented public API (with doxygen), documentation packages
*) complete reimplementation of the type and operator subsystems
*) reimplemented variable and object locking, no more possibility of nested
   locks and deadlocks
*) major performance and memory usage improvements
*) support for closures and encapsulating the state of local variables in the
   closure
*) some (quasi) functional programming support: new operators: map, foldr, 
   foldl, select
*) new implicit argument references: $$ (entire argument list), $1, $2, ...
*) new special object method: "memberNotification()", called when members are
   updated externally to the class
*) "static" class methods are now supported
*) dereference string characters and binary bytes with [] operator
*) new qt-core, qt-gui, qt-opengl, qt-svg, opengl, glut, asn1, and xmlsec 
   modules (delivered separately, see the file README-MODULES for more 
   information)
*) bz2 compressed data support (compression and decompression)
*) file locking support in the File class (based on fcntl())
*) support for SHA224, SHA256, SHA384, and SHA512 digest algorithms
*) 64-bit builds are the default on x86_64 CPUs
*) module dependencies
*) XML improvements, some XSD support
*) thread stack overrun protection on some platforms
*) build option support and constants
*) initial SOAP support included as user code
*) lots of bug fixes, new functions, new clases, class improvements, etc

*) COMPATIBILITY WARNING: local variables declared with "my" at the top-level
   are now global thread-local variables
This can be considered a bug fix as Qore was updated to match documented
behavior.  However, in order to implement this, a new restriction was added to
declaring local variables at the top-level: they can only be declared in the
first parsing call in a Program object.  That is; if you try to declare a new
top-level local variable with "my" in a Program object that already contains
code, a parse exception will be raised.

*) COMPATIBILITY WARNING: qore command-line options changed, 3 seldomly-used
   short options removed
The following short options were removed: 
 -C: corresponding to "--no-class-defs"
 -J: corresponding to "--no-constant-defs"
 -X: corresponding to "--no-thread-classes" (this short option was reused for a
     new option: --eval=arg)

The respective long options are still available.

Some new command-line options were added:
 --module-dir
 --module-api
 -X, --eval=arg

Also the -V, --version output gives much more information about the qore build.

*) all modules are delivered separately now from the library, see README-MODULES
   for more information
due to the fact that Qore now has a stable and documented API, and that the
number of qore modules is growing, modules have been separated from the qore
library and are now delivered separately.  See the file README-MODULES for more
information.

*) stable ABI and API, cleaned-up public header files, development packages
Finally Qore is useful for what it was designed to be in the first place: for
embedding code in arbitrary applications.  

With a public, stable, and documented API, qore can be used by anyone that wants
to support logic embedding in their application.

Relevant classes exported by the Qore API now have private implementations,
separating the interface from the implementation.
"const correctness" has been liberally applied to the API as well.
Modules may now be packaged and delivered separately from Qore.

Development packages (rpms) are now available as well.

*) library may be used under the GPL or LGPL 
With this release, the qore library may be used under either the GPL or LGPL
licenses.  

When calling qore_init() to initialize the library, you have to pass a license
argument.

When the qore library is initialized with the LGPL license, no licenses tagged
as requiring the GPL license can be loaded.

*) documented public API (with doxygen), documentation packages
The Qore API documentation is generated with doxygen directly from the Qore
header files.

Documentation packages (rpms) are now available as well.

*) complete reimplementation of the type and operator subsystems
The internal type and operator subsystems have been streamlined and improved for
this release.

*) reimplemented variable and object locking, no more possibility of nested
   locks and deadlocks
Internal locking in Qore was simplified by eliminating nested locks and the
possibility of deadlocking based on internal locks.

*) major performance and memory usage improvements
Performance of Qore code has been significantly improved for this release.
Additionally, the qore library uses less memory than in previous versions.

*) support for closures and encapsulating the state of local variables in the
   closure
Closures are now supported, ex:

my $a = sub () { return $x + $y * 3; };

the local variable $a can be returned as a return value of a function or called
like a call reference.  If the closure references local variables from outside
the closure's scope, when the closure is created the values of those variables
are encapsulated in the closure and can be used normally.  Such encapsulated
local variables can also be used in other threads (normally Qore local variables
are local to the thread they are declared in).

*) some (quasi) functional programming support: new operators: map, foldr,
   foldl, select
These operators provide advanced and efficient list processing functionality to
Qore.

  +) map: "maps" an expression onto a list and returns a list of the results of
     evaluting the expression on each element of the list
  +) foldr and foldl: "fold" an expression on a list, evaluting each new element
     of the list with the result of the last evaluation and the new element
  +) select: creates a new list from a list

*) new implicit argument references: $$ (entire argument list), $1, $2, ...
Implicit arguments are used primary with the new list operators (map, foldr,
foldl, and select), but can also be used in functions now as well.

*) new special object method: "memberNotification()", called when members are
   updated externally to the class
Objects can now be notified if public members are modified from outside the
object's scope by declaring a new special method: "memberNotification()"

*) "static" class methods are now supported
Static class methods are not associated with an object; they are like regular
functions attached to a class.
Static methods may also be private.

This allows programmers to write more efficient object-oriented programs and
also addresses some Qore programmers' desire to put functions in namespaces
(functions cannot be declared in a Qore namespace).

*) dereference string characters and binary bytes with [] operator
To get a single character of a string, the [] operator may be used, similar to
how it's used with lists.
To get the value of a byte, the [] operator may be used as well.

Note that the [] operator when used in an lvalue expression will always convert
its argument to a list
(i.e. $string[1] = "a" or $binary[1] = 0x1f will not work yet - assuming $string
is a string and $binary is a binary)

*) new modules: qt-core, qt-gui, qt-opengl, qt-svg, opengl, glut, asn1, and 
   xmlsec
QT modules are based on QT4
all modules are now delivered separately from the qore library, see the file
README-MODULES for more information

*) bz2 compressed data support (compression and decompression)
libbz2 is now required to run qore, and bz2 includes are required to build qore
new functions provided: bzip2(), bunzip2_to_binary(), bunzip2_to_string() 

*) improvements to the File class 
file locking support in the File class (based on fcntl()), more
new File class members:
  +) File::lock()
  +) File::lockBlocking()
  +) File::getLockInfo()
  +) File::chown()

*) support for SHA224, SHA256, SHA384, and SHA512 digest algorithms
if Qore is built with an appropriate version of openssl, support for these new
digest algorithms is supplied through the following functions:
  +) SHA224()
  +) SHA224_bin()
  +) SHA256()
  +) SHA256_bin()
  +) SHA384()
  +) SHA384_bin()
  +) SHA512()
  +) SHA512_bin()

*) 64-bit builds are the default on x86_64 CPUs on Linux
the configure script will automatically set the build to a 64-bit target if the
CPU is detected to be x86_64 on Linux
note that on Solaris x86_64 you still have to manually add --enable-64bit to
configure

*) XML improvements, XSD support
  +) parseXMLWithSchema() - new function supports parsing an XML string based on
     an XSD schema
  +) improved XML generation, top-level elements may now have attributes
  +) improved XML parse error reporting, more details are included and context
     is now reported in the exception strings

*) thread stack overrun protection on some platforms
there is a new "stack guard" implementation that will cause an exception to be
thrown when a thread runs out of stack space (instead of crashing the entire
process, which is what happened previously).

The "stack guard" implementation simply determines the stack size for the thread
and then checks the stack pointer before each Qore statement is executed to see
if if passes a threshold.  

If the threshold has been breached, the statement is not executed and an
exception is raised instead.

See the new test in test/stack-test.q for an example.

Stack guard availability depends on the compiler and CPU used to build qore; so
far there are tested implementations on:
  + i386 (gcc, SunPro CC), x86_64 (gcc, SunPro CC), 32-bit powerpc (gcc), 
    32-bit sparc (gcc, SunPro CC), 32-bit pa-risc (gcc, HP aCC)

Other platforms will still crash when the thread's stack is overrun.

*) build option support
now qore has constants that will tell you which options are available in the
library.

Furthermore all functions are now available for parsing; but functions without
an implementation will throw an exception (in previous versions of qore parse
exceptions would be raised due to missing functions, which meant that it was not
possible to build portable programs that could optionally use these functions if
available).

You can check the option constants before running the function.
Optional functions are: 
  +) round()                                                   (depends on C library support, missing on Solaris 8 for example)
  +) timegm()                                                  (depends on C library support, missing on Solaris for example)
  +) setegid()                                                 (depends on C library support)
  +) seteuid()                                                 (depends on C library support)
  +) parseXMLWithSchema()                                      (depends on libxml2 support)
  +) all SHA224*(), SHA256*(), SHA384*(), SHA512*() functions  (depends on openssl support)
  +) all MDC2*() functions                                     (depends on openssl support)
  +) all RC5*() functions                                      (depends on openssl support)

The new constants are all in the Option namespaace:
  +) HAVE_ATOMIC_OPERATIONS
  +) HAVE_STACK_GUARD
  +) HAVE_RUNTIME_THREAD_STACK_TRACE
  +) HAVE_ROUND
  +) HAVE_TIMEGM
  +) HAVE_SETEUID
  +) HAVE_SETEGID
  +) HAVE_PARSEXMLWITHSCHEMA
  +) HAVE_SHA224
  +) HAVE_SHA256
  +) HAVE_SHA224
  +) HAVE_SHA256
  +) HAVE_SHA384
  +) HAVE_SHA512
  +) HAVE_SHA384
  +) HAVE_SHA512
  +) HAVE_MDC2
  +) HAVE_RC5

you can see what options qore has now by typing "qore -V" as well from the 
command-line.

*) initial SOAP support included as user code
see new files: examples/WSDL.qc examples/SoapClient.qc examples/SoapHandler.qc

*) bug fixes, new functions, class improvements
  +) Qore revision tag now reflects the svn version used to make the build
     (instead of a meaningless private build number that was different on each
     machine).
  +) new "Dir" class for manipulating and traversing directories (by Wolfgang 
     Ritzinger)
  +) inlist() and inlist_hard() functions for checking if a value is in a list
  +) HTTPClient now understand bzip content encoding
  +) new chown(), lchown(), call_builtin_function(),
     call_builtin_function_args(), force_encoding(), get_script_path(),
     get_script_name() functions
  +) parseURL() fixes and improvements
  +) new Program restrictions: PO_NO_TERMINAL_IO and PO_NO_GUI
  +) "-" operator updated: hash - list and hash -= list now work to delete
     multiple hash keys in a single (atomic) expression
  +) SSLCertificate::getPublicKey() now returns the public key in DER format
     (before it returned an unusable binary object(
  +) major updates to internal object and class code to allow for c++ class
     hierarchies to be properly reflected as Qore class hierarchies (used
     extensively by the qt modules, for example)
  +) qore -V now gives verbose information about the build and library options


**********************************************
RELEASE SUMMARY for qore v0.6.2.1 and v0.6.2.2
**********************************************

0.6.2.2 contains one additional bugfix from 0.6.2.1:
        * fixed an XML parsing bug with multiple out-of-order keys that could cause a crash

0.6.2.1 is a bug-fix release from 0.6.2.  The following bugs were fixed in 0.6.2.1:
        * fixed a bug where null values could be inserted into the parse tree with certain invalid expressions (causing a subsequent segfault)
        * fixed a bug in HTTPClient::head() where the message body was erroneously attempted to be read
        * fixed a thread resource tracking bug in the DatasourcePool class that could cause a crash
        * fixed a bug with implicit conversions from Qore type boolean to Qore type string (caused memory corruption)
        * fixed a bug in QoreString::parseBase64ToString() that set an invalid internal string length marker
        * added a "decode_url()" function to replace percent encodings in URL strings with the characters encoded
        * updated HTTPClient to automatically encode space characters in the path as %20


*******************************
RELEASE SUMMARY for qore v0.6.2
*******************************

RELEASE SUMMARY: major new features (see compatibility warnings below)
	*) 3 new DBI drivers, PostgreSQL, Sybase, and FreeTDS ("pgsql", "sybase", "mssql")
	*) more support for database and driver-independent programming
	*) new DatasourcePool class for transparent Datasource connection pooling
	*) HTTPClient improvements (redirections, basic authentication, proxy support)
	*) safe signal handling
	*) complete deadlock detection and thread primitive error handling
	*) all thread locking primitives now take an optional timeout value
	*) call references (including object method references that will be executed in the context of the object referenced)
 	*) mysql and oracle driver improvements
	*) extensive enhancements for exception-safe programming (on_exit, on_error, on_success statements, new classes, etc)
	*) significant performance improvements
	*) tibae module improvements
	*) many new functions and methods, bug fixes, extensive documentation updates, etc

RPM NOTES: the "tibae" module was removed from Linux i386 F7 binary packages because it requires g++-32; if you need this module; build it from source

*) ***COMPATIBILITY WARNING***: all timeouts changed to milliseconds
affects Condition::wait(), Datasource::setTransactionLockTimeout(), and Datasource::getTransactionLockTimeout()
the optional timeout value is no longer seconds, but milliseconds

This change will be transparent for code using relative times, i.e.:
	$cond.wait($mutex, 2s);

Otherwise for integers make sure and multiply any values representing seconds by 1000, i.e.:
	$cond.wait($mutex, 2 * 1000); # wait for 2 seconds

*) ***COMPATIBILITY WARNING**: Gate::enter() no longer takes a key argument, takes an optional timeout in ms instead
the key is always assumed to be the TID (thread ID); meaning that only one thread can hold the lock at one time; however it can be acquired recursively
Any integer passed to this method will be assumed to be a timeout value in milliseconds
with a timeout, if the return value is -1, then the Gate was not grabbed
The Gate class participates in the new Qore deadlock detection, more on this below.

*) ***COMPATIBILITY WARNING**: the RMutex class is deprecated, use the Gate class instead
Internally the RMutex class as of this release is a clone of the new implementation of the Gate class
The RMutex class will be removed in the next release of Qore

*) significant performance improvements
stack traces are now generated on-demand when an exception occurs, instead of constantly allocating heap objects in each thread for each call.
"argv" stacks and program stacks are now stored per-thread with no allocations (or locking).
thread resource tracking is now done with a lock-free, per thread mechanism (the global lock has been removed)
local variable usage was optimized, the number of memory allocations/deallocations has been reduced by more than 2 orders of magnitude, also memory space usage has improved

note that the stack trace optimization means the getAllThreadCallStacks() function does not return any useful value with non-debugging versions of qore.
Call stacks are still maintained with debugging versions of qore so this function can be used to generate a live stack trace of all active threads at any time (useful for finding deadlocks, etc).  The performance impact vs. the utility of maintaining constant stack traces led to the decision to include continuous thread stack tracking only in debugging versions of qore.

Due to the performance improvements in this release, this release of Qore faster than previous releases, even in the face of significant enhancements to the Qore execution engine (deadlock detection, timeout support, etc).

Average speed improvement compared to 0.6.1.* on most platforms is 20%, however on Solaris 10 (sparc and x86_64, but mostly on x86_64) the difference is incredible.
On Solaris 10, qore 0.6.2 executes qore code normally between 2x - 3x as fast as with qore 0.6.1* (probably due to using libumem on this platform).  
With heavily threaded code the speed improvement is smaller, but still noticeable.

*) "pgsql" module: PostgreSQL driver
the new "pgsql" driver uses efficient binary communication with PostgreSQL servers for binding and retrieving values from queries.
The driver supports the following features:
* all builtin PostgreSQL data types are supported
* multi-dimensional arrays are supported for binding and retrieving
* is thread-safe
* stored procedure execution is supported
* transaction management is supported
* transparent character encoding conversion is supported if necessary

The driver's name is "pgsql" and the Datasource type constant is SQL::DSPGSQL
ex: $db = new Datasource(DSPGSQL);
ex: $db = new Datasource("pgsql");

*) "sybase" module: Sybase driver
the new "sybase" driver uses Sybase' ct-lib to communicate with Sybase servers.

The driver's name is "sybase" and the Datasource type constant is SQL::DSSybase
ex: $db = new Datasource(DSSybase);
ex: $db = new Datasource("sybase");

features:
* all builtin Sybase data types are supported
* is thread-safe
* stored procedure execution is supported
* transaction management is supported
* transparent character encoding conversion is supported if necessary
* verbose error reporting in exceptions using client and server message information when available

This driver also provides a special format for returning multiple result sets and/or output parameters in a single statement.  See the qore documentation for more information.

*) "mssql" module: FreeTDS-based driver for connecting to Sybase and MS SQL Server databases
This driver is built from the same sources as the "sybase" driver, but compiled with FreeTDS (http://www.freetds.org).

The driver's name is "mssql" and the Datasource type constant is SQL::DSMSSQL
ex: $db = new Datasource(DSMSSQL);
ex: $db = new Datasource("mssql");

It supports the same features as the "sybase" driver, except the freetds.conf file is used for connection information (instead of Sybase' interfaces file).

The main difference between this driver and the Sybase driver is that it can connect to more types of databases (if they are properly configured in freetds.conf, also with the correct tds version level), and the UNICHAR and VARUNICHAR column types are not yet supported (have not yet been able to make them work).

*) new DatasourcePool class provides transparent Datasource connection pooling
Use the DatasourcePool class like the Datasource class; when you enter a transaction, a Datasource is automatically allocated to the thread, and released when the transaction is committed or rolled back.  
Allocated connections are tracked with Qore's thread resource tracking and failure to release a connection before a thread terminates will result in an exception being thrown and the connection being automatically returned to the pool.

Minimum and maximum number of connections can be set in the constructor; see the DatasourcePool class documentation for more information.

Note that this class is only useful for transaction management; autocommit cannot be enabled with this class (this is because the automatic connection allocation to a thread is made when the thread starts a transaction).

*) HTTPClient improvements
the HTTPClient class now supports redirections, basic authentication, and proxy support (and basic proxy authentication).
new methods in the HTTPClient class:

	HTTPClient::setURL() allows the URL to be changed (will disconnect if connected)
	HTTPClient::getURL() returns the current URL
	HTTPClient::setProxyURL() allows a proxy URL to be set or cleared
	HTTPClient::getProxyURL() returns the current proxy URL
	HTTPClient::clearProxyURL() clears the currenty proxy URL
	HTTPClient::setProxySecure() sets TLS/SSL mode for next proxy connection
	HTTPClient::isProxySecure() return TLS/SSL flag for proxy connection
	HTTPClient::setMaxRedirects() set the maximum number of redirections (default: 5)
	HTTPClient::getMaxRedirects() returns the current max redirects value 

The constructor understands a couple of new hash keys:
	"max_redirects" to set the max redirects value
	"proxy" to set the proxy URL

Since the XmlRpcClient and JsonRpcClient inherit HTTPClient, all improvements to the HTTPClient class are also available in the XmlRpcClient and JsonRpcClient classes as well.

*) call references (references to functions and object methods) implemented
a reference to a function or an object method can be made like this
	function reference:
	$cr = \function_name();

	object method reference:
	$cr = \$object_expression.method_name();

such references can then be executed like this:
$result = $fr($arg1, ...);

so function f() returning a call reference can be executed like this:
$result = f()($arg);

Note that no arguments must be given when the reference is created; the empty parentheses in call references serve to distinguish normal references from call references.

The following functions accept call references:
	sort()                 - for an optional callback function
	sortStable()           - for an optional callback function
	min()                  - for an optional callback function
	max()                  - for an optional callback function
	set_signal_handler()   - for the signal handler code

function references are resolved at parse time during stage 2 parsing (commit phase).
object method references are resolved at run-time.

This change also enables pure object-oriented programming, as functions formerly requiring a user function name can now accept a call reference which may be an object method reference.

*) support for safe signal handling in qore scripts
see the documentation for the set_signal_handler() and remove_signal_handler() functions

qore-language signal handlers are handled in a dedicated thread that's launched when the qore library is initialized.  special handling is included to support fork() properly.

*) run-time module loading
a new function "load_module()" can be used to load modules at run-time

*) no modules in the "auto" directory by default, DBI drivers loaded on demand
before the "mysql" and "oracle" drivers were in the "auto" subdirectory of the modules subdirectory (ex: /usr/lib/qore-<VER>/auto) meaning that they were loaded every time qore was executed.
Now all drivers are in the module directory and the auto subdirectory is empty.
However, an atomic, thread-safe mechanism is used to load DBI drivers on-demand - if the driver is not already loaded, then qore will attempt to load a module of the same name.  If no module can be loaded, then an exception is thrown, otherwise the code continues normally.
So now to load any database driver all you have to do is execute:
	$db = new Datasource("<driver name>",...);

there is no need to write
	%requires <dbi-driver> 
anymore. (however you may want to do this if your code requires the database driver, so that if it cannot be loaded at parse time, the user will see a meaningful parse exception and the code will not execute)

*) new "on_exit", "on_success", and "on_error" statements
allows exception-safe cleanup code to be placed right next to the code requiring the cleanup
	on_exit : queues code to be executed when the current block is exited (regardless of exceptions or return statements)
	on_success: queues code to be executed when the current block is exited, if there is no active exception
	on_error: queues code to be executed when the current block is exited, but only if there is an active exception

These statements provide a powerful mechanism for exception-safe or exception-dependent cleanup code
	example:

	{
	    $mutex.lock();
	    # the lock will be released when the block is exited
	    on_exit
		$mutex.unlock();

	    # ... do something
	    return 0;
	}

*) deadlock detection
All Qore threading primitives (including internal locks for global variables and "synchronized" methods, etc) now use the new deadlock detection framework.  Potential deadlocks are checked before any primitive would otherwise block.  If a deadlock is detected, a DEADLOCK-EXCEPTION is thrown.  

See test/deadlock.q for deadlock and thread error tests.

Deadlock detection affects:
* all qore threading classes
* "synchronized" functions and methods
* global variable accesses
* object accesses

Deadlock detection has been optimized with a fast algorithm and efficient data structures and is only executed when a thread would block.

Despite the new deadlock detection infrastructure and significantly enhanced threading primitives in this release, this release of qore is faster than any previous release on single and multi-processor systems, even with Qore code making extensive use of global variables, objects, "synchronized" code, and threading primitives.

*) thread locking methods take optional timeouts in ms
All thread locking methods take an optional timeout value in ms.  
This affects:
	Mutex::lock()
	Gate::enter()
	RWLock::writeLock()
	RWLock::readLock()
	Condition::wait()
	Counter::waitForZero()
	Queue::get()
	Queue::pop()

It's recommended to use a relative time value to make the units clear, i.e
	$m = new Mutex();
	if ($m.lock(250ms))
	{
	    # lock not grabbed due to timeout...
	}

*) threading errors cause exceptions to be thrown
Common thread errors, such as trying to lock a Mutex twice in the same thread without an intervening Mutex::unlock(), or trying to release a lock that is not held, will cause exceptions to be thrown as of this version of Qore.
Furthermore, locks are tracked as thread resources, and if a thread terminates without freeing the lock, an exception is thrown and the lock is freed automatically.

See test/deadlock.q for deadlock and thread error tests.

*) Oracle driver improvements
added support for the following types:
TIMESTAMP* types
INTERVAL* types
BINARY_FLOAT
BINARY_DOUBLE
UNSIGNED INT
RAW
LONG RAW

Qore date/time types are now bound as TIMESTAMP value to preseve milliseconds when possible (for both binding by value and binding by placeholder).  Milliseconds are preserved in all TIMESTAMP* and INTERVAL DAY TO SECOND types.

Timezone information is discarded when converting from Oracle types to Qore types, as Qore's date/time type does not yet support timezone information.

*) mysql driver improvements
added support for binary types (BLOBs, etc)
mapped DECIMAL type to a string to avoid losing precision
timed-out connections will be automatically reconnected if no transaction is in progress
column names always returned in lower-case

*) Datasource class now throws an exception if deleted while in a transaction

*) new classes for exception-safe lock handling
	AutoLock       (for Mutexes)
	AutoGate       (for Gates)
	AutoReadLock   (for RWLocks - grabs the read lock)
	AutoWriteLock  (for RWLocks - grabs the write lock)

to be used ONLY with local variables - they grab the lock when created and release when destroyed, i.e.

$m = new Mutex();
...
{
   my $al = new AutoLock($m);
   # ... some more code
   # when the block is exited (by a return, exception, etc) the lock will automatically be released
}

or
$g = new Gate();
...
{
   my $ag = new AutoGate($g);
   # ... some more code
   # when the block is exited (by a return, exception, etc) the gate will automatically be released
}
etc...

*) SQL strings accept '%d' placeholder for integer values
provides a mechanism to deal with DECIMAL (NUMERIC, NUMBER) columns in a database-independent way (substitutes 'null' for NULL or NOTHING, the integer text for anything else).
This ensures that values will be set properly even for databases such as PostgreSQL that do not convert from string or integer types to DECIMAL when binding bx value.

*) new functions
	- reverse()                - reverses strings and lists
	- set_signal_handler()     - sets or replaces a signal handler 
	- remove_signal_handler()  - removes a signal handler
	- load_module()            - loads a module at run time
	- regex_extract()          - extracts patterns from a string based on a regular expression given at run time
	- gethostbyaddr()          - returns the fully qualified hostname for the given network address
	- gethostbyaddr_long()     - returns a hash of all host information (all names, addresses, etc) for the given network address
	- gethostbyname()          - returns the first network address for the given host name
	- gethostbyname_long()     - returns a hash of all host information (all names, addresses, etc) for the given host name
	- trim()                   - removes characters from the front and end of a string, by default whitespace characters, accepts references

modified functions:
	- chomp()                  - was modified to accept variable references to chomp in place (as an alternative to the chomp operator) 

*) new File class methods for reading unsigned integer values and for handling 64-bit integers
	File::readu1()
	File::readu2()
	File::readu4()
	File::readi8()
	File::readu2LSB()
	File::readu4LSB()
	File::readi8LSB()
	File::writei8()
	File::writei8LSB()

*) new Socket class methods for receiving unsigned integer values
	Socket::recvu1()
	Socket::recvu2()
	Socket::recvu4()
	Socket::recvu2LSB()
	Socket::recvu4LSB()

*) tibae module improvements
the tibae module (TIBCO ActiveEnterprise/Adapters(TM) module) now can deal with interval, time, and binary types.  Milliseconds are now preserved with datetime and time when sending and receiving.

the tibae_type() function has been added to allow control over how types are serialized (useful with the "any" type or to override default serialization).
New constants have been added to the Tibae namespace for use with the tibae_type() function:
        TIBAE_BINARY
        TIBAE_BOOLEAN
        TIBAE_BYTE
        TIBAE_CHAR
        TIBAE_DATE
        TIBAE_DATETIME
        TIBAE_FIXED
        TIBAE_I1
        TIBAE_I2
        TIBAE_I4
        TIBAE_I8
        TIBAE_INTERVAL
        TIBAE_R4
        TIBAE_R8
        TIBAE_STRING
        TIBAE_TIME
        TIBAE_U1
        TIBAE_U2
        TIBAE_U4
        TIBAE_U8

*) fixed parser to accept variable declarations and list assignment
i.e.:
	my ($a, $b, $c) = split(",", $string); 
	our ($a, $b, $c) = $list;

are now legal...

*) the switch/case statement accepts regular expressions and regular expression operators in case expressions
i.e.:
	switch ($str)
	{
	    case /abc/:
	    case /^hello[1-9]*/:
	}

*) trim operator implemented
removes whitespace from the beginning and end of strings, string elements of lists, and string values in hashes, similar to the chomp operator

*) chomp modified to ignore arguments that are not a string, list, or hash
before it would throw an exception, which was unfriendly when run on NOTHING

*) += and -= operators updated to work more naturally when the lvalue is NOTHING
now += and -= use the right-hand-side's type when assigning to the lvalue if the lvalue is NOTHING, i.e. the following is now possible:

	my $str += "hello";                  # assigns "hello" to $str
	my $hash += ( "new-key" : "value" ); # assigns ( "new-key" : "value" ) to $hash
	my $float -= -4.5;                   # assigns -4.5 to $float

before this change $str and $hash would be = 0 and $float would be = -4.  This means that it's no longer necessary to assign a type to a variable before using the += and -= operators; they will behave more intuitively in these cases. 

*) "reference optimization" for temporary objects disabled on platforms where atomic reference operations are not available (Sparc, PA-RISC)
This optiimzation, designed to reduce the number of cache invalidations in SMP environments, leads to a race condition on platforms requiring a mutex lock for atomic reference operations.
It's possible for one thread to delete an object while another thread is holding the lock.  This can lead to memory corruption/segmentation faults on these platforms.
The fix was to disable the optimization if atomic reference operations are not supported (ie: without a mutex lock).

*) significant documentation updates
many more code examples added, including examples for all functions and classes in the main section (module docs not yet updated)
the Datasource class, DBI drivers, and encryption functionality were significantly expanded
many corrections were made

*) other bugfixes, updates, etc
see CHANGELOG for details


*******************************
RELEASE SUMMARY for qore v0.6.1
*******************************

this release is mostly a bug-fix release

*) bugs in HTTPClient class fixed
the Host: header is now set correctly; this bug prohibited connections form being made to HTTP 1.1 servers
path is set to "/" when otherwise empty
host number is set in the Host: field if not port 80

*) HTTPClient class improvements
chunked traqnsfer encoding accepted and correctly parsed
"deflate" and "gzip" content-encoding accepted and handled transparently

*) thread-resource tracking bugs fixed, particularly affecting the Datasource class
leaving uncomitted transactions open when the thread terminates would cause programs to crash in the previous version of qore

*) compression functions rewritten, gzip() and gunzip_to_string() and gunzip_to_binary() implemented
buffer sizes are automatically handled (and transparently resized internally if necessary); it's now possible to specify the string character encoding for *_to_string() functions

*) min() and max() functions implemented for lists
callback functions accepted to work on lists of complex dta types

*) unicode numeric character sequences decoded in HTTP contexts and in JSON strings

*) CDATA elements in XML strings are now handled correctly
CDATA elements are put in ^cdata^ hash keys when deserializing XML strings - no escape code processing is performed on this data
conversely, serialization to XML strings will handle ^cdata^ keys by creating CDATA elements

*) strtoint() function implemented, gmtime() and localtime() modified to return current time if no argument passed

*) other minor bugs fixed, see CHANGELOG for details


*******************************
RELEASE SUMMARY for qore v0.6.0
*******************************

*) major SMP performance increases
work was done to dramatically reduce the number of cache invalidations which results in a very significant performance increase (more than 2x for affected code paths) - this also affects single-threaded code running on SMP machines.  Basically due to these changes the CPUs are able to use their caches much more effectively, thus improving performance drastically.  This was done without sacrificing the clean threading model - from the qore user code/programming interface perspective no compatibility has been sacrificed; the language is simply faster.

Future releases will take this further and give even better performance increases.

*) stable shared-library interface, version 1.0
The qore library now exports a stable shared-library interface - this will be further improved in future release as internal implementation details of exported classes are further abstracted from the interface.

*) qore line-number reporting bug finally quashed
The bug where qore would report an incorrect line number with multi-line statements has finally been fixed - error messages now give the entire statement range where the error occured.  Furthermore parse error reporting has been further improved by making error messages more informative and readable.

*) internal JSON-RPC support
support for JSON-RPC has been added, including support for serializing and deserializing between qore data structures and JSON strings and a built-in JsonRpcClient class subclassed from the new HTTPClient class - see the 0.6.0 documentation for more details.

*) builtin HTTPClient, XmlRpcClient, and JsonRpcClient classes
the old qore-language HTTPClient and XmlRpcClient classes have been replaced with new high-performance internal versions.  The external API has been kept backwards-compatible as well.  The XmlRpcClient and JsonRpcClient classes are subclassed from the new HTTPClient class using qore's new support for builtin class hierarchies (in previous releases class hierarchies could only be implemented in qore code).

*) the switch/case statement accepts simple relational operators in case expressions

*) new functions: is_dir(), is_file(), is_executable(), is_readable(), is_dev(), etc
To verify file types easier

*) new single compilation unit build support, visibility tagging
g++ visibility tagging is used when possible allowing header files to clearly label API entry points as well as private interfaces.
Furthermore, when used with the default single compilation unit builds (where all files in a given directory are built together), the compiler can perform much better optimizations on the code.
Visibiility tagging also allows the symbol table size to be drastically reduced (particularly with templated objects) as symbols for private interfaces are not included in the shared library.

*) BEA Tuxedo (TM) module implemented
The full Tuxedo client API is available in qore if you have a licensed version of BEA Tuxedo installed, see the updated documentation for the "tuxedo" module

*) TIBCO synchronous client operation support added to "tibae" module
The "tibae" module added new methods to the TibcoAdapter class to support client-side synchronous operation calls

*) initial support for deadlock detection
Due to time constraints the deadlock solution was not universally applied to all user locks.  Complete deadlock detection (with qore threading primitives, including deadlocks with "synchronous" methods/functions) will be delivered in the next version of qore.
However some deadlocks are now detected and will cause an exception to be thrown and all locks of one thread to be released.

*) bug fixes, miscellaneous new functions, etc
see CHANGELOG and the updated qore 0.6.0 documentation for details


*******************************
RELEASE SUMMARY for qore v0.5.3
*******************************

* scanner and parser modified to accept direct specification of opaque binary objects using hexadecimal digits enclosed in angle brackets:
        ex: const bin = <a4b7297b>;

must be an even number of digits or a parse error will result

* new functions
  + hstat(), hlstat() - perform a "stat()" on a file/directory/etc and return a hash instead of a list - much easier to use output, including a "type" key, which gives the file type
  + makeHexString(), parseHexString() - to covert from a binary object to a hex string and vice versa

* performance improvements
temporary objects no longer cause a cache sync on deletion, use STL map when hash_map is not available, more use of STL map in other data structures for quicker lookups

* Solaris shared library fix
finally Solaris shared-library builds are working properly

* GetOpt class date parsing improvements
all Qore formats should also be parsable by the GetOpt class

* lots of bug fixes
deadlocks in several classes were fixed that happened after timeouts (Datasource, SingleExitGate classes)
bug in Datasource copy constructor
broken ncurses module fixed, initscr() is now optional


*******************************
RELEASE SUMMARY for qore v0.5.2
*******************************

*) ***CHANGE***: COMPATIBILITY WARNING: "tibco" module renamed "tibae"
the "tibco" module was renamed "tibae" to be consistent with the new "tibrv" module - see below
programs requiring the old "tibco" module should now use "%requires tibae"

*) ***CHANGE***: COMPATIBILITY WARNING: date/time handling changes
**WARNING**: int <-> date conversions are now done with 64-bit offset from Jan 1, 1970 00:00:00
previously int <-> date conversions were done with a not-very-useful direct conversion, like this:
  int(2006-01-01) => 20060101000000   (and vice-versa)

as of v0.5.2 integers converted to a date and dates converted to an integer will be based on the offset in seconds from January 1, 1970 (the UNIX epoch).   This is done with a 64-bit number so dates far in the past and future are supported.  Note that the date algorithms implement a "proleptic gregorian calendar"; that is; leap years are still calculated according to the Gregorian formula before the actual adoption of the Gregorian calendar in 1582 (in parts of Europe anyway), so date calculations before 1582 may not match with historical records (when the Julian calendar was used in Europe).

Date differences are now much easier to calculate, for example:
# calculate the number of seconds different between two dates:
$diff = int(2006-01-01) - int(2005-12-31);

this gives 86400 seconds = 1 day.  previsouly you had to use mktime() which would only work with 32-bit offsets, so dates far in the past or future would give erroneous answers.

While this could in theory introduce incompatibilies in qore scripts, I expect that it will not in practice.  The only time where this conversion was useful was for specifying dates, i.e.: $date = date(20060101000000), however this should be changed to the clearer format: $date = 2006-01-01 (or $date = 2006-01-01-00:00:00), or for the lazy, the string <-> date conversion logic remains unchanged, so this could still be written as: $date = date("20060101000000") (just add quotes around the integer dates);

**WARNING**: date/time arithmetic no longer takes daylight savings time into consideration
this is because the internal 64-bit algorithm is not time-zone/DST aware - the old algorithm used mktime().  If you need to do date arithmetic possibly over DST changes and it's important to take these changes into account, and your dates are within the UNIX epoch (before Jan 19 2038), then use qore's mktime() function instead.

**FIX**: subtracting one absolute date by another will now give a relative date giving the time difference, 
i.e.: $d = 2006-01-02 - 2006-01-01 = 1D
the resulting relative date is normalized to days, hours, minutes, seconds, and milliseconds (months and years are not of fixed length - the units below can be reliably interconverted)

Additionally, the scanner has been modified to only accept valid month, day, hour, minute, and second values (i.e. dates like 2006-13-45-34:78:89 will throw parse exceptions)

Other date changes (not expected to cause compatibility problems) are:
* millisecond subtraction fixed
* ISO 8601 date formats like 2006-01-01T10:00:00 are accepted (without the time zone component) as well as qore's format: 2006-01-01-10:00:00
* ISO 8601 relative date formats like P0001-02-01T01:01:01 are accepted (however qore's relative date format is arguably more readable)
* dates can be specified with an optional millisecond value, i.e.: 2006-01-01T10:00:00.502 for 502 seconds after Jan 1 2006 10:00 am
* relative milliseconds can be directly specified with <num>ms: i.e.: $date + 250ms;
* absolute dates printed with the %n or %N *printf format specification that include a millisecond value will be output with the millisecond value like "2006-01-01 10:00:00.502"
* relative dates printed with the %n or %N *printf format specification will take the following format: <time: x years x months x days x hours x minutes x seconds x milliseconds>
  units that are zero are not printed, unless all units are zero and then only <time: 0 seconds> is printed
* new date functions & support for calculating ISO-8601 calendar week information: getISOWeekHash(), getISOWeekString(), getDateFromISOWeek(), getDayNumber(), getDayOfWeek(), getISODayOfWeek(), get_years(), get_months(), get_days(), get_hours(), get_minutes(), get_seconds(), get_milliseconds()
* all qore functions and methods taking timeout values will now accept date/time values, i.e. Queue::pop(250ms) will timeout after 250 milliseconds.  If an absolute date is passed then the timeout value will be calculated based on the current date (this will probably be only rarely used).  The ability of these functions and methods to accept relative times is good for the programmer - if in doubt about the units, just use a relative time - i.e. Queue::pop(10s) will wait 10 seconds before timing out, however if a method or function expects larger units than those passed, passing smaller units will not magically make the timeout period respect a smaller time resolution (i.e. Datasource::setTransactionLockTimeout(90s + 500ms) will have the ms units truncated to give a value of 90 seconds)

*) New direct TIBCO Rendezvous support
Direct TIBCO Rendezvous sending and listening is now supported with the new "tibrv" module - as of this version it's now possible to build in tibrv support without tibae support (tibrv is also supported on OS X ppc and intel now as well)

To use the new TIBCO Rendezvous support use the "%use tibrv" directive to ensure that the functionality is loaded

Classes supplied by this module:
 + TibrvListener         - for listening to reliable messages
 + TibrvSender           - for sending reliable messages
 + TibrvCmListener       - for listening to certified messages
 + TibrvCmSender         - for sending certified messages
 + TibrvFtMember         - to implement a fault-tolerant node
 + TibrvFtMonitor        - to monitor a fault-tolerant group
 + TibrvDistributedQueue - to manage certified messages in a distributed queue

NOTE: we do not send native Rendezvous arrays - we use the old style "multiple fields with the same name" approach to have more flexible arrays (different datatype in each element, etc).   Native Tibrv arrays are decoded properly when received.

automatic type mapping:
  TIBRVMSG_BOOL <-> boolean
  TIBRVMSG_I8,U8,I16,U16,I32,U32,I64,U64 -> int (note there is a loss of precision with the U64 -> int conversion)
  int -> TIBRVMSG_I64
  TIBRVMSG_F32,F64 -> float
  float -> TIBRVMSG_F64
  TIBRVMSG_DATETIME <-> date
  TIBRVMSG_OPAQUE <-> binary
  TIBRVMSG_STRING -> string     (strings are marked with the default encoding for the object)
  string -> TIBRVMSG_STRING     (encoding conversions are made if necessary to the encoding set for the object)
  TIBRVMSG_XML -> string        (to explicitly send this type, use the tibrv_xml() function)
  TIBRVMSG_IPPORT16 -> int      (to explicitly send this type, use the tibrv_ipport16() function)
  TIBRVMSG_IPADDR32 -> string   (produces a string like "192.168.1.1" - to explicitly send this type, use the tibrv_ipaddr32() function)

to do explicit qore->tibrv type mapping, use the following helper functions supplied by the module:
  tibrv_i8()
  tibrv_u8()
  tibrv_i16()
  tibrv_u16()
  tibrv_i32()
  tibrv_u32()
  tibrv_i64()
  tibrv_u64()
  tibrv_f32()
  tibrv_f64()
  tibrv_ipport16()
  tibrv_ipaddr32()  - note: takes a string argument like "192.168.1.1"
  tibrv_xml()
  tibrv_bool()

set certificates for secure daemons using tibrvSetDaemonCert() and tibrvSetUserCertWithKey() using the SSLCertificate and SSLPrivateKey classes.  Note that these functions are only available if your tibrvcpp library was compiled with secure daemon support.  See BUILD for more information.

*) strong encryption and digest support
added SSLCertificate and SSLPrivateKey classes - the constructors for these classes expect a text file in PEM format defining the appropriate object.  Detailed information about the objects can be retrieved using member functions, see the updated qore v0.5.2 documentation for details.

Added new functions supporting strong cryptography:
 *** BLOWFISH 
   + blowfish_encrypt_cbc()
   + blocfish_decrypt_cbc()
   + blowfish_decrypt_cbc_to_string()
 *** DES and DESX (including multiple-key algorithms)
   + des_encrypt_cbc()
   + des_decrypt_cbc()
   + des_decrypt_cbc_to_string()
   + des_ede_encrypt_cbc()
   + des_ede_decrypt_cbc()
   + des_ede_decrypt_cbc_to_string()
   + des_ede3_encrypt_cbc()
   + des_ede3_decrypt_cbc()
   + des_ede3_decrypt_cbc_to_string()
   + desx_encrypt_cbc()
   + desx_decrypt_cbc()
   + desx_decrypt_cbc_to_string()
 *** RC4
   + rc4_encrypt()
   + rc4_decrypt()
   + rc4_decrypt_to_string()
 *** RC2
   + rc2_encrypt_cbc()
   + rc2_decrypt_cbc()
   + rc2_decrypt_cbc_to_string()
 *** CAST5
   + cast5_encrypt_cbc()
   + cast5_decrypt_cbc()
   + cast5_decrypt_cbc_to_string()
 *** RC5
   + rc5_encrypt_cbc()
   + rc5_decrypt_cbc()
   + rc5_decrypt_cbc_to_string()

added digest functions: MD2(), MD4(), MD5(), SHA(), SHA1(), DSS(), DSS1(), RIPEMD160(), MDC2()

NOTE: when the digest functions are run on strings, the trailing null character is not included in the digest calculation.  however, when the cryptographic functions are run on strings, the trailing null is included, so that strings can be decrypted with the trailing null.

*) new Socket methods supporting TLS/SSL communication with strong encryption
making or accepting TLS/SSL connections is nearly transparent with the new Socket class changes.  Instead of Socket::connect() you would use Socket::connectSSL().  Instead of Socket::accept() you use Socket::acceptSSL() (requires setting a certificate and private key using the SSLCertificate and SSLPrivateKey classes and the Socket::setCertificate() and Socket::setPrivateKey() classes)

Once a TLS/SSL connection has been established on a socket, subsequent reads and writes using the standard Socket methods will be done using the equivalent SSL functions in a manner transparent to the programmer.

new methods:
  + Socket::connectSSL()              - makes a TLS/ SSL connection to a remote socket
  + Socket::acceptSSL()               - accepts a connection on a socket and negotiates a TLS/SSL session
  + Socket::shutdownSSL()             - shuts down an active TLS/SSH session by sending the "close notify" shutdown alert to the peer
  + Socket::setCertificate()          - associates a certificate with a socket
  + Socket::setPrivateKey()           - associates a private key with a socket
  + Socket::verifyPeerCertificate()   - returns a verification code describing the state of the peer's certificate
  + Socket::isSecure()                - returns True if a secure connection has been established
  + Socket::isOpen()                  - returns True if the socket is open
  + Socket::getSSLCipherName()        - returns the name of the encryption algorithm for secure connection
  + Socket::getSSLCipherVersion()     - returns the version of the encryption algorithm for secure connection

*) the FtpClient class has been modified to support the ftps protocol according to RFC-4217
a RFC-4217 compliant secure connection will be made if the protocol in the URL is set to "ftps" or if the setSecure() method is called before connect()

new FtpClient methods:
  + FtpClient::setSecure()                - will try to make an RFC-4217 compliant secure control and data connections to the server
  + FtpClient::setInsecure()              - will try to make unencrypted connections to the server
  + FtpClient::setInsecureData()          - will try to make unencrypted data connections to the server even if the control connection is secure
  + FtpClient::isSecure()                 - returns True if a secure control connection has been established
  + FtpClient::isDataSecure()             - returns True if the data connection is secure
  + FtpClient::getSSLCipherName()         - returns the name of the encryption algorithm for ftps connections
  + FtpClient::getSSLCipherVersion()      - returns the version of the encryption algorithm for ftps connections
  + FtpClient::verifyPeerCertificate()    - verifies the peer's certificate for ftps connections
  + FtpClient::setModeAuto()              - sets the object to automatically try EPSV, PASV, and PORT for the data connection
  + FtpClient::setModeEPSV()              - sets the object to only try EPSV mode for the data connection
  + FtpClient::setModePASV()              - sets the object to only try PASV mode for the data connection
  + FtpClient::setModePORT()              - sets the object to only try PORT mode for the data connection

*) "oracle" driver improvements
the select() and selectRows() methods both support binding data directly in queries with the same syntax as with exec()
for example:
my $result = $oradb.select("select * from table where value = %v", $value);

*) "mysql" driver improvements
The "mysql" module now supports directly binding data and retrieving values from queries in the qore DBI syntax (already supported by the "oracle" module) - also the select() and selectRows() DBI methods support value binding as well
for example, using the test database as given in examples/mysql-test-db.sql and the following stored procedure:
delimiter //
create procedure get_family (in id int, out fname varchar(32))
begin
   select name into fname from family where family_id = id;
end;
//

executing:
$h = $mysqldb.exec("call get_family(%v, :name)", 1);

will return ( "name" : "Smith" )

*) improved XML serialization and deserialization
mixed elements and text can now be serialized and deserialized without data loss (except whitespace is still not retained) - for example, now it's possible to deserialize (parse) a docbook xml file and then reserialize it (generate the XML from the Qore data structure) without losing information (this was not possible with previous versions of qore).

*) 64-bit build support on x86_64 (AMD64, etc)
native 64-bit binaries can now be built on Linux x86_64 - the build system has been modified to be able to correctly find paths and set directory names for 64-bit libraries if the --enable-64bit configure option is used.  By default 64-bit builds are made on x86_64 CPUs unless the --disable-64bit option is passed to the configure script

*) %requires error reporting improved
if any requested features cannot be loaded, then only exceptions related to missing features will be reported.  this avoids possibly hundreds (or more) exceptions in large programs where features cannot be loaded (i.e. unresolved classes, functions, etc)

*) new warning framework
enable warnings from the command-line with "-W" or from qore code with the new parse directives: %enable-all-warnings and %enable-warning <warn>.  Disable warnings from qore code with %disable-warning <warn>
initial warnings are: 
   duplicate-local-vars
   warning-mask-unchanged
   unknown-warning
   undeclared-var
   duplicate-global-vars
   unreachable-code

Other new command-line flags related to warnings: -r: treat warnings as errors, -A: lock warnings
The %lock-warnings parse directive and the PO_LOCK_WARNINGS parse option were implemented in order to ensure that warning levels can't be changed when this option is set

*) parse restrictions enforced for classes
all classes tagged with capabilities and the capabilities are checked against the parse options when the new operator is parsed and when inherited classes are declared
new parse restrictions: PO_NO_DATABASE (parse directive: %no-database), PO_NO_THREAD_CONTROL (%no-thread-control), PO_NO_THREAD_CLASSES (%no-thread-classes)
note that PO_NO_THREADS is now equivalent to PO_NO_THREAD_CONTROL | PO_NO_THREAD_CLASSES

*) internal qore class API significantly simplified and streamlined
it is now much easier to develop qore classes in c++ with the new API

*) lots of bug fixes, etc
see CHANGELOG for details


*******************************
RELEASE SUMMARY for qore v0.5.1
*******************************
*) PCRE (Perl-Compatible Regular Expression) support added
All regular expression operations in Qore are now performed using the PCRE library, meaning that regular expressions in Qore should be much more perl compatible and finally consistent on all platforms.
new flags for matching and substitution:
	/i = ignore case
	/s = makes a dot (.) match a newline character
	/x = extended matching
	/m = multiline matching

Subpattern backreference substitutions are now supported, i.e.:
	$str = "abc def";
	$str =~ s/(\w+) +(\w+)/$2, $1/;
	# now $str = "def, abc"

Regular expressions are now parsed one time at parse time (in previous versions of Qore using POSIX regular expression support, the regular expressions were parsed every time they were executed which was very inefficient).

*) UTF-8 multi-byte character support fixed - character offsets now used instead of byte offsets for multi-byte strings
Qore now assumes character offsets instead of byte offsets for multi-byte characters in: substr(), splice operator with strings, index(), rindex(), length()
NOTE: length() and strlen() will now return different values for strings with multi-byte characters.
The ord() function still accepts only byte offsets and returns single-byte values.

*) transliteration operator implemented, i.e.:
	$str =~ tr/abc/123/;
        $str =~ tr/a-z/A-Z/;
note that this operator is not yet multi-byte charset aware for range specifications

*) support for non-threading build of qore removed
had been broken for a long time anyway.  from now on optimizations will be concentrated on the single multi-threaded version of qore

*) rindex() semantics fixed
The optional offset value works like perl's rindex offset - if present, it specifies the character offset from which the reverse search will begin - starting at that character to the beginning of the string.

*) bindex() and brindex() functions added
give byte offsets into strings when a match is found.

*) new function "regex_subst()" added
allows regular expression substitution to be performed with patterns potentially generated at run-time

*) new constants added for regex() and regex_subst()
	RE_Caseless  - sets caseless matching
	RE_DotAll    - makes a dot (.) match a newline character
	RE_Extended  - extended matching
	RE_MultiLine - enables multiline matching

*) libz-based compression function support added
compress(), compress2(), uncompress_to_string(), and uncompress_to_binary() functions added to allow for compressing and uncompressing data

*) the "elements" operator modified to work on binary and string types
returns the number of bytes in a binary object
returns the number of characters in a string

*) the "-" and "-=" operators updated to delete keys from hashes
ex: $hash - "string" or $hash -= "string"
will remove the key "string" from the hash if it exists.  note that this will only dereference the value at that key, so if the value is an object and this is not the last reference to the object, the object will not be deleted.

* implemented "instanceof" operator
like Java's operator of the same name

*) implemented %= (modula-equals), *= (multiply-equals), /= (divide-equals), ^= (xor-equals), <<= (shift-left-equals), and >>= (shift-right-equals) operators

*) fixed bugs in the |=, &=, +=, and -= operators
the precision was artificially restricted to 32 bits

*) "shift" and "unshift" can now be used as function and method names

*) Oracle driver fixed to not throw parse exceptions when the ":" character is not followed by an alphabetic character
so ":=" is legal in SQL statements again :-)

*) added VARCHAR, CLOB, BLOB, DATE constants
to be used in Datasource::exec() and Datasource::vexec() calls to specify placeholder buffer types.

*) modified Oracle driver to accept an integer as a placeholder bind argument
To be used as an easy way to specify the length of a string buffer to bind - otherwise the maximum length is set by default to 512 bytes, which will cause a run-time exception to be thrown if a longer string is attempted to be bound to the buffer.

*) optional timeout values in ms implemented for Queue::pop() and Queue::get() methods

*) copy-on-write implemented for class definitions in subprograms
performance & memory efficiency improvement when creating subprograms (Program objects)

*) module subsystem enhacements
any program can use "%requires" at any time.

*) bug fixes and other miscellaneous enhancements
see CHANGELOG for details


*******************************
RELEASE SUMMARY for qore v0.5.0
*******************************
*) the release documentation has been greatly improved with this release; all Qore features, functions, classes are documented, see the qore.html file included with the release, or http://qore.sourceforge.net/?manual=1

*) deprecated "file" type removed, use the File class instead
the following functions have been removed, use File methods instead:
	fprint()        File::print()
	fprintf()       File::printf()
	f_fprintf()     File::f_printf()
	vfprintf()      File::vprintf()
	create_file()   File::open("name", O_CREAT | O_WRONLY)
	close_file()    File::close()
	open()          File::open()
	close()         File::close()
	readline()      File::readLine()
	fflush()        File::sync()
	eof()           N/A: test read return values

the following global variables have been removed:
	$STDERR, $STDOUT

the following constants have been implemented to replace them:
	stdout, stdin, stderr   - all objects of type File

the following new methods have been implemented in the File class:
	File::vprintf()
	File::f_printf()
	File::f_vprintf()

*) exception handling semantics changed and "rethrow" statement implemented
as of this release, catch blocks may only declare one parameter which will receive the exception hash.  user information is stored in the err, desc, and arg keys.  if a list is thrown, the elements of the list will be assigned to the new "err", "desc", and "arg" keys of the exception hash.  any type of value(s) can be thrown, but lists are mapped as described above.  If a list longer than 3 elements is thrown, then elements 2 - the remainder of the list are mapped to a new list assigned to the "arg" key of the exception hash.  If only one argument is thrown, it is mapped to the "err" key of the exception hash.
If no parameter is declared in the catch block then the exception information cannot be accessed in the catch block (however it can be rethrown, see the "rethrow" statement below).
The automatic $argv variable is no longer assigned in catch blocks.
The exception hash is otherwise the same as before.
System exceptions always populate the err and desc keys, and never the arg key.
    old syntax:
	try {
	    throw "ERROR", "description", new Info();
	}
	catch ($ex, $err, $desc, $arg)
	{
	    printf("exception at %s:%f: %s: %s (arg=%N)", $ex.file, $ex.line, $err, $desc, $arg);
	}

    new syntax:
	try {
	    throw "ERROR", "description", new Info();
	}
	catch ($ex)
	{
	    printf("exception at %s:%f: %s: %s (arg=%N)", $ex.file, $ex.line, $ex.err, $ex.desc, $ex.arg);
	}

the "rethrow" statement (taking no arguments) was implemented and can only be used in a catch block.  This statement will cause the current exception to be rethrown, and an entry is added on the call stack tagged as a rethrow entry (i.e.: $ex.type == "rethrow").  
This allows programs to maintain a coherent call stack even when exceptions are handled with one or more catch blocks.

*) Socket class method changes - consistent error handling for all Socket methods
socket errors will throw exceptions, when a read or write is attempted on a closed socket.  for example, if the other side closes the connection: a SOCKET-CLOSED exception is thrown, for socket read errors a SOCKET-RECV-ERROR exception is thrown.
Timeouts cause NOTHING to be returned.
These changes were made because some methods (like Socket::readi4() for example) could return a -1 value as a legitimate read - to make socket handling consistent across all qore Socket methods.
This will requre changes in almost all socket code in qore - I apologize for the inconvenience, but the changes were necessary to have a consistent socket API and to allow all socket methods to handle communications errors (previously it was not possible to catch errors in the Socket::readi*() methods, for example).

*) Module optimizations and reorganization
The XML module has been merged into qore: qore can no longer be built without libxml2 support.
The FtpClient module has also been merged into qore - there are no particular dependencies on this class anyway to justify it being a module.
Qore modules now need to declare their API conformity level and will be explicitly initialized.
Note that older qore modules used an OS-level mechanism for automatically initializing themselves, and, since the internal API is not yet clever enough to detect duplicate internal symbols, the older qore modules will register themselves with the qore runtime engine, which, in the case of the FtpClient and XML modules, can cause core dumps or other errors when the duplicate symbols are referenced.  Therefore older qore modules cannot be used with this version of qore.
The default module directory has been changed to pgklibdir-version, meaning that, if your --prefix=/usr, the module directory will now be /usr/lib/qore-0.5.0
Modules installed in the "auto" subdirectory of the module directory (and any modules in the directories listed in the QORE_AUTO_MODULE_DIR environment variable) will be automatically loaded when qore starts, before any parsing begins.
Other modules (in the root module directory) must be loaded with the %requires directive (see next point)

*) %requires directive for explicitly listing qore feature requirements
the "%requires" directive will attempt to load a module of the same name if the named feature is not already present in qore.
Modules are searched in the directories in colon-separated order listed in the QORE_MODULE_DIR environment variable and then in the pgklibdir-version (/usr/lib/qore-0.5.0 in the example above) directory.
Modules must have the same file name as the object of the "%requires" directive and must have the extension ".qmod"
The following modules must be explicitly loaded with %requires in a shared build of qore:
	tibco
	ncurses (still experimental)

*) Oracle driver enhancements
there is a new DB-independent Datasource::exec() syntax (although so far only the Oracle driver has been modified to support it).  In Oracle *LOB columns are supported for binding and passing values through ::exec().  The syntax is somewhat similar to *printf() except %v is used for all value types:
For example, to bind values in a generic SQL statement:
$ds.exec("insert into table values ( %v, %v, %v, %v, %v, %v )", binary($data), "string", 12345, True, now(), 1.43);
for Oracle, values are bound as follows:
	Type::Binary   = SQLT_BIN  (can be a BLOB for example)
	Type::String   = SQLT_STR
	Type::Integer  = SQLT_INT or SQLT_STR  (int > 32-bits = SQLT_STR, <= 32-bit int = SQLT_INT)
	Type::Boolean  = SQLT_INT  (1 or 0)
	Type::Float    = SQLT_FLT
	Type::Date     = SQLT_DAT

attempts to bind other types will result in a run-time exception.

To retrieve values from a stored procedure or function, you must specify placeholder with a syntax more similar to Oracle's as follows:
$hash = $ds.exec(begin stored_procedure_name('Literal String', :param1, :param2, param3); end;");

The placeholders are the :param* elements in the string, and will correspond to the keys in the result hash (without the leading ':' character).  If no types are defined by arguments following the string, then they default to strings with a maximum length of 512 bytes.  To retrieve other types or longer string values using placeholders, you have to include arguments after the string, one argument for each placeholder.  The arguments should be the data type for the bind as follows:
	Type::Binary  = BLOB
	"clob"        = CLOB
	Type::String  = SQLT_STR
	Type::Integer = SQLT_INT  (returns a 32 bit integer)
	Type::Float   = SQLT_FLT
	Type::Date    = SQLT_DAT
	Type::Hash    = SQLT_RSET (for result sets, stored procs that return cursors, etc)

This new syntax is meant to be driver-independent, so, for example, when the MySQL driver is updated to take advantage of MySQL 5.0 features like stored procedure execution, support for this syntax will be implemented as well.

*) splice, push, and pop list operators implemented
do not use parentheses directly after the operator keywords, if you do, qore will assume you want to call a function of the same name.
Generally this is another point where qore differs philosophically from perl.  In qore, operators can change lvalues directly, but functions must be explicitly passed references to change lvalues.
qore's splice operator works like perl's splice function
    i.e.: $l = (1, 2, 3);

    INCORRECT usage of the splice operator:
	splice($l, 1, 1);   # <- WRONG! this will try to call qore function "splice()", which can never change the value of $l in qore

    CORRECT example:
	splice $l, 1, 1;    # RIGHT! now $l = (1, 3) 

The same is true of the push and pop operators.  splice, push, and pop are all special keywords in qore in that they can also be used as function and method names.  The qore parser determines if you want to use the operator by checking if these special keywords are followed by an open parenthesis.  If so, then qore assumes you want to execute a function of the same name.

qore's push operator will add one element to the end of a list - to concatenate lists in qore use the + operator.  Note that this differs from perl's "push" function.
qore's pop operator removes the last element from a list and returns that element (i.e. it works like perl's pop function)

Note that all three operators (like all qore operators) perform thread-atomic operations - no explicit locking is needed in multithreaded programs to guarantee the atomicity of these operations.
Note also that the splice operator in qore works on strings as well as lists.

*) internal Gate class replaced with a more efficient RMutex class
the RMutex class is based on a recursive pthread lock; as this is the locking element most often used in Qore to ensure atomicity and thread-safety, this change should bring about a performance increase overall for Qore programs (even single-threaded ones)

*) ncurses classes
Some ncurses functions and classes (Window and Panel) have been added.  See examples in test/ncurses.q, examples/hanoi.q, examples/worm.q.  Note that threading is enabled but still highly experimental with qore ncurses programs.
Use "%requires ncurses" in qore programs that would like to use ncurses functionality.
This module is still experimental.

*) private inheritance has been implemented
ex: class MyClass inherits private Mutex;

With private inheritance methods of the parent classes can only be executed from within the class.  Any attempt to execute a method of a privately inherited class from outside the class will result in a run-time exception.  However the inheriting class has no restrictions on accessing members or methods of parent classes - private inheritance only affects access of instantiated objects from outside the class.

*) Datasource::selectRows() implemented returning a list of hashes
sometimes it's more convenient to work with a list of hashes, rather than the hash of lists as returned by the Datasource::select() method.  The Oracle and MySQL drivers have been updated with support for this new DBI method (however it's not implemented for old versions of MySQL without the prepared statement interface)

*) Datasource::vexec() implemented to allow a variable-length list of arguments to be passed

*) parseXMLRPCResponse(), parseXMLRPCCall(), and parseXMLRPCValue() implemented as native functions
now XML-RPC support is much better integrated in qore (and much faster).  The old user functions in examples/xmlrpc.ql have been removed.

*) HTTPServer.qc and HTTPClient.qc updated to perform HTTP 1.1 compliant connection handling
Now the HTTPServer class is a little closer to being actually HTTP 1.1 compliant :-)

*) build system updated to delete binary versions of modules
it's no longer required to include --disable-static in the configure command-line to keep useless static versions of qore modules from being built (however if you don't need the static library, the build should be about twice as fast with --disable-static)

*) added Socket::shutdown() method

*) added a Queue::pop() method so the Queue class can be used as a blocking and thread-safe stack

*) MySQL driver fixed to use the more efficient prepared statement interface when available
there was a bug in the driver causing it to always use the older character-based interface even when the prepared statement interface was available; this has been fixed

*) the SQL subsystem is no longer optional
DBI drivers are still optionally-compiled, but it will no longer be possible to build qore without SQL infrastructure support

*) other new functions, methods, backwards-compatible changes to existing methods, and lots of bug fixes
see CHANGELOG for details


*******************************
RELEASE SUMMARY for qore v0.4.3
*******************************
*) XML parsing and generation bugs fixed along with some memory leaks plugged...

*) *_thread_data() functions no longer accessible in programs with the PO_NO_THREADS option enabled

*) many run-time class inheritance fixes

*) Socket class bug fixes for server processes

*) Type::* constant values are now strings instead of unpredictable integers

*) HP-UX build fixes
still not 100% out-of-the-box supported, but coming soon...

*) core dump, memory leaks, Oracle stored proc execution fixes, and many other changes and fixes
for details see the CHANGELOG


*******************************
RELEASE SUMMARY for qore v0.4.2 
*******************************

*) objects and references
objects are always passed by reference now - like Java.  They are only copied if the special ::copy() method is explicitly executed, and the class supports copying.  This change was necessary to facilitate pure Object-Oriented programming.  The ::copy() method exists for every object as a system method, but can be overridden - to prevent an object from being copied, define a copy() method and throw an exception in it...

*) class inheritance
multiple class inheritance is supported; the basic syntax is:

	class [namespaces::...]class_name inherits [namespaces::...]class_1[, class 2 ...];

You can also give explicit arguments to base class constructors with a C++-like syntax, and you can override base class constructor arguments in subclasses withthe same syntax if desired.  see examples/inherit.q for more information.   Also see examples/XmlRpcClient.qc for another, more practical, example - the XmlRpcClient class is now a child of the HTTPClient client and gives explicit arguments to the HTTPClient constructor...

*) private class member support
references to private class members outside the class will cause an exception to be thrown.  declare like this (only in in-line class declarations):
	private $.mem_1[, $.mem_2 ...];

*) *LOB support in Datasource::select() in the Oracle driver
the 128K limit for CLOBs is now gone and BLOBs will now be selected as binary objects.  However I have found what I believe is a bug in Oracle 9i where even if you are trying to stream CLOB data you have to allocate a buffer bigger than the CLOB you are trying to stream or you will get an "ORA-24812: character set conversion to or from UCS2 failed" error (I saw this on Saolaris with a 9i client and 9i server), to change the buffer size in modules/oracle/oracle.h with the LOB_BLOCK_SIZE define (currently it's set at 32K as a compromise - not ideal for working streaming like with 10g, but medium large for the broken versions...)

*) internal GetOpt class support
works the same as the old GetOpt user class delivered in the examples directory, see the new examples/getopt.q script for more information

*) new command-line options
--exec-class (-x), taking an optional class name argument, will instantiate the class with the same same as the Qore script (override by giving an argument).  This option also turns on --no-top-level.  To be used for more pure OO programming.

*) much improved reference support
References are not quite universally supported, but getting closer; now recursive local variable reference expressions are supported as well as references to object members (i.e.: do_something(\$.var_name)) - these are now also properly supported in background expressions.

*) XML generation improvements, bug fixes
Generating formatted XML will give better-formatted XML, also empty elements will be output in the recommended short form (<node/> rather than <node></node>)

*) binary integer support in the Socket class
Socket::sendi1(), ::sendi2(), and ::sendi4() (and associated ::readi*() methods) have been implemented; they respect network byte order.

*) deprecated socket_* functions removed
use the Socket class instead...

* many miscellaneous bug fixes
see CHANGELOG for details


*******************************
RELEASE SUMMARY for qore v0.4.0
*******************************

*) mysql driver substantially updated  
It now supports threading, proper character set handling, transactions, and uses the more efficient prepared statement interface.

*) C/C++-style switch/case statement implemented
by popular demand :-).  The syntax is the same as the C/C++ statement of the same name, except that case values can be any expression non requiring run-time evaluation (any expression you can assign to a constant can be used as a case expression).

*) list assignment implemented
ex: ($a, $b, $c) = (1, 2, 3); 
does what you would expect.  Lists assignments in qore work (as far as I could tell by my testing) just like list assignments in perl.  The lvalues on the left-hand side of the assignment can be any valid lvalue expression.

*) "our" and "my" accept lists, "our" can appear anywhere
it's now possible to declare lists of local and global variables by putting a list of variables after "my" or "our", like:
my ($a, $b, $c);
our ($a, $b, $c);

*) elements in "foreach" can modify the list argument by using a reference
ex: 
--
$l = (1, 2);
foreach my $e in (\$l)
   $e = sprintf("str-%d", $e);
-- 
afterwards $l will be ("str-1", "str-2");

*) new command-line options "-e" (--exec) and "-m" (--show-module-errors)
-e allows a qore program to be given on the command line, and -m can be used to see if there are errors loading qore modules

*) empty programs do not throw a parse error

*) system() does a fork() and exec() if no shell meta-characters are present
means more efficent system() execution

*) imported functions can be exported to subprogram objects

*) new File::printf() and Socket::isDataAvailable() methods

*) Socket::recv*() methods accept negative or extremely large arguments safely

*) Socket::recv*() methods accept an optional timeout value in milliseconds after the buffer argument
With this change it's possible to do non-blocking I/O with Qore sockets

*) Socket::bind() can reuse socket addresses
Socket::bind() now takes a boolean argument after the socket specifier, if this is True, then the socket option SO_REUSEADDR will be set on the socket, meaning that even if the socket has not been 100% closed it can be opened and bound to (for example, if the socket is still in a TIME_WAIT state because the socket was closed while there were open client connections)

*) lists (and hashes) can end with a trailing comma
makes it easier to comment out the last element in a list or hash

*) new functions added
mkdir(), chmod(), rmdir(), pow(), hypot(), sqrt() functions added

*) STL hash_map used to accellerate hash lookups
on supported platforms

*) lots of bug fixes
see the CHANGELOG for details
