/*---------------------------------------------------------------------------------------------------------------------
- File      : globalsdef.h                                                                Project ELSE, EPFL - DI/LIA -
-                                                                       Evaluation in Language and Speech Engineering -
- Author    : Seydoux Florian   Creation date : xx May 1999                                                           -
- Eulogist  : -                 Approval date : -                  Version: 0.1                                       -
-                                                                                                                     -
- Descript. : Contains the definition of all global (basic) items                                                     -
-             Some minor adaptation for some components (compilator specific) to respect the ANSI C++ reference       -
-             'ISO/IEC Programming Languages --C++ 14 882  (1998 ANSI C++ Reference)'                                 -
-                                                                                                                     -
- Requested : -                                                                                                       -
-                                                                                                                     -
- Remarks   : o) [ANSI C++] Reference will refere to the "ISO/IEC Programming Languages --C++, Rf no 14882-1998(E)"   -
-                (An obsolet Draft version of this norme (1997 C++ Public Rewiew Document) can be found on the net    -
-                 http://www.maths.warwick.ac.uk/cpp/pub/wp/html/cd2/  or http://www.cygnus.com/misc/wp/ ).           -
-                                                                                                                     -
-             o) [STL] will refere to the SiliconGraphics's library (see http://www.sgi.com/Technology/STL/index.html)-
-                the current version (3.2, April 1999) seems to be conform with the ISO Standard.                     -
-                                                                                                                     -
-             o) [STR] will refere to the Bjarne Stroustrup's book:                                                   -
-                      The C++, Programming Language third edition, 7th Printing July 1998 (!!), ISBN: 0-21-88954-4   -
-                                                                                                                     -
-             o) Gcc 2.8.1. for Sun solaris raise internal error on constant and static attributes defined and        -
-                instanciated in header files... (without -g option, and with optimisation level 1, 2 or 3).          -
-                So we made all of these 'global' objects extern (in header), and instancied them in some .cc file    -
-                                                                                                                     -
- Gaps      : o)                                                                                                      -
-                                                                                                                     -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Rev. date | Reviser               | Revise's description                                                            -
- - - - - - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ../../....| ........              | ...                                                                             -
---------------------------------------------------------------------------------------------------------------------*/

//
// l'enregistrement du 'suivant' devrait (?) faire partie du modele 'agent'... ou specilisation suppl.
// 
// Cnv: lorsqu'une instance est tjs requise: passage par reference.
// Memorisation interne d'un acces (reference, modifiable): type*
// Creation: typePtr (event. auto-pointer)
// Passage de pointeur: typePtr
// Collection: passage de refence (instance): duree de vie gestion locale
// passage (enreggistrement) de pointeur: desalloue par la collection (event. flag fixant la strategie) 
// 
// Definition d'un cstring (ou autre nom, plus court que 'conform_string').
// Extension, hors specif. compilateur, ŕ un type 'privé', genre 'extendedString, ou estring, pstring, str...
// admettant les 'facilites' 'push_back, push_front, back, pop...
// 

#ifndef GLOBALSDEF_H
#define GLOBALSDEF_H    

#include <string>
#include <vector>
#include <cassert>
#include <iostream>
#include <climits>

/*-----------------------------------------------------------------------
-                                                                       -
- Compiler settings                                                     -
-                                                                       -
- This section must certainly adapted for particular compiler/version.  -
- Currently tested (and supported) compilers are:                       -
-                                                                       -
- // NOT // (1) MetroWerks CodeWarrior 3.1 for Win32                    -
- (2) Gnu Gcc (C++) 2.8.1. for SunSolaris                               -
- (3) Gnu Egcs(C++) 2.91 for linux i386                                 -
-                                                                       -
-----------------------------------------------------------------------*/

// 
// Some symbols and macros must be defined in this file. For the compilator's adaptation, they are:
// 
// _USE_NAMESPACES       -> defined if the compiler fully support the namespaces
// _MEMBER_TEMPLATES     -> defined if the compiler support template methode
// SKIP_UNTIL_EOF        -> max integer
// THROW(Exception)      -> must raise the (uncatched) exception, or provide a ~similar traitement.
//                          (With gcc 2.8.0/1, depend on the scope level, throwing an exception raise a bus error,
//                           but not the exception...)
// TYPEID_IS(x,Y)        -> must return true if (typeid(x) == typeid(Y))
// TYPEIS_IS_NOT(x,Y)    -> must return true if (typeid(x) != typeid(Y))
//                          (Again with gcc 2.8.0/1, the return type of 'typeid()' hasn't public '==' or '!=' operator)
//
// The others needed symbols are define at the end of this file.

// moche patch de isspace('é') == true ...
bool is_space(const char c);

#ifdef NDEBUG
    #define THROW(exception) throw exception
#else
    #define THROW(x) assert(false)
#endif
/* Warning: With gcc 2.8.(0/1), depend on scope level, throw raise a bus error, but not the exception ! */


#ifdef __GNUC__ 

    // 
    // Namespace supported by egcs (2.9.x), but not by gnu 2.8.x.
    // AnsiC++ support not very good (many headers miss).
    // 
   
    #include<strstream>
    #include<limits.h>
    
    #ifdef __STL_USE_NAMESPACES
        #define _USE_NAMESPACES
    #else
        #undef _USE_NAMESPACES
    #endif

    #ifdef __STL_MEMBER_TEMPLATES
        #define _MEMBER_TEMPLATES
    #else
        #undef _MEMBER_TEMPLATES
    #endif
    
    const int SKIP_UNTIL_EOF = INT_MAX;

    #ifdef _USE_NAMESPACES
    namespace std {
    #endif // _USE_NAMESPACES
    class conform_string: public string {
    public:
        // Constructors redirection ..................................
        inline explicit conform_string (): string()    {}
        inline conform_string (const string& str): string(str) {}
        inline conform_string (const string& str, size_type pos, size_type n = npos): string(str,pos,n) {}
        inline conform_string (const char* p, size_type n): string(p,n) {}
        inline conform_string (const char* p): string(p) {}
        inline conform_string (size_type n, char c): string(n,c) {}
        #ifdef _MEMBER_TEMPLATES
            template<class InputIterator>
            inline conform_string(InputIterator begin, InputIterator end): string(begin, end) {}
        #else
            inline conform_string(const_iterator begin, const_iterator end): string(begin, end) {}
        #endif // _MEMBER_TEMPLATES

        // Unimplemented features .................................. 

        /* Append a single character to *this 
         * [STR] § 20.3.9 (3th printing and later)
         * [STL] Sect. 3.2.3, bash_string
         * [ANSI C++]  § 21.3.5 basic_string
        */
        inline void push_back(const char t)
        {
            (*this) += t;
        }

        /* Erase the entire container
         * [STL] Sect. 3.2.3, bash_string
         * [ANSI C++]  § 21.3.3 basic_string
        */       
        inline void clear()
        {
            erase(); // erase(begin(), end());
            assert(empty());
        }

        // Useful features ..................................  (Not in the Norme!)

        /* Like other containers with back insertion (the most),
         * 'back' will return a reference to the last element of the container.
         * Warning: unchecked access !
        */
        inline char& back()
        {
            return *(end()-1);
        }

        inline const char& back() const
        {
            return *(end()-1);
        }

        inline void pop_back()
        {
            erase(end()-1);
        }

        inline char& front()
        {
            return *begin();
        }

        inline const char& front() const
        {
            return *begin();
        }

        inline void pop_front()
        {
            erase(begin());
        }

        /* Remove white character at the begining and/or the end of the string,
         * and return a reference to this. Not designed for efficiency !!!
        */
        inline conform_string& ws_front()
        {
            while ( !empty() && is_space(front()) )
                pop_front();
            return *this;
        }
        
        inline conform_string& ws_back()
        {
            while ( !empty() && is_space(back()) )
                pop_back();
            return *this;
        }

        inline conform_string& ws()
        {
            return ws_front().ws_back();
        }
    };

    typedef strstream   stringstream;

    class ostringstream: public ostrstream {
    public:
        string str() const
        {
            ostringstream& my(const_cast<ostringstream&>(*this));
            my << '\0';
            return string(my.ostrstream::str());
        }
    };

    class istringstream: public istrstream {
    public:
            istringstream(const string initStr) : istrstream(initStr.c_str()) { }
    };
   
    #ifdef _USE_NAMESPACES
    }        
    #endif // _USE_NAMESPACES


    #if ( __GNUC_MINOR__ <= 8 )
	    // Gnu Gcc 2.8.x
    	#undef THROW
	    #define THROW(x) assert(false)

		#define TYPEID_IS(x,Y) (dynamic_cast<Y>(x))
		#define TYPEIS_IS_NOT(x,Y) !(dynamic_cast<Y>(x))

    #elif __GNUC_MINOR__ <= 91
	    // Egcs gcc 2.9.91
        #undef THROW
	    #define THROW(x) assert(false)
		#define TYPEID_IS(x,Y) (typeid(x) == typeid(Y))
		#define TYPEIS_IS_NOT(x,Y) (typeid(x) != typeid(Y))
        
    #elif __GNU_MINOR_CC <= 95
    // Egcs-gnu 2.95, first mixed (and latest at this time) 

    // Add your __GNUC__ compiler version and adaptation 
    // ...
    

    #endif


#elif defined  __MWERKS__
    //
    // Namespace supported by default. AnsiC++ support good, with only
    // on or two miss; perhaps ok in newer release (4 and later).
    // (My version is very yet obsolecent, but...)
    // 

    #include<sstream>
    #include<limit>
    
    #ifdef MSIPL_USING_NAMESPACE
        #define _USE_NAMESPACES
        const int SKIP_UNTIL_EOF = std::numeric_limits<int>::max();
    #else
        #undef _USE_NAMESPACES
        const int SKIP_UNTIL_EOF = numeric_limits<int>::max();
    #endif

    #ifdef MSIPL_MEMBER_TEMPLATE
        #define _MEMBER_TEMPLATES
    #else
        #undef _MEMBER_TEMPLATES
    #endif

	#define TYPEID_IS(x,Y) (typeid(x) == typeid(Y))
	#define TYPEIS_IS_NOT(x,Y) (typeid(x) != typeid(Y))

    #ifdef _USE_NAMESPACES
    namespace std {
    #endif // _USE_NAMESPACES
    typedef allocator<char> Allocator;
    class conform_string: public string {
    public:
    
        // Constructors redirection ..................................

        inline explicit conform_string(const Allocator& a = Allocator())
               : string(a)
        { } 
        inline conform_string(const char* p, size_type n, const Allocator& a = Allocator())
               : string(p,n,a)
        { }
        inline conform_string(const char* p, const Allocator& a = Allocator())
               : string(p,a)
        { }
        inline conform_string(size_type n, char c, const Allocator& a = Allocator())
               : string(n,c,a)
        { }
        inline conform_string(const string& s, size_type pos = 0,
                              size_type n = npos, const Allocator& a = Allocator())
               : string(s,pos,n,a)
        { }

        #ifdef _MEMBER_TEMPLATES
            template<class InputIterator>
            inline conform_string(InputIterator first, InputIterator last,
                                  const Allocator& a = Allocator())
                      : string(first, last, a)
            { }
        #else
            inline conform_string(const_iterator first, const_iterator last,
                                  const Allocator& a = Allocator ())
                      : string(first, last, a)
            { }
        #endif // _MEMBER_TEMPLATES


        // Unimplemented functions ..................................

        inline void push_back(const char t)
        {
            (*this) += t;
        }

        // Useful features ..................................  (Not in the Norme!)

        /* Like other containers with back insertion (the most),
         * 'back' will return a reference to the last element of the container.
         * Warning: unchecked access.
        */
        inline char& back()
        {
            return *(end()-1);
        }

        inline const char& back() const
        {
            return *(end()-1);
        }

        inline void pop_back()
        {
            erase(end()-1);
        }
        inline char& front()
        {
            return *begin();
        }

        inline const char& front() const
        {
            return *begin();
        }

        inline void pop_front()
        {
            erase(begin());
        }

        /* Remove white character at the begining and/or the end of the string,
         * and return a reference to this. Not designed for efficiency !!!
        */
        inline conform_string& ws_front()
        {
            while ( !empty() && is_space(front()) )
                pop_front();
            return *this;
        }
        
        inline conform_string& ws_back()
        {
            while ( !empty() && is_space(back()) )
                pop_back();
            return *this;
        }

        inline conform_string& ws() 
        {
            return ws_front().ws_back();
        }
    };
}

// Add your non __GNUC__ compiler and adaptation
// ...

#endif // __MWERKS__


#ifdef _USE_NAMESPACES
    namespace Else { using namespace std;
#endif // _USE_NAMESPACES

//
// Required and optional macros or symbols are, for the project's part:
// 
// ShortNatural -> a numeric type of integer, ...  // A completer (c.f. AdaLRM for proper definition)
// Natural      -> idem than ShortNatural, but with a same or larger domain.
// ...
// Macros:
// MAX_SHORT_NATURAL, MIN_SHORT_NATURAL
// ...
// 


// Enable verification of ContractedTag's segmentation (c.f. tags.h).
// Comment next lines, or give option -DNO_UNCHECKED_TAG at compil. time to disable this verification.
#ifndef NO_UNCHECKED_TAG
#define UNCHECKED_TAG
#endif

// Enable reference tags patching: (A+B) -> (A+B|A|B) (c.f. tags_mapping_table.h)
// Comment next lines, or give option -DNO_CONTRACTED_PATCH at compil. time to disable this patch.
#ifndef NO_CONTRACTED_PATCH
#define CONTRACTED_PATCH
#endif

// Enable the specific evaluation (enable post-mapping remove of neutralized tags, and the specific case checking).
// Comment next lines or give option -DNO_SPECIFIC  at compil. time to disable this feature.
#ifndef NO_SPECIFIC
#define SPECIFIC
#endif

typedef unsigned int          Natural;
typedef unsigned long         LongNatural;
typedef unsigned short        ShortNatural;
typedef unsigned long long    VeryLongNatural;

typedef float                 ShortReal;
typedef double                Real;

typedef string*               StringPtr;
typedef const string*         StringCPtr;
typedef conform_string*       ConformStringPtr;
typedef const conform_string* ConformStringCPtr;

extern const Natural MAX_NATURAL;
extern const ShortNatural MAX_SHORT_NATURAL;


class Parameters: public vector<const char*> {
public:
    Parameters(int argc, char* argv[])
    : vector<const char*>()
    {
        for (int i = 1; i < argc; ++i)
            push_back(argv[i]);
    }
};

class GraceTools {  // voir si mth static, ou simplement attribut cst ne serait pas mieux
public:
    virtual const string& nickname() const = 0;
    virtual const unsigned char& id() const = 0;
};

enum SeparatorId { EndToken = 0, EndTag = 1, StartCmt = 2, EndCmt = 3, StartCmtTbl = 4, EndCmtTbl = 5 };
enum TypeTable { DirectTbl, ReverseTbl, UnknownTbl };
enum SingleRes { Ok, NonEval, Err, Sil };

const char ALTERNATE_MARK('|');
const char CONTRACTION_MARK('+');
const char SEGMENTATION_MARK('/');
const char SEGMENTATION_SUBMARK('.');

extern const string START_EVALUATED_PART;
extern const string STOP_EVALUATED_PART;

enum CharCategory { Alphabetic, Numeric, Other, Separator };
CharCategory categorize(const char& chr);

// Reads a string (s) from the input stream (in), stopping when it reaches one of delim, and don't put it on s.
// Return the index of the reached delimitor, npos if end stream is reached before any delimiter.
string::size_type extendedGetLine(istream& in, string& s, const string& delim);

// Like extendedGetLine, but delim char are not extracted from the stream.
string::size_type extendedGet(istream& in, string& s, const string& delim);

//
// A placer ailleur (ds fichier unique, mais de niveau direct. inf).
// 
class LocalisedData {
      friend ostream& operator<<(ostream&, const LocalisedData&); // a virer.
public:
    LocalisedData()
    : from(0),
      to(0)
    { }
    
    LocalisedData(const VeryLongNatural& from, const VeryLongNatural& to)
    : from(from),
      to(to)
    { }

    void clear()
    {
        from = 0;
        to = 0;
    }

public:
    VeryLongNatural from;
    VeryLongNatural to;
};

class LocalisedString : public conform_string, public LocalisedData {
public:
    LocalisedString()
    : conform_string(),
      LocalisedData()
    { }

    LocalisedString(const string& str)
    : conform_string(str),
      LocalisedData()
    { }

    LocalisedString(const string& str, const LocalisedData& loc)
    : conform_string(str),
      LocalisedData(loc)
    { }
    
    LocalisedString(const string& str, const VeryLongNatural& from, const VeryLongNatural& to)
    : conform_string(str),
      LocalisedData(from,to)
    { }

    void clear()
    {
        conform_string::clear();
        LocalisedData::clear();
    }

    LocalisedString& append(const string& str)
    {
        conform_string::append(str);
        return *this;
    }
        
};


extern ostream& errorStream; // (cout);  /// A virer (MessagesManager)


#ifdef _USE_NAMESPACES
    }
#endif // _USE_NAMESPACES

#endif // GLOBALSDEF_H

