<commit_before>/*
 * application_main.cpp
 *
 *  Created on: 2015年1月7日
 *      Author: salmon
 */

#include <iostream>
#include <string>

#include "../io/io.h"
#include "../parallel/parallel.h"
#include "../sp_config.h"
#include "../utilities/log.h"
#include "../utilities/config_parser.h"
#include "application.h"
#include "logo.h"

/**
 *  @ingroup application
 *
 *  main entry of user case.
 */
int main(int argc, char **argv)
{
	using namespace simpla;

	init_logger(argc, argv);
	init_parallel(argc, argv);
	init_io(argc, argv);

	ConfigParser options;
	options.init(argc, argv);

	bool no_logo = false;
	bool show_help = false;

	if (options["V"] || options["version"])
	{
		MESSAGE << "SIMPla " << ShowVersion();
		TheEnd(0);
		return TERMINATE;
	}
	else if (options["h"] || options["help"])
	{
		show_help = true;
	}

	SpAppList & applist = SingletonHolder<SpAppList>::instance();
	if (GLOBAL_COMM.process_num() == 0)

	MESSAGE << ShowCopyRight() << endl;

	if (options["SHOW_HELP"])
	{
		MESSAGE << " Usage: " << argv[0]
				<< " --case <id of use case>  <options> ..." << endl << endl;

		MESSAGE << " Use cases:" << std::endl;

		for (auto const & item : applist)
		{
			MESSAGE << "\t" << item.first << "\t:" << item.second->description()
					<< std::endl;
		}

		MESSAGE << " Options:" << endl;

		SHOW_OPTIONS("-h", "Print help information");
		SHOW_OPTIONS("-v,--version", "Print version");
		SHOW_OPTIONS("-g,--generator", "Generates  demo configure file");
	}

	auto item = applist.begin();

	if (options["case"])
	{
		item = applist.find(options["case"].template as<std::string>());
	}

	if (item != applist.end())
	{
		GLOBAL_COMM.barrier();
		MESSAGE
		<<std::endl
		<<"===================================================="<<std::endl
		<<"   Use Case ["<<item->first <<"]:  "<<std::endl
		<<"\t"<<item->second->description()<<std::endl
		<<"----------------------------------------------------"<<std::endl
		;

		item->second->body(options);

		GLOBAL_COMM.barrier();
	}

	close_io();
	close_parallel();
	close_logger();

	return 0;

}
<commit_msg>snapshot<commit_after>/*
 * application_main.cpp
 *
 *  Created on: 2015年1月7日
 *      Author: salmon
 */

#include <iostream>
#include <string>

#include "../io/io.h"
#include "../parallel/parallel.h"
#include "../sp_config.h"
#include "../utilities/log.h"
#include "../utilities/config_parser.h"
#include "application.h"
#include "logo.h"

/**
 *  @ingroup application
 *
 *  main entry of user case.
 */
int main(int argc, char **argv)
{
	using namespace simpla;

	init_logger(argc, argv);
	init_parallel(argc, argv);
	init_io(argc, argv);

	ConfigParser options;
	options.init(argc, argv);

	bool no_logo = false;
	bool show_help = false;

	if (options["V"] || options["version"])
	{
		MESSAGE << "SIMPla " << ShowVersion();
		TheEnd(0);
		return TERMINATE;
	}
	else if (options["h"] || options["help"])
	{
		show_help = true;
	}

	SpAppList & applist = SingletonHolder<SpAppList>::instance();
	if (GLOBAL_COMM.process_num() == 0)

	MESSAGE << ShowCopyRight() << endl;

	if (options["SHOW_HELP"])
	{
		MESSAGE << " Usage: " << argv[0]
				<< " --case <id of use case>  <options> ..." << endl << endl;

		MESSAGE << " Use case list:" << std::endl;

		for (auto const & item : applist)
		{
			MESSAGE << "\t" << item.first << "\t:" << item.second->description()
					<< std::endl;
		}

		MESSAGE << " Options:" << endl;

		SHOW_OPTIONS("-h", "Print help information");
		SHOW_OPTIONS("-v,--version", "Print version");
		SHOW_OPTIONS("-g,--generator", "Generates  demo configure file");
	}

	auto item = applist.begin();

	if (options["case"])
	{
		item = applist.find(options["case"].template as<std::string>());
	}

	if (item != applist.end())
	{
		GLOBAL_COMM.barrier();

		MESSAGE
		<<std::endl
		<<"===================================================="<<std::endl
		<<"   Use Case ["<<item->first <<"]:  "<<std::endl
		<<"\t"<<item->second->description()<<std::endl
		<<"----------------------------------------------------"<<std::endl
		;

		item->second->body(options);

		GLOBAL_COMM.barrier();
	}

	MESSAGE << "===================================================="
			<< std::endl

			<< "\t >>> Done <<< " << std::endl;
	close_io();
	close_parallel();
	close_logger();

	return 0;

}
<|endoftext|>


<commit_before>Mac OS X        	2ATTRxThis resource fork intentionally left blank   <commit_msg>Removes temporary Mac hidden binary file<commit_after><|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <string>
#include <cstring>
#include <bh.h>
#include "bh_fuse.h"
#include "bh_fuse_cache.h"
#include <fstream>
#include <exception>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/version.hpp>
#include <boost/algorithm/string/predicate.hpp> //For iequals()

using namespace std;
using namespace boost;
using namespace boost::filesystem;

namespace bohrium {

    //Constructor of the InstrHash class
    InstrHash::InstrHash(BatchHash &batch, const bh_instruction &instr)
    {
        BOOST_FOREACH(const bh_view &view, instr.operand)
        {
            if(bh_is_constant(&view))//We ignore constants
                continue;

            //Hash the base array pointer
            uint64_t base_id;
            map<const bh_base*, uint64_t>::iterator it = batch.base2id.find(view.base);
            if(it != batch.base2id.end())
            {
                base_id = it->second;
            }
            else
            {
                base_id = batch.base_id_count++;
                batch.base2id.insert(make_pair(view.base, base_id));
            }
            this->append((char*)&base_id, sizeof(base_id));

            //Hash ndim and start
            this->append((char*)&view.ndim, sizeof(view.ndim));
            this->append((char*)&view.start, sizeof(view.start));

            //Hash shape and stride
            this->append((char*)view.shape, sizeof(bh_index)*view.ndim);
            this->append((char*)view.stride, sizeof(bh_index)*view.ndim);
        }
    }

    //Constructor of the BatchHash class
    BatchHash::BatchHash(const vector<bh_instruction> &instr_list):base_id_count(0)
    {
        string data;
        BOOST_FOREACH(const bh_instruction &instr, instr_list)
        {
            data.append(InstrHash(*this, instr));
        }
        boost::hash<string> hasher;
        _hash = hasher(data);
    }

    void FuseCache::insert(const BatchHash &batch,
                           const vector<bh_ir_kernel> &kernel_list)
    {
        cache[batch.hash()] = InstrIndexesList(kernel_list, batch.hash(), fuser_name);
    }

    bool FuseCache::lookup(const BatchHash &batch,
                           bh_ir &bhir,
                           vector<bh_ir_kernel> &kernel_list) const
    {
//        cout << "looking up " << batch.hash() << ": ";

        assert(kernel_list.size() == 0);
        CacheMap::const_iterator it = cache.find(batch.hash());
        if(it == cache.end())
        {
//            cout << "cache miss!" << endl;
            return false;
        }
        else
        {
            it->second.fill_kernel_list(bhir, kernel_list);
//          cout << "cache hit!" << endl;
          return true;
        }
    }

    void FuseCache::write_to_files() const
    {
        if(dir_path == NULL)
        {
            cout << "[FUSE-CACHE] Couldn't find the 'cache_path' key in "\
            "the configure file thus no cache files are written to disk!" << endl;
            return;
        }
        path cache_dir(dir_path);
        if(create_directories(cache_dir))
        {
            cout << "[FUSE-CACHE] Creating cache diretory " << cache_dir << endl;
        #if BOOST_VERSION > 104900
            permissions(cache_dir, all_all);
        #endif
        }

        path tmp_dir = cache_dir / unique_path();
        create_directories(tmp_dir);
        for(CacheMap::const_iterator it=cache.begin(); it != cache.end(); ++it)
        {
            string name;
            it->second.get_filename(name);
            path shared_name = cache_dir / name;

            if(exists(shared_name))
                continue;//No need to overwrite an existing file

            path unique_name = tmp_dir / name;
            ofstream ofs(unique_name.string());
            boost::archive::text_oarchive oa(ofs);
            oa << it->second;
            ofs.close();
        #if BOOST_VERSION > 104900
            permissions(unique_name, all_all);
        #endif
            rename(unique_name, shared_name);
        }
        remove(tmp_dir);
    }

    void FuseCache::load_from_files()
    {
        if(dir_path == NULL)
        {
            cout << "[FUSE-CACHE] Couldn't find the 'cache_path' key in "\
            "the configure file thus no cache files are loaded from disk!" << endl;
            return;
        }
        path p(dir_path);
        if(not (exists(p) and is_directory(p)))
            return;

        string fuse_model_name;
        fuse_model_text(fuse_get_selected_model(), fuse_model_name);

        //Iterate the 'dir_path' diretory and load each file
        directory_iterator it(p), eod;
        BOOST_FOREACH(const path &f, make_pair(it, eod))
        {
            if(is_regular_file(f))
            {
                int tries = 0;
                while(1)
                {
                    try
                    {
                        ifstream ifs(f.string());
                        boost::archive::text_iarchive ia(ifs);
                        InstrIndexesList t;
                        ia >> t;
                        if(iequals(t.fuser_name(), fuser_name) and
                           iequals(t.fuse_model(), fuse_model_name))
                        {
                            cache[t.hash()] = t;
                        }
                    }
                    catch(const std::exception &e)
                    {
                        if(++tries >= 10)
                        {
                            cerr << "[FUSE-CACHE] failed to open file '" << f.string();
                            cerr << "' (" << tries << " tries): " << e.what() << endl;
                        }
                        else
                            continue;
                    }
                    break;
                }
            }
        }
    }
} //namespace bohrium
<commit_msg>fuse-cache: fixed some issue with old OSX and string()<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <string>
#include <cstring>
#include <bh.h>
#include "bh_fuse.h"
#include "bh_fuse_cache.h"
#include <fstream>
#include <exception>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/version.hpp>
#include <boost/algorithm/string/predicate.hpp> //For iequals()

using namespace std;
using namespace boost;
using namespace boost::filesystem;

namespace bohrium {

    //Constructor of the InstrHash class
    InstrHash::InstrHash(BatchHash &batch, const bh_instruction &instr)
    {
        BOOST_FOREACH(const bh_view &view, instr.operand)
        {
            if(bh_is_constant(&view))//We ignore constants
                continue;

            //Hash the base array pointer
            uint64_t base_id;
            map<const bh_base*, uint64_t>::iterator it = batch.base2id.find(view.base);
            if(it != batch.base2id.end())
            {
                base_id = it->second;
            }
            else
            {
                base_id = batch.base_id_count++;
                batch.base2id.insert(make_pair(view.base, base_id));
            }
            this->append((char*)&base_id, sizeof(base_id));

            //Hash ndim and start
            this->append((char*)&view.ndim, sizeof(view.ndim));
            this->append((char*)&view.start, sizeof(view.start));

            //Hash shape and stride
            this->append((char*)view.shape, sizeof(bh_index)*view.ndim);
            this->append((char*)view.stride, sizeof(bh_index)*view.ndim);
        }
    }

    //Constructor of the BatchHash class
    BatchHash::BatchHash(const vector<bh_instruction> &instr_list):base_id_count(0)
    {
        string data;
        BOOST_FOREACH(const bh_instruction &instr, instr_list)
        {
            data.append(InstrHash(*this, instr));
        }
        boost::hash<string> hasher;
        _hash = hasher(data);
    }

    void FuseCache::insert(const BatchHash &batch,
                           const vector<bh_ir_kernel> &kernel_list)
    {
        cache[batch.hash()] = InstrIndexesList(kernel_list, batch.hash(), fuser_name);
    }

    bool FuseCache::lookup(const BatchHash &batch,
                           bh_ir &bhir,
                           vector<bh_ir_kernel> &kernel_list) const
    {
//        cout << "looking up " << batch.hash() << ": ";

        assert(kernel_list.size() == 0);
        CacheMap::const_iterator it = cache.find(batch.hash());
        if(it == cache.end())
        {
//            cout << "cache miss!" << endl;
            return false;
        }
        else
        {
            it->second.fill_kernel_list(bhir, kernel_list);
//          cout << "cache hit!" << endl;
          return true;
        }
    }

    void FuseCache::write_to_files() const
    {
        if(dir_path == NULL)
        {
            cout << "[FUSE-CACHE] Couldn't find the 'cache_path' key in "\
            "the configure file thus no cache files are written to disk!" << endl;
            return;
        }
        path cache_dir(dir_path);
        if(create_directories(cache_dir))
        {
            cout << "[FUSE-CACHE] Creating cache diretory " << cache_dir << endl;
        #if BOOST_VERSION > 104900
            permissions(cache_dir, all_all);
        #endif
        }

        path tmp_dir = cache_dir / unique_path();
        create_directories(tmp_dir);
        for(CacheMap::const_iterator it=cache.begin(); it != cache.end(); ++it)
        {
            string name;
            it->second.get_filename(name);
            path shared_name = cache_dir / name;

            if(exists(shared_name))
                continue;//No need to overwrite an existing file

            path unique_name = tmp_dir / name;
            ofstream ofs(unique_name.string().c_str());
            boost::archive::text_oarchive oa(ofs);
            oa << it->second;
            ofs.close();
        #if BOOST_VERSION > 104900
            permissions(unique_name, all_all);
        #endif
            rename(unique_name, shared_name);
        }
        remove(tmp_dir);
    }

    void FuseCache::load_from_files()
    {
        if(dir_path == NULL)
        {
            cout << "[FUSE-CACHE] Couldn't find the 'cache_path' key in "\
            "the configure file thus no cache files are loaded from disk!" << endl;
            return;
        }
        path p(dir_path);
        if(not (exists(p) and is_directory(p)))
            return;

        string fuse_model_name;
        fuse_model_text(fuse_get_selected_model(), fuse_model_name);

        //Iterate the 'dir_path' diretory and load each file
        directory_iterator it(p), eod;
        BOOST_FOREACH(const path &f, make_pair(it, eod))
        {
            if(is_regular_file(f))
            {
                int tries = 0;
                while(1)
                {
                    try
                    {
                        ifstream ifs(f.string().c_str());
                        boost::archive::text_iarchive ia(ifs);
                        InstrIndexesList t;
                        ia >> t;
                        if(iequals(t.fuser_name(), fuser_name) and
                           iequals(t.fuse_model(), fuse_model_name))
                        {
                            cache[t.hash()] = t;
                        }
                    }
                    catch(const std::exception &e)
                    {
                        if(++tries >= 10)
                        {
                            cerr << "[FUSE-CACHE] failed to open file '" << f.string();
                            cerr << "' (" << tries << " tries): " << e.what() << endl;
                        }
                        else
                            continue;
                    }
                    break;
                }
            }
        }
    }
} //namespace bohrium
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
<commit_msg>:construction: chore(colorful): updated the colorful module<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <Common/Macros.hh>
#if defined(TADPOLE_MSVC)
# include <io.h>
# include <Windows.h>
#else
# include <unistd.h>
#endif
#include <Common/Colorful.hh>

namespace Tadpole::Common::Colorful {

inline FILE* get_standard_stream(const std::ostream& stream) noexcept {
  if (&stream == &std::cout)
    return stdout;
  else if (&stream == &std::cerr || &stream == &std::clog)
    return stderr;
  return nullptr;
}

inline bool is_atty(std::ostream& stream) noexcept {
  FILE* std_stream = get_standard_stream(stream);
  if (!std_stream)
    return false;

#if defined(TADPOLE_MSVC)
  return ::_isatty(::_fileno(std_stream));
#else
  return ::isatty(::fileno(std_stream));
#endif
}

#if defined(TADPOLE_MSVC)
inline int get_colorful(Color c) noexcept {
  switch (c) {
  case Color::kReset: return -1;
  case Color::kForegroundBlack: return FOREGROUND_RED & FOREGROUND_GREEN & FOREGROUND_BLUE;
  case Color::kForegroundRed: return FOREGROUND_RED;
  case Color::kForegroundGreen: return FOREGROUND_GREEN;
  case Color::kForegroundYellow: return FOREGROUND_RED | FOREGROUND_GREEN;
  case Color::kForegroundBlue: return FOREGROUND_BLUE;
  case Color::kForegroundMagenta: return FOREGROUND_RED | FOREGROUND_BLUE;
  case Color::kForegroundCyan: return FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Color::kForegroundWhite: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Color::kForegroundGray: return FOREGROUND_INTENSITY;
  case Color::kForegroundLightRed: return FOREGROUND_INTENSITY | FOREGROUND_RED;
  case Color::kForegroundLightGreen: return FOREGROUND_INTENSITY | FOREGROUND_GREEN;
  case Color::kForegroundLightYellow: return FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN;
  case Color::kForegroundLightBlue: return FOREGROUND_INTENSITY | FOREGROUND_BLUE;
  case Color::kForegroundLightMagenta: return FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE;
  case Color::kForegroundLightCyan: return FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Color::kForegroundLightWhite: return FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Color::kBackgroundBlack: return BACKGROUND_RED & BACKGROUND_GREEN & BACKGROUND_BLUE;
  case Color::kBackgroundRed: return BACKGROUND_RED;
  case Color::kBackgroundGreen: return BACKGROUND_GREEN;
  case Color::kBackgroundYellow: return BACKGROUND_RED | BACKGROUND_GREEN;
  case Color::kBackgroundBlue: return BACKGROUND_BLUE;
  case Color::kBackgroundMagenta: return BACKGROUND_RED | BACKGROUND_BLUE;
  case Color::kBackgroundCyan: return BACKGROUND_GREEN | BACKGROUND_BLUE;
  case Color::kBackgroundWhite: return BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
  case Color::kBackgroundGray: return BACKGROUND_INTENSITY;
  case Color::kBackgroundLightRed: return BACKGROUND_INTENSITY | BACKGROUND_RED;
  case Color::kBackgroundLightGreen: return BACKGROUND_INTENSITY | BACKGROUND_GREEN;
  case Color::kBackgroundLightYellow: return BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN;
  case Color::kBackgroundLightBlue: return BACKGROUND_INTENSITY | BACKGROUND_BLUE;
  case Color::kBackgroundLightMagenta: return BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE;
  case Color::kBackgroundLightCyan: return BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE;
  case Color::kBackgroundLightWhite: return BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
  }
  return -1;
}

inline std::ostream& set_colorful(
    std::ostream& stream, int foreground = -1, int background = -1) noexcept {
  static WORD wDefaultAttributes = 0;

  if (!is_atty(stream))
    return stream;

  HANDLE hTerminal = INVALID_HANDLE_VALUE;
  if (&stream == &std::cout)
    hTerminal = ::GetStdHandle(STD_OUTPUT_HANDLE);
  else if (&stream == &std::cerr)
    hTerminal = ::GetStdHandle(STD_ERROR_HANDLE);

  if (!wDefaultAttributes) {
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (!::GetConsoleScreenBufferInfo(hTerminal, &info))
      return stream;
    wDefaultAttributes = info.wAttributes;
  }

  WORD wAttributes;
  if (foreground == -1 && background == -1) {
    wAttributes = wDefaultAttributes;
  }
  else {
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (!::GetConsoleScreenBufferInfo(hTerminal, &info))
      return stream;

    wAttributes = info.wAttributes;
    if (foreground != -1) {
      wAttributes &= ~(info.wAttributes & 0x0F);
      wAttributes |= as_type<WORD>(foreground);
    }
    if (background != -1) {
      wAttributes &= ~(info.wAttributes & 0xF0);
      wAttributes |= as_type<WORD>(background);
    }
  }

  ::SetConsoleTextAttribute(hTerminal, wAttributes);
  return stream;
}
#else
inline const char* get_colorful(Color c) noexcept {
  switch (c) {
  case Color::kReset: return "\033[00m";
  case Color::kForegroundBlack: return "\033[30m";
  case Color::kForegroundRed: return "\033[31m";
  case Color::kForegroundGreen: return "\033[32m";
  case Color::kForegroundYellow: return "\033[33m";
  case Color::kForegroundBlue: return "\033[34m";
  case Color::kForegroundMagenta: return "\033[35m";
  case Color::kForegroundCyan: return "\033[36m";
  case Color::kForegroundWhite: return "\033[37m";
  case Color::kForegroundGray: return "\033[90m";
  case Color::kForegroundLightRed: return "\033[91m";
  case Color::kForegroundLightGreen: return "\033[92m";
  case Color::kForegroundLightYellow: return "\033[93m";
  case Color::kForegroundLightBlue: return "\033[94m";
  case Color::kForegroundLightMagenta: return "\033[95m";
  case Color::kForegroundLightCyan: return "\033[96m";
  case Color::kForegroundLightWhite: return "\033[97m";
  case Color::kBackgroundBlack: return "\033[40m";
  case Color::kBackgroundRed: return "\033[41m";
  case Color::kBackgroundGreen: return "\033[42m";
  case Color::kBackgroundYellow: return "\033[43m";
  case Color::kBackgroundBlue: return "\033[44m";
  case Color::kBackgroundMagenta: return "\033[45m";
  case Color::kBackgroundCyan: return "\033[46m";
  case Color::kBackgroundWhite: return "\033[47m;
  case Color::kBackgroundGray: return "\033[100m";
  case Color::kBackgroundLightRed: return "\033[101m";
  case Color::kBackgroundLightGreen: return "\033[102m";
  case Color::kBackgroundLightYellow: return "\033[103m";
  case Color::kBackgroundLightBlue: return "\033[104m";
  case Color::kBackgroundLightMagenta: return "\033[105m";
  case Color::kBackgroundLightCyan: return "\033[106m";
  case Color::kBackgroundLightWhite: return "\033[107m";
  }
  return "\033[00m";
}
#endif

std::ostream& set_colorful(std::ostream& stream, Color color) noexcept {
#if defined(TADPOLE_MSVC)
  return set_colorful(stream, get_colorful(color));
#else
  return stream << get_colorful(color);
#endif
}

std::ostream& set_foreground_colorful(std::ostream& stream, Color color) noexcept {
  return set_colorful(stream, color);
}

std::ostream& set_background_colorful(std::ostream& stream, Color color) noexcept {
#if defined(TADPOLE_MSVC)
  return set_colorful(stream, -1, get_colorful(color));
#else
  return stream << get_colorful(color)
#endif
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <Common/Colorful.hh>
#include <Lex/Lexer.hh>
#include <Object/StringObject.hh>
#include <Core/TadpoleVM.hh>
#include <Compiler/Parser.hh>

namespace Tadpole::Compiler {

GlobalParser::GlobalParser(Core::TadpoleVM& vm, Lex::Lexer& lex) noexcept
  : vm_(vm), lex_(lex) {
}

void GlobalParser::iter_objects(Object::ObjectVisitor&& visitor) {
  for (FunctionCompiler* c = curr_compiler_; c != nullptr; c = c->enclosing())
    visitor(c->fn());
}

Object::FunctionObject* GlobalParser::compile() {
  FunctionCompiler compiler;
  init_compiler(&compiler, 0, FunctionType::TOPLEVEL);

  advance();
  while (!check(Lex::TokenKind::TK_EOF))
    declaration();
  Object::FunctionObject* fn = finish_compiler();

  return had_error_ ? nullptr : fn;
}

const ParseRule& GlobalParser::get_rule(Lex::TokenKind kind) const noexcept {
#define _RULE(fn) [](GlobalParser& p, bool b) { p.fn(b); }
  static const ParseRule _rules[] = {
    {_RULE(grouping), _RULE(call), Precedence::CALL}, // PUNCTUATOR(LPAREN, "(")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RPAREN, ")")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(LBRACE, "{")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RBRACE, "}")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(COMMA, ",")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(MINUS, "-")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(PLUS, "+")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(SEMI, ";")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(SLASH, "/")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(STAR, "*")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(EQ, "=")

    {_RULE(variable), nullptr, Precedence::NONE},     // TOKEN(IDENTIFIER, "Identifier")
    {_RULE(numeric), nullptr, Precedence::NONE},      // TOKEN(NUMERIC, "Numeric")
    {_RULE(string), nullptr, Precedence::NONE},       // TOKEN(STRING, "String")

    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(FALSE, "false")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(FN, "fn")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(NIL, "nil")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(TRUE, "true")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(VAR, "var")

    {nullptr, nullptr, Precedence::NONE},             // TOKEN(EOF, "Eof")
    {nullptr, nullptr, Precedence::NONE},             // TOKEN(ERR, "Error")
  };
#undef _RULE

  return _rules[Common::as_type<int>(kind)];
}

void GlobalParser::error_at(const Lex::Token& tok, const str_t& msg) noexcept {
  if (panic_mode_)
    return;
  panic_mode_ = true;

  std::cerr
    << Common::Colorful::fg::red
    << "SyntaxError:" << std::endl
    << "  [LINE: " << tok.lineno() << "] ERROR ";
  if (tok.kind() == Lex::TokenKind::TK_EOF)
    std::cerr << "at end ";
  else if (tok.kind() == Lex::TokenKind::TK_ERR)
    TADPOLE_UNUSED(0);
  else
    std::cerr << "at `" << tok.literal() << "` ";
  std::cerr << ": " << msg << Common::Colorful::reset << std::endl;
}

void GlobalParser::advance() {
  prev_ = curr_;

  for (;;) {
    curr_ = lex_.next_token();
    if (!check(Lex::TokenKind::TK_ERR))
      break;

    error_at_current(curr_.as_string());
  }
}

void GlobalParser::consume(Lex::TokenKind kind, const str_t& msg) {
  if (check(kind))
    advance();
  else
    error_at_current(msg);
}

bool GlobalParser::match(Lex::TokenKind kind) {
  if (check(kind)) {
    advance();
    return true;
  }
  return false;
}

void GlobalParser::init_compiler(FunctionCompiler* compiler, int scope_depth, FunctionType fn_type) {
  Object::StringObject* fn_name{};
  if (fn_type == FunctionType::FUNCTION)
    fn_name = Object::StringObject::create(prev_.as_string());

  compiler->set_compiler(
      curr_compiler_,
      Object::FunctionObject::create(fn_name),
      fn_type,
      scope_depth);
  curr_compiler_ = compiler;

  curr_compiler_->append_local({Lex::Token::make(""), curr_compiler_->scope_depth(), false});
}

Object::FunctionObject* GlobalParser::finish_compiler() {
  emit_return();

  Object::FunctionObject* fn = curr_compiler_->fn();
#if defined(_TADPOLE_DEBUG_VM)
  if (!had_error_)
    curr_chunk()->dis(fn->name_asstr());
#endif

  curr_compiler_ = curr_compiler_->enclosing();
  return fn;
}

void GlobalParser::enter_scope() {
  curr_compiler_->enter_scope();
}

void GlobalParser::leave_scope() {
  curr_compiler_->leave_scope([this](const LocalVar& var) {
        emit_byte(var.is_upvalue ? Core::Code::CLOSE_UPVALUE : Core::Code::POP);
      });
}

u8_t GlobalParser::identifier_constant(const Lex::Token& name) noexcept {
  return curr_chunk()->add_constant(Object::StringObject::create(name.as_string()));
}

u8_t GlobalParser::parse_variable(const str_t& msg) {
  consume(Lex::TokenKind::TK_IDENTIFIER, msg);

  curr_compiler_->declare_localvar(prev_, [this](const str_t& m) { error(m); });
  if (curr_compiler_->scope_depth() > 0)
    return 0;
  return identifier_constant(prev_);
}

void GlobalParser::mark_initialized() {
  if (curr_compiler_->scope_depth() == 0)
    return;
  curr_compiler_->peek_local().depth = curr_compiler_->scope_depth();
}

void GlobalParser::define_global(u8_t global) {
  if (curr_compiler_->scope_depth() > 0) {
    mark_initialized();
    return;
  }
  emit_bytes(Core::Code::DEF_GLOBAL, global);
}

u8_t GlobalParser::arguments() {
  u8_t nargs = 0;
  if (!check(Lex::TokenKind::TK_RPAREN)) {
    do {
      expression();
      ++nargs;

      if (nargs > kMaxArgs)
        error(Common::from_fmt("cannot have more than `%d` arguments", kMaxArgs));
    } while (match(Lex::TokenKind::TK_COMMA));
  }
  consume(Lex::TokenKind::TK_RPAREN, "expect `)` after function arguments");

  return nargs;
}

void GlobalParser::named_variable(const Lex::Token& name, bool can_assign) {
  auto errfn = [this](const str_t& msg) { error(msg); };

  Core::Code getop, setop;
  int arg = curr_compiler_->resolve_local(name, errfn);
  if (arg != -1) {
    getop = Core::Code::GET_LOCAL;
    setop = Core::Code::SET_LOCAL;
  }
  else if (arg = curr_compiler_->resolve_upvalue(name, errfn); arg != -1) {
    getop = Core::Code::GET_UPVALUE;
    setop = Core::Code::SET_UPVALUE;
  }
  else {
    arg = identifier_constant(name);
    getop = Core::Code::GET_GLOBAL;
    setop = Core::Code::SET_GLOBAL;
  }

  if (can_assign && match(Lex::TokenKind::TK_EQ)) {
    expression();
    emit_bytes(setop, arg);
  }
  else {
    emit_bytes(getop, arg);
  }
}

void GlobalParser::parse_precedence(Precedence precedence) {
  advance();
  auto& prefix_fn = get_rule(prev_.kind()).prefix;
  if (!prefix_fn) {
    error("expect expression");
    return;
  }

  bool can_assign = precedence <= Precedence::ASSIGN;
  prefix_fn(*this, can_assign);

  while (precedence <= get_rule(curr_.kind()).precedence) {
    advance();
    auto& infix_fn = get_rule(prev_.kind()).infix;

    if (infix_fn)
      infix_fn(*this, can_assign);
  }

  if (can_assign && match(Lex::TokenKind::TK_EQ)) {
    error("invalid assignment target");
    expression();
  }
}

void GlobalParser::binary(bool can_assign) {
  Lex::TokenKind op = prev_.kind();

  parse_precedence(get_rule(op).precedence + 1);
  switch (op) {
  case Lex::TokenKind::TK_PLUS: emit_byte(Core::Code::ADD); break;
  case Lex::TokenKind::TK_MINUS: emit_byte(Core::Code::SUB); break;
  case Lex::TokenKind::TK_STAR: emit_byte(Core::Code::MUL); break;
  case Lex::TokenKind::TK_SLASH: emit_byte(Core::Code::DIV); break;
  default: break;
  }
}

void GlobalParser::call(bool can_assign) {
  emit_byte(Core::Code::CALL_0 + arguments());
}

void GlobalParser::grouping(bool can_assign) {
  expression();
  consume(Lex::TokenKind::TK_RPAREN, "expect `)` after grouping expression");
}

void GlobalParser::literal(bool can_assign) {
  switch (prev_.kind()) {
  case Lex::TokenKind::KW_NIL: emit_byte(Core::Code::NIL); break;
  case Lex::TokenKind::KW_FALSE: emit_byte(Core::Code::FALSE); break;
  case Lex::TokenKind::KW_TRUE: emit_byte(Core::Code::TRUE); break;
  default: break;
  }
}

void GlobalParser::variable(bool can_assign) {
  named_variable(prev_, can_assign);
}

void GlobalParser::numeric(bool can_assign) {
  emit_constant(prev_.as_numeric());
}

void GlobalParser::string(bool can_assign) {
  emit_constant(Object::StringObject::create(prev_.as_string()));
}

void GlobalParser::block() {
  while (!check(Lex::TokenKind::TK_EOF) && !check(Lex::TokenKind::TK_RBRACE))
    declaration();
  consume(Lex::TokenKind::TK_RBRACE, "expect `}` after block body");
}

void GlobalParser::function(FunctionType fn_type) {
  FunctionCompiler fn_compiler;
  init_compiler(&fn_compiler, 1, fn_type);

  consume(Lex::TokenKind::TK_LPAREN, "expect `(` after function name");
  if (!check(Lex::TokenKind::TK_RPAREN)) {
    do {
      u8_t param_constant = parse_variable("expect function parameters' name");
      define_global(param_constant);

      curr_compiler_->fn()->inc_arity();
      if (curr_compiler_->fn()->arity() > kMaxArgs)
        error(Common::from_fmt("cannot have more than `%d` parameters", kMaxArgs));
    } while (match(Lex::TokenKind::TK_COMMA));
  }
  consume(Lex::TokenKind::TK_RPAREN, "expect `)` after function parameters");

  consume(Lex::TokenKind::TK_LBRACE, "expect `{` before function body");
  block();

  leave_scope();
  Object::FunctionObject* fn = finish_compiler();

  emit_bytes(Core::Code::CLOSURE, curr_chunk()->add_constant(fn));
  for (sz_t i = 0; i < fn->upvalues_count(); ++i) {
    auto& upvalue = fn_compiler.get_upvalue(i);
    emit_bytes(upvalue.is_local ? 1 : 0, upvalue.index);
  }
}

void GlobalParser::synchronize() {
  panic_mode_ = false;

  while (!check(Lex::TokenKind::TK_EOF)) {
    if (prev_.kind() == Lex::TokenKind::TK_SEMI)
      break;

    switch (curr_.kind()) {
    case Lex::TokenKind::KW_FN:
    case Lex::TokenKind::KW_VAR:
      return;
    default: break;
    }
    advance();
  }
}

void GlobalParser::expression() {}
void GlobalParser::declaration() {}
void GlobalParser::statement() {}
void GlobalParser::fn_decl() {}
void GlobalParser::var_decl() {}
void GlobalParser::expr_stmt() {}

}
<commit_msg>:construction: chore(declaration): add declaration implementation of parser for tadpole<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <Common/Colorful.hh>
#include <Lex/Lexer.hh>
#include <Object/StringObject.hh>
#include <Core/TadpoleVM.hh>
#include <Compiler/Parser.hh>

namespace Tadpole::Compiler {

GlobalParser::GlobalParser(Core::TadpoleVM& vm, Lex::Lexer& lex) noexcept
  : vm_(vm), lex_(lex) {
}

void GlobalParser::iter_objects(Object::ObjectVisitor&& visitor) {
  for (FunctionCompiler* c = curr_compiler_; c != nullptr; c = c->enclosing())
    visitor(c->fn());
}

Object::FunctionObject* GlobalParser::compile() {
  FunctionCompiler compiler;
  init_compiler(&compiler, 0, FunctionType::TOPLEVEL);

  advance();
  while (!check(Lex::TokenKind::TK_EOF))
    declaration();
  Object::FunctionObject* fn = finish_compiler();

  return had_error_ ? nullptr : fn;
}

const ParseRule& GlobalParser::get_rule(Lex::TokenKind kind) const noexcept {
#define _RULE(fn) [](GlobalParser& p, bool b) { p.fn(b); }
  static const ParseRule _rules[] = {
    {_RULE(grouping), _RULE(call), Precedence::CALL}, // PUNCTUATOR(LPAREN, "(")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RPAREN, ")")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(LBRACE, "{")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(RBRACE, "}")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(COMMA, ",")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(MINUS, "-")
    {nullptr, _RULE(binary), Precedence::TERM},       // PUNCTUATOR(PLUS, "+")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(SEMI, ";")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(SLASH, "/")
    {nullptr, _RULE(binary), Precedence::FACTOR},     // PUNCTUATOR(STAR, "*")
    {nullptr, nullptr, Precedence::NONE},             // PUNCTUATOR(EQ, "=")

    {_RULE(variable), nullptr, Precedence::NONE},     // TOKEN(IDENTIFIER, "Identifier")
    {_RULE(numeric), nullptr, Precedence::NONE},      // TOKEN(NUMERIC, "Numeric")
    {_RULE(string), nullptr, Precedence::NONE},       // TOKEN(STRING, "String")

    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(FALSE, "false")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(FN, "fn")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(NIL, "nil")
    {_RULE(literal), nullptr, Precedence::NONE},      // KEYWORD(TRUE, "true")
    {nullptr, nullptr, Precedence::NONE},             // KEYWORD(VAR, "var")

    {nullptr, nullptr, Precedence::NONE},             // TOKEN(EOF, "Eof")
    {nullptr, nullptr, Precedence::NONE},             // TOKEN(ERR, "Error")
  };
#undef _RULE

  return _rules[Common::as_type<int>(kind)];
}

void GlobalParser::error_at(const Lex::Token& tok, const str_t& msg) noexcept {
  if (panic_mode_)
    return;
  panic_mode_ = true;

  std::cerr
    << Common::Colorful::fg::red
    << "SyntaxError:" << std::endl
    << "  [LINE: " << tok.lineno() << "] ERROR ";
  if (tok.kind() == Lex::TokenKind::TK_EOF)
    std::cerr << "at end ";
  else if (tok.kind() == Lex::TokenKind::TK_ERR)
    TADPOLE_UNUSED(0);
  else
    std::cerr << "at `" << tok.literal() << "` ";
  std::cerr << ": " << msg << Common::Colorful::reset << std::endl;
}

void GlobalParser::advance() {
  prev_ = curr_;

  for (;;) {
    curr_ = lex_.next_token();
    if (!check(Lex::TokenKind::TK_ERR))
      break;

    error_at_current(curr_.as_string());
  }
}

void GlobalParser::consume(Lex::TokenKind kind, const str_t& msg) {
  if (check(kind))
    advance();
  else
    error_at_current(msg);
}

bool GlobalParser::match(Lex::TokenKind kind) {
  if (check(kind)) {
    advance();
    return true;
  }
  return false;
}

void GlobalParser::init_compiler(FunctionCompiler* compiler, int scope_depth, FunctionType fn_type) {
  Object::StringObject* fn_name{};
  if (fn_type == FunctionType::FUNCTION)
    fn_name = Object::StringObject::create(prev_.as_string());

  compiler->set_compiler(
      curr_compiler_,
      Object::FunctionObject::create(fn_name),
      fn_type,
      scope_depth);
  curr_compiler_ = compiler;

  curr_compiler_->append_local({Lex::Token::make(""), curr_compiler_->scope_depth(), false});
}

Object::FunctionObject* GlobalParser::finish_compiler() {
  emit_return();

  Object::FunctionObject* fn = curr_compiler_->fn();
#if defined(_TADPOLE_DEBUG_VM)
  if (!had_error_)
    curr_chunk()->dis(fn->name_asstr());
#endif

  curr_compiler_ = curr_compiler_->enclosing();
  return fn;
}

void GlobalParser::enter_scope() {
  curr_compiler_->enter_scope();
}

void GlobalParser::leave_scope() {
  curr_compiler_->leave_scope([this](const LocalVar& var) {
        emit_byte(var.is_upvalue ? Core::Code::CLOSE_UPVALUE : Core::Code::POP);
      });
}

u8_t GlobalParser::identifier_constant(const Lex::Token& name) noexcept {
  return curr_chunk()->add_constant(Object::StringObject::create(name.as_string()));
}

u8_t GlobalParser::parse_variable(const str_t& msg) {
  consume(Lex::TokenKind::TK_IDENTIFIER, msg);

  curr_compiler_->declare_localvar(prev_, [this](const str_t& m) { error(m); });
  if (curr_compiler_->scope_depth() > 0)
    return 0;
  return identifier_constant(prev_);
}

void GlobalParser::mark_initialized() {
  if (curr_compiler_->scope_depth() == 0)
    return;
  curr_compiler_->peek_local().depth = curr_compiler_->scope_depth();
}

void GlobalParser::define_global(u8_t global) {
  if (curr_compiler_->scope_depth() > 0) {
    mark_initialized();
    return;
  }
  emit_bytes(Core::Code::DEF_GLOBAL, global);
}

u8_t GlobalParser::arguments() {
  u8_t nargs = 0;
  if (!check(Lex::TokenKind::TK_RPAREN)) {
    do {
      expression();
      ++nargs;

      if (nargs > kMaxArgs)
        error(Common::from_fmt("cannot have more than `%d` arguments", kMaxArgs));
    } while (match(Lex::TokenKind::TK_COMMA));
  }
  consume(Lex::TokenKind::TK_RPAREN, "expect `)` after function arguments");

  return nargs;
}

void GlobalParser::named_variable(const Lex::Token& name, bool can_assign) {
  auto errfn = [this](const str_t& msg) { error(msg); };

  Core::Code getop, setop;
  int arg = curr_compiler_->resolve_local(name, errfn);
  if (arg != -1) {
    getop = Core::Code::GET_LOCAL;
    setop = Core::Code::SET_LOCAL;
  }
  else if (arg = curr_compiler_->resolve_upvalue(name, errfn); arg != -1) {
    getop = Core::Code::GET_UPVALUE;
    setop = Core::Code::SET_UPVALUE;
  }
  else {
    arg = identifier_constant(name);
    getop = Core::Code::GET_GLOBAL;
    setop = Core::Code::SET_GLOBAL;
  }

  if (can_assign && match(Lex::TokenKind::TK_EQ)) {
    expression();
    emit_bytes(setop, arg);
  }
  else {
    emit_bytes(getop, arg);
  }
}

void GlobalParser::parse_precedence(Precedence precedence) {
  advance();
  auto& prefix_fn = get_rule(prev_.kind()).prefix;
  if (!prefix_fn) {
    error("expect expression");
    return;
  }

  bool can_assign = precedence <= Precedence::ASSIGN;
  prefix_fn(*this, can_assign);

  while (precedence <= get_rule(curr_.kind()).precedence) {
    advance();
    auto& infix_fn = get_rule(prev_.kind()).infix;

    if (infix_fn)
      infix_fn(*this, can_assign);
  }

  if (can_assign && match(Lex::TokenKind::TK_EQ)) {
    error("invalid assignment target");
    expression();
  }
}

void GlobalParser::binary(bool can_assign) {
  Lex::TokenKind op = prev_.kind();

  parse_precedence(get_rule(op).precedence + 1);
  switch (op) {
  case Lex::TokenKind::TK_PLUS: emit_byte(Core::Code::ADD); break;
  case Lex::TokenKind::TK_MINUS: emit_byte(Core::Code::SUB); break;
  case Lex::TokenKind::TK_STAR: emit_byte(Core::Code::MUL); break;
  case Lex::TokenKind::TK_SLASH: emit_byte(Core::Code::DIV); break;
  default: break;
  }
}

void GlobalParser::call(bool can_assign) {
  emit_byte(Core::Code::CALL_0 + arguments());
}

void GlobalParser::grouping(bool can_assign) {
  expression();
  consume(Lex::TokenKind::TK_RPAREN, "expect `)` after grouping expression");
}

void GlobalParser::literal(bool can_assign) {
  switch (prev_.kind()) {
  case Lex::TokenKind::KW_NIL: emit_byte(Core::Code::NIL); break;
  case Lex::TokenKind::KW_FALSE: emit_byte(Core::Code::FALSE); break;
  case Lex::TokenKind::KW_TRUE: emit_byte(Core::Code::TRUE); break;
  default: break;
  }
}

void GlobalParser::variable(bool can_assign) {
  named_variable(prev_, can_assign);
}

void GlobalParser::numeric(bool can_assign) {
  emit_constant(prev_.as_numeric());
}

void GlobalParser::string(bool can_assign) {
  emit_constant(Object::StringObject::create(prev_.as_string()));
}

void GlobalParser::block() {
  while (!check(Lex::TokenKind::TK_EOF) && !check(Lex::TokenKind::TK_RBRACE))
    declaration();
  consume(Lex::TokenKind::TK_RBRACE, "expect `}` after block body");
}

void GlobalParser::function(FunctionType fn_type) {
  FunctionCompiler fn_compiler;
  init_compiler(&fn_compiler, 1, fn_type);

  consume(Lex::TokenKind::TK_LPAREN, "expect `(` after function name");
  if (!check(Lex::TokenKind::TK_RPAREN)) {
    do {
      u8_t param_constant = parse_variable("expect function parameters' name");
      define_global(param_constant);

      curr_compiler_->fn()->inc_arity();
      if (curr_compiler_->fn()->arity() > kMaxArgs)
        error(Common::from_fmt("cannot have more than `%d` parameters", kMaxArgs));
    } while (match(Lex::TokenKind::TK_COMMA));
  }
  consume(Lex::TokenKind::TK_RPAREN, "expect `)` after function parameters");

  consume(Lex::TokenKind::TK_LBRACE, "expect `{` before function body");
  block();

  leave_scope();
  Object::FunctionObject* fn = finish_compiler();

  emit_bytes(Core::Code::CLOSURE, curr_chunk()->add_constant(fn));
  for (sz_t i = 0; i < fn->upvalues_count(); ++i) {
    auto& upvalue = fn_compiler.get_upvalue(i);
    emit_bytes(upvalue.is_local ? 1 : 0, upvalue.index);
  }
}

void GlobalParser::synchronize() {
  panic_mode_ = false;

  while (!check(Lex::TokenKind::TK_EOF)) {
    if (prev_.kind() == Lex::TokenKind::TK_SEMI)
      break;

    switch (curr_.kind()) {
    case Lex::TokenKind::KW_FN:
    case Lex::TokenKind::KW_VAR:
      return;
    default: break;
    }
    advance();
  }
}

void GlobalParser::expression() {
  parse_precedence(Precedence::ASSIGN);
}

void GlobalParser::declaration() {
  if (match(Lex::TokenKind::KW_FN))
    fn_decl();
  else if (match(Lex::TokenKind::KW_VAR))
    var_decl();
  else
    statement();

  if (panic_mode_)
    synchronize();
}

void GlobalParser::statement() {}
void GlobalParser::fn_decl() {}
void GlobalParser::var_decl() {}
void GlobalParser::expr_stmt() {}

}
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <Common/Harness.hh>
#include <Core/Chunk.hh>

TADPOLE_TEST(TadpoleChunk) {
  using TC = Tadpole::Core::Code;

#define EXPV(value) c.write_constant((value), n)
#define EXPC(code)  c.write((code), n)
#define EXPC2(code) c.write((code), n++)

  Tadpole::Core::Chunk c;
  int n = 1;

  // 22.56 + 34
  EXPV(34); EXPV(22.56); EXPC2(TC::ADD);

  // 10.56 - 89.92
  EXPV(89.92); EXPV(10.56); EXPC2(TC::SUB);

  // 67 * 0.89
  EXPV(0.89); EXPV(67); EXPC2(TC::MUL);

  // 99.03 / 712.37
  EXPV(712.37); EXPV(99.03); EXPC2(TC::DIV);

  // return
  c.write(TC::RETURN, n);

  c.dis("TadpoleChunk");

#undef EXPC2
#undef EXPC
#undef EXPV
}
<commit_msg>:white_check_mark: test(Chunk): updated the test case for chunk module<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <Common/Harness.hh>
#include <Core/Chunk.hh>

TADPOLE_TEST(TadpoleChunk) {
  using TC = Tadpole::Core::Code;

#define EXPV(value) c.write_constant((value), n)
#define EXPC(code)  c.write((code), n)
#define EXPC2(code) c.write((code), n++)

  Tadpole::Core::Chunk c;
  int n = 1;

  // 22.56 + 34
  EXPV(34); EXPV(22.56); EXPC2(TC::ADD);

  // 10.56 - 89.92
  EXPV(89.92); EXPV(10.56); EXPC2(TC::SUB);

  // 67 * 0.89
  EXPV(0.89); EXPV(67); EXPC2(TC::MUL);

  // 99.03 / 712.37
  EXPV(712.37); EXPV(99.03); EXPC2(TC::DIV);

  // (92.33 - 1.65 + 38.07) / 59.79
  EXPV(59.79); EXPV(38.07); EXPV(1.65); EXPV(92.79); EXPC(TC::SUB); EXPC(TC::ADD); EXPC2(TC::DIV);

  // return
  c.write(TC::RETURN, n);

  c.dis("TadpoleChunk");

#undef EXPC2
#undef EXPC
#undef EXPV
}
<|endoftext|>


<commit_before>// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX - License - Identifier: Apache - 2.0

// snippet-start:[s3.cpp.delete_object.inc]
#include <iostream>
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/DeleteObjectRequest.h>
#include <awsdoc/s3/s3_examples.h>
// snippet-end:[s3.cpp.delete_object.inc]

/* ////////////////////////////////////////////////////////////////////////////
 * Purpose: Deletes an object from a bucket in Amazon S3.
 *
 * Prerequisites: The bucket containing the object to be deleted.
 *
 * Inputs:
 * - objectKey: The name of the object to delete.
 * - fromBucket: The name of the bucket to delete the object from.
 * - region: The AWS Region to create the bucket in.
 *
 * Outputs: true if the object was deleted; otherwise, false.
 * ///////////////////////////////////////////////////////////////////////// */

// snippet-start:[s3.cpp.delete_object.code]
bool AwsDoc::S3::DeleteObject(const Aws::String& objectKey,
    const Aws::String& fromBucket,const Aws::String& region)
{
    Aws::Client::ClientConfiguration config;

    if (!region.empty())
    {
        config.region = region;
    }

    Aws::S3::S3Client s3_client(config);

    Aws::S3::Model::DeleteObjectRequest request;

    request.WithKey(objectKey)
        .WithBucket(fromBucket);

    Aws::S3::Model::DeleteObjectOutcome outcome =
        s3_client.DeleteObject(request);

    if (!outcome.IsSuccess())
    {
        auto err = outcome.GetError();
        std::cout << "Error: DeleteObject: " <<
            err.GetExceptionName() << ": " << err.GetMessage() << std::endl;

        return false;
    }
    else
    {
        return true;
    }
}

int main()
{
    //TODO: The object_key is the unique identifier for the object in the bucket. In this example set,
    //it is the filename you added in put_object.cpp.
    Aws::String object_key = "my-file.txt";
    //TODO: Change from_bucket to the name of a bucket in your account.
    Aws::String from_bucket = "DOC-EXAMPLE-BUCKET";
    //TODO: Set to the AWS Region in which the bucket was created.
    Aws::String region = "us-east-1";

    Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        if (AwsDoc::S3::DeleteObject(object_key, from_bucket, region))
        {
            std::cout << "Deleted object " << object_key <<
                " from " << from_bucket << "." << std::endl;
        }
    }
    ShutdownAPI(options);

    return 0;
}
// snippet-end:[s3.cpp.delete_object.code]<commit_msg>Update delete_object.cpp<commit_after>//snippet-sourcedescription:[delete_object.cpp demonstrates how to delete an object from an Amazon Simple Storage Service (Amazon S3) bucket.]
//snippet-keyword:[AWS SDK for C++]
//snippet-keyword:[Code Sample]
//snippet-service:[Amazon S3]
//snippet-sourcetype:[full-example]
//snippet-sourcedate:[12/15/2021]
//snippet-sourceauthor:[scmacdon - aws]

/*
   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   SPDX-License-Identifier: Apache-2.0
*/

// snippet-start:[s3.cpp.delete_object.inc]
#include <iostream>
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/DeleteObjectRequest.h>
// snippet-end:[s3.cpp.delete_object.inc]

/*
 *
 * Prerequisites: The bucket containing the object to delete.
 *
 * Inputs:
 * - objectKey: The name of the object to delete.
 * - fromBucket: The name of the bucket to delete the object from.
 * - region: The AWS Region to create the bucket in.
 *
 *  To run this C++ code example, ensure that you have setup your development environment, including your credentials.
 *  For information, see this documentation topic:
 *  https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/getting-started.html
 */

// snippet-start:[s3.cpp.delete_object.code]
using namespace Aws;

int main()
{
    //TODO: The object_key is the unique identifier for the object in the bucket. In this example set,
    //it is the filename you added in put_object.cpp.
    Aws::String objectKey = "<Enter object key>";
    //TODO: Change from_bucket to the name of a bucket in your account.
    Aws::String fromBucket = "<Enter bucket name>";
    //TODO: Set to the AWS Region in which the bucket was created.
    Aws::String region = "us-east-1";

    Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        Aws::Client::ClientConfiguration clientConfig;
        if (!region.empty())
            clientConfig.region = region;

        S3::S3Client client(clientConfig);
        Aws::S3::Model::DeleteObjectRequest request;

        request.WithKey(objectKey)
            .WithBucket(fromBucket);

        Aws::S3::Model::DeleteObjectOutcome outcome =
            client.DeleteObject(request);

        if (!outcome.IsSuccess())
        {
            auto err = outcome.GetError();
            std::cout << "Error: DeleteObject: " <<
                err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
        }
        else
        {
            std::cout << "Successfully deleted the object." << std::endl;
        }
    }
    ShutdownAPI(options);

    return 0;
}
// snippet-end:[s3.cpp.delete_object.code]
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: intercept.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_embeddedobj.hxx"
#include <com/sun/star/embed/EmbedStates.hpp>
#include <cppuhelper/weak.hxx>

#include "intercept.hxx"
#include "docholder.hxx"
#include "commonembobj.hxx"

using namespace ::com::sun::star;

#define IUL 6

uno::Sequence< ::rtl::OUString > Interceptor::m_aInterceptedURL(IUL);

struct equalOUString
{
    bool operator()(
        const rtl::OUString& rKey1,
        const rtl::OUString& rKey2 ) const
    {
        return !!( rKey1 == rKey2 );
    }
};

struct hashOUString
{
    size_t operator()( const rtl::OUString& rName ) const
    {
        return rName.hashCode();
    }
};

class StatusChangeListenerContainer
    : public ::cppu::OMultiTypeInterfaceContainerHelperVar<
rtl::OUString,hashOUString,equalOUString>
{
public:
    StatusChangeListenerContainer( ::osl::Mutex& aMutex )
        :  cppu::OMultiTypeInterfaceContainerHelperVar<
    rtl::OUString,hashOUString,equalOUString>(aMutex)
    {
    }
};

void Interceptor::DisconnectDocHolder()
{
    osl::MutexGuard aGuard( m_aMutex );
    m_pDocHolder = NULL;
}

void SAL_CALL
Interceptor::addEventListener(
    const uno::Reference<lang::XEventListener >& Listener )
    throw( uno::RuntimeException )
{
    osl::MutexGuard aGuard( m_aMutex );

    if ( ! m_pDisposeEventListeners )
        m_pDisposeEventListeners =
            new cppu::OInterfaceContainerHelper( m_aMutex );

    m_pDisposeEventListeners->addInterface( Listener );
}

void SAL_CALL
Interceptor::removeEventListener(
    const uno::Reference< lang::XEventListener >& Listener )
    throw( uno::RuntimeException )
{
    osl::MutexGuard aGuard( m_aMutex );

    if ( m_pDisposeEventListeners )
        m_pDisposeEventListeners->removeInterface( Listener );
}

void SAL_CALL Interceptor::dispose()
    throw( uno::RuntimeException )
{
    lang::EventObject aEvt;
    aEvt.Source = static_cast< frame::XDispatch* >( this );

    osl::MutexGuard aGuard(m_aMutex);

    if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
        m_pDisposeEventListeners->disposeAndClear( aEvt );

    if(m_pStatCL)
        m_pStatCL->disposeAndClear( aEvt );

    m_xSlaveDispatchProvider = 0;
    m_xMasterDispatchProvider = 0;
}

Interceptor::Interceptor( DocumentHolder* pDocHolder )
    : m_pDocHolder( pDocHolder ),
      m_pDisposeEventListeners(0),
      m_pStatCL(0)
{
    m_aInterceptedURL[0] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
    m_aInterceptedURL[1] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAll"));
    m_aInterceptedURL[2] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc"));
    m_aInterceptedURL[3] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));
    m_aInterceptedURL[4] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame"));
    m_aInterceptedURL[5] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs"));

}

Interceptor::~Interceptor()
{
    if( m_pDisposeEventListeners )
        delete m_pDisposeEventListeners;

    if(m_pStatCL)
        delete m_pStatCL;
}

//XDispatch
void SAL_CALL
Interceptor::dispatch(
    const util::URL& URL,
    const uno::Sequence<
    beans::PropertyValue >& Arguments )
    throw (uno::RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);
    if( m_pDocHolder )
        if(URL.Complete == m_aInterceptedURL[0])
            m_pDocHolder->GetEmbedObject()->SaveObject_Impl();
        else if(URL.Complete == m_aInterceptedURL[2] ||
                URL.Complete == m_aInterceptedURL[3] ||
                URL.Complete == m_aInterceptedURL[4])
        {
            try {
                m_pDocHolder->GetEmbedObject()->changeState( embed::EmbedStates::RUNNING );
            }
            catch( uno::Exception& )
            {
            }
        }
        else if ( URL.Complete == m_aInterceptedURL[5] )
        {
            uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
            sal_Int32 nInd = 0;

            while( nInd < aNewArgs.getLength() )
            {
                if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) )
                {
                    aNewArgs[nInd].Value <<= sal_True;
                    break;
                }
                nInd++;
            }

            if ( nInd == aNewArgs.getLength() )
            {
                aNewArgs.realloc( nInd + 1 );
                aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" );
                aNewArgs[nInd].Value <<= sal_True;
            }

            uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
                URL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
            if ( xDispatch.is() )
                xDispatch->dispatch( URL, aNewArgs );
        }
}

void Interceptor::GenerateFeatureStateEvent()
{
    if(m_pStatCL)
    {
        for(int i = 0; i < IUL; ++i)
        {
            if( i == 1 )
                continue;

            cppu::OInterfaceContainerHelper* pICH =
                m_pStatCL->getContainer(m_aInterceptedURL[i]);
            uno::Sequence<uno::Reference<uno::XInterface> > aSeq;
            if(pICH)
                aSeq = pICH->getElements();
            if(!aSeq.getLength())
                continue;

            frame::FeatureStateEvent aStateEvent;
            aStateEvent.IsEnabled = sal_True;
            aStateEvent.Requery = sal_False;
            if(i == 0)
            {
                aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
                aStateEvent.FeatureDescriptor = rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("Update"));
                aStateEvent.State <<= (rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("($1) ")) + m_pDocHolder->GetTitle() );

            }
            else if ( i == 5 )
            {
                aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
                aStateEvent.FeatureDescriptor = rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
                aStateEvent.State <<= (rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("($3)")));
            }
            else
            {
                aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
                aStateEvent.FeatureDescriptor = rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
                aStateEvent.State <<= (rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("($2) ")) + m_pDocHolder->GetTitle() );

            }

            for(sal_Int32 k = 0; k < aSeq.getLength(); ++k)
            {
                uno::Reference<frame::XStatusListener>
                    Control(aSeq[k],uno::UNO_QUERY);
                if(Control.is())
                    Control->statusChanged(aStateEvent);

            }
        }
    }
}

void SAL_CALL
Interceptor::addStatusListener(
    const uno::Reference<
    frame::XStatusListener >& Control,
    const util::URL& URL )
    throw (
        uno::RuntimeException
    )
{
    if(!Control.is())
        return;

    if(URL.Complete == m_aInterceptedURL[0])
    {   // Save
        frame::FeatureStateEvent aStateEvent;
        aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
        aStateEvent.FeatureDescriptor = rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM("Update"));
        aStateEvent.IsEnabled = sal_True;
        aStateEvent.Requery = sal_False;
        aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($1) ")) + m_pDocHolder->GetTitle() );
        Control->statusChanged(aStateEvent);

        {
            osl::MutexGuard aGuard(m_aMutex);
            if(!m_pStatCL)
                m_pStatCL =
                    new StatusChangeListenerContainer(m_aMutex);
        }

        m_pStatCL->addInterface(URL.Complete,Control);
        return;
    }

    sal_Int32 i = 2;
    if(URL.Complete == m_aInterceptedURL[i] ||
       URL.Complete == m_aInterceptedURL[++i] ||
       URL.Complete == m_aInterceptedURL[++i] )
    {   // Close and return
        frame::FeatureStateEvent aStateEvent;
        aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
        aStateEvent.FeatureDescriptor = rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
        aStateEvent.IsEnabled = sal_True;
        aStateEvent.Requery = sal_False;
        aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($2) ")) + m_pDocHolder->GetTitle() );
        Control->statusChanged(aStateEvent);

        {
            osl::MutexGuard aGuard(m_aMutex);
            if(!m_pStatCL)
                m_pStatCL =
                    new StatusChangeListenerContainer(m_aMutex);
        }

        m_pStatCL->addInterface(URL.Complete,Control);
        return;
    }

    if(URL.Complete == m_aInterceptedURL[5])
    {   // SaveAs
        frame::FeatureStateEvent aStateEvent;
        aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
        aStateEvent.FeatureDescriptor = rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
        aStateEvent.IsEnabled = sal_True;
        aStateEvent.Requery = sal_False;
        aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)")));
        Control->statusChanged(aStateEvent);

        {
            osl::MutexGuard aGuard(m_aMutex);
            if(!m_pStatCL)
                m_pStatCL =
                    new StatusChangeListenerContainer(m_aMutex);
        }

        m_pStatCL->addInterface(URL.Complete,Control);
        return;
    }

}

void SAL_CALL
Interceptor::removeStatusListener(
    const uno::Reference<
    frame::XStatusListener >& Control,
    const util::URL& URL )
    throw (
        uno::RuntimeException
    )
{
    if(!(Control.is() && m_pStatCL))
        return;
    else {
        m_pStatCL->removeInterface(URL.Complete,Control);
        return;
    }
}

//XInterceptorInfo
uno::Sequence< ::rtl::OUString >
SAL_CALL
Interceptor::getInterceptedURLs(  )
    throw (
        uno::RuntimeException
    )
{
    // now implemented as update

    return m_aInterceptedURL;
}

// XDispatchProvider

uno::Reference< frame::XDispatch > SAL_CALL
Interceptor::queryDispatch(
    const util::URL& URL,
    const ::rtl::OUString& TargetFrameName,
    sal_Int32 SearchFlags )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    if(URL.Complete == m_aInterceptedURL[0])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[1])
        return (frame::XDispatch*)0   ;
    else if(URL.Complete == m_aInterceptedURL[2])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[3])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[4])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[5])
        return (frame::XDispatch*)this;
    else {
        if(m_xSlaveDispatchProvider.is())
            return m_xSlaveDispatchProvider->queryDispatch(
                URL,TargetFrameName,SearchFlags);
        else
            return uno::Reference<frame::XDispatch>(0);
    }
}

uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
Interceptor::queryDispatches(
    const uno::Sequence<frame::DispatchDescriptor >& Requests )
    throw (
        uno::RuntimeException
    )
{
    uno::Sequence< uno::Reference< frame::XDispatch > > aRet;
    osl::MutexGuard aGuard(m_aMutex);
    if(m_xSlaveDispatchProvider.is())
        aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
    else
        aRet.realloc(Requests.getLength());

    for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
        if(m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) 0;
        else if(m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;

    return aRet;
}

//XDispatchProviderInterceptor

uno::Reference< frame::XDispatchProvider > SAL_CALL
Interceptor::getSlaveDispatchProvider(  )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    return m_xSlaveDispatchProvider;
}

void SAL_CALL
Interceptor::setSlaveDispatchProvider(
    const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    m_xSlaveDispatchProvider = NewDispatchProvider;
}

uno::Reference< frame::XDispatchProvider > SAL_CALL
Interceptor::getMasterDispatchProvider(  )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    return m_xMasterDispatchProvider;
}

void SAL_CALL
Interceptor::setMasterDispatchProvider(
    const uno::Reference< frame::XDispatchProvider >& NewSupplier )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    m_xMasterDispatchProvider = NewSupplier;
}

<commit_msg>INTEGRATION: CWS fwk88 (1.7.4); FILE MERGED 2008/05/27 15:30:33 mav 1.7.4.1: #i86367# integrate the patch<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: intercept.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_embeddedobj.hxx"
#include <com/sun/star/embed/EmbedStates.hpp>
#include <cppuhelper/weak.hxx>

#include "intercept.hxx"
#include "docholder.hxx"
#include "commonembobj.hxx"

using namespace ::com::sun::star;

#define IUL 6

uno::Sequence< ::rtl::OUString > Interceptor::m_aInterceptedURL(IUL);

struct equalOUString
{
    bool operator()(
        const rtl::OUString& rKey1,
        const rtl::OUString& rKey2 ) const
    {
        return !!( rKey1 == rKey2 );
    }
};

struct hashOUString
{
    size_t operator()( const rtl::OUString& rName ) const
    {
        return rName.hashCode();
    }
};

class StatusChangeListenerContainer
    : public ::cppu::OMultiTypeInterfaceContainerHelperVar<
rtl::OUString,hashOUString,equalOUString>
{
public:
    StatusChangeListenerContainer( ::osl::Mutex& aMutex )
        :  cppu::OMultiTypeInterfaceContainerHelperVar<
    rtl::OUString,hashOUString,equalOUString>(aMutex)
    {
    }
};

void Interceptor::DisconnectDocHolder()
{
    osl::MutexGuard aGuard( m_aMutex );
    m_pDocHolder = NULL;
}

void SAL_CALL
Interceptor::addEventListener(
    const uno::Reference<lang::XEventListener >& Listener )
    throw( uno::RuntimeException )
{
    osl::MutexGuard aGuard( m_aMutex );

    if ( ! m_pDisposeEventListeners )
        m_pDisposeEventListeners =
            new cppu::OInterfaceContainerHelper( m_aMutex );

    m_pDisposeEventListeners->addInterface( Listener );
}

void SAL_CALL
Interceptor::removeEventListener(
    const uno::Reference< lang::XEventListener >& Listener )
    throw( uno::RuntimeException )
{
    osl::MutexGuard aGuard( m_aMutex );

    if ( m_pDisposeEventListeners )
        m_pDisposeEventListeners->removeInterface( Listener );
}

Interceptor::Interceptor( DocumentHolder* pDocHolder )
    : m_pDocHolder( pDocHolder ),
      m_pDisposeEventListeners(0),
      m_pStatCL(0)
{
    m_aInterceptedURL[0] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
    m_aInterceptedURL[1] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAll"));
    m_aInterceptedURL[2] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc"));
    m_aInterceptedURL[3] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));
    m_aInterceptedURL[4] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame"));
    m_aInterceptedURL[5] = rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs"));

}

Interceptor::~Interceptor()
{
    if( m_pDisposeEventListeners )
        delete m_pDisposeEventListeners;

    if(m_pStatCL)
        delete m_pStatCL;
}

//XDispatch
void SAL_CALL
Interceptor::dispatch(
    const util::URL& URL,
    const uno::Sequence<
    beans::PropertyValue >& Arguments )
    throw (uno::RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);
    if( m_pDocHolder )
        if(URL.Complete == m_aInterceptedURL[0])
            m_pDocHolder->GetEmbedObject()->SaveObject_Impl();
        else if(URL.Complete == m_aInterceptedURL[2] ||
                URL.Complete == m_aInterceptedURL[3] ||
                URL.Complete == m_aInterceptedURL[4])
        {
            try {
                m_pDocHolder->GetEmbedObject()->changeState( embed::EmbedStates::RUNNING );
            }
            catch( uno::Exception& )
            {
            }
        }
        else if ( URL.Complete == m_aInterceptedURL[5] )
        {
            uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
            sal_Int32 nInd = 0;

            while( nInd < aNewArgs.getLength() )
            {
                if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) )
                {
                    aNewArgs[nInd].Value <<= sal_True;
                    break;
                }
                nInd++;
            }

            if ( nInd == aNewArgs.getLength() )
            {
                aNewArgs.realloc( nInd + 1 );
                aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" );
                aNewArgs[nInd].Value <<= sal_True;
            }

            uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
                URL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
            if ( xDispatch.is() )
                xDispatch->dispatch( URL, aNewArgs );
        }
}

void SAL_CALL
Interceptor::addStatusListener(
    const uno::Reference<
    frame::XStatusListener >& Control,
    const util::URL& URL )
    throw (
        uno::RuntimeException
    )
{
    if(!Control.is())
        return;

    if(URL.Complete == m_aInterceptedURL[0])
    {   // Save
        frame::FeatureStateEvent aStateEvent;
        aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
        aStateEvent.FeatureDescriptor = rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM("Update"));
        aStateEvent.IsEnabled = sal_True;
        aStateEvent.Requery = sal_False;
        aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($1) ")) + m_pDocHolder->GetTitle() );
        Control->statusChanged(aStateEvent);

        {
            osl::MutexGuard aGuard(m_aMutex);
            if(!m_pStatCL)
                m_pStatCL =
                    new StatusChangeListenerContainer(m_aMutex);
        }

        m_pStatCL->addInterface(URL.Complete,Control);
        return;
    }

    sal_Int32 i = 2;
    if(URL.Complete == m_aInterceptedURL[i] ||
       URL.Complete == m_aInterceptedURL[++i] ||
       URL.Complete == m_aInterceptedURL[++i] )
    {   // Close and return
        frame::FeatureStateEvent aStateEvent;
        aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
        aStateEvent.FeatureDescriptor = rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
        aStateEvent.IsEnabled = sal_True;
        aStateEvent.Requery = sal_False;
        aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($2) ")) + m_pDocHolder->GetTitle() );
        Control->statusChanged(aStateEvent);

        {
            osl::MutexGuard aGuard(m_aMutex);
            if(!m_pStatCL)
                m_pStatCL =
                    new StatusChangeListenerContainer(m_aMutex);
        }

        m_pStatCL->addInterface(URL.Complete,Control);
        return;
    }

    if(URL.Complete == m_aInterceptedURL[5])
    {   // SaveAs
        frame::FeatureStateEvent aStateEvent;
        aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
        aStateEvent.FeatureDescriptor = rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
        aStateEvent.IsEnabled = sal_True;
        aStateEvent.Requery = sal_False;
        aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)")));
        Control->statusChanged(aStateEvent);

        {
            osl::MutexGuard aGuard(m_aMutex);
            if(!m_pStatCL)
                m_pStatCL =
                    new StatusChangeListenerContainer(m_aMutex);
        }

        m_pStatCL->addInterface(URL.Complete,Control);
        return;
    }

}

void SAL_CALL
Interceptor::removeStatusListener(
    const uno::Reference<
    frame::XStatusListener >& Control,
    const util::URL& URL )
    throw (
        uno::RuntimeException
    )
{
    if(!(Control.is() && m_pStatCL))
        return;
    else {
        m_pStatCL->removeInterface(URL.Complete,Control);
        return;
    }
}

//XInterceptorInfo
uno::Sequence< ::rtl::OUString >
SAL_CALL
Interceptor::getInterceptedURLs(  )
    throw (
        uno::RuntimeException
    )
{
    // now implemented as update

    return m_aInterceptedURL;
}

// XDispatchProvider

uno::Reference< frame::XDispatch > SAL_CALL
Interceptor::queryDispatch(
    const util::URL& URL,
    const ::rtl::OUString& TargetFrameName,
    sal_Int32 SearchFlags )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    if(URL.Complete == m_aInterceptedURL[0])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[1])
        return (frame::XDispatch*)0   ;
    else if(URL.Complete == m_aInterceptedURL[2])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[3])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[4])
        return (frame::XDispatch*)this;
    else if(URL.Complete == m_aInterceptedURL[5])
        return (frame::XDispatch*)this;
    else {
        if(m_xSlaveDispatchProvider.is())
            return m_xSlaveDispatchProvider->queryDispatch(
                URL,TargetFrameName,SearchFlags);
        else
            return uno::Reference<frame::XDispatch>(0);
    }
}

uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
Interceptor::queryDispatches(
    const uno::Sequence<frame::DispatchDescriptor >& Requests )
    throw (
        uno::RuntimeException
    )
{
    uno::Sequence< uno::Reference< frame::XDispatch > > aRet;
    osl::MutexGuard aGuard(m_aMutex);
    if(m_xSlaveDispatchProvider.is())
        aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
    else
        aRet.realloc(Requests.getLength());

    for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
        if(m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) 0;
        else if(m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;
        else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
            aRet[i] = (frame::XDispatch*) this;

    return aRet;
}

//XDispatchProviderInterceptor

uno::Reference< frame::XDispatchProvider > SAL_CALL
Interceptor::getSlaveDispatchProvider(  )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    return m_xSlaveDispatchProvider;
}

void SAL_CALL
Interceptor::setSlaveDispatchProvider(
    const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    m_xSlaveDispatchProvider = NewDispatchProvider;
}

uno::Reference< frame::XDispatchProvider > SAL_CALL
Interceptor::getMasterDispatchProvider(  )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    return m_xMasterDispatchProvider;
}

void SAL_CALL
Interceptor::setMasterDispatchProvider(
    const uno::Reference< frame::XDispatchProvider >& NewSupplier )
    throw (
        uno::RuntimeException
    )
{
    osl::MutexGuard aGuard(m_aMutex);
    m_xMasterDispatchProvider = NewSupplier;
}

<|endoftext|>