//@copyright_begin
// ================================================================
// Copyright Notice
// Copyright (C) 1998-2004 by Joe Linoff
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL JOE LINOFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// 
// Comments and suggestions are always welcome.
// Please report bugs to http://ccdoc.sourceforge.net/ccdoc
// ================================================================
//@copyright_end

// MULTIPLE INCLUSION GUARD
#ifndef ccdoc_statement_h
#define ccdoc_statement_h

/**
 * This variable allows the header version
 * to be queried at runtime.
 */
namespace {
   char ccdoc_types_h_rcsid[] = "$Id: statement.h,v 1.8 2004/09/30 04:16:07 jlinoff Exp $";
}

#include "strmgr.h"
#include <iostream>
#include <vector>
#include <string>

namespace ccdoc {
  namespace statement {
    // ================================================================
    //@{
    // Statement base object.
    // @author Joe Linoff
    // @version $Id: statement.h,v 1.8 2004/09/30 04:16:07 jlinoff Exp $
    //@}
    // ================================================================
    class base {
    public:
      typedef vector<const char*> cstrs_t;
      typedef vector<const char*>::iterator cstrs_itr_t;
      typedef vector<const char*>::const_iterator cstrs_citr_t;
      typedef vector<const char*>::reverse_iterator cstrs_ritr_t;
    public:
      typedef vector<ccdoc::statement::base*> stmts_t;
      typedef vector<ccdoc::statement::base*>::iterator stmts_itr_t;
      typedef vector<ccdoc::statement::base*>::const_iterator stmts_citr_t;
      typedef vector<ccdoc::statement::base*>::reverse_iterator stmts_ritr_t;
    public:
      typedef vector<string> strs_t;
      typedef vector<string>::iterator strs_itr_t;
      typedef vector<string>::const_iterator strs_citr_t;
      typedef vector<string>::reverse_iterator strs_ritr_t;
    public:
      typedef vector<vector<string> > strss_t;
      typedef vector<vector<string> >::iterator strss_itr_t;
      typedef vector<vector<string> >::const_iterator strss_citr_t;
      typedef vector<vector<string> >::reverse_iterator strss_ritr_t;
    public:
      enum TYPE
	{
	  STMT_IGNORE,
	  STMT_ATTRIBUTE, // a class variable
	  STMT_ATTRIBUTE_FUNCTION, // a class variable
	  STMT_ENUM,
	  STMT_EXTERN,
	  STMT_FRIEND_CLASS,
	  STMT_FRIEND_FUNCTION,
	  STMT_FUNCTION,
	  STMT_FUNCTION_OPERATOR,
	  STMT_CLASS_BEGIN,
	  STMT_CLASS_END,
	  STMT_COMMENT_PKGDOC,
	  STMT_COMMENT_PKGDOC_URL,
	  STMT_COMMENT_PREFIX,
	  STMT_COMMENT_SUFFIX,
	  STMT_MACRODEF_0_0, // No args, no tokens: #define a
	  STMT_MACRODEF_0_1, // No args, 1 token: #define a b
	  STMT_MACRODEF_0_N, // No args, n tokens: #define a b+c
	  STMT_MACRODEF_N_N, // N args, n tokens: #define a(x,y,z) x+y+z
	  STMT_MACROINST_FUNCTION,
	  STMT_MACROINST_VARIABLE,
	  STMT_METHOD,
	  STMT_METHOD_CONSTRUCTOR,
	  STMT_METHOD_DESTRUCTOR,
	  STMT_METHOD_OPERATOR,
	  STMT_NAMESPACE_BEGIN,
	  STMT_NAMESPACE_END,
	  STMT_PACKAGE,
	  STMT_STRUCT_BEGIN,
	  STMT_STRUCT_END,
	  STMT_TYPEDEF_FUNCTION,
	  STMT_TYPEDEF_VARIABLE,
	  STMT_UNION_BEGIN,
	  STMT_UNION_END,
	  STMT_VARIABLE,
	  STMT_VARIABLE_FUNCTION
	};
      enum ACCESS
	{
	  STMT_PUBLIC,
	  STMT_PROTECTED,
	  STMT_PRIVATE
	};
    public:
      base();
      base(const base& x);
      ~base();
      base& operator=(const base& x);
      void clear();
    public:
      ACCESS get_access() const {return m_access;}
      void set_access(ACCESS t) {m_access=t;}
      const char* get_terse_access_name() const {return get_terse_access_name(m_access);}
      static const char* get_terse_access_name(ACCESS t);
      static ACCESS get_terse_access(const string&);
      const char* get_access_name() const {return get_access_name(m_access);}
      static const char* get_access_name(ACCESS t);
    public:
      TYPE get_type() const {return m_type;}
      void set_type(TYPE t) {m_type=t;}
      const char* get_terse_type_name() const {return get_terse_type_name(m_type);}
      static const char* get_terse_type_name(TYPE t);
      static TYPE get_terse_type(const string&);
      const char* get_type_name() const {return get_type_name(m_type);}
      static const char* get_type_name(TYPE t);
    public:
      /**
       * The full type name in lower case.
       * @returns The full type name in lower case.
       */
      const char* get_type_name1() const {return get_type_name1(m_type);}
      static const char* get_type_name1(TYPE t);
      /**
       * Get the full type name with static prepended.
       * @returns The full type name in lower case with static
       *          pre-pended if m_static is true.
       */
      string get_type_name2() const;
    public:
      base* get_matching_begin() const;
    private:
      base* get_matching_begin(TYPE) const;
    public:
      unsigned get_depth() const;
      unsigned get_depth_no_pkgs() const;
    public:
      unsigned get_tag() const {return m_tag;}
      void set_tag(unsigned x) {m_tag = x;}
    public:
      unsigned get_lineno() const {return m_lineno;}
      void set_lineno(unsigned x) {m_lineno = x;}
    public:
      const char* get_file() const {return m_file;}
      void set_file(const char* fn);
      void set_file(const string& fn) {set_file(fn.c_str());}
    public:
      const char* get_extern() const {return m_extern;}
      void set_extern(const char* x);
      void set_extern(const string& x) {set_extern(x.c_str());}
    public:
      const char* get_id() const {return m_id;}
      void get_hier_id(string&) const;
      void get_hier_id_no_pkgs(string&) const;
      void set_id(const char* id);
      void set_id(const string& id);
    public:
      bool get_static() const {return m_static;}
      void set_static(bool f) {m_static=f;}
    public:
      bool get_template() const {return m_template;}
      void set_template(bool f) {m_template=f;}
    public:
      void get_parents(stmts_t& parents) const;
      void get_parents_no_pkgs(stmts_t& parents) const;
      base* get_parent() const {return m_parent;}
      void set_parent(base* parent);
    public:
      base* get_comment() const {return m_comment;}
      void set_comment(base* comment) {m_comment=comment;}
    public:
      void get_all_children(stmts_t& children) const;
      stmts_t& get_children() {return m_children;}
      base* get_child_by_id(const char*) const;
      base* get_child_by_id(const string&) const;
      base* get_child_by_id_type(const char*,TYPE t) const;
      base* get_child_by_id_type(const string&,TYPE t) const;
      bool find_child(base*) const;
      void add_child(base*);
      void remove_child(base*);
      bool get_children_by_id(stmts_t&,const char*);
      bool get_children_by_id(stmts_t&,const string&);
    public:
      void insert_before(base*);
      void insert_after(base*);
    public:
      const cstrs_t& get_tokens() const {return m_tokens;}
      void set_tokens(strs_t& vec);
      void add_token(const string& str) {add_token(str.c_str());}
      void add_token(const char* str);
    public:
      void set_next(base* next) {m_next=next;}
      base* get_next() const {return m_next;}
    public:
      /**
       * Sort the children for fast access.
       */
      void sort_children();
    private:
      stmts_itr_t search(const char*);
      stmts_itr_t search(const string&);
    public:
      void debug_dump(const char* prefix);
    public:
      /**
       * Report whether this statement has an id that is a macro name
       * that should be ignored (as specified by the -rptmac1 switch).
       * This method exists here because it can be used in phase 1 or
       * phase 3.
       * @param id The macro id.
       * @returns True if this macro s/b ignored or false otherwise.
       */
       bool is_rptmac1_id() const;
      /**
       * Report whether this id is a macro name that should
       * be ignored (as specified by the -rptmac1 switch).
       * This method exists here because it can be used
       * in phase 1 or phase 3.
       * @param id The macro id.
       * @returns True if this macro s/b ignored or false otherwise.
       */
      static bool is_rptmac1_id(const char* id);
    public:
      static strmgr& get_strmgr();
    private:
      const char* set_string(const char*);
    private:
      stmts_t      m_children;
      base*        m_comment;
      const char*  m_file;
      const char*  m_id;
      const char*  m_extern;
      unsigned     m_lineno;
      base*        m_parent;
      cstrs_t      m_tokens;
      TYPE         m_type;
      ACCESS       m_access;
      unsigned     m_tag;
      bool         m_sorted;
      bool         m_static;
      bool         m_template;
      base*        m_next;
    };
    // ================================================================
    //@{
    // Statement comment object.
    // @author Joe Linoff
    // @version $Id: statement.h,v 1.8 2004/09/30 04:16:07 jlinoff Exp $
    //@}
    // ================================================================
    class comment {
    public:
      //@{
      // Default constructor.
      //@}
      comment();
      //@{
      // Statement based constructor.
      // The fields are filled from the statement tokens.
      // @param comment The comment statement.
      // If the comment is NULL, the object will have no
      // entries.
      //@}
      comment(base* stmt);
      //@{
      // Destructor.
      //@}
      ~comment();
    public:
      void set(const base::cstrs_t& tokens);
    private:
      bool set_scalar(string& token,
		      base::cstrs_citr_t& i,
		      base::cstrs_citr_t& e,
		      const char* match=0);
      bool set(string& token,
	       base::cstrs_citr_t& i,
	       base::cstrs_citr_t& e,
	       const char* match=0);
      bool set(base::strs_t& vec,
	       base::cstrs_citr_t& i,
	       base::cstrs_citr_t& e,
	       const char* match);
      bool set(base::strss_t& vec,
	       base::cstrs_citr_t& i,
	       base::cstrs_citr_t& e,
	       const char* match,
	       const char* match1);
    public:
      void get(base::strs_t& tokens);
    private:
      void get(base::strs_t& tokens,
	       const base::strs_t& vec,
	       const char* type);
      void get(base::strs_t& tokens,
	       base::strss_t& vecvec,
	       const char* type);
    public:
      bool empty() const;
      void clear();
    public:
      void add_author         (const string& name);
      void add_deprecated     (const string& name);
      void add_new_exception  (const string& name);
      void add_new_exception  (const string& name,const string& desc);
      void add_exception_desc (const string& desc);
      void add_file           (const string& name);
      void add_lineno         (const string& name);
      void add_long_desc      (const string& desc);
      void add_new_param      (const string& name);
      void add_new_param      (const string& name,const string& desc);
      void add_param_desc     (const string& desc);
      void add_pkg            (const string& desc);
      void add_pkgdoc         (const string& desc);
      void add_pkgdoc_tid     (const string& desc);
      void add_returns        (const string& desc);
      void add_new_see        (const string& name);
      void add_new_see        (const string& name,const string& desc);
      void add_see_desc       (const string& desc);
      void add_short_desc     (const string& desc);
      void add_todo           (const string& desc);
      /**
       * Set the version for the @since directive.
       * @param version The since version string.
       * @since r24
       */
      void add_since          (const string& version);
      void add_source         (const string& name);
      void add_version        (const string& name);
      void add_suffix         (bool f            ) {m_suffix=f;}
    public:
      const base::strs_t&  get_authors()    const {return m_authors;}
      const base::strs_t&  get_deprecated() const {return m_deprecated;}
      const base::strss_t& get_exceptions() const {return m_exceptions;}
      const string&        get_file()       const {return m_file;}
      const string&        get_lineno()     const {return m_lineno;}
      const base::strs_t&  get_long_desc()  const {return m_long_desc;}
      const base::strss_t& get_params()     const {return m_params;}
      const base::strs_t&  get_pkg()        const {return m_pkg;}
      const base::strs_t&  get_pkgdoc()     const {return m_pkgdoc;}
      const base::strs_t&  get_returns()    const {return m_returns;}
      const base::strss_t& get_sees()       const {return m_sees;}
      const base::strs_t&  get_short_desc() const {return m_short_desc;}
      const base::strs_t&  get_todo()       const {return m_todo;}
      /**
       * Get the version for the @since directive.
       * @returns The since string.
       * @since r24
       */
      const string&        get_since()      const {return m_since;}
      const string&        get_source()     const {return m_source;}
      const string&        get_version()    const {return m_version;}
      bool                 get_suffix()     const {return m_suffix;}
    public:
      const string& get_pkgdoc_url() const;
      const string& get_pkgdoc_tid() const;
    private:
      base*         m_stmt; // Issue 0053
      base::strs_t  m_authors;
      base::strs_t  m_deprecated;
      base::strss_t m_exceptions;
      string        m_file;
      string        m_lineno;
      base::strs_t  m_long_desc;
      base::strss_t m_params;
      base::strs_t  m_pkg;
      base::strs_t  m_pkgdoc;
      base::strs_t  m_returns;
      base::strss_t m_sees;
      base::strs_t  m_short_desc;
      string        m_since;
      string        m_source;
      base::strs_t  m_todo; // Issue 0120
      string        m_version;
      bool          m_suffix;
    };
  }
}

#endif

