Updated 99/11/10
 Sun WorkShop(TM) 6 Tools.h++ 7.1.0 Readme



  Introduction

  Sun WorkShop 6 Early Access Release

  This document contains last minute information about Tools.h++ version
  7.1.0. It describes the software corrections addressed by this release
  and lists the known problems, limitations, and incompatibilities. This
  readme describes version 7.1.0 of Tools.h++ as of September 1999, and as
  well as earlier versions (where indicated).


  ------------------------------------------------------------------------
  Contents

    A. Software Corrections and New Features
    B. Problems and Work Arounds
    C. Limitations and Incompatibilities
    D. Documentation Errata
    E. Frequently Asked Questions


  ------------------------------------------------------------------------
  A. Software Corrections and New Features

    1. New Static Function for Deducing Daylight Saving Rule: RWZone::os()

       A new static function, RWZone::os() has been added to zone.cpp. When
       envoked, this function will deduce the current daylight saving rule
       fron the underlying system. Instantiating RWZone::local(
       RWZone::os() ) will set the daylight rule for the current year.

    2. Fixed an RWXDRi(o)stream bug(7340): XDR stream supports 64-bit on
       IRIX.

    3. Fixed an RWTime bug(9194) in converting from time_t and back to
       RWTime.

    4. Fixed an RWCRExpr bug(11049): infinite loop in compiling an
       unterminated bracket list.

    5. Fixed a problem in RWCRExpr that will result in an invalid status if
       caret (^ is found not immediately following open bracket inside a
       bracket expression.

    6. Fixed a bug in RWCRExpr that does not match the longest pattern in a
       string.

    7. The removeFirst() method of templatized vectors now throws a
       Boundary Error if the index is invalid.

    8. Added operator== to RWT***OrderedVector and also operator< to
       RWT***SortedVector so that these classes can now be instantiated
       recursively without using the Standard C++ Library.


  ------------------------------------------------------------------------
  B. Problems and Work Arounds

  This section discusses the software bugs that could not be fixed in time
  for this release. (Check Hot News for Sun WorkShop 6
  (http://www.sun.com/workshop/users/ws.html) for updated information):

    1. RWCString constructors are still significantly slower in the
       thread-ready version of the library. This should not affect most
       users.

    2. We have changed several member functions in the template collection
       classes to return const T& rather than T. This is generally a win
       because it means that the overhead of copying things from method to
       method is avoided. However, in a few cases, code will break: If your
       code depended on getting a copy of an object to avoid const issues,
       you may now find that your non-const methods will not work with our
       const references. The ideal solution is to re-write your code to be
       const correct.

    3. Problems persisting RWBoolean or bool using operators << and >> with
       vstreams. If your compiler supports bool as a "real type", we undef
       RW_NO_BOOL, and typedef RWBoolean to bool. But because converting a
       pointer to a bool is a standard conversion, if we had provided
       operators >> and << to extract or insert RWBoolean (bool) from and
       to vstreams, your compiler might correctly complain that it cannot
       choose between (for instance):

              RWpostream::operator<<(RWBoolean)

       (for instance)

              operator<<(RWVostream&, const RWCollectable*)

       when you attempt code like

              anRWpostream << aDerivedCollectable*

       (The reason it cannot decide is that in each case, one of the
       arguments is an exact match, but the other requires a built-in
       conversion, thus each choice is equally good.)

       This problem can be addressed by re-designing the Tools.h++ virtual
       streams, but the required change is neither link compatible (nor
       even code compatible for some users) with the current state of our
       code, so that solution will be postponed. For the moment, we have
       instead removed the insertion and extraction operators overloaded
       for bool. This restriction does not apply to the put() and get()
       methods of the vstream hierarchy, so RWBoolean (bool) may still be
       persisted, but not using the overloaded operators.

       Unfortunately, those compilers which trigger this problem will
       quietly convert a bool to some other type when inserting into a
       vstream: code such as this appears to work:

            aPostream << FALSE << " or " << TRUE;

       but the corresponding extractor will fail:

            aPistream >> oneRWBoolean << aString << anotherRWBoolean;

       Equally unfortunate, at least one of these compilers will issue a
       completely unhelpful diagnostic suggesting that oneRWBoolean and
       anotherRWBoolean be changed to "const int reference." If your
       compiler issues any diagnostic suggestive of a problem extracting a
       bool from a vistream, you must apply the following fix, not just to
       extraction code (flagged by the compiler) but also to insertion
       code, because otherwise the number of bytes inserted will not match
       the number which you get() from the stream. The fix is to replace
       code like this:

            aVostream << anyBoolean;

       with this instead:

            aVostream.put(anyBoolean);

       and

            aVistream &t;> anyBoolean;

       with this instead:

            aVistream.get(anyBoolean);

       Note that these fixes must be made in the bodies of both rwSaveGuts
       and rwRestoreGuts for any of your classes which need it, and also in
       both the saveGuts and restoreGuts methods of any of your own classes
       which derive from RWCollectable.


  ------------------------------------------------------------------------
  C. Limitations and Incompatibilities

  Because Tools.h++ 7.1.0 is not fully link compatible with the version of
  Tools.h++ shipped with Sun WorkShop Compilers C++ versions prior to
  version 5.0, applications and libraries that would use Tools.h++ 7.1.0
  should recompile all source modules before linking.


  ------------------------------------------------------------------------
  D. Documentation Errata

    1. Do Not Use Internal Classes

       Some classes which were developed purely for internal use by
       Tools.h++ appear in the documented hierarchy, but not in the class
       reference section. This omission is deliberate, and implies that the
       undocumented classes may be changed, augmented, or removed in a
       later release without warning to users. You should not use such
       classes.

    2. RWFactory

       The example for using RWFactory in the Class Reference is in error.

       This code example is wrong:


              RWBag* b = (RWBag*)getRWFactory()->create(__RWBAG);

       This code example is correct:

              RWBag* b = (RWBag*)rwCreateFromFactory(__RWBAG);

    3. RWTPtrSlistIterator

       Class Reference for RWTPtrSlistIterator should tell the user that if
       the slist is modified, the iterator is no longer valid. This is
       generally true for all iterators.

    4. Values Stored in the Templatized Dictionary Containers

       Values stored in the templatized dictionary containers must be able
       to respond to operator==() and operator<(). This is necessary when
       the Standard C++ Library is being used as the implementation for
       these classes because the standard requires it, and when our own
       implementation is used because we wanted to be sure that containers
       with identical keys but distinct values were not considered the
       same. According to the Draft ANSII/ISO Standard, compilers should
       only require these operators if they are used. Unfortunately, we
       know of several compilers that do not meet this part of the draft
       standard.

    5. Wording About operator== Too Restrictive

       The manual talks about the semantics of the types that may
       instantiate the templatized collections by saying something like
       "Class K must have * well-defined equality semantics
       (K::operator==(const K&))." The example is too restrictive. We
       should be saying that the compiler must be able to unambiguously
       find an operator== that applies to two instances of K regardless of
       how the operator is implemented.

    6. RW_CENTURY_REQD

       RW_CENTURY_REQD will force asString with the "x" format to output 4
       digit years. Since asString defaults to the "x" formatting option, 4
       digit years will also be the default. This doesn't affect the other
       formatting options, which are handled by the operating system.

    7. RWLocaleSnapshot

       The following paragraph applies to RWLocaleSnapshot, but is not in
       the documentation:

       Note - The constructor for class RWLocaleSnapshot calls the function
       setlocale, which is not thread-safe. For safety in multithreaded
       applications, instances of RWLocaleSnapshot must be constructed only
       when it can be guaranteed that no other thread may be using
       locale-dependent functions. To guarantee this condition, construct
       all instances of RWLocaleSnapshot in the initial thread before
       starting any other thread.There is no new information at this time.


  ------------------------------------------------------------------------
  E. Frequently Asked Questions

    1. How do I contact Rogue Wave Software?

       Please don't contact Rogue Wave for support of your Sun product. If
       you want information on other Rogue Wave products you can call:

       541-754-3010 or
       800-487-3217

    2. How do I get support for Tools.h++?

       Use Sun support as you would for any other Sun product. Sun has
       access to Rogue Wave for updates, consulting, fixes, and so on, but
       Sun fully supports Tools.h++.

    3. Is the Sun version different from the Rogue Wave version?

       The Sun and Rogue Wave versions of Tools.h++ are built from the same
       source base. Bug fixes are brought into the master sources. Each
       releases on a separate schedule, however, so released versions are
       likely to be a slightly different. In general, Rogue Wave releases
       more often, so they are usually (although not always) a bit ahead.

       Sun maintains link-compatibility across minor releases, and may hold
       back selected fixes if they must break link compatibility.
       Maintaining link compatibility means you can link your new Tools.h++
       library with object files compiled for the old Tools.h++ library.)

    4. Can I get the latest Rogue Wave version from Sun?

       Usually no; only if that's what Sun ships anyway. Sufficiently
       important bug fixes are likely to be available from Sun.

    5. Where are the Tools.h++ header files?

       Use

       example% CC -H <file>.cc

       to determine the location of the Tools.h++ header files in in your
       installation, where <file>.cc includes at least one Tools.h++ header
       file.

    6. Is there a shared library version of librwtool?

       Yes, there is a shared library version for Tools.h++ 7.

    7. Can I build libraries that use Tools.h++?

       It's all right to build an archive library that depends on Tools.h++
       if your library is just used internally inside your project, for
       example to simplify build procedures. If you intend to ship your
       archive library to anyone, your customer needs to have access to
       Tools.h++ as well. Sun customers may redistribute librwtool.so.2,
       but not the header files that go with it. See
       <install-directory>/READMEs/runtime.libraries for details.

    8. How do I print RWCStrings in dbx

       In Sun WorkShop, the command interpreter for dbx is a Korn shell, so
       you can define new dbx commands that do specialized debugging
       functions. Printing strings is an often-wanted facility. The
       Tools.h++ manual chapter on compiling and debugging describes ways
       to print strings in dbx. Another way to print an RWCString is to
       define a new dbx command, such as:

       function dumpstr
       {
         print (char*)($1.pref_+1)
       }

       Then in dbx you can say:

       (dbx) dumpstr myString
       (char *) (myString.pref_+1) = 0x28d5c "Contents of myString"
       (dbx)

       You can put the definition of dumpstr into your .dbxrc file.

    9. Additional details

          o The capacity of RWCString and RWWString may be changed by
            calling the clone member function: aString.clone(0) will adjust
            the capacity of aString to be exactly large enough, whereas
            calling aString.clone(aString.length()+someMore) will leave
            someMore extra bytes in the buffer.

          o All iterators: If the collection is modified directly or
            through the use of any iterator except the one in question,
            then that iterator is no longer guaranteed to be valid. Some
            collections may be altered "most of the time" without such side
            effects, which could lead you into a trap if you come to expect
            that iterators may be trusted after the collection is modified.
            Beware.

          o Some templatized containers have a method clearAndDestroy(),
            which is not protected against the possibility that the
            container holds more than one pointer to the same object. Do
            not call clearAndDestroy() unless you are sure your container
            holds no duplicates. (This warning does not apply to
            RWCollections.)

          o Some Tools.h++ methods are overloaded to take either a pointer
            or an integer type. RWTime constructors, for example, may be
            passed either a struct tm* or an unsigned long representing
            seconds since the "beginning of time." If you attempt to pass a
            zero to such methods, the compiler will correctly complain
            about ambiguity. This may be resolved by holding the zero value
            in the appropriate type, casting it, or using a construction
            such as "0ul" for a manifest constant.

          o Problems with incorrect RWTime construction from struct tm*:
            The system function localtime() returns a pointer to a static
            struct tm. Subsequent calls to localtime overwrite that struct.
            RWTime uses RWZone::local(), which is not created until needed.
            That creation also calls localtime(). If you experience
            difficulty related to calls to localtime(), make a call to
            RWZone::local() before you first call localtime().

          o RWLocale::asString(struct tm*, ..%U.., RWZone&=
            RWZone::local()) returns different values for week of the year,
            for years that begin on Sunday, depending on the platform.
            Although the standard is precise, many vendors disagree on it.
            Rogue Wave passes the vendor's result without examining it, so
            if you care about cross-platform results, do not use the %U
            format specifier.

          o Problems using RWFactory, or polymorphic persistence: Before
            the factory can create an RWCollectable, that collectable and
            its identifier must be registered. The easy way to do this is
            by creating at least one instance of the particular
            RWCollectable in the program.

            This problem may manifest in several ways. Usually you will see
            this message:

            "[NOCREATE] RWFactory: no create function for class with ID
            (something)"

            However, it is possible to get a core dump or GPF during a call
            to theFactory->create(someID) (This call is made while reading
            in persisted RWCollectables). This can happen with some
            compilers that do not create an instance of an object if you
            instantiate only a pointer to the object.

          o When creating your own RWCollectable, it is important to
            provide your class with all the methods that the RWCollectable
            methods use. In particular, you must provide a default
            constructor that can be used to create new "empty" instances
            for the persistence mechanism to "fill", and a copy constructor
            that may be used to clone copies of your object to a new
            location. You should also be careful to have related methods
            and operators be consistent with each other: If you have
            comparison operators defined for your class, they should give
            results that match the values returned by the method
            compareTo().

          o When to use RWCollectable::recursiveStoreSize() and when to use
            RWCollectable::binaryStoreSize(). Although the answer is
            simple, it does sometimes require a bit of thought:
            recursiveStoreSize() should be used at the _top_ level of an
            RWCollectable when you plan to use operator<<() or the
            undocumented recursiveSaveOn() method. On the other hand,
            binaryStoreSize() should be used when you are interested in
            working with a _part_ of the entire collection; when you plan
            to use saveGuts().

            Neither of these methods deals with streams; these methods are
            only of use for RWFile. If you need to find the size of an
            RWCollectable as saved to a virtual stream, use the class
            RWAuditStreamBuffer.

          o Use of mutexes prior to main suffers from the paired difficulty
            of knowing the order of static initialization (no general
            solution) and knowing which pre-main thread should initialize a
            given mutex. There are no known software solutions to this
            problem. Therefore do not use static initialization code to
            call any thread-hot functions.

          o Using templatized hash-based containers in your class. Many
            customers have asked how to add to their own classes a class
            member that requires a non-default constructor, such as the
            Tools.h++ hash based containers. The answer is a special syntax
            known as "member initialization." Suppose your class should
            have a hash dictionary member:

              class MyClass {
                // ...
                RWTValHashDictionary myDict; // no ctor args here!
              public:
                 MyClass();
              };

            Member initialization looks like this: Where you provide the
            actual constructor body, you have to use a ":" followed by a
            comma-separated list of constructors for each member which
            requires non-default construction. This example extends the
            previous example.

               MyClass::MyClass() : myDict(theHashFunction) /* like this */
               { /* code for your constructor */ }

            Of course, you could instead use the member initialization
            syntax to write an inline constructor if that makes sense. What
            you cannot do is add the constructor arguments to the
            _declaration_ of the dictionary in the class declaration.


  ------------------------------------------------------------------------

  Copyright 1999 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto,
  CA 94303, U.S.A. All rights reserved.

