/*
  CoreLinux++ 
  Copyright (C) 1999 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library Library is distributed in the hope that it will 
   be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/   

/** \example examp1.cpp
   This example is to show use of CoreLinux includes and define
   capability, while also setting up a build.
   
   CoreLinux C++ standards shown in this example:
   
   Section  3.0   Liberal comments
                  Code and comments visually seperated
                  Header comments (thats what this is)
                  Block comments
                  Spaces instead of tabs
                  3 spaces used for indentation
                  
   other examples are noted in the code.                  
   
*/                   

//
// Common.hpp included before anything else. This is not
// required but it makes things consistent. You can also
// wrap it with:
//
// #if   !defined(_COMMON_HPP)
// #include <Common.hpp>
// #endif
//
// if file i/o during compilation should be reduced.
// Each CoreLinux header has itself wrapped as well so
// multiple includes or cross-includes are harmless
//

#include <Common.hpp>          

#include <Person.hpp>

using namespace corelinux;

#include <iostream>
using namespace std;
#include <exception>


//
// In module function prototypes
//

int   main( void );                       // Aligned trailing comments 
void  checkWifesAge( AgeCref, AgeCref );  // (Section 3.0)
void  bar( void );   // WRONG! Comment should line up

//
// Assertion and Exception handlers
//
void  handleAssertion( AssertionCref aAssert );
void  handleException( ExceptionCref );   


int main( void )
{
   Age      oldAge(99);                   // Use constructor syntax
   Age      agetErr = 0;                  // WRONG! Use constructor syntax
                                          // We would construct and then
                                          // assign if real object.

   //
   // Practice gracefull exception management
   //

   try
   {

      Name     franksName(TEXT("Frank"));    
      Person   frank(franksName,42);         // Person instance

      //
      // Comment out the following if you want to
      // ignore test invarient and illegal attempts
      //

      cout  << frank.getName() << " is " << frank.getAge() << endl;
      try
      {
         frank.setAge(Limits::LONGMAX);
      }
      catch( AssertionRef aAssert )
      {
         handleAssertion(aAssert);
      }
      catch( ExceptionRef aException )
      {
         handleException(aException);
      }
      cout  << frank.getName() << " is " << frank.getAge() << endl;

      //
      // The following is to show that the developer
      // knows the intent of the if test, and clearly
      // shows this by the empty else (Section 4.3). 
      // See ex2 for assertion examples
      //

      if( frank < oldAge )
      {
         cout  << "Ahh, to be young again!" << endl;
      }
      else
      {
         ;  // do nothing
      }

      //
      // WRONG! Line too long, no continuation, etc.
      //

      if( frank > oldAge ) cout  << "Wow, they let you out in the world? " << agetErr << endl;

      //
      // This shows that we don't want to instantiate until needed
      //
      Name     wifesName(TEXT("Jane"));
      Person   franksWife(wifesName,21);
      Age      wifesRealAge(41);

      //
      // Test wife units age and call her on it (Section 3.0)
      //

      cout  << "My wife " << franksWife.getName() <<
         " says that she is " << AgeCref(franksWife) <<
         " years old. Lets see about that..." << endl;

      checkWifesAge( franksWife,wifesRealAge );

      //
      // Section 4.3
      //

      if( agetErr < 0 )
      {
         ;  // do nothing
      }
      else if( agetErr > 0 )
      {
         ;  // do nothing
      }
      else
      {
         // NEVER_GET_HERE;
         throw Exception(TEXT("Un-handled situation"),LOCATION);
      }

   }
   catch( AssertionRef aAssert )
   {
      handleAssertion(aAssert);
   }
   catch( ExceptionRef aException )
   {
      handleException(aException);
   }
   catch( std::exception & e )
   {
      cerr  << e.what() << endl;
   }
   catch( ... )
   {
      cerr  << "Unknown exception." << endl;
   }
   // No line exceeds the 78 column positions (Section 4.6)                --|

   return 0;               // Single exit point (Section 4.0)
}

//
// Routine to check what age was specified against
// the reality of it.
//

void checkWifesAge( AgeCref aToldAge, AgeCref aRealAge )
{
   if( aToldAge < aRealAge  )
   {
      //
      // Two points:
      // 1. Comment block is indented to indicate what it is
      // that is being commented on. (Section 3.0)
      // 2. Wrapping indents continuation lines (Section 4.6)
      //

      cout  << "She has some explaining to do because " <<
         aRealAge  - aToldAge << 
            " years is a big difference! ";

   }
   else if( aToldAge == aRealAge )      // Section 4.3
   {
      cout  << "I'll never tell";
   }
   else
   {
      cout  << "Don't worry, you look great.";
   }

   // Flush buffer

   cout  << endl;

   return;  // not required on void 
}

//
// Peform default (just show it)
//

void  handleAssertion( AssertionCref aAssert )
{
   cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << 
      "Assertion: ";

   if( aAssert.getType() == Assertion::NEVERGETHERE )
   {
      cerr << "NEVER_GET_HERE";
   }
   else
   {
      if( aAssert.getType() == Assertion::REQUIRE )
      {
         cerr  << "REQUIRE";
      }
      else if( aAssert.getType() == Assertion::ENSURE )
      {
         cerr  << "ENSURE";
      }
      else if( aAssert.getType() == Assertion::CHECK )
      {
         cerr  << "CHECK";
      }
      else 
      {
         cerr  << "ASSERT";
      }
      cerr << "( " << aAssert.getWhy() << " )";
   }

   cerr << endl;
}

void  handleException( ExceptionCref aExcp )
{
   cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
      "Exception: " << aExcp.getWhy() << endl;
}

// Trailer CVS information only (Section 3.0)

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.3 $
   $Date: 2000/08/31 22:51:01 $
   $Locker:  $
*/


