//@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_phase1_scanner_h
#define ccdoc_phase1_scanner_h

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

#include <string>
#include <vector>
#include <fstream>
#include "switches.h"
#include "statement.h"

namespace ccdoc {
  namespace phase1 {
    // ================================================================
    //@{
    // Scanner object.
    // @author Joe Linoff
    // @version $Id: phase1_scanner.h,v 1.7 2004/09/30 04:16:07 jlinoff Exp $
    //@}
    // ================================================================
    class scanner {
    public:
      scanner(switches&);
      ~scanner();
    public:
      void open(const string& name);
      void close();
    public:
      bool get_debug() const {return m_debug;}
      void set_debug(bool f) {m_debug=f;}
    public:
      char get_char();
      void put_char(char ch);
    public:
      bool get_token(string& token)
      {
	const char* x = get_token();
	token = x;
	return *x != 0;
      }
      void put_token(const string& token);
      const char* get_token();
    public:
      unsigned get_lineno() const {return m_lineno;}
      const char* get_file() const {return m_name.c_str();}
    private:
      const char* scan_token();
      char skip_ws();
      char scan_trigraph();
      void get_string_literal(char* token,int max);
      void get_char_literal(char* token,int max);
      void get_number_literal(char* token,int max);
      void get_identifier(char* token,int max);
      const char* scan_ccdoc_style1(char*,int max);
      bool scan_ccdoc_style1_special();
      const char* scan_ccdoc_style2(char*,int max);
      void strip_token(char* buf,const char* token) const;
      bool contains_token(const char* buf,const char* token) const;
    private:
      string m_name;
      ifstream m_is;
      unsigned m_lineno;
      vector<char> m_put_chars;
      vector<string> m_put_tokens;
      switches& m_sw;
      bool m_debug;
    };
    // ================================================================
    //@{
    // Scanner doc object.
    // @author Joe Linoff
    // @version $Id: phase1_scanner.h,v 1.7 2004/09/30 04:16:07 jlinoff Exp $
    //@}
    // ================================================================
    class scanner_doc {
    public:
      scanner_doc(scanner&,switches& sw);
      ~scanner_doc();
      bool empty() const;
      const char* format(char* token,int max);
      void parse_line(char* line);
    private:
      void parse_comment_line(const char* line);
      bool is_directive(const char*,const char*,bool =false) const;
      void add_line(const char* line);
      void add_line(const char* line,vector<string>&);
      bool scan_1arg(const char* line,
		     string& arg,
		     const char* directive,
		     const char* argid,
		     bool report_errors=true);
      bool scan_2args(char* pstr,
		      string& arg1,
		      string& arg2,
		      const char* directive,
		      const char* arg1id,
		      const char* arg2id,
		      bool arg2_required=true);
      void parse_pkg_path(string& arg,
			  const char* directive,
			  vector<string>& vec);
      bool parse_pkg_path_entry(char*,const char*);
      void report_multiply_defined_error(const char* directive) const;
    public:
      scanner& m_scanner;
      enum MODE
	{
	  DEPRECATED,
	  EXCEPTION,
	  LONG,
	  PARAM,
	  RETURNS,
	  SEE,
	  SHORT,
          TODO
	};
      MODE m_mode;
      statement::comment m_comment;
    private:
      switches& m_sw;
    };
  }
}

#endif
