#!/bin/bash

#    C++ class template utility
#          by sandro@w3.org, over many years
#

# TO DO
#       use an "init" in constructor, normally, so 
#       body can be in .cc, with : init(...) in .h  ?
#        

# make more configurable
author='\URL[Sandro Hawke]{http://www.w3.org/People/Sandro} (sandro@w3.org)'

class=$1

if [ -z "$1" ]; then
  echo "usage: $0 <classname>"
  exit 1
fi

if (echo $class | grep -q '::'); then
  ns=`echo $class | sed 's/::.*//'`
  class=`echo $class | sed 's/.*:://'`
  echo Using namespace '"'$ns'"' with class '"'$class'"'.
  begin_ns="namespace $ns {

"
  end_ns="}

"
  using_ns="using $ns::$class;

"
  ns_filepre="${ns}_"
  ns_classpre="${ns}::"
fi

hf=${ns_filepre}$class.h
cf=${ns_filepre}$class.cpp

if [ -f $hf ]; then
  echo file $hf already exists.   remove it first.
  exit 1
fi
if [ -f $cf ]; then
  echo file $cf already exists.   remove it first.
  exit 1
fi

# I'm assuming the path part of the root is probably highly redundant
cvsroot=`cat CVS/Root | sed s/:.*//`
cvsrepos=`cat CVS/Repository`
package="${cvsroot}__${cvsrepos}"
uppercase=`echo ${package}_${ns_filepre}$hf | tr a-z./: A-Z_`
flag=$uppercase

if [ -f boilerplate.txt ]; then
  sed 's:^:// :' < boilerplate.txt > $hf
fi

cat <<_EOF >> $hf
#ifndef $flag
#define $flag
// \$Id\$
#include "config.h"

$begin_ns/**
    A $class is a (documentation goes here).
**/
class $class {
      
public:

    // STANDARD MEMBER FUNCTIONS
    $class();
    $class(const $class& other);
    const $class& operator=(const $class& other);
    bool operator==(const $class& other) const;
    bool operator<(const $class& other) const;
    size_t hash() const;
    friend std::ostream& operator<<(std::ostream& s, const $class& me);
    std::ostream& print_to(std::ostream& stream) const;	
    ~$class();       

    // OVERRIDES

    // CLASS-SPECIFIC PUBLIC INTERFACE


private:


};     
$end_ns
STANDARD_EXTERNAL($ns_classpre$class)

#endif  /* $flag */   // -*-C++-*-
_EOF
#// Local Variables:
#// mode:C++
#// End:



if [ -f boilerplate.txt ]; then
  sed 's:^:// :' < boilerplate.txt > $cf
fi

cat <<_EOF > $cf
#define TRACE_NAME "$class"
#include "$hf"
// \$Id\$

$using_ns
////////////////////////////////////////////////////////////////
//
//  Static Initializers
//
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
//
//  Standard Member Functions
//
////////////////////////////////////////////////////////////////

$class::$class()
{
    // blank default	
}

#if 0  /* omit definitions until they are implemented */

$class::$class(const $class& other)
{
    NOT_IMPLEMENTED
}

const $class& $class::operator=(const $class& other)
{
    NOT_IMPLEMENTED
}

bool $class::operator==(const $class& other) const
{
    NOT_IMPLEMENTED
}

bool $class::operator<(const $class& other) const
{
    NOT_IMPLEMENTED
}

size_t $class::hash() const
{
    NOT_IMPLEMENTED
}

std::ostream& $class::print_to(std::ostream& stream) const
{
    NOT_IMPLEMENTED
}

#endif /* omit definitions until they are implemented */
	
$class::~$class()
{
    // blank default	
}

////////////////////////////////////////////////////////////////
//
//  Additional Public Member Functions
//
////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////
//
//  Additional Private Member Functions
//
////////////////////////////////////////////////////////////////

_EOF
exit
fi
