/***************************************************************************
 *
 * rw/locimpl - Declarations for the Standard Library locale private
 *              implementation classes.
 *
 * $Id: locimpl,v 1.25 1996/10/02 01:48:00 smithey Exp $
 *
 ***************************************************************************
 *
 * (c) Copyright 1994-1996 Rogue Wave Software, Inc.
 * ALL RIGHTS RESERVED
 *
 * The software and information contained herein are proprietary to, and
 * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
 * intends to preserve as trade secrets such software and information.
 * This software is furnished pursuant to a written license agreement and
 * may be used, copied, transmitted, and stored only in accordance with
 * the terms of such license and with the inclusion of the above copyright
 * notice.  This software and information or any other copies thereof may
 * not be provided or otherwise made available to any other person.
 *
 * Notwithstanding any other lease or license that may pertain to, or
 * accompany the delivery of, this computer software and information, the
 * rights of the Government regarding its use, reproduction and disclosure
 * are as set forth in Section 52.227-19 of the FARS Computer
 * Software-Restricted Rights clause.
 * 
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7013.
 * Contractor/Manufacturer is Rogue Wave Software, Inc.,
 * P.O. Box 2328, Corvallis, Oregon 97339.
 *
 * This computer software and information is distributed with "restricted
 * rights."  Use, duplication or disclosure is subject to restrictions as
 * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
 * Computer Software-Restricted Rights (April 1985)."  If the Clause at
 * 18-52.227-74 "Rights in Data General" is specified in the contract,
 * then the "Alternate III" clause applies.
 *
 **************************************************************************/

#ifndef __STD_RW_LOCIMPL__
#define __STD_RW_LOCIMPL__
//
//
//  Copyright Digital Equipment Corporation 1996. All rights reserved.
//
//  Restricted Rights: Use, duplication, or disclosure by the U.S.
//  Government is subject to restrictions as set forth in subparagraph
//  (c) (1) (ii) of DFARS 252.227-7013, or in FAR 52.227-19, or in FAR
//  52.227-14 Alt. III, as applicable.
//
//  This software is proprietary to and embodies the confidential
//  technology of Digital Equipment Corporation. Possession, use, or
//  copying of this software and media is authorized only pursuant to a
//  valid written license from Digital or an authorized sublicensor.
//
//
#if defined(__DECCXX)
#   ifdef __PRAGMA_ENVIRONMENT
#      pragma __environment __save
#      pragma __environment __header_defaults
#   endif
#endif

// Included only from <locale>

// Macro for use with syntax like _RWSTD_STD::name to ensure we can always reach
// names declared at the ::std namespace scope.  Put in stdcomp?

#ifndef _RWSTD_NO_NAMESPACE
#define _RWSTD_STD std
#else
#define _RWSTD_STD
#endif

// Macros for declaring and referencing implementation type and object names in
// our private implementation namespace, or with our private prefix __rw_ stuck
// on the fronts of the names if namespaces are not supported by the compiler.
// The DECL version is for use inside the implementation namespace, the NAME
// version for refering to the names from elsewhere.  Move to stdcomp?

// #define _RWSTD_SIEMENS_NAMESPACE_PROBLEM 1

#ifdef _RWSTD_SIEMENS_NAMESPACE_PROBLEM
#define __rwstd std
#endif

#ifndef _RWSTD_NO_NAMESPACE
#define _RWSTD_IMP_DECL(name) name
#define _RWSTD_IMP_NAME(name) __rwstd::name
#define _RWSTD_HAS_FACET std::has_facet
#define _RWSTD_USE_FACET std::use_facet
#else
#define _RWSTD_IMP_DECL(name) __rw_##name
#define _RWSTD_IMP_NAME(name) __rw_##name
#define _RWSTD_HAS_FACET has_facet
#define _RWSTD_USE_FACET use_facet
#endif

// Macro for declaring all the has_facet and use_facet functions to be friends.

#ifndef _RWSTD_NO_FRIEND_TEMPLATES
#ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
#define _RWSTD_FRIEND_USE_HAS_FACET                                      \
  template <class Facet> friend                                         \
      const Facet& _RWSTD_USE_FACET (const locale&);                \
  template <class Facet> friend                                         \
      bool _RWSTD_HAS_FACET (const locale&) _RWSTD_THROW_SPEC_NULL;
#else
#define _RWSTD_FRIEND_USE_HAS_FACET                                      \
  template <class Facet> friend                                         \
    const Facet& _RWSTD_USE_FACET (const locale&,Facet*);           \
  template <class Facet> friend                                         \
    bool _RWSTD_HAS_FACET (const locale&,Facet*) _RWSTD_THROW_SPEC_NULL;
#endif
#else
#define _RWSTD_FRIEND_USE_HAS_FACET public:
#endif

#ifndef _RWSTD_NO_NAMESPACE
namespace __rwstd {
#ifndef _RWSTD_SIEMENS_NAMESPACE_PROBLEM
  using namespace std;
#endif
#endif

// Implementation class template -- timepunct<charT>
//
// A facet such as this should have been included in the standard.  We just
// declare it here; the definition occurs below, after locale::facet has been
// defined.

template <class charT> class _RWSTD_IMP_DECL(timepunct);

// Implementation forward declarations:

class _RWSTDExport _RWSTD_IMP_DECL(locale_imp);
class _RWSTDExport _RWSTD_IMP_DECL(facet_imp);

class _RWSTDExport _RWSTD_IMP_DECL(digit_map_base);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(digit_map);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(keyword_def);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(keyword_map);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(keyword_cracker);

class _RWSTDExport _RWSTD_IMP_DECL(digit_reader_base);
template <class charT> class _RWSTD_IMP_DECL(digit_reader_base_1);
template <class charT,class InputIterator>
  class _RWSTDExportTemplate _RWSTD_IMP_DECL(digit_reader);

class _RWSTDExport _RWSTD_IMP_DECL(digit_writer_base);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(digit_writer_base_1);
template <class charT,class OutputIterator>
  class _RWSTDExportTemplate _RWSTD_IMP_DECL(digit_writer);

template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(money_handler_base_1);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(money_reader_base_1);
template <class charT,class OutputIterator>
  class _RWSTDExportTemplate _RWSTD_IMP_DECL(money_reader_base_2);
template <class charT> class _RWSTDExportTemplate _RWSTD_IMP_DECL(money_writer_base_1);
template <class charT,class OutputIterator>
  class _RWSTDExportTemplate _RWSTD_IMP_DECL(money_writer_base_2);

// ------------------------------------
// Implementation class -- ref_counted.
// ------------------------------------

// Common base class for reference-counted classes.  Currently used only by
// locale_imp and facet_imp, but could be used more generally.

class _RWSTDExport _RWSTD_IMP_DECL(ref_counted) {
#if defined(__DECCXX) && !defined(__DECFIXCXXL462)
  friend class std::locale;
#else
  friend class locale;
#endif

  size_t ref_count_;
  #ifdef _RWSTD_MULTI_THREAD
  _RWSTDMutex mutex_;
  #endif

 protected:
  _RWSTD_IMP_DECL(ref_counted) (size_t initial_refs):
      ref_count_(initial_refs) { }

  // Ensure derived class destructors are always virtual.
  virtual ~_RWSTD_IMP_DECL(ref_counted) (void);

  // Does protected access make these accessible to friends of derived classes?
  // We're about to find out ...

  static void add_reference (_RWSTD_IMP_DECL(ref_counted) *ob) {
    STDGUARD(ob->mutex_);
    ++ob->ref_count_;
  }

  static void remove_reference (_RWSTD_IMP_DECL(ref_counted) *ob) {
    size_t refs;
    {
      STDGUARD(ob->mutex_);
      refs=--ob->ref_count_;
    }
    if (!refs)
      delete ob;
  }

  static void add_possible_reference (_RWSTD_IMP_DECL(ref_counted) *ob) {
    if (ob)
      add_reference(ob);
  }

  static void remove_possible_reference (_RWSTD_IMP_DECL(ref_counted) *ob) {
    if (ob)
      remove_reference(ob);
  }
};

// We would prefer to define locale::id and locale::facet entirely as nested
// classes of locale, but current compilers have problems with out-of-line
// definition of members of such classes, so we have to derive most of their
// behavior from unnested implementation classes:

// --------------------------------------
// Implementation class -- locale_id_imp.
// --------------------------------------

class _RWSTDExport _RWSTD_IMP_DECL(locale_id_imp) {
 protected:
  _MUTABLE size_t id_;
  static size_t last_used_id_;
  void init() const;
};

// ----------------------------------
// Implementation class -- facet_imp.
// ----------------------------------

class _RWSTDExport _RWSTD_IMP_DECL(facet_imp): public _RWSTD_IMP_DECL(ref_counted)
{
  _RWSTD_FRIEND_USE_HAS_FACET
  friend class _RWSTD_IMP_DECL(locale_imp);
#if defined(__DECCXX) && !defined(__DECFIXCXXL462)
  friend class std::locale;
#else
  friend class locale;
#endif

  enum {
    facet_cat_ = 0,
    ok_implicit_ = 0,
    init_done  = 0x0001
  };

 private:
  int flags_;
  int category_;     // Should be same type as locale::category

 protected:
  _RWSTD_IMP_DECL(facet_imp) (size_t refs, int cat=0):
      _RWSTD_IMP_DECL(ref_counted)(refs), flags_(0), category_(cat) { }

  // rw_init() is called by locale::install the first time a facet is installed
  // in its first locale.  Some facets override it to set up private data that
  // depends on return values of virtual do_xxx functions that can't be called
  // in the constructor.
  virtual void rw_init (void) { }
};

// -----------------------------------
// Implementation class -- locale_imp.
// -----------------------------------

class _RWSTDExport _RWSTD_IMP_DECL(locale_imp): public _RWSTD_IMP_DECL(ref_counted)
{
  _RWSTD_FRIEND_USE_HAS_FACET
#if defined(__DECCXX) && !defined(__DECFIXCXXL462)
 friend class std::locale;
#else
 friend class locale;
#endif

  // Same type as locale::category ...
  typedef int locale_category;

  vector<_RWSTD_IMP_DECL(facet_imp)*,allocator<void> > vec_;
  vector<string,allocator<void> > names_;
  locale_category native_cats_;
  locale_category named_cats_;
  string big_name_;
  bool named_;

  _RWSTD_IMP_DECL(locale_imp) (size_t sz=36, size_t refs=0);
  _RWSTD_IMP_DECL(locale_imp) (const _RWSTD_IMP_DECL(locale_imp)&,size_t refs);
 ~_RWSTD_IMP_DECL(locale_imp) ();

  inline _RWSTD_IMP_DECL(facet_imp) *get_facet (size_t i) const
    { return i<vec_.size()? vec_[i] : NULL; }
  const char *category_name (locale_category) const;

  // Map C library LC_xxx constants into facet categories.
  static locale_category map_category (locale_category);

  // Parse a locale name into category names.
  static bool parse_name (vector<string,allocator<void> >&,const char*);
  // Combine category names to create a locale name.
  static bool build_name (string&,const vector<string,allocator<void> >&);
};

// ---------------------------------------
// Implementation class -- digit_map_base.
// ---------------------------------------

// A place to stash some static constants, so that each instantiation of the
// derived class rwstd::digit_map does not have to have a separate copy.

struct _RWSTDExport _RWSTD_IMP_DECL(digit_map_base) {
  enum { zero, minus, plus, X, x, E, e };
  static const char punct_chars[7];   // "0-+XxEe"
  static const char digit_chars[22];  // "0123456789ABCDEFabcdef"
  static const char char_values[22];  // Corresponding values in range 0-15
};

// --------------------------------------------------
// Implementation class template -- digit_map<charT>.
// --------------------------------------------------

// Maps digits into their corresponding numeric values, and caches widened
// equivalents of some number-related punctuation characters that don't depend
// on the numpunct facet.  A private instance of this class is hidden in
// ctype<charT> for use by numeric conversion facets.  A call to init must
// precede the first call to eval if is_inited() is false.  Eval returns 0-15
// if argument is a valid digit, a negative value otherwise.
//
// Specialized for char for performance.  The specialization assumes digits
// fit into the char code-set in an ASCII-like manner ('0'..'9' contiguous,
// 'A'..'F' contiguous, 'a'..'f' contiguous, '0' < 'A' < 'a').

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(digit_map):
    public _RWSTD_IMP_DECL(digit_map_base)
{
  bool inited;
  charT punct_array[7];
  charT digit_array[22];
  char value_array[22];
 public:
  typedef charT char_type;

  _RWSTD_IMP_DECL(digit_map) (void): inited(false) { }
  bool is_inited (void) const { return inited; }
  void init (const ctype<charT>& ct);
  const charT *get_punct (void) const { return punct_array; }
  int eval (charT) const;

  // Can-opener for getting the digit_map out of a ctype.  (Works because of
  // the friend declaration in ctype_helper<charT> below.)
  static inline const _RWSTD_IMP_DECL(digit_map)<charT>&
      get_digit_map (const ctype<charT>&);
};

#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExportTemplate _RWSTD_IMP_DECL(digit_map)<char>:
    public _RWSTD_IMP_DECL(digit_map_base)
{
 public:
  typedef char char_type;

  bool is_inited (void) const { return true; }
  const char *get_punct (void) const { return punct_chars; }
  inline int eval (char c) const;
  static inline const _RWSTD_IMP_DECL(digit_map)<char>&
      get_digit_map (const ctype<char>&);

 private:
  // These declarations stop BC5 from firing the template for member function
  // digit_map<charT>::init on char, then complaining that init and inited are
  // not members of digit_map<char>.
  void init (const ctype<char>&);
  bool inited;
};

// ----------------------------------------------------
// Implementation class template -- keyword_def<charT>.
// ----------------------------------------------------

// Helper class used in parsing keywords from input (such as true/false in
// num_get, month and day names in time_get, etc).

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(keyword_def) {
 public:
  const charT *s;
  int v;
};

// ----------------------------------------------------
// Implementation class template -- keyword_map<charT>.
// ----------------------------------------------------

// Defines a set of keywords to be recognized on input and to be written to
// output.  Private instances are hidden in numpunct (for true/false) and
// rwstd::timepunct (for month and weekday names).

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(keyword_map) {
 public:
  int num_defs_;
  const _RWSTD_IMP_DECL(keyword_def)<charT> *defs_;
};

// -----------------------------------------------------
// Implementation class template -- ctype_helper<charT>.
// -----------------------------------------------------

// Character classification facet ctype<charT> derives from this to obtain
// its private digit_map member.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(ctype_helper) {
  friend class _RWSTD_IMP_DECL(digit_map)<charT>;
  _RWSTD_IMP_DECL(digit_map)<charT> digit_map_;
};

// ------------------------------------------------------
// Implementation class template -- collate_table<charT>.
// ------------------------------------------------------

// Data structure that drives the collate<charT> process.  It contains a
// binary tree of nodes, each of which defines the collation treatment to be
// applied to a range of characters.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(collate_table) {
 public:
  struct node {
    node *left;             // Node for charT values that are too small (resp.
    node *right;            //  too large) for this node
    const charT *table;     // Translate table or NULL
    charT minC,maxC;        // Range of charT-s covered by this node
    charT offset;           // Amount to add to charT if table is NULL
  };

  long length;              // Length of memory block containing all the nodes
  node root;                // Root node of table
};

// -----------------------------------------------------
// Implementation class template -- collate_data<charT>.
// -----------------------------------------------------

// collate<charT> derives from this (via rwstd::collate_impl) to get its
// private data members.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(collate_data)
{
 public:
  typedef _RWSTD_IMP_DECL(collate_table)<charT> table;
  typedef _TYPENAME table::node node;

  const table *table_;

  _RWSTD_IMP_DECL(collate_data) (const table &t): table_(&t) { }
  charT coll_order (charT) const;
};

template <class charT>
_RWSTD_TRICKY_INLINE charT _RWSTDExportTemplate _RWSTD_IMP_DECL(collate_data)<charT>::
    coll_order (charT c) const
{
  const node *t=&table_->root;
  while (t)
    if (c < t->minC)
      t=t->left;
    else if (c > t->maxC)
      t=t->right;
    else {
      if (t->table)
        c=t->table[size_t(c-t->minC)];
      else
        c+=t->offset;
      break;
    }

  return c;
}

// -----------------------------------------------------
// Implementation class template -- collate_impl<charT>.
// -----------------------------------------------------

// Facet collate<charT> derives from this to get the part of its behavior that
// is specialized for char and wchar_t.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(collate_impl):
    public _RWSTD_IMP_DECL(collate_data)<charT>
{
  static _RWSTD_IMP_DECL(collate_table)<charT> _RWSTDExport default_table_;
 public:
  _RWSTD_IMP_DECL(collate_impl) (void):
      _RWSTD_IMP_DECL(collate_data)<charT>(default_table_) { }
};

// Specialization for char.
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(collate_impl)<char>:
    public _RWSTD_IMP_DECL(collate_data)<char>
{
  static _RWSTD_IMP_DECL(collate_table)<char> _RWSTDExport default_table_;
 public:
  _RWSTD_IMP_DECL(collate_impl) (void):
      _RWSTD_IMP_DECL(collate_data)<char>(default_table_) { }
};


#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
// Specialization for wchar_t.
#ifndef _RWSTD_NO_WIDE_CHAR
class _RWSTDExport _RWSTD_IMP_DECL(collate_impl)<wchar_t>:
    public _RWSTD_IMP_DECL(collate_data)<wchar_t>
{
  static _RWSTD_IMP_DECL(collate_table)<wchar_t> _RWSTDExport default_table_;
 public:
  _RWSTD_IMP_DECL(collate_impl) (void):
      _RWSTD_IMP_DECL(collate_data)<wchar_t>(default_table_) { }
};
#endif


// ---------------------------------------------------
// Implementation class template -- punct_data<charT>.
// ---------------------------------------------------

// Common base class for rwstd::numpunct_data and rwstd::moneypunct_data.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(punct_data) {
  friend class _RWSTD_IMP_DECL(digit_reader_base_1)<charT>;
  friend class _RWSTD_IMP_DECL(digit_writer_base_1)<charT>;
 public:
  typedef basic_string<charT,char_traits<charT>,allocator<void> > string_type;
 protected:
  charT dp_, ts_;
  string gr_;
};

// ------------------------------------------------------
// Implementation class template -- numpunct_init<charT>.
// ------------------------------------------------------

// Structure used to initialize a rwstd::numpunct_data.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(numpunct_init) {
 public:
  bool del_;                    // Kill the bearer of this message
  charT dp_, ts_;               // Decimal point and thousands separator
  const char *gr_;              // Digit grouping rule
  const charT *tn_, *fn_;       // Strings for boolean true and false
};

// --------------------------------------
// Implementation class -- numpunct_base.
// --------------------------------------

// Contains parts of numpunct<charT> that don't depend on the charT template
// parameter.

class _RWSTDExport _RWSTD_IMP_DECL(numpunct_base) {
 public:
  static _RWSTD_IMP_DECL(numpunct_init)<char> *get_named_init_ (const char*);
};

// ------------------------------------------------------
// Implementation class template -- numpunct_data<charT>.
// ------------------------------------------------------

// numpunct<charT> derives from this (via rwstd::numpunct_impl) to get its
// private data members.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(numpunct_data):
    public _RWSTD_IMP_DECL(numpunct_base),
    public _RWSTD_IMP_DECL(punct_data)<charT>
{
  friend class numpunct<charT>;
  friend class _RWSTD_IMP_DECL(keyword_cracker)<charT>;

  typedef basic_string<charT,char_traits<charT>,allocator<void> > string_type;

  string_type tn_, fn_;

  _RWSTD_IMP_DECL(keyword_def)<charT> tf_defs_[2];
  _RWSTD_IMP_DECL(keyword_map)<charT> tf_map_;

 protected:
  _RWSTD_IMP_DECL(numpunct_data) (const _RWSTD_IMP_DECL(numpunct_init)<charT>*);
  _RWSTD_IMP_DECL(numpunct_init)<charT> *get_init_by_name_ (const char*);
  void rw_init (void);
};

template <class charT>
inline _RWSTD_IMP_DECL(numpunct_data)<charT>::_RWSTD_IMP_DECL(numpunct_data)
    (const _RWSTD_IMP_DECL(numpunct_init)<charT> *init)
{
  if (!init) {
    this->dp_=charT('.');
    this->ts_=charT(',');
  } else {
    this->dp_=init->dp_;
    this->ts_=init->ts_;
    this->gr_=init->gr_;
    tn_=init->tn_;
    fn_=init->fn_;

    if (init->del_)
      delete[] (char*) init;
  }
}

template <class charT>
_RWSTD_IMP_DECL(numpunct_init)<charT>*
_RWSTD_IMP_DECL(fixup_numpunct_init)
    (_RWSTD_IMP_DECL(numpunct_init)<char>*,charT*);

// ------------------------------------------------------
// Implementation class template -- numpunct_impl<charT>.
// ------------------------------------------------------

// numpunct<charT> derives from this to obtain the part of its behavior that
// must be specialized for char and wchar_t.  This lets us avoid specializing
// the whole numpunct<charT> template.  Currently the only specialized behavior
// is the initialization of private data members in the constructor.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(numpunct_impl):
    public _RWSTD_IMP_DECL(numpunct_data)<charT>
{
 protected:
  _RWSTD_IMP_DECL(numpunct_impl) (const _RWSTD_IMP_DECL(numpunct_init)<charT>*);
  static const _RWSTD_IMP_DECL(numpunct_init)<charT> *get_ivals_ ()
    { return NULL; }
};

#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(numpunct_impl)<char>:                  // Specialization
    public _RWSTD_IMP_DECL(numpunct_data)<char>
{
  static _RWSTD_IMP_DECL(numpunct_init)<char> _RWSTDExport ivals_;        // Vendor-supplied
 protected:
  _RWSTD_IMP_DECL(numpunct_impl)
      (const _RWSTD_IMP_DECL(numpunct_init)<char> *init):
       _RWSTD_IMP_DECL(numpunct_data)<char>(init) { }
  static const _RWSTD_IMP_DECL(numpunct_init)<char> *get_ivals_ ()
    { return &ivals_; }
};

#ifndef _RWSTD_NO_WIDE_CHAR
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(numpunct_impl)<wchar_t>:               // Specialization
    public _RWSTD_IMP_DECL(numpunct_data)<wchar_t>
{
  static _RWSTD_IMP_DECL(numpunct_init)<wchar_t> _RWSTDExport ivals_;     // Vendor-supplied
 protected:
  _RWSTD_IMP_DECL(numpunct_impl)
      (const _RWSTD_IMP_DECL(numpunct_init)<wchar_t> *init):
       _RWSTD_IMP_DECL(numpunct_data)<wchar_t>(init) { }
  static const _RWSTD_IMP_DECL(numpunct_init)<wchar_t> *get_ivals_ ()
    { return &ivals_; }
};
#endif // _RWSTD_NO_WIDE_CHAR

// -------------------------------------------------------
// Implementation class template -- timepunct_init<charT>.
// -------------------------------------------------------

// Structure used to initialize the private data members of timepunct<charT>.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(timepunct_init) {
 public:
  const charT *dn_[7][2];       // Day names and abbreviations
  const charT *mn_[12][2];      // Month names and abbreviations
  const charT *ampm_[2];        // AM/PM strings
  const charT *bad_;            // Bad value output signal
  const charT *ord_[100];       // Ordinal numbers
  const charT *pat_[6];         // Patterns for formats "xXcDrT" resp.
};

// -------------------------------------------------------
// Implementation class template -- timepunct_data<charT>.
// -------------------------------------------------------

// timepunct<charT> derives from this (via rwstd::timepunct_impl) to get its
// private data members.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(timepunct_data) {
  friend class _RWSTD_IMP_DECL(timepunct)<charT>;
  friend class _RWSTD_IMP_DECL(keyword_cracker)<charT>;
 public:
  typedef basic_string<charT,char_traits<charT>,allocator<void> > string_type;
 private:

  string_type dn_[7][2];
  string_type mn_[12][2];
  string_type ampm_[2];
  string_type bad_;
  string_type ord_[100];
  string_type pat_[6];

  _RWSTD_IMP_DECL(keyword_def)<charT> dn_defs_[7][2];
  _RWSTD_IMP_DECL(keyword_map)<charT> dn_map_;
  _RWSTD_IMP_DECL(keyword_def)<charT> mn_defs_[12][2];
  _RWSTD_IMP_DECL(keyword_map)<charT> mn_map_;

 protected:
  _RWSTD_IMP_DECL(timepunct_data)
      (const _RWSTD_IMP_DECL(timepunct_init)<charT> &i);
  void rw_init (void);
};

// -------------------------------------------------------
// Implementation class template -- timepunct_impl<charT>.
// -------------------------------------------------------

// timepunct<charT> derives from this to get the parts of its behavior that
// must be specialized on the character type.  Currently the only specialized
// behavior is the initialization logic in the constructor.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(timepunct_impl):
    public _RWSTD_IMP_DECL(timepunct_data)<charT>
{
 protected:
  _RWSTD_IMP_DECL(timepunct_impl)(void);
};

#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(timepunct_impl)<char>:                 // Specialization
    public _RWSTD_IMP_DECL(timepunct_data)<char>
{
  static _RWSTD_IMP_DECL(timepunct_init)<char> _RWSTDExport ivals_;       // Vendor-supplied
 protected:
  _RWSTD_IMP_DECL(timepunct_impl) (void):
      _RWSTD_IMP_DECL(timepunct_data)<char>(ivals_) { }
};

#ifndef _RWSTD_NO_WIDE_CHAR
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(timepunct_impl)<wchar_t>:              // Specialization
    public _RWSTD_IMP_DECL(timepunct_data)<wchar_t>
{
  static _RWSTD_IMP_DECL(timepunct_init)<wchar_t> _RWSTDExport ivals_;    // Vendor-supplied
 protected:
  _RWSTD_IMP_DECL(timepunct_impl)(void):
      _RWSTD_IMP_DECL(timepunct_data)<wchar_t>(ivals_) { }
};
#endif // _RWSTD_NO_WIDE_CHAR

// --------------------------------------------------------
// Implementation class template -- moneypunct_init<charT>.
// --------------------------------------------------------

// Structure used to initialize a rwstd::moneypunct_data<charT>.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(moneypunct_init) {
 public:
  bool del_;                        // Delete when initialization is done
  charT dp_, ts_;                   // Decimal point and thousands separator
  const char *gr_;                  // Grouping pattern
  const charT *cs_;                 // Currency symbol string
  const charT *ps_, *ns_;           // Positive and negative sign strings
  int fd_;                          // Number of fractional digits
  money_base::pattern pf_, nf_;     // Positive and negative format patterns
};

// ----------------------------------------
// Implementation class -- moneypunct_base.
// ----------------------------------------

// Contains parts of moneypunct<charT> that do not depend on the template
// parameter.

class _RWSTDExport _RWSTD_IMP_DECL(moneypunct_base) {
 public:
  static _RWSTD_IMP_DECL(moneypunct_init)<char> *get_named_init_
      (const char*,bool);
};

// --------------------------------------------------------
// Implementation class template -- moneypunct_data<charT>.
// --------------------------------------------------------

// moneypunct<charT,Intl> derives from this (via moneypunct_impl<charT,Intl>)
// to get its private data members.

template <class charT>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(moneypunct_data):
    public _RWSTD_IMP_DECL(moneypunct_base),
    public _RWSTD_IMP_DECL(punct_data)<charT>
{
  friend class _RWSTD_IMP_DECL(money_handler_base_1)<charT>;
  friend class moneypunct<charT,false>;
  friend class moneypunct<charT,true>;

  typedef basic_string<charT,char_traits<charT>,allocator<void> > string_type;

  string_type cs_;                  // Currency symbol
  string_type ps_, ns_;             // Positive and negative sign strings
  int fd_;                          // Number of fractional digits
  money_base::pattern pf_, nf_;     // Positive and negative format patterns

 protected:
  _RWSTD_IMP_DECL(moneypunct_data) (_RWSTD_IMP_DECL(moneypunct_init)<charT>*);

  void rw_init (void);
  _RWSTD_IMP_DECL(moneypunct_init)<charT> *get_init_by_name_ (const char*,bool);
};

template <class charT>
_RWSTD_IMP_DECL(moneypunct_init)<charT>*
_RWSTD_IMP_DECL(fixup_moneypunct_init)
    (_RWSTD_IMP_DECL(moneypunct_init)<char>*,charT*);

// -------------------------------------------------------------
// Implementation class template -- moneypunct_impl<charT,Intl>.
// -------------------------------------------------------------

// moneypunct<charT,Intl> derives from this to get the parts of its behavior
// that are specialized for the character type and the Intl format selection.

template <class charT,bool Intl>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(moneypunct_impl):
    public _RWSTD_IMP_DECL(moneypunct_data)<charT>
{
 protected:
  _RWSTD_IMP_DECL(moneypunct_impl) (void);
};

#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(moneypunct_impl)<char,false>:          // Specialization
    public _RWSTD_IMP_DECL(moneypunct_data)<char>
{
  friend class _RWSTD_IMP_DECL(moneypunct_base);
 protected:
  typedef _RWSTD_IMP_DECL(moneypunct_data)<char> parent_type;
  static _RWSTD_IMP_DECL(moneypunct_init)<char> _RWSTDExport ivals_;      // Vendor-supplied
  _RWSTD_IMP_DECL(moneypunct_impl)
      ( _RWSTD_IMP_DECL(moneypunct_init)<char> *init=&ivals_ ):
        parent_type(init) { }
};


#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(moneypunct_impl)<char,true>:           // Specialization
    public _RWSTD_IMP_DECL(moneypunct_data)<char>
{
  friend class _RWSTD_IMP_DECL(moneypunct_base);
 protected:
  typedef _RWSTD_IMP_DECL(moneypunct_data)<char> parent_type;
  static _RWSTD_IMP_DECL(moneypunct_init)<char> _RWSTDExport ivals_;      // Vendor-supplied
  _RWSTD_IMP_DECL(moneypunct_impl)
      ( _RWSTD_IMP_DECL(moneypunct_init)<char> *init=&ivals_ ):
        parent_type(init) { }
};

#ifndef _RWSTD_NO_WIDE_CHAR
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(moneypunct_impl)<wchar_t,false>:       // Specialization
    public _RWSTD_IMP_DECL(moneypunct_data)<wchar_t>
{
 protected:
  typedef _RWSTD_IMP_DECL(moneypunct_data)<wchar_t> parent_type;
  static _RWSTD_IMP_DECL(moneypunct_init)<wchar_t> _RWSTDExport ivals_;   // Vendor-supplied
  _RWSTD_IMP_DECL(moneypunct_impl)
      ( _RWSTD_IMP_DECL(moneypunct_init)<wchar_t> *init=&ivals_ ):
        parent_type(init) { }
};

#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport _RWSTD_IMP_DECL(moneypunct_impl)<wchar_t,true>:        // Specialization
    public _RWSTD_IMP_DECL(moneypunct_data)<wchar_t>
{
 protected:
  typedef _RWSTD_IMP_DECL(moneypunct_data)<wchar_t> parent_type;
  static _RWSTD_IMP_DECL(moneypunct_init)<wchar_t> _RWSTDExport ivals_;   // Vendor-supplied
  _RWSTD_IMP_DECL(moneypunct_impl)
      ( _RWSTD_IMP_DECL(moneypunct_init)<wchar_t> *init=&ivals_ ):
        parent_type(init) { }
};
#endif // _RWSTD_NO_WIDE_CHAR

// --------------------------------------
// Implementation class -- messages_impl.
// --------------------------------------

class _RWSTDExport _RWSTD_IMP_DECL(messages_impl) {
  string loc_name_;
 protected:
  _RWSTD_IMP_DECL(messages_impl) (string name);

  messages_base::catalog open_cat_ (const string &,const locale &) const;
  char *get_mess_ (messages_base::catalog,int,int) const;
  const locale &get_loc_ (messages_base::catalog) const;
  void close_cat_ (messages_base::catalog) const;
  static string get_loc_name_ (const char*);
};

// ----------------------------------------------------
// Implementation class template -- facet_maker<Facet>.
// ----------------------------------------------------

// When use_facet (inline) finds that a locale does not contain an _EXPLICIT
// facet of the requested type, it calls locale::make__EXPLICIT (non-template)
// to create or find the facet in a cache, and install it in the locale.  As a
// parameter to make__EXPLICIT, use_facet passes a call-back function which
// make__EXPLICIT can call to construct a facet of the requested type if needed.
// The call-back functions are obtained by instantiating the following helper
// class template:

template <class Facet>
class _RWSTDExportTemplate _RWSTD_IMP_DECL(facet_maker) {
 public:
#if defined(__DECCXX) && !defined(CXXLFIX730)
  static inline _RWSTD_IMP_DECL(facet_imp) *maker_func (int,const char*,size_t);
#else
  static _RWSTD_IMP_DECL(facet_imp) *maker_func (int,const char*,size_t);
#endif
};

// ------------------------------------------------------
// Implementation function templates -- create_xxx_facet.
// ------------------------------------------------------

// The facet_maker<Facet>::maker_func functions described above delegate the
// actual construction of facets to three inline function templates named
// create_xxx_facet, where xxx is 'classic' or 'native' or 'named'.  The
// default (template) versions of these functions construct facets as follows:
//
//   classic -- default constructor for the facet with only the refs argument.
//   native -- calls create_named_facet with a name of "".
//   named -- calls create_classic_facet, ignoring the passed name.
//
// This default behavior is overridden (specialized) for certain facet types.
// In particular, create_named_facet is specialized for all facet types that
// have a derived _byname version, to construct that version with the passed
// name (see <byname>) and create_native_facet is specialized for all
// facet types whose "native" behavior (as determined by the vendor) differs
// from the byname facet with a name of "" (see <vendor>).

#if defined(__DECCXX) && !defined(CXXLFIX730)
template <class Facet>
inline _RWSTD_IMP_DECL(facet_imp) * 
_RWSTDExport _RWSTD_IMP_DECL(facet_maker)<Facet>::
    maker_func (int t, const char *name, size_t refs)
{
  if (t==0)
    return _RWSTD_IMP_DECL(create_classic_facet) ((Facet*)0);
  else if (t==1)
    return _RWSTD_IMP_DECL(create_native_facet) ((Facet*)0);
  else
    return _RWSTD_IMP_DECL(create_named_facet) ((Facet*)0,name,refs);
}
#endif

template <class Facet>
inline Facet*  _RWSTDExportTemplate _RWSTD_IMP_DECL(create_named_facet)
    (Facet*,const char*,size_t refs);

template <class Facet>
inline Facet*  _RWSTDExportTemplate _RWSTD_IMP_DECL(create_native_facet) (Facet*);

template <class Facet>
inline Facet* _RWSTDExportTemplate _RWSTD_IMP_DECL(create_classic_facet) (Facet*);

#ifndef _RWSTD_NO_NAMESPACE
} // namespace __rwstd
#endif

#if defined(__DECCXX)
#   ifdef __PRAGMA_ENVIRONMENT
#      pragma __environment __restore
#   endif
#endif

#endif // __STD_RW_LOCIMPL__
