<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#endif

#include "common.h"

#include <algorithm>

#include "AutoCompleter.h"

void AutoCompleter::registerWord(const std::string& str) {
  words.insert(std::lower_bound(words.begin(), words.end(), str), str);
}

void AutoCompleter::unregisterWord(const std::string& str) {
  std::vector<std::string>::iterator iter = std::lower_bound(words.begin(), words.end(), str);
  if (iter != words.end() && *iter == str)
    words.erase(iter);
}

std::string AutoCompleter::complete(const std::string& str) {

  if (str.size() == 0)
    return str;

  // find the first and last word with the prefix str
  std::vector<std::string>::iterator first, last;
  first = std::lower_bound(words.begin(), words.end(), str);
  if (first == words.end() || first->substr(0, str.size()) != str)
    return str;
  std::string tmp = str;
  tmp[tmp.size() - 1]++;
  last = std::lower_bound(first, words.end(), tmp) - 1;

  // return the largest common prefix
  unsigned int i;
  for (i = 0; i < first->size() && i < last->size(); ++i)
    if ((*first)[i] != (*last)[i])
      break;
  return first->substr(0, i);
}

DefaultCompleter::DefaultCompleter() {
  setDefaults();
}

void DefaultCompleter::setDefaults() {
  words.clear();
  registerWord("/ban ");
  registerWord("/banlist");
  registerWord("/countdown");
  registerWord("/clientquery");
  registerWord("/date");
  registerWord("/deregister");
  registerWord("/flag ");
  registerWord("reset");
  registerWord("up");
  registerWord("show");
  registerWord("/flaghistory");
  registerWord("/gameover");
  registerWord("/ghost ");
  registerWord("/groupperms");
  registerWord("/help");
  registerWord("/highlight ");
  registerWord("/identify ");
  registerWord("/idlestats");
  registerWord("/kick ");
  registerWord("/kill ");
  registerWord("/lagstats");
  registerWord("/lagwarn ");
  registerWord("/localset ");
  registerWord("/mute ");
  registerWord("/password ");
  registerWord("/playerlist");
  registerWord("/poll ");
  registerWord("ban");
  registerWord("kick");
  registerWord("kill");
  registerWord("/quit");
  registerWord("/record");
  registerWord("start");
  registerWord("stop");
  registerWord("size");
  registerWord("rate");
  registerWord("stats");
  registerWord("file");
  registerWord("save");
  registerWord("/register ");
  registerWord("/reload");
  registerWord("/masterban"); // also uses list
  registerWord("reload");
  registerWord("flush");
  registerWord("/removegroup ");
  registerWord("/replay ");
  registerWord("list");
  registerWord("load");
  registerWord("play");
  registerWord("skip");
  registerWord("/report ");
  registerWord("/reset");
  registerWord("/retexture");
  registerWord("/roampos ");
  registerWord("/set");
  registerWord("/setgroup ");
  registerWord("/setpass ");
  registerWord("/showgroup ");
  registerWord("/shutdownserver");
  registerWord("/superkill");
  registerWord("/time");
  registerWord("/unban ");
  registerWord("/unmute ");
  registerWord("/uptime");
  registerWord("/veto");
  registerWord("/viewreports");
  registerWord("/vote");
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>added serverquery<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#endif

#include "common.h"

#include <algorithm>

#include "AutoCompleter.h"

void AutoCompleter::registerWord(const std::string& str) {
  words.insert(std::lower_bound(words.begin(), words.end(), str), str);
}

void AutoCompleter::unregisterWord(const std::string& str) {
  std::vector<std::string>::iterator iter = std::lower_bound(words.begin(), words.end(), str);
  if (iter != words.end() && *iter == str)
    words.erase(iter);
}

std::string AutoCompleter::complete(const std::string& str) {

  if (str.size() == 0)
    return str;

  // find the first and last word with the prefix str
  std::vector<std::string>::iterator first, last;
  first = std::lower_bound(words.begin(), words.end(), str);
  if (first == words.end() || first->substr(0, str.size()) != str)
    return str;
  std::string tmp = str;
  tmp[tmp.size() - 1]++;
  last = std::lower_bound(first, words.end(), tmp) - 1;

  // return the largest common prefix
  unsigned int i;
  for (i = 0; i < first->size() && i < last->size(); ++i)
    if ((*first)[i] != (*last)[i])
      break;
  return first->substr(0, i);
}

DefaultCompleter::DefaultCompleter() {
  setDefaults();
}

void DefaultCompleter::setDefaults() {
  words.clear();
  registerWord("/ban ");
  registerWord("/banlist");
  registerWord("/countdown");
  registerWord("/clientquery");
  registerWord("/date");
  registerWord("/deregister");
  registerWord("/flag ");
  registerWord("reset");
  registerWord("up");
  registerWord("show");
  registerWord("/flaghistory");
  registerWord("/gameover");
  registerWord("/ghost ");
  registerWord("/groupperms");
  registerWord("/help");
  registerWord("/highlight ");
  registerWord("/identify ");
  registerWord("/idlestats");
  registerWord("/kick ");
  registerWord("/kill ");
  registerWord("/lagstats");
  registerWord("/lagwarn ");
  registerWord("/localset ");
  registerWord("/mute ");
  registerWord("/password ");
  registerWord("/playerlist");
  registerWord("/poll ");
  registerWord("ban");
  registerWord("kick");
  registerWord("kill");
  registerWord("/quit");
  registerWord("/record");
  registerWord("start");
  registerWord("stop");
  registerWord("size");
  registerWord("rate");
  registerWord("stats");
  registerWord("file");
  registerWord("save");
  registerWord("/register ");
  registerWord("/reload");
  registerWord("/masterban"); // also uses list
  registerWord("reload");
  registerWord("flush");
  registerWord("/removegroup ");
  registerWord("/replay ");
  registerWord("list");
  registerWord("load");
  registerWord("play");
  registerWord("skip");
  registerWord("/report ");
  registerWord("/reset");
  registerWord("/retexture");
  registerWord("/roampos ");
  registerWord("/serverquery");
  registerWord("/set");
  registerWord("/setgroup ");
  registerWord("/setpass ");
  registerWord("/showgroup ");
  registerWord("/shutdownserver");
  registerWord("/superkill");
  registerWord("/time");
  registerWord("/unban ");
  registerWord("/unmute ");
  registerWord("/uptime");
  registerWord("/veto");
  registerWord("/viewreports");
  registerWord("/vote");
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include <rtcmix_types.h>
#include <PField.h>
#include <string.h>		// for strcmp()
#include <stdlib.h>		// for free()

Arg::~Arg() { if (_type == ArrayType) free(_val.array); }

bool
Arg::operator == (const char *str) const {
	return isType(StringType) && !strcmp(_val.string, str);
}

void
Arg::printInline(FILE *stream) const
{
	switch (type()) {
	case DoubleType:
		fprintf(stream, "%g ", _val.number);
		break;
	case StringType:
		fprintf(stream, "\"%s\" ", _val.string);
		break;
	case HandleType:
		fprintf(stream, "%sHndl:",
				_val.handle->type == PFieldType ? "PF" :
				_val.handle->type == InstrumentPtrType ? "Inst" :
				_val.handle->type == PFieldType ? "AudioStr" : "Unknown");
		if (_val.handle->type == PFieldType) {
			// Print PField start and end values.
			PField *pf = (PField *) _val.handle->ptr;
			double start = pf->doubleValue(0);
			double end = pf->doubleValue(1.0);
			fprintf(stream, "[%g,...,%g] ", start, end);
		}
		else
			fprintf(stream, " ");
		break;
	case ArrayType:
		fprintf(stream, "[%g,...,%g] ", _val.array->data[0],
				_val.array->data[_val.array->len - 1]);
		break;
	default:
		break;
	}
}

<commit_msg>Changed arg printout from PFHndl: to PF:<commit_after>#include <rtcmix_types.h>
#include <PField.h>
#include <string.h>		// for strcmp()
#include <stdlib.h>		// for free()

Arg::~Arg() { if (_type == ArrayType) free(_val.array); }

bool
Arg::operator == (const char *str) const {
	return isType(StringType) && !strcmp(_val.string, str);
}

void
Arg::printInline(FILE *stream) const
{
	switch (type()) {
	case DoubleType:
		fprintf(stream, "%g ", _val.number);
		break;
	case StringType:
		fprintf(stream, "\"%s\" ", _val.string);
		break;
	case HandleType:
		fprintf(stream, "%s:",
				_val.handle->type == PFieldType ? "PF" :
				_val.handle->type == InstrumentPtrType ? "Inst" :
				_val.handle->type == PFieldType ? "AudioStr" : "Unknown");
		if (_val.handle->type == PFieldType) {
			// Print PField start and end values.
			PField *pf = (PField *) _val.handle->ptr;
			double start = pf->doubleValue(0);
			double end = pf->doubleValue(1.0);
			fprintf(stream, "[%g,...,%g] ", start, end);
		}
		else
			fprintf(stream, " ");
		break;
	case ArrayType:
		fprintf(stream, "[%g,...,%g] ", _val.array->data[0],
				_val.array->data[_val.array->len - 1]);
		break;
	default:
		break;
	}
}

<|endoftext|>


<commit_before>#include "REPL.h"
#include "ConsoleWriter.h"
#include <iostream>
#include <parser/Parser.h>
#include <common/Errors.h>
#include <semantics/SemanticAnalyzer.h>
#include <semantics/ScopedNodes.h>
#include <cassert>
#include <ast/ast.h>
#include <semantics/GlobalScope.h>
#include <semantics/FunctionOverloadedSymbol.h>
#include <semantics/FunctionSymbol.h>

using namespace std;
using namespace Swallow;

REPL::REPL(const ConsoleWriterPtr& out)
:out(out), canQuit(false)
{
    initCommands();
    resultId = 0;

}

void REPL::repl()
{
    wstring line;
    int id = 1;
    out->printf(L"Welcome to Swallow! Type :help for assistance.\n");
    program = nodeFactory.createProgram();
    while(!canQuit && !wcin.eof())
    {
        out->printf(L"%3d> ", id);
        getline(wcin, line);
        if(line.empty())
            continue;
        if(line[0] == ':')
        {
            evalCommand(line.substr(1));
            continue;
        }
        CompilerResults compilerResults;
        eval(compilerResults, line);
        dumpCompilerResults(compilerResults, line);
        id++;
    }
}

void REPL::eval(CompilerResults& compilerResults, const wstring& line)
{
    Parser parser(&nodeFactory, &compilerResults);
    parser.setFileName(L"<file>");
    //remove parsed nodes in last eval
    program->clearStatements();

    bool successed = parser.parse(line.c_str(), program);
    if(!successed)
        return;
    try
    {
        SemanticAnalyzer analyzer(&registry, &compilerResults);
        program->accept(&analyzer);
        dumpProgram();
    }
    catch(const Abort&)
    {
//ignore this
    }

}
void REPL::dumpProgram()
{
    SymbolScope* scope = static_pointer_cast<ScopedProgram>(program)->getScope();
    assert(scope != nullptr);
    out->setForegroundColor(Cyan);
    for(const StatementPtr& st : *program)
    {
        SymbolPtr sym = nullptr;
        switch(st->getNodeType())
        {
            case NodeType::Identifier:
            {
                IdentifierPtr id = static_pointer_cast<Identifier>(st);
                sym = scope->lookup(id->getIdentifier());
                dumpSymbol(sym);
                break;
            }
            case NodeType::ValueBindings:
            {
                ValueBindingsPtr vars = static_pointer_cast<ValueBindings>(st);
                for(const ValueBindingPtr& var : *vars)
                {
                    if(IdentifierPtr id = dynamic_pointer_cast<Identifier>(var->getName()))
                    {
                        sym = scope->lookup(id->getIdentifier());
                        dumpSymbol(sym);
                    }
                }
                break;
            }
            default:
            {
                if(PatternPtr pat = dynamic_pointer_cast<Pattern>(st))
                {
                    if(pat->getType() && !Type::equals(registry.getGlobalScope()->t_Void, pat->getType()))
                    {
                        wstringstream s;
                        s<<L"$R"<<(resultId++);
                        SymbolPlaceHolderPtr sym(new SymbolPlaceHolder(s.str(), pat->getType(), SymbolPlaceHolder::R_LOCAL_VARIABLE, 0));
                        dumpSymbol(sym);
                    }
                }
                break;
            }
        }
    }
    out->reset();
}

void REPL::dumpSymbol(const SymbolPtr& sym)
{
    if(sym && sym->getType())
    {
        wstring type = sym->getType()->toString();
        out->printf(L"%ls : %ls\n", sym->getName().c_str(), type.c_str());
    }
}

void REPL::dumpCompilerResults(CompilerResults& compilerResults, const std::wstring& code)
{
    for(auto res : compilerResults)
    {
        out->setForegroundColor(White);
        out->printf(L"%d:%d: ", res.line, res.column);
        switch(res.level)
        {
            case ErrorLevel::Fatal:
                out->setForegroundColor(Red);
                out->printf(L"fatal");
                break;
            case ErrorLevel::Error:
                out->setForegroundColor(Red, Bright);
                out->printf(L"error");
                break;
            case ErrorLevel::Note:
                out->setForegroundColor(White);
                out->printf(L"note");
                break;
            case ErrorLevel::Warning:
                out->setForegroundColor(Yellow);
                out->printf(L"warning");
                break;
        }
        out->setForegroundColor(White, Bright);
        out->printf(L": ");
        wstring msg = Errors::format(res.code, res.items);
        out->printf(L"%ls\n", msg.c_str());
        out->reset();
        out->printf(L"%ls\n", code.c_str());
        for(int i = 1; i < res.column; i++)
        {
            out->printf(L" ");
        }
        out->setForegroundColor(Green);
        out->printf(L"^\n");
        out->reset();
    }
}

void REPL::evalCommand(const wstring &command)
{
    wstring cmd = command;
    wstring args;
    wstring::size_type pos = command.find(L' ');
    if(pos != wstring::npos)
    {
        cmd = command.substr(0, pos);
        args = command.substr(pos + 1, command.size() - pos - 1);
    }
    auto iter = methods.find(cmd);
    if(iter == methods.end())
    {
        out->printf(L"error: '%ls' is not a valid command.\n", cmd.c_str());
        return;
    }
    (this->*iter->second)(args);
}

void REPL::initCommands()
{
    methods.insert(make_pair(L"help", &REPL::commandHelp));
    methods.insert(make_pair(L"quit", &REPL::commandQuit));
    methods.insert(make_pair(L"exit", &REPL::commandQuit));
    methods.insert(make_pair(L"symbols", &REPL::commandSymbols));
}
void REPL::commandHelp(const wstring& args)
{
    out->printf(L"The Swallow REPL (Read-Eval-Print-Loop) acts like an interpreter.  Valid statements, expressions, and declarations.\n");
    out->printf(L"Compiler and execution is not finished yet.");
    out->printf(L"\n");
    out->printf(L"The complete set of commands are also available as described below.  Commands must be prefixed with a colon at the REPL prompt (:quit for example.) \n\n\n");
    out->printf(L"REPL commands:\n");
    out->printf(L"  help              -- Show a list of all swallow commands, or give details about specific commands.\n");
    out->printf(L"  symbols           -- Dump symbols\n");
    out->printf(L"  quit              -- Quit out of the Swallow REPL.\n\n");
}
void REPL::commandQuit(const wstring& args)
{
    canQuit = true;
}

static void dumpSymbol(const wstring& name, const SymbolPtr& sym, const ConsoleWriterPtr& out)
{
    const wchar_t* kind = L"?????";

    if(dynamic_pointer_cast<Type>(sym))
        kind = L"Type";
    else if(dynamic_pointer_cast<SymbolPlaceHolder>(sym))
        kind = L"Placeholder";
    else if(dynamic_pointer_cast<FunctionSymbol>(sym))
        kind = L"Function";

    out->setForegroundColor(White , Bright);
    out->printf(L"%10ls\t", name.c_str());
    out->setForegroundColor(Magenta , Bright);
    out->printf(L"%7ls\t", kind);

    if(sym->getType())
    {
        wstring type = sym->getType()->toString();
        out->setForegroundColor(Yellow, Bright);
        out->printf(L"%ls\t", type.c_str());
    }

    out->setForegroundColor(Cyan, Bright);
    static const SymbolFlags flags[] = {SymbolFlagInitializing, SymbolFlagInitialized, SymbolFlagMember, SymbolFlagWritable, SymbolFlagReadable, SymbolFlagTemporary,
            SymbolFlagHasInitializer, SymbolFlagStatic, SymbolFlagInit};
    static const wchar_t* flagNames[] = {L"initializing", L"initialized", L"member", L"writable", L"readable", L"temporary", L"has_initializer", L"static", L"init"};
    for(int i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
    {
        if(sym->hasFlags(flags[i]))
            out->printf(L"%ls,", flagNames[i]);
    }

    out->printf(L"\n");
    out->reset();
}
static void dumpSymbols(SymbolScope* scope, const ConsoleWriterPtr& out)
{
    for(auto entry : scope->getSymbols())
    {
        if(FunctionOverloadedSymbolPtr funcs = dynamic_pointer_cast<FunctionOverloadedSymbol>(entry.second))
        {
            for(const FunctionSymbolPtr& func : *funcs)
            {
                dumpSymbol(entry.first, func, out);
            }
        }
        else
        {
            dumpSymbol(entry.first, entry.second, out);
        }
    }
}
void REPL::commandSymbols(const wstring& args)
{
    SymbolScope* scope = nullptr;
    ScopedProgramPtr p = static_pointer_cast<ScopedProgram>(program);
    if(args == L"global")
        scope = this->registry.getGlobalScope();
    else
        scope = p->getScope();
    dumpSymbols(scope, out);
}<commit_msg>Refactored the type's naming in GlobalScope.h<commit_after>#include "REPL.h"
#include "ConsoleWriter.h"
#include <iostream>
#include <parser/Parser.h>
#include <common/Errors.h>
#include <semantics/SemanticAnalyzer.h>
#include <semantics/ScopedNodes.h>
#include <cassert>
#include <ast/ast.h>
#include <semantics/GlobalScope.h>
#include <semantics/FunctionOverloadedSymbol.h>
#include <semantics/FunctionSymbol.h>

using namespace std;
using namespace Swallow;

REPL::REPL(const ConsoleWriterPtr& out)
:out(out), canQuit(false)
{
    initCommands();
    resultId = 0;

}

void REPL::repl()
{
    wstring line;
    int id = 1;
    out->printf(L"Welcome to Swallow! Type :help for assistance.\n");
    program = nodeFactory.createProgram();
    while(!canQuit && !wcin.eof())
    {
        out->printf(L"%3d> ", id);
        getline(wcin, line);
        if(line.empty())
            continue;
        if(line[0] == ':')
        {
            evalCommand(line.substr(1));
            continue;
        }
        CompilerResults compilerResults;
        eval(compilerResults, line);
        dumpCompilerResults(compilerResults, line);
        id++;
    }
}

void REPL::eval(CompilerResults& compilerResults, const wstring& line)
{
    Parser parser(&nodeFactory, &compilerResults);
    parser.setFileName(L"<file>");
    //remove parsed nodes in last eval
    program->clearStatements();

    bool successed = parser.parse(line.c_str(), program);
    if(!successed)
        return;
    try
    {
        SemanticAnalyzer analyzer(&registry, &compilerResults);
        program->accept(&analyzer);
        dumpProgram();
    }
    catch(const Abort&)
    {
//ignore this
    }

}
void REPL::dumpProgram()
{
    SymbolScope* scope = static_pointer_cast<ScopedProgram>(program)->getScope();
    assert(scope != nullptr);
    out->setForegroundColor(Cyan);
    for(const StatementPtr& st : *program)
    {
        SymbolPtr sym = nullptr;
        switch(st->getNodeType())
        {
            case NodeType::Identifier:
            {
                IdentifierPtr id = static_pointer_cast<Identifier>(st);
                sym = scope->lookup(id->getIdentifier());
                dumpSymbol(sym);
                break;
            }
            case NodeType::ValueBindings:
            {
                ValueBindingsPtr vars = static_pointer_cast<ValueBindings>(st);
                for(const ValueBindingPtr& var : *vars)
                {
                    if(IdentifierPtr id = dynamic_pointer_cast<Identifier>(var->getName()))
                    {
                        sym = scope->lookup(id->getIdentifier());
                        dumpSymbol(sym);
                    }
                }
                break;
            }
            default:
            {
                if(PatternPtr pat = dynamic_pointer_cast<Pattern>(st))
                {
                    if(pat->getType() && !Type::equals(registry.getGlobalScope()->Void, pat->getType()))
                    {
                        wstringstream s;
                        s<<L"$R"<<(resultId++);
                        SymbolPlaceHolderPtr sym(new SymbolPlaceHolder(s.str(), pat->getType(), SymbolPlaceHolder::R_LOCAL_VARIABLE, 0));
                        dumpSymbol(sym);
                    }
                }
                break;
            }
        }
    }
    out->reset();
}

void REPL::dumpSymbol(const SymbolPtr& sym)
{
    if(sym && sym->getType())
    {
        wstring type = sym->getType()->toString();
        out->printf(L"%ls : %ls\n", sym->getName().c_str(), type.c_str());
    }
}

void REPL::dumpCompilerResults(CompilerResults& compilerResults, const std::wstring& code)
{
    for(auto res : compilerResults)
    {
        out->setForegroundColor(White);
        out->printf(L"%d:%d: ", res.line, res.column);
        switch(res.level)
        {
            case ErrorLevel::Fatal:
                out->setForegroundColor(Red);
                out->printf(L"fatal");
                break;
            case ErrorLevel::Error:
                out->setForegroundColor(Red, Bright);
                out->printf(L"error");
                break;
            case ErrorLevel::Note:
                out->setForegroundColor(White);
                out->printf(L"note");
                break;
            case ErrorLevel::Warning:
                out->setForegroundColor(Yellow);
                out->printf(L"warning");
                break;
        }
        out->setForegroundColor(White, Bright);
        out->printf(L": ");
        wstring msg = Errors::format(res.code, res.items);
        out->printf(L"%ls\n", msg.c_str());
        out->reset();
        out->printf(L"%ls\n", code.c_str());
        for(int i = 1; i < res.column; i++)
        {
            out->printf(L" ");
        }
        out->setForegroundColor(Green);
        out->printf(L"^\n");
        out->reset();
    }
}

void REPL::evalCommand(const wstring &command)
{
    wstring cmd = command;
    wstring args;
    wstring::size_type pos = command.find(L' ');
    if(pos != wstring::npos)
    {
        cmd = command.substr(0, pos);
        args = command.substr(pos + 1, command.size() - pos - 1);
    }
    auto iter = methods.find(cmd);
    if(iter == methods.end())
    {
        out->printf(L"error: '%ls' is not a valid command.\n", cmd.c_str());
        return;
    }
    (this->*iter->second)(args);
}

void REPL::initCommands()
{
    methods.insert(make_pair(L"help", &REPL::commandHelp));
    methods.insert(make_pair(L"quit", &REPL::commandQuit));
    methods.insert(make_pair(L"exit", &REPL::commandQuit));
    methods.insert(make_pair(L"symbols", &REPL::commandSymbols));
}
void REPL::commandHelp(const wstring& args)
{
    out->printf(L"The Swallow REPL (Read-Eval-Print-Loop) acts like an interpreter.  Valid statements, expressions, and declarations.\n");
    out->printf(L"Compiler and execution is not finished yet.");
    out->printf(L"\n");
    out->printf(L"The complete set of commands are also available as described below.  Commands must be prefixed with a colon at the REPL prompt (:quit for example.) \n\n\n");
    out->printf(L"REPL commands:\n");
    out->printf(L"  help              -- Show a list of all swallow commands, or give details about specific commands.\n");
    out->printf(L"  symbols           -- Dump symbols\n");
    out->printf(L"  quit              -- Quit out of the Swallow REPL.\n\n");
}
void REPL::commandQuit(const wstring& args)
{
    canQuit = true;
}

static void dumpSymbol(const wstring& name, const SymbolPtr& sym, const ConsoleWriterPtr& out)
{
    const wchar_t* kind = L"?????";

    if(dynamic_pointer_cast<Type>(sym))
        kind = L"Type";
    else if(dynamic_pointer_cast<SymbolPlaceHolder>(sym))
        kind = L"Placeholder";
    else if(dynamic_pointer_cast<FunctionSymbol>(sym))
        kind = L"Function";

    out->setForegroundColor(White , Bright);
    out->printf(L"%10ls\t", name.c_str());
    out->setForegroundColor(Magenta , Bright);
    out->printf(L"%7ls\t", kind);

    if(sym->getType())
    {
        wstring type = sym->getType()->toString();
        out->setForegroundColor(Yellow, Bright);
        out->printf(L"%ls\t", type.c_str());
    }

    out->setForegroundColor(Cyan, Bright);
    static const SymbolFlags flags[] = {SymbolFlagInitializing, SymbolFlagInitialized, SymbolFlagMember, SymbolFlagWritable, SymbolFlagReadable, SymbolFlagTemporary,
            SymbolFlagHasInitializer, SymbolFlagStatic, SymbolFlagInit};
    static const wchar_t* flagNames[] = {L"initializing", L"initialized", L"member", L"writable", L"readable", L"temporary", L"has_initializer", L"static", L"init"};
    for(int i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
    {
        if(sym->hasFlags(flags[i]))
            out->printf(L"%ls,", flagNames[i]);
    }

    out->printf(L"\n");
    out->reset();
}
static void dumpSymbols(SymbolScope* scope, const ConsoleWriterPtr& out)
{
    for(auto entry : scope->getSymbols())
    {
        if(FunctionOverloadedSymbolPtr funcs = dynamic_pointer_cast<FunctionOverloadedSymbol>(entry.second))
        {
            for(const FunctionSymbolPtr& func : *funcs)
            {
                dumpSymbol(entry.first, func, out);
            }
        }
        else
        {
            dumpSymbol(entry.first, entry.second, out);
        }
    }
}
void REPL::commandSymbols(const wstring& args)
{
    SymbolScope* scope = nullptr;
    ScopedProgramPtr p = static_pointer_cast<ScopedProgram>(program);
    if(args == L"global")
        scope = this->registry.getGlobalScope();
    else
        scope = p->getScope();
    dumpSymbols(scope, out);
}<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit.C
/// @brief Initialize dram
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit.H>
#include <lib/utils/count_dimm.H>
#include <lib/fir/training_fir.H>
#include <lib/utils/conversions.H>
#include <lib/dimm/bcw_load.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_DIMM;
using fapi2::FAPI2_RC_SUCCESS;

extern "C"
{
///
/// @brief Initialize dram
/// @param[in] i_target, the McBIST of the ports of the dram you're initializing
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        fapi2::buffer<uint64_t> l_data;

        mss::ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst;
        mss::ccs::instruction_t<TARGET_TYPE_MCBIST> l_des = mss::ccs::des_command<TARGET_TYPE_MCBIST>();

        mss::ccs::program<TARGET_TYPE_MCBIST> l_program;

        // Up, down P down, up N. Somewhat magic numbers - came from Centaur and proven to be the
        // same on Nimbus. Why these are what they are might be lost to time ...
        constexpr uint64_t PCLK_INITIAL_VALUE = 0b10;
        constexpr uint64_t NCLK_INITIAL_VALUE = 0b01;

        const auto l_mca = mss::find_targets<TARGET_TYPE_MCA>(i_target);

        FAPI_INF("Start draminit: %s", mss::c_str(i_target));

        // If we don't have any ports, lets go.
        if (l_mca.size() == 0)
        {
            FAPI_INF("++++ No ports? %s ++++", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // If we don't have any DIMM, lets go.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("++++ NO DIMM on %s ++++", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // Configure the CCS engine. Since this is a chunk of MCBIST logic, we don't want
        // to do it for every port. If we ever break this code out so f/w can call draminit
        // per-port (separate threads) we'll need to provide them a way to set this up before
        // sapwning per-port threads.
        {
            fapi2::buffer<uint64_t> l_ccs_config;

            FAPI_TRY( mss::ccs::read_mode(i_target, l_ccs_config) );

            // It's unclear if we want to run with this true or false. Right now (10/15) this
            // has to be false. Shelton was unclear if this should be on or off in general BRS
            mss::ccs::stop_on_err(i_target, l_ccs_config, mss::LOW);
            mss::ccs::ue_disable(i_target, l_ccs_config, mss::LOW);
            mss::ccs::copy_cke_to_spare_cke(i_target, l_ccs_config, mss::HIGH);
            mss::ccs::parity_after_cmd(i_target, l_ccs_config, mss::HIGH);

            FAPI_TRY( mss::ccs::write_mode(i_target, l_ccs_config) );
        }

        // We initialize dram by iterating over the (ungarded) ports. We could allow the caller
        // to initialize each port's dram on a separate thread if we could synchronize access
        // to the MCBIST (CCS engine.) Right now we can't, so we'll do it this way.

        //
        // We expect to come in to draminit with the following setup:
        // 1. ENABLE_RESET_N (FARB5Q(6)) 0
        // 2. RESET_N (FARB5Q(4)) 0 - driving reset
        // 3. CCS_ADDR_MUX_SEL (FARB5Q(5)) - 1
        // 4. CKE out of high impedence
        //
        for (const auto& p : l_mca)
        {
            FAPI_TRY( mss::draminit_entry_invariant(p) );
            FAPI_TRY( mss::ddr_resetn(p, mss::HIGH) );

            // Begin driving mem clks, and wait 10ns (we'll do this outside the loop)
            FAPI_TRY( mss::drive_mem_clks(p, PCLK_INITIAL_VALUE, NCLK_INITIAL_VALUE) );
        }

        // From the DDR4 JEDEC Spec (79-A): Power-up Initialization Sequence
        // Lets find our max delay in ns
        {
            // Clocks (CK_t,CK_c) need to be started and stable for 10ns or 5tCK
            // (whichever is greater) before CKE goes active.
            constexpr uint64_t DELAY_5TCK = 5;
            uint64_t l_delay_in_ns = std::max( static_cast<uint64_t>(mss::DELAY_10NS),
                                               mss::cycles_to_ns(i_target, DELAY_5TCK) );

            uint64_t l_delay_in_cycles = mss::ns_to_cycles(i_target, l_delay_in_ns);

            // Set our delay (for HW and SIM)
            FAPI_TRY( fapi2::delay(l_delay_in_ns, mss::cycles_to_simcycles(l_delay_in_cycles)) );
        }

        // Also a Deselect command must be registered as required from the Spec.
        // Register DES instruction, which pulls CKE high. Idle 400 cycles, and then begin RCD loading
        // Note: This only is sent to one of the MCA as we still have the mux_addr_sel bit set, meaning
        // we'll PDE/DES all DIMM at the same time.
        l_des.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(400);
        l_program.iv_instructions.push_back(l_des);
        FAPI_TRY( mss::ccs::execute(i_target, l_program, l_mca[0]) );

        // Per conversation with Shelton and Steve 10/9/15, turn off addr_mux_sel after the CKE CCS but
        // before the RCD/MRS CCSs
        for (const auto& p : l_mca)
        {
            FAPI_TRY( change_addr_mux_sel(p, mss::LOW) );
        }

        // Load RCD control words
        FAPI_TRY( mss::rcd_load(i_target) );

        // Load data buffer control words (BCW)
        FAPI_TRY( mss::bcw_load(i_target) );

        // Register has been configured, so we can unmask 'training' errors which includes parity
        // which we want to see during MRS load
        FAPI_TRY( mss::unmask_training_errors(i_target) );

        // Load MRS
        FAPI_TRY( mss::mrs_load(i_target) );

    fapi_try_exit:
        FAPI_INF("End draminit: %s (0x%lx)", mss::c_str(i_target), uint64_t(fapi2::current_err));
        return fapi2::current_err;
    }
}
<commit_msg>Add Memory Subsystem FIR support<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit.C
/// @brief Initialize dram
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit.H>
#include <lib/utils/count_dimm.H>
#include <lib/utils/conversions.H>
#include <lib/dimm/bcw_load.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_DIMM;
using fapi2::FAPI2_RC_SUCCESS;

extern "C"
{
///
/// @brief Initialize dram
/// @param[in] i_target, the McBIST of the ports of the dram you're initializing
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        fapi2::buffer<uint64_t> l_data;

        mss::ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst;
        mss::ccs::instruction_t<TARGET_TYPE_MCBIST> l_des = mss::ccs::des_command<TARGET_TYPE_MCBIST>();

        mss::ccs::program<TARGET_TYPE_MCBIST> l_program;

        // Up, down P down, up N. Somewhat magic numbers - came from Centaur and proven to be the
        // same on Nimbus. Why these are what they are might be lost to time ...
        constexpr uint64_t PCLK_INITIAL_VALUE = 0b10;
        constexpr uint64_t NCLK_INITIAL_VALUE = 0b01;

        const auto l_mca = mss::find_targets<TARGET_TYPE_MCA>(i_target);

        FAPI_INF("Start draminit: %s", mss::c_str(i_target));

        // If we don't have any ports, lets go.
        if (l_mca.size() == 0)
        {
            FAPI_INF("++++ No ports? %s ++++", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // If we don't have any DIMM, lets go.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("++++ NO DIMM on %s ++++", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // Configure the CCS engine. Since this is a chunk of MCBIST logic, we don't want
        // to do it for every port. If we ever break this code out so f/w can call draminit
        // per-port (separate threads) we'll need to provide them a way to set this up before
        // sapwning per-port threads.
        {
            fapi2::buffer<uint64_t> l_ccs_config;

            FAPI_TRY( mss::ccs::read_mode(i_target, l_ccs_config) );

            // It's unclear if we want to run with this true or false. Right now (10/15) this
            // has to be false. Shelton was unclear if this should be on or off in general BRS
            mss::ccs::stop_on_err(i_target, l_ccs_config, mss::LOW);
            mss::ccs::ue_disable(i_target, l_ccs_config, mss::LOW);
            mss::ccs::copy_cke_to_spare_cke(i_target, l_ccs_config, mss::HIGH);
            mss::ccs::parity_after_cmd(i_target, l_ccs_config, mss::HIGH);

            FAPI_TRY( mss::ccs::write_mode(i_target, l_ccs_config) );
        }

        // We initialize dram by iterating over the (ungarded) ports. We could allow the caller
        // to initialize each port's dram on a separate thread if we could synchronize access
        // to the MCBIST (CCS engine.) Right now we can't, so we'll do it this way.

        //
        // We expect to come in to draminit with the following setup:
        // 1. ENABLE_RESET_N (FARB5Q(6)) 0
        // 2. RESET_N (FARB5Q(4)) 0 - driving reset
        // 3. CCS_ADDR_MUX_SEL (FARB5Q(5)) - 1
        // 4. CKE out of high impedence
        //
        for (const auto& p : l_mca)
        {
            FAPI_TRY( mss::draminit_entry_invariant(p) );
            FAPI_TRY( mss::ddr_resetn(p, mss::HIGH) );

            // Begin driving mem clks, and wait 10ns (we'll do this outside the loop)
            FAPI_TRY( mss::drive_mem_clks(p, PCLK_INITIAL_VALUE, NCLK_INITIAL_VALUE) );
        }

        // From the DDR4 JEDEC Spec (79-A): Power-up Initialization Sequence
        // Lets find our max delay in ns
        {
            // Clocks (CK_t,CK_c) need to be started and stable for 10ns or 5tCK
            // (whichever is greater) before CKE goes active.
            constexpr uint64_t DELAY_5TCK = 5;
            const uint64_t l_delay_in_ns = std::max( static_cast<uint64_t>(mss::DELAY_10NS),
                                           mss::cycles_to_ns(i_target, DELAY_5TCK) );

            const uint64_t l_delay_in_cycles = mss::ns_to_cycles(i_target, l_delay_in_ns);

            // Set our delay (for HW and SIM)
            FAPI_TRY( fapi2::delay(l_delay_in_ns, mss::cycles_to_simcycles(l_delay_in_cycles)) );
        }

        // Also a Deselect command must be registered as required from the Spec.
        // Register DES instruction, which pulls CKE high. Idle 400 cycles, and then begin RCD loading
        // Note: This only is sent to one of the MCA as we still have the mux_addr_sel bit set, meaning
        // we'll PDE/DES all DIMM at the same time.
        l_des.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(400);
        l_program.iv_instructions.push_back(l_des);
        FAPI_TRY( mss::ccs::execute(i_target, l_program, l_mca[0]) );

        // Per conversation with Shelton and Steve 10/9/15, turn off addr_mux_sel after the CKE CCS but
        // before the RCD/MRS CCSs
        for (const auto& p : l_mca)
        {
            FAPI_TRY( change_addr_mux_sel(p, mss::LOW) );
        }

        // Load RCD control words
        FAPI_TRY( mss::rcd_load(i_target) );

        // Load data buffer control words (BCW)
        FAPI_TRY( mss::bcw_load(i_target) );

        // Load MRS
        FAPI_TRY( mss::mrs_load(i_target) );

    fapi_try_exit:
        FAPI_INF("End draminit: %s (0x%lx)", mss::c_str(i_target), uint64_t(fapi2::current_err));
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2007 <SWGEmu>
This File is part of Core3.
This program 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 2 of the License,
or (at your option) any later version.

This program 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 for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.

*/

#include "LairSpawnArea.h"
#include "server/zone/objects/scene/SceneObject.h"
#include "server/zone/managers/creature/LairSpawnGroup.h"
#include "server/zone/managers/creature/CreatureManager.h"
#include "server/zone/managers/creature/CreatureTemplateManager.h"
#include "server/zone/managers/planet/PlanetManager.h"
#include "SpawnObserver.h"
#include "server/zone/managers/terrain/TerrainManager.h"
#include "server/zone/managers/collision/CollisionManager.h"
#include "events/RemoveNoSpawnAreaTask.h"
#include "server/ServerCore.h"
#include "server/zone/templates/mobile/LairTemplate.h"

void LairSpawnAreaImplementation::notifyEnter(SceneObject* object) {
	if (!object->isPlayerCreature())
		return;

	ManagedReference<SceneObject*> parent = object->getParent();

	if (parent != NULL && parent->isCellObject())
		return;

	if (object->getCityRegion() != NULL)
		return;

	trySpawnLair(object);
}

int LairSpawnAreaImplementation::notifyObserverEvent(unsigned int eventType, Observable* observable, ManagedObject* arg1, int64 arg2) {
	if (eventType != ObserverEventType::OBJECTREMOVEDFROMZONE)
		return 1;

	TangibleObject* tano = dynamic_cast<TangibleObject*>(observable);

	if (tano == NULL)
		return 1;

	Locker locker(_this.get());

	uint32 lairTemplate = lairTypes.remove(tano->getObjectID());

	if (lairTemplate != 0) {
		int currentSpawnCount = spawnedGroupsCount.get(lairTemplate) - 1;

		if (currentSpawnCount < 1)
			spawnedGroupsCount.remove(lairTemplate);
		else
			spawnedGroupsCount.put(lairTemplate, currentSpawnCount);

		--currentlySpawnedLairs;

		locker.release();

		ManagedReference<ActiveArea*> area = cast<ActiveArea*>(ServerCore::getZoneServer()->createObject(String("object/active_area.iff").hashCode(), 0));

		area->setRadius(64);
		area->setNoSpawnArea(true);

		zone->transferObject(area, -1, true);

		Reference<Task*> task = new RemoveNoSpawnAreaTask(area);
		task->schedule(300000);
	}

	//info("removing spawned lair from here", true);

	return 1;
}

LairSpawnGroup* LairSpawnAreaImplementation::getSpawnGroup() {
	if (spawnGroup == NULL && spawnCreatureTemplates.size() != 0) {
		uint32 templateGroupCRC = spawnCreatureTemplates.get(0);

		spawnGroup = CreatureTemplateManager::instance()->getLairGroup(templateGroupCRC);
	}

	return spawnGroup;
}

int LairSpawnAreaImplementation::trySpawnLair(SceneObject* object) {
	if (spawnGroup == NULL && spawnCreatureTemplates.size() != 0) {
		uint32 templateGroupCRC = spawnCreatureTemplates.get(0);

		spawnGroup = CreatureTemplateManager::instance()->getLairGroup(templateGroupCRC);
	}

	if (spawnGroup == NULL) {
		error("spawnGroup is NULL");
		return 1;
	}

	Vector<Reference<LairSpawn*> >* lairs = spawnGroup->getLairList();

	int totalSize = lairs->size();

	if (totalSize == 0) {
		error("totalSize is NULL");
		return 2;
	}

	Zone* zone = getZone();

	if (zone == NULL) {
		error("zone is NULL");
		return 3;
	}

	if (currentlySpawnedLairs >= spawnGroup->getMaxSpawnLimit())
		return 4;

	if (lastSpawn.miliDifference() < MINSPAWNINTERVAL)
		return 5;

	ManagedReference<PlanetManager*> planetManager = zone->getPlanetManager();

	Vector3 randomPosition = getRandomPosition(object);

	if (randomPosition.getX() == 0 && randomPosition.getY() == 0) {
		return 6;
	}

	float spawnZ = zone->getHeight(randomPosition.getX(), randomPosition.getY());

	randomPosition.setZ(spawnZ);

	//lets check if we intersect with some object (buildings, etc..)
	if (CollisionManager::checkSphereCollision(randomPosition, 64, zone))
		return 7;

	//dont spawn in cities
	SortedVector<ManagedReference<ActiveArea* > > activeAreas;
	zone->getInRangeActiveAreas(randomPosition.getX(), randomPosition.getY(), &activeAreas, true);

	for (int i = 0; i < activeAreas.size(); ++i) {
		ActiveArea* area = activeAreas.get(i);

		if (area->isRegion() || area->isMunicipalZone() || area->isNoSpawnArea())
			return 8;
	}

	//check in range objects for no build radi
	if (!planetManager->isBuildingPermittedAt(randomPosition.getX(), randomPosition.getY(), object)) {
		return 9;
	}

	//Lets choose 3 random spawns;
	LairSpawn* firstSpawn = lairs->get(System::random(totalSize - 1));
	LairSpawn* secondSpawn = lairs->get(System::random(totalSize - 1));
	LairSpawn* thirdSpawn = lairs->get(System::random(totalSize - 1));

	LairSpawn* finalSpawn = NULL;

	int totalWeights = firstSpawn->getWeighting() + secondSpawn->getWeighting() + thirdSpawn->getWeighting();

	int finalChoice = System::random(totalWeights);

	if (finalChoice <= firstSpawn->getWeighting()) {
		finalSpawn = firstSpawn;
	} else if (finalChoice <= firstSpawn->getWeighting() + secondSpawn->getWeighting()) {
		finalSpawn = secondSpawn;
	} else {
		finalSpawn = thirdSpawn;
	}

	int spawnLimit = finalSpawn->getSpawnLimit();

	Locker _locker(_this.get());

	lastSpawn.updateToCurrentTime();

	String lairTemplate = finalSpawn->getLairTemplateName();
	uint32 lairHashCode = lairTemplate.hashCode();

	int currentSpawnCount = spawnedGroupsCount.get(lairHashCode);

	if (spawnLimit != -1) {
		if (currentSpawnCount >= spawnLimit)
			return 10;
	}

	CreatureManager* creatureManager = zone->getCreatureManager();

	int difficulty = System::random(finalSpawn->getMaxDifficulty() - finalSpawn->getMinDifficulty()) + finalSpawn->getMinDifficulty();

	LairTemplate* lair = CreatureTemplateManager::instance()->getLairTemplate(lairHashCode);

	if (lair == NULL)
		return 12;

	unsigned int faction = lair->getFaction();

	ManagedReference<SceneObject*> obj = creatureManager->spawnLair(lairHashCode, difficulty, randomPosition.getX(), spawnZ, randomPosition.getY(), faction);

	if (obj != NULL) {
		StringBuffer msg;
		msg << "lair spawned at " << obj->getPositionX() << " " << obj->getPositionY();
		obj->info(msg.toString());
	} else {
		error("could not spawn lair " + lairTemplate);

		return 11;
	}

	if (exitObserver == NULL) {
		exitObserver = new SpawnObserver(_this.get());
		exitObserver->deploy();
	}

	lairTypes.put(obj->getObjectID(), lairHashCode);

	Locker objLocker(obj);

	obj->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, exitObserver);

	++currentlySpawnedLairs;

	spawnedGroupsCount.put(lairTemplate.hashCode(), currentSpawnCount);

	return 0;
}

void LairSpawnAreaImplementation::notifyPositionUpdate(QuadTreeEntry* obj) {
	CreatureObject* creature = dynamic_cast<CreatureObject*>(obj);

	if (creature == NULL)
		return;

	if (!creature->isPlayerCreature())
		return;

	ManagedReference<SceneObject*> parent = creature->getParent();

	if (parent != NULL && parent->isCellObject())
		return;

	if (System::random(25) == 1)
		trySpawnLair(creature);
}

void LairSpawnAreaImplementation::notifyExit(SceneObject* object) {

}
<commit_msg>(unstable) [fixed] temp no spawn lair areas position<commit_after>/*
Copyright (C) 2007 <SWGEmu>
This File is part of Core3.
This program 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 2 of the License,
or (at your option) any later version.

This program 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 for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.

*/

#include "LairSpawnArea.h"
#include "server/zone/objects/scene/SceneObject.h"
#include "server/zone/managers/creature/LairSpawnGroup.h"
#include "server/zone/managers/creature/CreatureManager.h"
#include "server/zone/managers/creature/CreatureTemplateManager.h"
#include "server/zone/managers/planet/PlanetManager.h"
#include "SpawnObserver.h"
#include "server/zone/managers/terrain/TerrainManager.h"
#include "server/zone/managers/collision/CollisionManager.h"
#include "events/RemoveNoSpawnAreaTask.h"
#include "server/ServerCore.h"
#include "server/zone/templates/mobile/LairTemplate.h"

void LairSpawnAreaImplementation::notifyEnter(SceneObject* object) {
	if (!object->isPlayerCreature())
		return;

	ManagedReference<SceneObject*> parent = object->getParent();

	if (parent != NULL && parent->isCellObject())
		return;

	if (object->getCityRegion() != NULL)
		return;

	trySpawnLair(object);
}

int LairSpawnAreaImplementation::notifyObserverEvent(unsigned int eventType, Observable* observable, ManagedObject* arg1, int64 arg2) {
	if (eventType != ObserverEventType::OBJECTREMOVEDFROMZONE)
		return 1;

	TangibleObject* tano = dynamic_cast<TangibleObject*>(observable);

	if (tano == NULL)
		return 1;

	Locker locker(_this.get());

	uint32 lairTemplate = lairTypes.remove(tano->getObjectID());

	if (lairTemplate != 0) {
		int currentSpawnCount = spawnedGroupsCount.get(lairTemplate) - 1;

		if (currentSpawnCount < 1)
			spawnedGroupsCount.remove(lairTemplate);
		else
			spawnedGroupsCount.put(lairTemplate, currentSpawnCount);

		--currentlySpawnedLairs;

		locker.release();

		ManagedReference<ActiveArea*> area = cast<ActiveArea*>(ServerCore::getZoneServer()->createObject(String("object/active_area.iff").hashCode(), 0));

		area->setRadius(64);
		area->setNoSpawnArea(true);
		area->initializePosition(tano->getPositionX(), tano->getPositionZ(), tano->getPositionZ());

		zone->transferObject(area, -1, true);

		Reference<Task*> task = new RemoveNoSpawnAreaTask(area);
		task->schedule(300000);
	}

	//info("removing spawned lair from here", true);

	return 1;
}

LairSpawnGroup* LairSpawnAreaImplementation::getSpawnGroup() {
	if (spawnGroup == NULL && spawnCreatureTemplates.size() != 0) {
		uint32 templateGroupCRC = spawnCreatureTemplates.get(0);

		spawnGroup = CreatureTemplateManager::instance()->getLairGroup(templateGroupCRC);
	}

	return spawnGroup;
}

int LairSpawnAreaImplementation::trySpawnLair(SceneObject* object) {
	if (spawnGroup == NULL && spawnCreatureTemplates.size() != 0) {
		uint32 templateGroupCRC = spawnCreatureTemplates.get(0);

		spawnGroup = CreatureTemplateManager::instance()->getLairGroup(templateGroupCRC);
	}

	if (spawnGroup == NULL) {
		error("spawnGroup is NULL");
		return 1;
	}

	Vector<Reference<LairSpawn*> >* lairs = spawnGroup->getLairList();

	int totalSize = lairs->size();

	if (totalSize == 0) {
		error("totalSize is NULL");
		return 2;
	}

	Zone* zone = getZone();

	if (zone == NULL) {
		error("zone is NULL");
		return 3;
	}

	if (currentlySpawnedLairs >= spawnGroup->getMaxSpawnLimit())
		return 4;

	if (lastSpawn.miliDifference() < MINSPAWNINTERVAL)
		return 5;

	ManagedReference<PlanetManager*> planetManager = zone->getPlanetManager();

	Vector3 randomPosition = getRandomPosition(object);

	if (randomPosition.getX() == 0 && randomPosition.getY() == 0) {
		return 6;
	}

	float spawnZ = zone->getHeight(randomPosition.getX(), randomPosition.getY());

	randomPosition.setZ(spawnZ);

	//lets check if we intersect with some object (buildings, etc..)
	if (CollisionManager::checkSphereCollision(randomPosition, 64, zone))
		return 7;

	//dont spawn in cities
	SortedVector<ManagedReference<ActiveArea* > > activeAreas;
	zone->getInRangeActiveAreas(randomPosition.getX(), randomPosition.getY(), &activeAreas, true);

	for (int i = 0; i < activeAreas.size(); ++i) {
		ActiveArea* area = activeAreas.get(i);

		if (area->isRegion() || area->isMunicipalZone() || area->isNoSpawnArea())
			return 8;
	}

	//check in range objects for no build radi
	if (!planetManager->isBuildingPermittedAt(randomPosition.getX(), randomPosition.getY(), object)) {
		return 9;
	}

	//Lets choose 3 random spawns;
	LairSpawn* firstSpawn = lairs->get(System::random(totalSize - 1));
	LairSpawn* secondSpawn = lairs->get(System::random(totalSize - 1));
	LairSpawn* thirdSpawn = lairs->get(System::random(totalSize - 1));

	LairSpawn* finalSpawn = NULL;

	int totalWeights = firstSpawn->getWeighting() + secondSpawn->getWeighting() + thirdSpawn->getWeighting();

	int finalChoice = System::random(totalWeights);

	if (finalChoice <= firstSpawn->getWeighting()) {
		finalSpawn = firstSpawn;
	} else if (finalChoice <= firstSpawn->getWeighting() + secondSpawn->getWeighting()) {
		finalSpawn = secondSpawn;
	} else {
		finalSpawn = thirdSpawn;
	}

	int spawnLimit = finalSpawn->getSpawnLimit();

	Locker _locker(_this.get());

	lastSpawn.updateToCurrentTime();

	String lairTemplate = finalSpawn->getLairTemplateName();
	uint32 lairHashCode = lairTemplate.hashCode();

	int currentSpawnCount = spawnedGroupsCount.get(lairHashCode);

	if (spawnLimit != -1) {
		if (currentSpawnCount >= spawnLimit)
			return 10;
	}

	CreatureManager* creatureManager = zone->getCreatureManager();

	int difficulty = System::random(finalSpawn->getMaxDifficulty() - finalSpawn->getMinDifficulty()) + finalSpawn->getMinDifficulty();

	LairTemplate* lair = CreatureTemplateManager::instance()->getLairTemplate(lairHashCode);

	if (lair == NULL)
		return 12;

	unsigned int faction = lair->getFaction();

	ManagedReference<SceneObject*> obj = creatureManager->spawnLair(lairHashCode, difficulty, randomPosition.getX(), spawnZ, randomPosition.getY(), faction);

	if (obj != NULL) {
		StringBuffer msg;
		msg << "lair spawned at " << obj->getPositionX() << " " << obj->getPositionY();
		obj->info(msg.toString());
	} else {
		error("could not spawn lair " + lairTemplate);

		return 11;
	}

	if (exitObserver == NULL) {
		exitObserver = new SpawnObserver(_this.get());
		exitObserver->deploy();
	}

	lairTypes.put(obj->getObjectID(), lairHashCode);

	Locker objLocker(obj);

	obj->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, exitObserver);

	++currentlySpawnedLairs;

	spawnedGroupsCount.put(lairTemplate.hashCode(), currentSpawnCount);

	return 0;
}

void LairSpawnAreaImplementation::notifyPositionUpdate(QuadTreeEntry* obj) {
	CreatureObject* creature = dynamic_cast<CreatureObject*>(obj);

	if (creature == NULL)
		return;

	if (!creature->isPlayerCreature())
		return;

	ManagedReference<SceneObject*> parent = creature->getParent();

	if (parent != NULL && parent->isCellObject())
		return;

	if (System::random(25) == 1)
		trySpawnLair(creature);
}

void LairSpawnAreaImplementation::notifyExit(SceneObject* object) {

}
<|endoftext|>


<commit_before>/**
 * @file Cosa/Cipher/RC4.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2013, Mikael Patel
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef __COSA_CIPHER_RC4_HH__
#define __COSA_CIPHER_RC4_HH__

#include "Cosa/Types.h"

/**
 * RC4 cipher.
 * @section See Also
 * 1. http://en.wikipedia.org/wiki/RC4
 * 2. http://cypherpunks.venona.com/archive/1994/09/msg00304.html
 */
class RC4 {
private:
  uint8_t m_state[256];
  uint8_t m_x;
  uint8_t m_y;

public:
  /**
   * Construct RC4 cipher for given key and length.
   * @param[in] key pointer to key.
   * @param[in] len length of key in bytes.
   */
  RC4(const void* key, size_t len)
  {
    restart(key, len);
  }

  /**
   * Restart the given key and length.
   * @param[in] key pointer to key.
   * @param[in] len length of key in bytes.
   */
  void restart(const void* key, size_t len);

  /**
   * Encrypt the given character.
   * @param[in] c character to encode.
   * @return encoded character.
   */
  char encrypt(char c)
  {
    m_y = m_y + m_state[++m_x];
    uint8_t tmp = m_state[m_x];
    m_state[m_x] = m_state[m_y];
    m_state[m_y] = tmp;
    uint8_t ix = m_state[m_x] + m_state[m_y];
    return (c ^ m_state[ix]);
  }

  /**
   * Encrypt the given buffer.
   * @param[in] buf buffer pointer.
   * @param[in] n number of bytes.
   */
  void encrypt(void* buf, size_t n)
  {
    for (char* bp = (char*) buf; n--; bp++)
      *bp = encrypt(*bp);
  }

  /**
   * Encrypt the given src buffer to the dest buffer.
   * @param[in] dest buffer pointer.
   * @param[in] src buffer pointer.
   * @param[in] n number of bytes.
   */
  void encrypt(void* dest, const void* src, size_t n)
  {
    char* dp = (char*) dest;
    const char* sp = (const char*) src;
    while (n--) *dp++ = encrypt(*sp++);
  }

  /**
   * Decrypt the given character.
   * @param[in] c character to decode.
   * @return decoded character.
   */
  char decrypt(char c)
  {
    return (encrypt(c));
  }

  /**
   * Decrypt the given buffer.
   * @param[in] buf buffer pointer.
   * @param[in] n number of bytes.
   */
  void decrypt(void* buf, size_t n)
  {
    for (char* bp = (char*) buf; n--; bp++)
      *bp = decrypt(*bp);
  }

  /**
   * Decrypt the given src buffer to the dest buffer.
   * @param[in] dest buffer pointer.
   * @param[in] src buffer pointer.
   * @param[in] n number of bytes.
   */
  void decrypt(void* dest, const void* src, size_t n)
  {
    char* dp = (char*) dest;
    const char* sp = (const char*) src;
    while (n--) *dp++ = decrypt(*sp++);
  }
};

#endif
<commit_msg>Remove a few instructions in RC4::encrypt(). Down to 2,1 us per byte.<commit_after>/**
 * @file Cosa/Cipher/RC4.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2013, Mikael Patel
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef __COSA_CIPHER_RC4_HH__
#define __COSA_CIPHER_RC4_HH__

#include "Cosa/Types.h"

/**
 * RC4 cipher.
 * @section See Also
 * 1. http://en.wikipedia.org/wiki/RC4
 * 2. http://cypherpunks.venona.com/archive/1994/09/msg00304.html
 */
class RC4 {
private:
  uint8_t m_state[256];
  uint8_t m_x;
  uint8_t m_y;

public:
  /**
   * Construct RC4 cipher for given key and length.
   * @param[in] key pointer to key.
   * @param[in] len length of key in bytes.
   */
  RC4(const void* key, size_t len)
  {
    restart(key, len);
  }

  /**
   * Restart the given key and length.
   * @param[in] key pointer to key.
   * @param[in] len length of key in bytes.
   */
  void restart(const void* key, size_t len);

  /**
   * Encrypt the given character.
   * @param[in] c character to encode.
   * @return encoded character.
   */
  char encrypt(char c)
  {
    m_x += 1;
    uint8_t sx = m_state[m_x];
    m_y += sx;
    uint8_t sy = m_state[m_y];
    m_state[m_x] = sy;
    m_state[m_y] = sx;
    uint8_t ix = sx + sy;
    return (c ^ m_state[ix]);
  }

  /**
   * Encrypt the given buffer.
   * @param[in] buf buffer pointer.
   * @param[in] n number of bytes.
   */
  void encrypt(void* buf, size_t n)
  {
    for (char* bp = (char*) buf; n--; bp++)
      *bp = encrypt(*bp);
  }

  /**
   * Encrypt the given src buffer to the dest buffer.
   * @param[in] dest buffer pointer.
   * @param[in] src buffer pointer.
   * @param[in] n number of bytes.
   */
  void encrypt(void* dest, const void* src, size_t n)
  {
    char* dp = (char*) dest;
    const char* sp = (const char*) src;
    while (n--) *dp++ = encrypt(*sp++);
  }

  /**
   * Decrypt the given character.
   * @param[in] c character to decode.
   * @return decoded character.
   */
  char decrypt(char c)
  {
    return (encrypt(c));
  }

  /**
   * Decrypt the given buffer.
   * @param[in] buf buffer pointer.
   * @param[in] n number of bytes.
   */
  void decrypt(void* buf, size_t n)
  {
    for (char* bp = (char*) buf; n--; bp++)
      *bp = decrypt(*bp);
  }

  /**
   * Decrypt the given src buffer to the dest buffer.
   * @param[in] dest buffer pointer.
   * @param[in] src buffer pointer.
   * @param[in] n number of bytes.
   */
  void decrypt(void* dest, const void* src, size_t n)
  {
    char* dp = (char*) dest;
    const char* sp = (const char*) src;
    while (n--) *dp++ = decrypt(*sp++);
  }
};

#endif
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * 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.
 *
 ************************************************************************/

#include <stdio.h>
#include <dlfcn.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
#include <cxxabi.h>
#else
#include <typeinfo>
#endif
#include <boost/unordered_map.hpp>

#include <rtl/instance.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <com/sun/star/uno/genfunc.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"
#include <typelib/typedescription.hxx>
#include <uno/any2.h>

#include "share.hxx"

using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
using namespace ::__cxxabiv1;
#endif

namespace CPPU_CURRENT_NAMESPACE
{

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070

// MacOSX10.4u.sdk/usr/include/c++/4.0.0/cxxabi.h defined
// __cxxabiv1::__class_type_info and __cxxabiv1::__si_class_type_info but
// MacOSX10.7.sdk/usr/include/cxxabi.h no longer does, so instances of those
// classes need to be created manually:

// std::type_info defined in <typeinfo> offers a protected ctor:
struct FAKE_type_info: public std::type_info {
    FAKE_type_info(char const * name): type_info(name) {}
};

// Modeled after __cxxabiv1::__si_class_type_info defined in
// MacOSX10.4u.sdk/usr/include/c++/4.0.0/cxxabi.h (i.e.,
// abi::__si_class_type_info documented at
// <http://www.codesourcery.com/public/cxx-abi/abi.html#rtti>):
struct FAKE_si_class_type_info: public FAKE_type_info {
    FAKE_si_class_type_info(char const * name, std::type_info const * theBase):
        FAKE_type_info(name), base(theBase) {}

    std::type_info const * base;
        // actually a __cxxabiv1::__class_type_info pointer
};

struct Base {};
struct Derived: Base {};

std::type_info * create_FAKE_class_type_info(char const * name) {
    std::type_info * p = new FAKE_type_info(name);
        // cxxabiv1::__class_type_info has no data members in addition to
        // std::type_info
    *reinterpret_cast< void ** >(p) = *reinterpret_cast< void * const * >(
        &typeid(Base));
        // copy correct __cxxabiv1::__class_type_info vtable into place
    return p;
}

std::type_info * create_FAKE_si_class_type_info(
    char const * name, std::type_info const * base)
{
    std::type_info * p = new FAKE_si_class_type_info(name, base);
    *reinterpret_cast< void ** >(p) = *reinterpret_cast< void * const * >(
        &typeid(Derived));
        // copy correct __cxxabiv1::__si_class_type_info vtable into place
    return p;
}

#endif

void dummy_can_throw_anything( char const * )
{
}

//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW(())
{
#if OSL_DEBUG_LEVEL > 1
    char const * start = p;
#endif

    // example: N3com3sun4star4lang24IllegalArgumentExceptionE

    OUStringBuffer buf( 64 );
    OSL_ASSERT( 'N' == *p );
    ++p; // skip N

    while ('E' != *p)
    {
        // read chars count
        long n = (*p++ - '0');
        while ('0' <= *p && '9' >= *p)
        {
            n *= 10;
            n += (*p++ - '0');
        }
        buf.appendAscii( p, n );
        p += n;
        if ('E' != *p)
            buf.append( (sal_Unicode)'.' );
    }

#if OSL_DEBUG_LEVEL > 1
    OUString ret( buf.makeStringAndClear() );
    OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}

//==================================================================================================
class RTTI
{
    typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map;

    Mutex m_mutex;
    t_rtti_map m_rttis;
    t_rtti_map m_generatedRttis;

    void * m_hApp;

public:
    RTTI() SAL_THROW(());
    ~RTTI() SAL_THROW(());

    type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW(());
};
//__________________________________________________________________________________________________
RTTI::RTTI() SAL_THROW(())
    : m_hApp( dlopen( 0, RTLD_LAZY ) )
{
}
//__________________________________________________________________________________________________
RTTI::~RTTI() SAL_THROW(())
{
    dlclose( m_hApp );
}

//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW(())
{
    type_info * rtti;

    OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;

    MutexGuard guard( m_mutex );
    t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
    if (iFind == m_rttis.end())
    {
        // RTTI symbol
        OStringBuffer buf( 64 );
        buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
        sal_Int32 index = 0;
        do
        {
            OUString token( unoName.getToken( 0, '.', index ) );
            buf.append( token.getLength() );
            OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
            buf.append( c_token );
        }
        while (index >= 0);
        buf.append( 'E' );

        OString symName( buf.makeStringAndClear() );
        rtti = (type_info *)dlsym( m_hApp, symName.getStr() );

        if (rtti)
        {
            pair< t_rtti_map::iterator, bool > insertion(
                m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
            OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
        }
        else
        {
            // try to lookup the symbol in the generated rtti map
            t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) );
            if (iFind2 == m_generatedRttis.end())
            {
                // we must generate it !
                // symbol and rtti-name is nearly identical,
                // the symbol is prefixed with _ZTI
                char const * rttiName = symName.getStr() +4;
#if OSL_DEBUG_LEVEL > 1
                fprintf( stderr,"generated rtti for %s\n", rttiName );
#endif
                if (pTypeDescr->pBaseTypeDescription)
                {
                    // ensure availability of base
                    type_info * base_rtti = getRTTI(
                        (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
                    rtti = new __si_class_type_info(
                        strdup( rttiName ), (__class_type_info *)base_rtti );
#else
                    rtti = create_FAKE_si_class_type_info(
                        strdup( rttiName ), base_rtti );
#endif
                }
                else
                {
                    // this class has no base class
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
                    rtti = new __class_type_info( strdup( rttiName ) );
#else
                    rtti = create_FAKE_class_type_info( strdup( rttiName ) );
#endif
                }

                pair< t_rtti_map::iterator, bool > insertion(
                    m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
                OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" );
            }
            else // taking already generated rtti
            {
                rtti = iFind2->second;
            }
        }
    }
    else
    {
        rtti = iFind->second;
    }

    return rtti;
}

struct RTTISingleton: public rtl::Static< RTTI, RTTISingleton > {};

//--------------------------------------------------------------------------------------------------
static void deleteException( void * pExc )
{
    __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
    typelib_TypeDescription * pTD = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pTD, unoName.pData );
    OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
    if (pTD)
    {
        ::uno_destructData( pExc, pTD, cpp_release );
        ::typelib_typedescription_release( pTD );
    }
}

//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
#if OSL_DEBUG_LEVEL > 1
    OString cstr(
        OUStringToOString(
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
#endif
    void * pCppExc;
    type_info * rtti;

    {
    // construct cpp exception object
    typelib_TypeDescription * pTypeDescr = 0;
    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
    OSL_ASSERT( pTypeDescr );
    if (! pTypeDescr)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }

    pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );

    // destruct uno exception
    ::uno_any_destruct( pUnoExc, 0 );
	rtti = (type_info *)RTTISingleton::get().getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
    if (! rtti)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }
    }

    __cxa_throw( pCppExc, rtti, deleteException );
}

//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
    if (! header)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if OSL_DEBUG_LEVEL > 0
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_FAIL( cstr.getStr() );
#endif
        return;
    }

    typelib_TypeDescription * pExcTypeDescr = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
#if OSL_DEBUG_LEVEL > 1
    OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() );
#endif
    typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
    if (0 == pExcTypeDescr)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if OSL_DEBUG_LEVEL > 0
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_FAIL( cstr.getStr() );
#endif
    }
    else
    {
        // construct uno exception any
        uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
        typelib_typedescription_release( pExcTypeDescr );
    }
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>WaE: unused variable<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * 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.
 *
 ************************************************************************/

#include <stdio.h>
#include <dlfcn.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
#include <cxxabi.h>
#else
#include <typeinfo>
#endif
#include <boost/unordered_map.hpp>

#include <rtl/instance.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <com/sun/star/uno/genfunc.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"
#include <typelib/typedescription.hxx>
#include <uno/any2.h>

#include "share.hxx"

using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
using namespace ::__cxxabiv1;
#endif

namespace CPPU_CURRENT_NAMESPACE
{

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070

// MacOSX10.4u.sdk/usr/include/c++/4.0.0/cxxabi.h defined
// __cxxabiv1::__class_type_info and __cxxabiv1::__si_class_type_info but
// MacOSX10.7.sdk/usr/include/cxxabi.h no longer does, so instances of those
// classes need to be created manually:

// std::type_info defined in <typeinfo> offers a protected ctor:
struct FAKE_type_info: public std::type_info {
    FAKE_type_info(char const * name): type_info(name) {}
};

// Modeled after __cxxabiv1::__si_class_type_info defined in
// MacOSX10.4u.sdk/usr/include/c++/4.0.0/cxxabi.h (i.e.,
// abi::__si_class_type_info documented at
// <http://www.codesourcery.com/public/cxx-abi/abi.html#rtti>):
struct FAKE_si_class_type_info: public FAKE_type_info {
    FAKE_si_class_type_info(char const * name, std::type_info const * theBase):
        FAKE_type_info(name), base(theBase) {}

    std::type_info const * base;
        // actually a __cxxabiv1::__class_type_info pointer
};

struct Base {};
struct Derived: Base {};

std::type_info * create_FAKE_class_type_info(char const * name) {
    std::type_info * p = new FAKE_type_info(name);
        // cxxabiv1::__class_type_info has no data members in addition to
        // std::type_info
    *reinterpret_cast< void ** >(p) = *reinterpret_cast< void * const * >(
        &typeid(Base));
        // copy correct __cxxabiv1::__class_type_info vtable into place
    return p;
}

std::type_info * create_FAKE_si_class_type_info(
    char const * name, std::type_info const * base)
{
    std::type_info * p = new FAKE_si_class_type_info(name, base);
    *reinterpret_cast< void ** >(p) = *reinterpret_cast< void * const * >(
        &typeid(Derived));
        // copy correct __cxxabiv1::__si_class_type_info vtable into place
    return p;
}

#endif

void dummy_can_throw_anything( char const * )
{
}

//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW(())
{
#if OSL_DEBUG_LEVEL > 1
    char const * start = p;
#endif

    // example: N3com3sun4star4lang24IllegalArgumentExceptionE

    OUStringBuffer buf( 64 );
    OSL_ASSERT( 'N' == *p );
    ++p; // skip N

    while ('E' != *p)
    {
        // read chars count
        long n = (*p++ - '0');
        while ('0' <= *p && '9' >= *p)
        {
            n *= 10;
            n += (*p++ - '0');
        }
        buf.appendAscii( p, n );
        p += n;
        if ('E' != *p)
            buf.append( (sal_Unicode)'.' );
    }

#if OSL_DEBUG_LEVEL > 1
    OUString ret( buf.makeStringAndClear() );
    OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
    return ret;
#else
    return buf.makeStringAndClear();
#endif
}

//==================================================================================================
class RTTI
{
    typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map;

    Mutex m_mutex;
    t_rtti_map m_rttis;
    t_rtti_map m_generatedRttis;

    void * m_hApp;

public:
    RTTI() SAL_THROW(());
    ~RTTI() SAL_THROW(());

    type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW(());
};
//__________________________________________________________________________________________________
RTTI::RTTI() SAL_THROW(())
    : m_hApp( dlopen( 0, RTLD_LAZY ) )
{
}
//__________________________________________________________________________________________________
RTTI::~RTTI() SAL_THROW(())
{
    dlclose( m_hApp );
}

//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW(())
{
    type_info * rtti;

    OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;

    MutexGuard guard( m_mutex );
    t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
    if (iFind == m_rttis.end())
    {
        // RTTI symbol
        OStringBuffer buf( 64 );
        buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
        sal_Int32 index = 0;
        do
        {
            OUString token( unoName.getToken( 0, '.', index ) );
            buf.append( token.getLength() );
            OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
            buf.append( c_token );
        }
        while (index >= 0);
        buf.append( 'E' );

        OString symName( buf.makeStringAndClear() );
        rtti = (type_info *)dlsym( m_hApp, symName.getStr() );

        if (rtti)
        {
            pair< t_rtti_map::iterator, bool > insertion(
                m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
            SAL_WARN_IF( !insertion.second,
                         "bridges",
                         "inserting new rtti failed" );
        }
        else
        {
            // try to lookup the symbol in the generated rtti map
            t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) );
            if (iFind2 == m_generatedRttis.end())
            {
                // we must generate it !
                // symbol and rtti-name is nearly identical,
                // the symbol is prefixed with _ZTI
                char const * rttiName = symName.getStr() +4;
#if OSL_DEBUG_LEVEL > 1
                fprintf( stderr,"generated rtti for %s\n", rttiName );
#endif
                if (pTypeDescr->pBaseTypeDescription)
                {
                    // ensure availability of base
                    type_info * base_rtti = getRTTI(
                        (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
                    rtti = new __si_class_type_info(
                        strdup( rttiName ), (__class_type_info *)base_rtti );
#else
                    rtti = create_FAKE_si_class_type_info(
                        strdup( rttiName ), base_rtti );
#endif
                }
                else
                {
                    // this class has no base class
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
                    rtti = new __class_type_info( strdup( rttiName ) );
#else
                    rtti = create_FAKE_class_type_info( strdup( rttiName ) );
#endif
                }

                pair< t_rtti_map::iterator, bool > insertion(
                    m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
                SAL_WARN_IF( !insertion.second,
                             "bridges",
                             "inserting new generated rtti failed" );
            }
            else // taking already generated rtti
            {
                rtti = iFind2->second;
            }
        }
    }
    else
    {
        rtti = iFind->second;
    }

    return rtti;
}

struct RTTISingleton: public rtl::Static< RTTI, RTTISingleton > {};

//--------------------------------------------------------------------------------------------------
static void deleteException( void * pExc )
{
    __cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
    typelib_TypeDescription * pTD = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
    ::typelib_typedescription_getByName( &pTD, unoName.pData );
    OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
    if (pTD)
    {
        ::uno_destructData( pExc, pTD, cpp_release );
        ::typelib_typedescription_release( pTD );
    }
}

//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
#if OSL_DEBUG_LEVEL > 1
    OString cstr(
        OUStringToOString(
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
#endif
    void * pCppExc;
    type_info * rtti;

    {
    // construct cpp exception object
    typelib_TypeDescription * pTypeDescr = 0;
    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
    OSL_ASSERT( pTypeDescr );
    if (! pTypeDescr)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }

    pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
    ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );

    // destruct uno exception
    ::uno_any_destruct( pUnoExc, 0 );
	rtti = (type_info *)RTTISingleton::get().getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
    if (! rtti)
    {
        throw RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
            *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
            Reference< XInterface >() );
    }
    }

    __cxa_throw( pCppExc, rtti, deleteException );
}

//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
    if (! header)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if OSL_DEBUG_LEVEL > 0
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_FAIL( cstr.getStr() );
#endif
        return;
    }

    typelib_TypeDescription * pExcTypeDescr = 0;
    OUString unoName( toUNOname( header->exceptionType->name() ) );
#if OSL_DEBUG_LEVEL > 1
    OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
    fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() );
#endif
    typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
    if (0 == pExcTypeDescr)
    {
        RuntimeException aRE(
            OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
            Reference< XInterface >() );
        Type const & rType = ::getCppuType( &aRE );
        uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if OSL_DEBUG_LEVEL > 0
        OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
        OSL_FAIL( cstr.getStr() );
#endif
    }
    else
    {
        // construct uno exception any
        uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
        typelib_typedescription_release( pExcTypeDescr );
    }
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>