<commit_before>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//رϷ
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();
	if (g_Engine.pInput->IsKeyDown('1'))
	{
		CAction* pAction = m_pRole->OrceAction("attack02");
		if (pAction)
		{
			pAction->SetupSkillThrow(vec3_zero, -1.0f, 2.0f);
			m_pRole->StopMove();
		}
	}
	return 0;
}
<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//رϷ
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();

	if (g_Engine.pInput->IsKeyDown('1'))
	{
		CAction* pAction = m_pRole->OrceAction("attack02");
		if (pAction)
		{
			pAction->SetupSkillThrow(vec3_zero, -1.0f, 2.0f);
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('2'))
	{

	}

	return 0;
}

<|endoftext|>


<commit_before>/* This file is part of Zanshin Todo.

   Copyright 2008-2009 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

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

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

#include "sidebarpage.h"

#include <KDE/KDebug>
#include <KDE/KInputDialog>
#include <KDE/KLocale>
#include <KDE/KMessageBox>
#include <KJob>

#include <QtGui/QVBoxLayout>
#include <QtGui/QHeaderView>

#include "globaldefs.h"
#include "todohelpers.h"
#include "todotreeview.h"
#include "pimitemrelationinterface.h"

SideBarPage::SideBarPage(QAbstractItemModel *model,
                         const QList<QAction*> &contextActions,
                         QWidget *parent)
    : QWidget(parent)
{
    setLayout(new QVBoxLayout(this));
    m_treeView = new TodoTreeView(this);
    layout()->addWidget(m_treeView);
    layout()->setContentsMargins(0, 0, 0, 0);

    m_treeView->setFocusPolicy(Qt::NoFocus);
    m_treeView->header()->hide();
    m_treeView->setSortingEnabled(true);
    m_treeView->sortByColumn(0, Qt::AscendingOrder);
    m_treeView->setAnimated(true);
    m_treeView->setModel(model);
    m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    m_treeView->setDragEnabled(true);
    m_treeView->viewport()->setAcceptDrops(true);
    m_treeView->setDropIndicatorShown(true);
    m_treeView->setRootIsDecorated(false);
    m_treeView->setStyleSheet("QTreeView { background: transparent; border-style: none; }");

    m_treeView->setCurrentIndex(m_treeView->model()->index(0, 0));

    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            m_treeView, SLOT(expand(QModelIndex)));

    m_treeView->setContextMenuPolicy(Qt::ActionsContextMenu);
    m_treeView->addActions(contextActions);
}

QItemSelectionModel *SideBarPage::selectionModel() const
{
    return m_treeView->selectionModel();
}

void SideBarPage::addNewItem()
{
    QModelIndex parentItem = selectionModel()->currentIndex();
    Zanshin::ItemType type = (Zanshin::ItemType) parentItem.data(Zanshin::ItemTypeRole).toInt();

    QString title;
    QString text;

    if (type==Zanshin::Collection
     || type==Zanshin::ProjectTodo) {
        title = i18n("New Project");
        text = i18n("Enter project name:");

    } else if (type==Zanshin::CategoryRoot
            || type==Zanshin::Category) {
        title = i18n("New Context");
        text = i18n("Enter context name:");

    } else if (type==Zanshin::TopicRoot
            || type==Zanshin::Topic) {
        title = i18n("New Topic");
        text = i18n("Enter topic name:");

    } else {
        kFatal() << "We should never, ever, get in this case...";
    }

    bool ok;
    QString summary = KInputDialog::getText(title, text,
                                            QString(), &ok, this);
    summary = summary.trimmed();

    if (!ok || summary.isEmpty()) return;

    if (type==Zanshin::Collection) {
        Akonadi::Collection collection = parentItem.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
        PimItemStructureInterface::create(PimNode::Project, summary, QList<PimNode>(), collection);
    } else if (type==Zanshin::ProjectTodo) {
        PimItemStructureInterface::create(PimNode::Project, summary, QList<PimNode>() << PimItemStructureInterface::fromIndex(parentItem));
    } else if (type==Zanshin::CategoryRoot) {
        PimItemStructureInterface::create(PimNode::Context, summary);
    } else if (type==Zanshin::Category) {
        PimItemStructureInterface::create(PimNode::Context, summary, QList<PimNode>() << PimItemStructureInterface::fromIndex(parentItem));
    } else if (type==Zanshin::TopicRoot) {
        PimItemStructureInterface::create(PimNode::Topic, summary);
    } else if (type==Zanshin::Topic) {
        PimItemStructureInterface::create(PimNode::Topic, summary, QList<PimNode>() << PimItemStructureInterface::fromIndex(parentItem));
    } else {
        kFatal() << "We should never, ever, get in this case...";
    }
}

void SideBarPage::result(KJob *job)
{
    kDebug() << job->error() << job->errorString();
}

void SideBarPage::removeCurrentItem()
{
    QModelIndex current = selectionModel()->currentIndex();
    if (!current.isValid()) {
        return;
    }
    PimItemStructureInterface::remove(PimItemStructureInterface::fromIndex(current), this);
    //TODO only if remove succeeded
    m_treeView->setCurrentIndex(current.parent());
}

void SideBarPage::renameCurrentItem()
{
    m_treeView->edit(selectionModel()->currentIndex());
}

void SideBarPage::selectPreviousItem()
{
    QModelIndex index = m_treeView->currentIndex();
    index = m_treeView->indexAbove(index);

    if (index.isValid()) {
        m_treeView->setCurrentIndex(index);
    }
}

void SideBarPage::selectNextItem()
{
    QModelIndex index = m_treeView->currentIndex();
    m_treeView->expand(index);
    index = m_treeView->indexBelow(index);

    if (index.isValid()) {
        m_treeView->setCurrentIndex(index);
    }
}
<commit_msg>Create new projects in the right parent collection.<commit_after>/* This file is part of Zanshin Todo.

   Copyright 2008-2009 Kevin Ottens <ervin@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

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

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

#include "sidebarpage.h"

#include <KDE/KDebug>
#include <KDE/KInputDialog>
#include <KDE/KLocale>
#include <KDE/KMessageBox>
#include <KJob>

#include <QtGui/QVBoxLayout>
#include <QtGui/QHeaderView>

#include "globaldefs.h"
#include "todohelpers.h"
#include "todotreeview.h"
#include "pimitemrelationinterface.h"

SideBarPage::SideBarPage(QAbstractItemModel *model,
                         const QList<QAction*> &contextActions,
                         QWidget *parent)
    : QWidget(parent)
{
    setLayout(new QVBoxLayout(this));
    m_treeView = new TodoTreeView(this);
    layout()->addWidget(m_treeView);
    layout()->setContentsMargins(0, 0, 0, 0);

    m_treeView->setFocusPolicy(Qt::NoFocus);
    m_treeView->header()->hide();
    m_treeView->setSortingEnabled(true);
    m_treeView->sortByColumn(0, Qt::AscendingOrder);
    m_treeView->setAnimated(true);
    m_treeView->setModel(model);
    m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    m_treeView->setDragEnabled(true);
    m_treeView->viewport()->setAcceptDrops(true);
    m_treeView->setDropIndicatorShown(true);
    m_treeView->setRootIsDecorated(false);
    m_treeView->setStyleSheet("QTreeView { background: transparent; border-style: none; }");

    m_treeView->setCurrentIndex(m_treeView->model()->index(0, 0));

    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            m_treeView, SLOT(expand(QModelIndex)));

    m_treeView->setContextMenuPolicy(Qt::ActionsContextMenu);
    m_treeView->addActions(contextActions);
}

QItemSelectionModel *SideBarPage::selectionModel() const
{
    return m_treeView->selectionModel();
}

void SideBarPage::addNewItem()
{
    QModelIndex parentItem = selectionModel()->currentIndex();
    Zanshin::ItemType type = (Zanshin::ItemType) parentItem.data(Zanshin::ItemTypeRole).toInt();

    QString title;
    QString text;

    if (type==Zanshin::Collection
     || type==Zanshin::ProjectTodo) {
        title = i18n("New Project");
        text = i18n("Enter project name:");

    } else if (type==Zanshin::CategoryRoot
            || type==Zanshin::Category) {
        title = i18n("New Context");
        text = i18n("Enter context name:");

    } else if (type==Zanshin::TopicRoot
            || type==Zanshin::Topic) {
        title = i18n("New Topic");
        text = i18n("Enter topic name:");

    } else {
        kFatal() << "We should never, ever, get in this case...";
    }

    bool ok;
    QString summary = KInputDialog::getText(title, text,
                                            QString(), &ok, this);
    summary = summary.trimmed();

    if (!ok || summary.isEmpty()) return;

    if (type==Zanshin::Collection) {
        Akonadi::Collection collection = parentItem.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
        PimItemStructureInterface::create(PimNode::Project, summary, QList<PimNode>(), collection);
    } else if (type==Zanshin::ProjectTodo) {
        Akonadi::Collection collection = parentItem.data(Akonadi::EntityTreeModel::ParentCollectionRole).value<Akonadi::Collection>();
        PimItemStructureInterface::create(PimNode::Project, summary, QList<PimNode>() << PimItemStructureInterface::fromIndex(parentItem), collection);
    } else if (type==Zanshin::CategoryRoot) {
        PimItemStructureInterface::create(PimNode::Context, summary);
    } else if (type==Zanshin::Category) {
        PimItemStructureInterface::create(PimNode::Context, summary, QList<PimNode>() << PimItemStructureInterface::fromIndex(parentItem));
    } else if (type==Zanshin::TopicRoot) {
        PimItemStructureInterface::create(PimNode::Topic, summary);
    } else if (type==Zanshin::Topic) {
        PimItemStructureInterface::create(PimNode::Topic, summary, QList<PimNode>() << PimItemStructureInterface::fromIndex(parentItem));
    } else {
        kFatal() << "We should never, ever, get in this case...";
    }
}

void SideBarPage::result(KJob *job)
{
    kDebug() << job->error() << job->errorString();
}

void SideBarPage::removeCurrentItem()
{
    QModelIndex current = selectionModel()->currentIndex();
    if (!current.isValid()) {
        return;
    }
    PimItemStructureInterface::remove(PimItemStructureInterface::fromIndex(current), this);
    //TODO only if remove succeeded
    m_treeView->setCurrentIndex(current.parent());
}

void SideBarPage::renameCurrentItem()
{
    m_treeView->edit(selectionModel()->currentIndex());
}

void SideBarPage::selectPreviousItem()
{
    QModelIndex index = m_treeView->currentIndex();
    index = m_treeView->indexAbove(index);

    if (index.isValid()) {
        m_treeView->setCurrentIndex(index);
    }
}

void SideBarPage::selectNextItem()
{
    QModelIndex index = m_treeView->currentIndex();
    m_treeView->expand(index);
    index = m_treeView->indexBelow(index);

    if (index.isValid()) {
        m_treeView->setCurrentIndex(index);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 *          Nathan Binkert
 */

//The purpose of this file is to provide endainness conversion utility
//functions. Depending on the endianness of the guest system, either
//the LittleEndianGuest or BigEndianGuest namespace is used.

#ifndef __SIM_BYTE_SWAP_HH__
#define __SIM_BYTE_SWAP_HH__

#include "base/misc.hh"
#include "sim/host.hh"

// This lets us figure out what the byte order of the host system is
#if defined(linux)
#include <endian.h>
// If this is a linux system, lets used the optimized definitions if they exist.
// If one doesn't exist, we pretty much get what is listed below, so it all
// works out
#include <byteswap.h>
#elif defined (__sun__)
#include <sys/isa_defs.h>
#else
#include <machine/endian.h>
#endif

#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#endif

//These functions actually perform the swapping for parameters
//of various bit lengths
static inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(linux)
    return bswap_64(x);
#elif defined(__APPLE__)
    return OSSwapInt64(x);
#else
    return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
            ((uint64_t)(x) & 0xff00ULL) << 40 |
            ((uint64_t)(x) & 0xff0000ULL) << 24 |
            ((uint64_t)(x) & 0xff000000ULL) << 8 |
            ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
            ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
            ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
            ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
}

static inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(linux)
    return bswap_32(x);
#elif defined(__APPLE__)
    return OSSwapInt32(x);
#else
    return  (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
            ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
            ((uint32_t)(x) & 0xff000000) >> 24);
#endif
}

static inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(linux)
    return bswap_16(x);
#elif defined(__APPLE__)
    return OSSwapInt16(x);
#else
    return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
                      ((uint16_t)(x) & 0xff00) >> 8);
#endif
}

// This function lets the compiler figure out how to call the
// swap_byte functions above for different data types.  Since the
// sizeof() values are known at compiel time, it should inline to a
// direct call to the right swap_byteNN() function.
template <typename T>
static inline T swap_byte(T x) {
    if (sizeof(T) == 8)
        return swap_byte64((uint64_t)x);
    else if (sizeof(T) == 4)
        return swap_byte32((uint32_t)x);
    else if (sizeof(T) == 2)
        return swap_byte16((uint16_t)x);
    else if (sizeof(T) == 1)
        return x;
    else
        panic("Can't byte-swap values larger than 64 bits");
}

//The conversion functions with fixed endianness on both ends don't need to
//be in a namespace
template <typename T> static inline T betole(T value) {return swap_byte(value);}
template <typename T> static inline T letobe(T value) {return swap_byte(value);}

//For conversions not involving the guest system, we can define the functions
//conditionally based on the BYTE_ORDER macro and outside of the namespaces
#if defined(_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN
template <typename T> static inline T htole(T value) {return swap_byte(value);}
template <typename T> static inline T letoh(T value) {return swap_byte(value);}
template <typename T> static inline T htobe(T value) {return value;}
template <typename T> static inline T betoh(T value) {return value;}
#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
template <typename T> static inline T htole(T value) {return value;}
template <typename T> static inline T letoh(T value) {return value;}
template <typename T> static inline T htobe(T value) {return swap_byte(value);}
template <typename T> static inline T betoh(T value) {return swap_byte(value);}
#else
        #error Invalid Endianess
#endif

namespace BigEndianGuest
{
        template <typename T>
        static inline T gtole(T value) {return betole(value);}
        template <typename T>
        static inline T letog(T value) {return letobe(value);}
        template <typename T>
        static inline T gtobe(T value) {return value;}
        template <typename T>
        static inline T betog(T value) {return value;}
        template <typename T>
        static inline T htog(T value) {return htobe(value);}
        template <typename T>
        static inline T gtoh(T value) {return betoh(value);}
}

namespace LittleEndianGuest
{
        template <typename T>
        static inline T gtole(T value) {return value;}
        template <typename T>
        static inline T letog(T value) {return value;}
        template <typename T>
        static inline T gtobe(T value) {return letobe(value);}
        template <typename T>
        static inline T betog(T value) {return betole(value);}
        template <typename T>
        static inline T htog(T value) {return htole(value);}
        template <typename T>
        static inline T gtoh(T value) {return letoh(value);}
}
#endif // __SIM_BYTE_SWAP_HH__
<commit_msg>fix compiling on x86/Solaris<commit_after>/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 *          Nathan Binkert
 */

//The purpose of this file is to provide endainness conversion utility
//functions. Depending on the endianness of the guest system, either
//the LittleEndianGuest or BigEndianGuest namespace is used.

#ifndef __SIM_BYTE_SWAP_HH__
#define __SIM_BYTE_SWAP_HH__

#include "base/misc.hh"
#include "sim/host.hh"

// This lets us figure out what the byte order of the host system is
#if defined(linux)
#include <endian.h>
// If this is a linux system, lets used the optimized definitions if they exist.
// If one doesn't exist, we pretty much get what is listed below, so it all
// works out
#include <byteswap.h>
#elif defined (__sun__)
#include <sys/isa_defs.h>
#else
#include <machine/endian.h>
#endif

#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#endif

//These functions actually perform the swapping for parameters
//of various bit lengths
static inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(linux)
    return bswap_64(x);
#elif defined(__APPLE__)
    return OSSwapInt64(x);
#else
    return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
            ((uint64_t)(x) & 0xff00ULL) << 40 |
            ((uint64_t)(x) & 0xff0000ULL) << 24 |
            ((uint64_t)(x) & 0xff000000ULL) << 8 |
            ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
            ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
            ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
            ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
}

static inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(linux)
    return bswap_32(x);
#elif defined(__APPLE__)
    return OSSwapInt32(x);
#else
    return  (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
            ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
            ((uint32_t)(x) & 0xff000000) >> 24);
#endif
}

static inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(linux)
    return bswap_16(x);
#elif defined(__APPLE__)
    return OSSwapInt16(x);
#else
    return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
                      ((uint16_t)(x) & 0xff00) >> 8);
#endif
}

// This function lets the compiler figure out how to call the
// swap_byte functions above for different data types.  Since the
// sizeof() values are known at compiel time, it should inline to a
// direct call to the right swap_byteNN() function.
template <typename T>
static inline T swap_byte(T x) {
    if (sizeof(T) == 8)
        return swap_byte64((uint64_t)x);
    else if (sizeof(T) == 4)
        return swap_byte32((uint32_t)x);
    else if (sizeof(T) == 2)
        return swap_byte16((uint16_t)x);
    else if (sizeof(T) == 1)
        return x;
    else
        panic("Can't byte-swap values larger than 64 bits");
}

//The conversion functions with fixed endianness on both ends don't need to
//be in a namespace
template <typename T> static inline T betole(T value) {return swap_byte(value);}
template <typename T> static inline T letobe(T value) {return swap_byte(value);}

//For conversions not involving the guest system, we can define the functions
//conditionally based on the BYTE_ORDER macro and outside of the namespaces
#if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
template <typename T> static inline T htole(T value) {return swap_byte(value);}
template <typename T> static inline T letoh(T value) {return swap_byte(value);}
template <typename T> static inline T htobe(T value) {return value;}
template <typename T> static inline T betoh(T value) {return value;}
#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
template <typename T> static inline T htole(T value) {return value;}
template <typename T> static inline T letoh(T value) {return value;}
template <typename T> static inline T htobe(T value) {return swap_byte(value);}
template <typename T> static inline T betoh(T value) {return swap_byte(value);}
#else
        #error Invalid Endianess
#endif

namespace BigEndianGuest
{
        template <typename T>
        static inline T gtole(T value) {return betole(value);}
        template <typename T>
        static inline T letog(T value) {return letobe(value);}
        template <typename T>
        static inline T gtobe(T value) {return value;}
        template <typename T>
        static inline T betog(T value) {return value;}
        template <typename T>
        static inline T htog(T value) {return htobe(value);}
        template <typename T>
        static inline T gtoh(T value) {return betoh(value);}
}

namespace LittleEndianGuest
{
        template <typename T>
        static inline T gtole(T value) {return value;}
        template <typename T>
        static inline T letog(T value) {return value;}
        template <typename T>
        static inline T gtobe(T value) {return letobe(value);}
        template <typename T>
        static inline T betog(T value) {return betole(value);}
        template <typename T>
        static inline T htog(T value) {return htole(value);}
        template <typename T>
        static inline T gtoh(T value) {return letoh(value);}
}
#endif // __SIM_BYTE_SWAP_HH__
<|endoftext|>


<commit_before>/* Copyright 2009 SPARTA, Inc., dba Cobham Analytic Solutions
 *
 * This file is part of WATCHER.
 *
 *     WATCHER is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     WATCHER 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 Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Watcher.  If not, see <http://www.gnu.org/licenses/>.
 */

//
// This file gets processed by doxygen and ends up as the main page in index.html.
// Do not put code here, just comments for doxyen that don't seem to fit elsewhere.
//
/**
 ***************************************************************
 @mainpage

 @section Introduction

 The watcher system is composed of three components: a number of test node daemons, a watcher daemon instance,

 @section Build
 @subsection Dependencies

 The watcher relies on a bunch of stuff, they are here: @ref WatcherDependencies.

 @subsection Instructions

 The watcher system is built using auto-tools.

 @section Components
 @subsection Test Node Daemons

  @ref sendColorMessage

  @ref sendConnectivityMessage

  @ref sendGPSMessage

 @subpage watcherd "Watcher Daemon"
 @subsection GUIs
 @subsubsection Legacy Watcher
 @subsubsection Watcher3d

 @section About

  Point of contact: Geoff Lawler <geoff.lawler@cobham.com>

 **
 **********************************************************************/

/** @namespace libconfig
 * The libconfig namespace is the namespace in the third party library libconfig++, which the watcher system uses for reading and writing cfg files
 */
/** @namespace log4cxx
 * The namespace for the third party library log4cxx which the watcher uses to do all its logging. */

/**
 * @page UsersGuide
 * @section TOC
 *
Table of Contents

 * @section Modules
 *  Module Descriptions
 * @section HowTo
 *  How to do stuff
 * @section Glossary
 *  Glossary of Terms
 * @section Index
 */

/**
 * @page WatcherDependencies
 *
 * @section ThirdParty
 *
 * @li libconfig 1.3.1
 *
 *  the system uses this for creating, reading, and writing to configuration ("cfg") files.
 *
 * @li log4cxx 0.10.0, which depends on lib apr 1.3.3 and lib apr util 1.3.4
 *
 * This is used for all logging.
 *
 * @li boost 1.38
 *
 * C++ library used more many things: serialization, network code, regular expressions, etc.
 *
 * @li qt 4.3
 *
 * Used in the GUI for window frames, GUI widgets, mouse and keyboard handling, etc.
 *
 * @li sqlite 3
 *
 * This is the database used in the watcher daemon.
 *
 * @li qwt-5.1.1
 *
 * A small Qt-based library used to draw the 2d scrolling graphs in the watcher .
 *
 * @section Internal
 *
 * @li libwatcherutil
 *
 * Holds a few things that most components need, like parsing command line args to get to the cfg file.
 *
 * @li liblogger
 *
 * A small wrapper around log4cxx to abstract which logging library we use.
 *
 * @li libwatcher
 *
 * The core of the watcher messaging system, the watcher APIs between test node daemons, a watcher daemon, and the GUI(s)s.
 *
 *
 */
<commit_msg>point people to the ./src/doc directory for the User's Guide.<commit_after>/* Copyright 2009 SPARTA, Inc., dba Cobham Analytic Solutions
 *
 * This file is part of WATCHER.
 *
 *     WATCHER is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     WATCHER 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 Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Watcher.  If not, see <http://www.gnu.org/licenses/>.
 */

//
// This file gets processed by doxygen and ends up as the main page in index.html.
// Do not put code here, just comments for doxyen that don't seem to fit elsewhere.
//
/**
 ***************************************************************
 @mainpage

 @section Introduction

 The watcher system is composed of three components: a number of test node daemons, a watcher daemon instance,

 @section Build
 @subsection Dependencies

 The watcher relies on a bunch of stuff, they are here: @ref WatcherDependencies.

 @subsection Instructions

 The watcher system is built using auto-tools.

 @section Components
 @subsection Test Node Daemons

  @ref sendColorMessage

  @ref sendConnectivityMessage

  @ref sendGPSMessage

 @subpage watcherd "Watcher Daemon"
 @subsection GUIs
 @subsubsection Legacy Watcher
 @subsubsection Watcher3d

 @section About

  Point of contact: Geoff Lawler <geoff.lawler@cobham.com>

 **
 **********************************************************************/

/** @namespace libconfig
 * The libconfig namespace is the namespace in the third party library libconfig++, which the watcher system uses for reading and writing cfg files
 */
/** @namespace log4cxx
 * The namespace for the third party library log4cxx which the watcher uses to do all its logging. */

/**
 * @page UsersGuide
 * The User's Guide can be built by doing a 'make' in the ./src/doc directory.
 */

/**
 * @page WatcherDependencies
 *
 * @section ThirdParty
 *
 * @li libconfig 1.3.1
 *
 *  the system uses this for creating, reading, and writing to configuration ("cfg") files.
 *
 * @li log4cxx 0.10.0, which depends on lib apr 1.3.3 and lib apr util 1.3.4
 *
 * This is used for all logging.
 *
 * @li boost 1.38
 *
 * C++ library used more many things: serialization, network code, regular expressions, etc.
 *
 * @li qt 4.3
 *
 * Used in the GUI for window frames, GUI widgets, mouse and keyboard handling, etc.
 *
 * @li sqlite 3
 *
 * This is the database used in the watcher daemon.
 *
 * @li qwt-5.1.1
 *
 * A small Qt-based library used to draw the 2d scrolling graphs in the watcher .
 *
 * @section Internal
 *
 * @li libwatcherutil
 *
 * Holds a few things that most components need, like parsing command line args to get to the cfg file.
 *
 * @li liblogger
 *
 * A small wrapper around log4cxx to abstract which logging library we use.
 *
 * @li libwatcher
 *
 * The core of the watcher messaging system, the watcher APIs between test node daemons, a watcher daemon, and the GUI(s)s.
 *
 *
 */
<|endoftext|>


<commit_before>// Copyright 2017 The Minimal Configuration Manager Authors
//
// 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.

#include "luacat/main.h"

#include <unistd.h>
#include <fcntl.h>
#include "kj/debug.h"
#include "kj/exception.h"
#include "capnp/serialize.h"

extern "C" {
#include "lauxlib.h"
#include "lualib.h"
}

#include "luacat/convert.h"
#include "luacat/lib.h"
#include "luacat/path.h"

namespace mcm {

namespace luacat {

namespace {
  const luaL_Reg loadedlibs[] = {
    {"_G", luaopen_base},
    {LUA_LOADLIBNAME, luaopen_package},
    {LUA_COLIBNAME, luaopen_coroutine},
    {LUA_TABLIBNAME, luaopen_table},
    {LUA_STRLIBNAME, luaopen_string},
    {LUA_MATHLIBNAME, luaopen_math},
    {LUA_UTF8LIBNAME, luaopen_utf8},
    {NULL, NULL}
  };

  bool isValidLuaInclude(const kj::ArrayPtr<const char> path) {
    for (char c: path) {
      if (c == '?') {
        return true;
      }
    }
    return false;
  }

  int printfunc(lua_State *state) {
    // Customized implementation of print().
    // We could customize this in vendored copy, but this keeps the
    // application/vendored code separation clean.

    auto& stream = *reinterpret_cast<kj::OutputStream*>(lua_touserdata(state, lua_upvalueindex(1)));
    int n = lua_gettop(state);  // number of arguments
    int i;
    lua_getglobal(state, "tostring");
    for (i = 1; i <= n; i++) {
      const char *s;
      size_t l;
      lua_pushvalue(state, -1);  // function to be called
      lua_pushvalue(state, i);   // value to print
      lua_call(state, 1, 1);
      s = lua_tolstring(state, -1, &l);  // get result
      if (s == NULL) {
        return luaL_error(state, "'tostring' must return a string to 'print'");
      }
      if (i > 1) {
        stream.write("\t", 1);
      }
      stream.write(s, l);
      lua_pop(state, 1);  // pop result
    }
    stream.write("\n", 1);
    return 0;
  }
}  // namespace

Main::Main(kj::ProcessContext& context, kj::OutputStream& outStream, kj::OutputStream& logStream):
    context(context), outStream(&outStream), logStream(logStream) {
}

void Main::setFallbackIncludePath(kj::StringPtr include) {
  if (include.size() == 0) {
    fallbackInclude = kj::heapString(include);
    return;
  }
  auto parts = splitStr(include, ';');
  kj::StringTree cleaned;
  for (auto part: parts) {
    if (!isValidLuaInclude(part)) {
      continue;
    }
    if (cleaned.size() > 0) {
      cleaned = kj::strTree(kj::mv(cleaned), ";");
    }
    cleaned = kj::strTree(kj::mv(cleaned), part);
  }
  fallbackInclude = cleaned.flatten();
}

kj::MainBuilder::Validity Main::addIncludePath(kj::StringPtr include) {
  auto parts = splitStr(include, ';');
  for (auto part: parts) {
    if (!isValidLuaInclude(part)) {
      return kj::str("path '", part, "' does not include a '?' wildcard");
    }
  }
  if (includes.size() == 0) {
    includes = kj::strTree(include);
    return true;
  }
  includes = kj::strTree(kj::mv(includes), ";", include);
  return true;
}

kj::MainBuilder::Validity Main::setOutputPath(kj::StringPtr outPath) {
  int fd;
  KJ_SYSCALL(fd = open(outPath.cStr(), O_WRONLY | O_CREAT | O_TRUNC, 0666), outPath);
  kj::AutoCloseFd autoclose(fd);
  ownOutStream = kj::heap<kj::FdOutputStream>(kj::mv(autoclose));
  outStream = ownOutStream;
  return true;
}

kj::MainBuilder::Validity Main::processFile(kj::StringPtr src) {
  if (src.size() == 0) {
    return kj::str("empty source");
  }
  auto chunkName = kj::str("@", src);
  auto maybeExc = kj::runCatchingExceptions([&]() {
    int fd;
    KJ_SYSCALL(fd = open(src.cStr(), O_RDONLY, 0), src);
    kj::AutoCloseFd afd(fd);
    kj::FdInputStream stream(kj::mv(afd));
    capnp::MallocMessageBuilder message;
    process(message, chunkName, stream);
    capnp::writeMessage(*outStream, message);
  });
  KJ_IF_MAYBE(e, maybeExc) {
    context.error(e->getDescription());
  }

  return true;
}

void Main::process(capnp::MessageBuilder& message, kj::StringPtr chunkName, kj::InputStream& stream) {
  auto state = newLuaState();

  // Load libraries
  const luaL_Reg *reg;
  for (reg = loadedlibs; reg->func; reg++) {
    luaL_requiref(state, reg->name, reg->func, 1);
    lua_pop(state, 1);  // remove lib
  }
  LibState libState;
  openlib(state, libState);  // push mcm module
  lua_setglobal(state, "mcm");  // _G.mcm = module

  // Override print function.
  lua_getglobal(state, "_G");
  lua_pushlightuserdata(state, &logStream);
  lua_pushcclosure(state, printfunc, 1);
  lua_setfield(state, -2, "print");
  lua_pop(state, 1);

  // Set package.path
  {
    auto inc = buildIncludePath(chunkName);
    lua_getglobal(state, "package");
    pushLua(state, inc);
    lua_setfield(state, -2, "path");
    lua_pop(state, 1);
  }

  // Run script
  if (luaLoad(state, chunkName, stream) || lua_pcall(state, 0, 0, 0)) {
    auto errMsg = kj::heapString(luaStringPtr(state, -1));
    lua_pop(state, 1);
    throw kj::Exception(kj::Exception::Type::FAILED, __FILE__, __LINE__, kj::mv(errMsg));
  }

  // Create catalog
  auto catalog = message.initRoot<Catalog>();
  auto resources = libState.getResources();
  auto rlist = catalog.initResources(resources.size());
  // TODO(soon): sort
  for (size_t i = 0; i < resources.size(); i++) {
    rlist.setWithCaveats(i, resources[i].get());
  }
}

kj::String Main::buildIncludePath(kj::StringPtr chunkName) {
  kj::StringTree tree;
  if (chunkName.startsWith("@")) {
    // Actual file name; add containing directory.
    auto srcDir = dirName(chunkName.slice(1));
    tree = kj::strTree(joinPath(srcDir, "?.lua"), ";", joinPath(srcDir, "?", "init.lua"));
  }
  if (includes.size() > 0) {
    if (tree.size() > 0) {
      tree = kj::strTree(kj::mv(tree), ";");
    }
    tree = kj::strTree(kj::mv(tree), includes.flatten());
  }
  if (fallbackInclude.size() > 0) {
    if (tree.size() > 0) {
      tree = kj::strTree(kj::mv(tree), ";");
    }
    tree = kj::strTree(kj::mv(tree), fallbackInclude);
  }
  return tree.flatten();
}

kj::MainFunc Main::getMain() {
  return kj::MainBuilder(context, "mcm-luacat", "Interprets Lua source and generates an mcm catalog.")
      .addOptionWithArg({'I'}, KJ_BIND_METHOD(*this, addIncludePath),
          "<templates>", "Add a package path template in package.searchpath format.")
      .addOptionWithArg({'o'}, KJ_BIND_METHOD(*this, setOutputPath),
          "FILE", "Write output to FILE instead of stdout.")
      .expectArg("FILE", KJ_BIND_METHOD(*this, processFile))
      .build();
}

OwnState newLuaState() {
  // TODO(someday): use lua_newstate and set atpanic
  lua_State* state = luaL_newstate();
  KJ_ASSERT_NONNULL(state);
  return OwnState(state);
}

}  // namespace luacat
}  // namespace mcm
<commit_msg>luacat: add tty output error<commit_after>// Copyright 2017 The Minimal Configuration Manager Authors
//
// 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.

#include "luacat/main.h"

#include <unistd.h>
#include <fcntl.h>
#include "kj/debug.h"
#include "kj/exception.h"
#include "capnp/serialize.h"

extern "C" {
#include "lauxlib.h"
#include "lualib.h"
}

#include "luacat/convert.h"
#include "luacat/lib.h"
#include "luacat/path.h"

namespace mcm {

namespace luacat {

namespace {
  const luaL_Reg loadedlibs[] = {
    {"_G", luaopen_base},
    {LUA_LOADLIBNAME, luaopen_package},
    {LUA_COLIBNAME, luaopen_coroutine},
    {LUA_TABLIBNAME, luaopen_table},
    {LUA_STRLIBNAME, luaopen_string},
    {LUA_MATHLIBNAME, luaopen_math},
    {LUA_UTF8LIBNAME, luaopen_utf8},
    {NULL, NULL}
  };

  bool isValidLuaInclude(const kj::ArrayPtr<const char> path) {
    for (char c: path) {
      if (c == '?') {
        return true;
      }
    }
    return false;
  }

  int printfunc(lua_State *state) {
    // Customized implementation of print().
    // We could customize this in vendored copy, but this keeps the
    // application/vendored code separation clean.

    auto& stream = *reinterpret_cast<kj::OutputStream*>(lua_touserdata(state, lua_upvalueindex(1)));
    int n = lua_gettop(state);  // number of arguments
    int i;
    lua_getglobal(state, "tostring");
    for (i = 1; i <= n; i++) {
      const char *s;
      size_t l;
      lua_pushvalue(state, -1);  // function to be called
      lua_pushvalue(state, i);   // value to print
      lua_call(state, 1, 1);
      s = lua_tolstring(state, -1, &l);  // get result
      if (s == NULL) {
        return luaL_error(state, "'tostring' must return a string to 'print'");
      }
      if (i > 1) {
        stream.write("\t", 1);
      }
      stream.write(s, l);
      lua_pop(state, 1);  // pop result
    }
    stream.write("\n", 1);
    return 0;
  }
}  // namespace

Main::Main(kj::ProcessContext& context, kj::OutputStream& outStream, kj::OutputStream& logStream):
    context(context), outStream(&outStream), logStream(logStream) {
}

void Main::setFallbackIncludePath(kj::StringPtr include) {
  if (include.size() == 0) {
    fallbackInclude = kj::heapString(include);
    return;
  }
  auto parts = splitStr(include, ';');
  kj::StringTree cleaned;
  for (auto part: parts) {
    if (!isValidLuaInclude(part)) {
      continue;
    }
    if (cleaned.size() > 0) {
      cleaned = kj::strTree(kj::mv(cleaned), ";");
    }
    cleaned = kj::strTree(kj::mv(cleaned), part);
  }
  fallbackInclude = cleaned.flatten();
}

kj::MainBuilder::Validity Main::addIncludePath(kj::StringPtr include) {
  auto parts = splitStr(include, ';');
  for (auto part: parts) {
    if (!isValidLuaInclude(part)) {
      return kj::str("path '", part, "' does not include a '?' wildcard");
    }
  }
  if (includes.size() == 0) {
    includes = kj::strTree(include);
    return true;
  }
  includes = kj::strTree(kj::mv(includes), ";", include);
  return true;
}

kj::MainBuilder::Validity Main::setOutputPath(kj::StringPtr outPath) {
  int fd;
  KJ_SYSCALL(fd = open(outPath.cStr(), O_WRONLY | O_CREAT | O_TRUNC, 0666), outPath);
  kj::AutoCloseFd autoclose(fd);
  ownOutStream = kj::heap<kj::FdOutputStream>(kj::mv(autoclose));
  outStream = ownOutStream;
  return true;
}

kj::MainBuilder::Validity Main::processFile(kj::StringPtr src) {
  if (src.size() == 0) {
    return kj::str("empty source");
  }
  auto maybeFdStream = kj::dynamicDowncastIfAvailable<kj::FdOutputStream, kj::OutputStream>(*outStream);
  KJ_IF_MAYBE(f, maybeFdStream) {
    if (isatty(f->getFd())) {
      context.exitError("mcm-luacat: output file is a tty\n\nWriting a binary catalog will likely mess up your terminal. Either\nredirect stdout or use -o.");
    }
  }
  auto chunkName = kj::str("@", src);
  auto maybeExc = kj::runCatchingExceptions([&]() {
    int fd;
    KJ_SYSCALL(fd = open(src.cStr(), O_RDONLY, 0), src);
    kj::AutoCloseFd afd(fd);
    kj::FdInputStream stream(kj::mv(afd));
    capnp::MallocMessageBuilder message;
    process(message, chunkName, stream);
    capnp::writeMessage(*outStream, message);
  });
  KJ_IF_MAYBE(e, maybeExc) {
    context.error(e->getDescription());
  }

  return true;
}

void Main::process(capnp::MessageBuilder& message, kj::StringPtr chunkName, kj::InputStream& stream) {
  auto state = newLuaState();

  // Load libraries
  const luaL_Reg *reg;
  for (reg = loadedlibs; reg->func; reg++) {
    luaL_requiref(state, reg->name, reg->func, 1);
    lua_pop(state, 1);  // remove lib
  }
  LibState libState;
  openlib(state, libState);  // push mcm module
  lua_setglobal(state, "mcm");  // _G.mcm = module

  // Override print function.
  lua_getglobal(state, "_G");
  lua_pushlightuserdata(state, &logStream);
  lua_pushcclosure(state, printfunc, 1);
  lua_setfield(state, -2, "print");
  lua_pop(state, 1);

  // Set package.path
  {
    auto inc = buildIncludePath(chunkName);
    lua_getglobal(state, "package");
    pushLua(state, inc);
    lua_setfield(state, -2, "path");
    lua_pop(state, 1);
  }

  // Run script
  if (luaLoad(state, chunkName, stream) || lua_pcall(state, 0, 0, 0)) {
    auto errMsg = kj::heapString(luaStringPtr(state, -1));
    lua_pop(state, 1);
    throw kj::Exception(kj::Exception::Type::FAILED, __FILE__, __LINE__, kj::mv(errMsg));
  }

  // Create catalog
  auto catalog = message.initRoot<Catalog>();
  auto resources = libState.getResources();
  auto rlist = catalog.initResources(resources.size());
  // TODO(soon): sort
  for (size_t i = 0; i < resources.size(); i++) {
    rlist.setWithCaveats(i, resources[i].get());
  }
}

kj::String Main::buildIncludePath(kj::StringPtr chunkName) {
  kj::StringTree tree;
  if (chunkName.startsWith("@")) {
    // Actual file name; add containing directory.
    auto srcDir = dirName(chunkName.slice(1));
    tree = kj::strTree(joinPath(srcDir, "?.lua"), ";", joinPath(srcDir, "?", "init.lua"));
  }
  if (includes.size() > 0) {
    if (tree.size() > 0) {
      tree = kj::strTree(kj::mv(tree), ";");
    }
    tree = kj::strTree(kj::mv(tree), includes.flatten());
  }
  if (fallbackInclude.size() > 0) {
    if (tree.size() > 0) {
      tree = kj::strTree(kj::mv(tree), ";");
    }
    tree = kj::strTree(kj::mv(tree), fallbackInclude);
  }
  return tree.flatten();
}

kj::MainFunc Main::getMain() {
  return kj::MainBuilder(context, "mcm-luacat", "Interprets Lua source and generates an mcm catalog.")
      .addOptionWithArg({'I'}, KJ_BIND_METHOD(*this, addIncludePath),
          "<templates>", "Add a package path template in package.searchpath format.")
      .addOptionWithArg({'o'}, KJ_BIND_METHOD(*this, setOutputPath),
          "FILE", "Write output to FILE instead of stdout.")
      .expectArg("FILE", KJ_BIND_METHOD(*this, processFile))
      .build();
}

OwnState newLuaState() {
  // TODO(someday): use lua_newstate and set atpanic
  lua_State* state = luaL_newstate();
  KJ_ASSERT_NONNULL(state);
  return OwnState(state);
}

}  // namespace luacat
}  // namespace mcm
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "chinese_translationdialog.hxx"
#include "chinese_dictionarydialog.hxx"
#include <com/sun/star/i18n/TextConversionOption.hpp>
// header for define RET_OK
#include <vcl/msgbox.hxx>
// header for class SvtLinguConfigItem
#include <unotools/lingucfg.hxx>
#include <unotools/linguprops.hxx>
#include "helpid.hrc"

namespace textconversiondlgs
{

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

ChineseTranslationDialog::ChineseTranslationDialog( Window* pParent )
    : ModalDialog(pParent, "ChineseConversionDialog", "svx/ui/chineseconversiondialog.ui")
    , m_pDictionaryDialog(0)
{
    get(m_pBP_OK, "ok");
    get(m_pPB_Editterms, "editterms");
    get(m_pRB_To_Simplified, "tosimplified");
    get(m_pRB_To_Traditional, "totraditional");
    get(m_pCB_Translate_Commonterms, "commonterms");

    SvtLinguConfig  aLngCfg;
    bool bValue;
    Any aAny( aLngCfg.GetProperty( OUString( UPN_IS_DIRECTION_TO_SIMPLIFIED ) ) );
    aAny >>= bValue;
    if( bValue )
        m_pRB_To_Simplified->Check();
    else
        m_pRB_To_Traditional->Check();

    aAny = aLngCfg.GetProperty( OUString( UPN_IS_TRANSLATE_COMMON_TERMS ) );
    if( aAny >>= bValue )
        m_pCB_Translate_Commonterms->Check( bValue );

    m_pPB_Editterms->SetClickHdl( LINK( this, ChineseTranslationDialog, DictionaryHdl ) );
    m_pBP_OK->SetClickHdl( LINK( this, ChineseTranslationDialog, OkHdl ) );
}

ChineseTranslationDialog::~ChineseTranslationDialog()
{
    if(m_pDictionaryDialog)
    {
        if(m_pDictionaryDialog->IsInExecute())
            m_pDictionaryDialog->EndDialog();
        delete m_pDictionaryDialog;
    }
}

void ChineseTranslationDialog::getSettings( bool& rbDirectionToSimplified
                                          , bool& rbTranslateCommonTerms ) const
{
    rbDirectionToSimplified = m_pRB_To_Simplified->IsChecked();
    rbTranslateCommonTerms = m_pCB_Translate_Commonterms->IsChecked();
}

IMPL_LINK_NOARG(ChineseTranslationDialog, OkHdl)
{
    //save settings to configuration
    SvtLinguConfig  aLngCfg;
    Any aAny;
    aAny <<= m_pRB_To_Simplified->IsChecked();
    aLngCfg.SetProperty( OUString( UPN_IS_DIRECTION_TO_SIMPLIFIED ), aAny );
    aAny <<= m_pCB_Translate_Commonterms->IsChecked();
    aLngCfg.SetProperty( OUString( UPN_IS_TRANSLATE_COMMON_TERMS ), aAny );

    EndDialog( RET_OK );
    return 0;
}

IMPL_LINK_NOARG(ChineseTranslationDialog, DictionaryHdl)
{
    if( !m_pDictionaryDialog )
    {
        m_pDictionaryDialog = new ChineseDictionaryDialog(this);
    }
    if( m_pDictionaryDialog )
    {
        if( m_pDictionaryDialog->IsInExecute() )
        {
            if( !m_pDictionaryDialog->IsReallyVisible() )
            {
                m_pDictionaryDialog->ToTop();
                m_pDictionaryDialog->GrabFocusToFirstControl();
            }
        }
        else
        {
            sal_Int32 nTextConversionOptions = i18n::TextConversionOption::NONE;
            if( !m_pCB_Translate_Commonterms->IsChecked() )
                nTextConversionOptions = nTextConversionOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
            m_pDictionaryDialog->setDirectionAndTextConversionOptions( m_pRB_To_Simplified->IsChecked(), nTextConversionOptions );
            m_pDictionaryDialog->Execute();
        }
    }
    return 0;
}

} //end namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>WaE: 'bValue' may be used uninitialized in this function<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "chinese_translationdialog.hxx"
#include "chinese_dictionarydialog.hxx"
#include <com/sun/star/i18n/TextConversionOption.hpp>
// header for define RET_OK
#include <vcl/msgbox.hxx>
// header for class SvtLinguConfigItem
#include <unotools/lingucfg.hxx>
#include <unotools/linguprops.hxx>
#include "helpid.hrc"

namespace textconversiondlgs
{

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

ChineseTranslationDialog::ChineseTranslationDialog( Window* pParent )
    : ModalDialog(pParent, "ChineseConversionDialog", "svx/ui/chineseconversiondialog.ui")
    , m_pDictionaryDialog(0)
{
    get(m_pBP_OK, "ok");
    get(m_pPB_Editterms, "editterms");
    get(m_pRB_To_Simplified, "tosimplified");
    get(m_pRB_To_Traditional, "totraditional");
    get(m_pCB_Translate_Commonterms, "commonterms");

    SvtLinguConfig  aLngCfg;
    bool bValue = false;
    Any aAny( aLngCfg.GetProperty( OUString( UPN_IS_DIRECTION_TO_SIMPLIFIED ) ) );
    aAny >>= bValue;
    if( bValue )
        m_pRB_To_Simplified->Check();
    else
        m_pRB_To_Traditional->Check();

    aAny = aLngCfg.GetProperty( OUString( UPN_IS_TRANSLATE_COMMON_TERMS ) );
    if( aAny >>= bValue )
        m_pCB_Translate_Commonterms->Check( bValue );

    m_pPB_Editterms->SetClickHdl( LINK( this, ChineseTranslationDialog, DictionaryHdl ) );
    m_pBP_OK->SetClickHdl( LINK( this, ChineseTranslationDialog, OkHdl ) );
}

ChineseTranslationDialog::~ChineseTranslationDialog()
{
    if(m_pDictionaryDialog)
    {
        if(m_pDictionaryDialog->IsInExecute())
            m_pDictionaryDialog->EndDialog();
        delete m_pDictionaryDialog;
    }
}

void ChineseTranslationDialog::getSettings( bool& rbDirectionToSimplified
                                          , bool& rbTranslateCommonTerms ) const
{
    rbDirectionToSimplified = m_pRB_To_Simplified->IsChecked();
    rbTranslateCommonTerms = m_pCB_Translate_Commonterms->IsChecked();
}

IMPL_LINK_NOARG(ChineseTranslationDialog, OkHdl)
{
    //save settings to configuration
    SvtLinguConfig  aLngCfg;
    Any aAny;
    aAny <<= m_pRB_To_Simplified->IsChecked();
    aLngCfg.SetProperty( OUString( UPN_IS_DIRECTION_TO_SIMPLIFIED ), aAny );
    aAny <<= m_pCB_Translate_Commonterms->IsChecked();
    aLngCfg.SetProperty( OUString( UPN_IS_TRANSLATE_COMMON_TERMS ), aAny );

    EndDialog( RET_OK );
    return 0;
}

IMPL_LINK_NOARG(ChineseTranslationDialog, DictionaryHdl)
{
    if( !m_pDictionaryDialog )
    {
        m_pDictionaryDialog = new ChineseDictionaryDialog(this);
    }
    if( m_pDictionaryDialog )
    {
        if( m_pDictionaryDialog->IsInExecute() )
        {
            if( !m_pDictionaryDialog->IsReallyVisible() )
            {
                m_pDictionaryDialog->ToTop();
                m_pDictionaryDialog->GrabFocusToFirstControl();
            }
        }
        else
        {
            sal_Int32 nTextConversionOptions = i18n::TextConversionOption::NONE;
            if( !m_pCB_Translate_Commonterms->IsChecked() )
                nTextConversionOptions = nTextConversionOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
            m_pDictionaryDialog->setDirectionAndTextConversionOptions( m_pRB_To_Simplified->IsChecked(), nTextConversionOptions );
            m_pDictionaryDialog->Execute();
        }
    }
    return 0;
}

} //end namespace

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


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#ifndef __SLAVE_HPP__
#define __SLAVE_HPP__

#include <process/http.hpp>
#include <process/process.hpp>
#include <process/protobuf.hpp>

#include <stout/hashmap.hpp>
#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/uuid.hpp>

#include "slave/constants.hpp"
#include "slave/flags.hpp"
#include "slave/gc.hpp"
#include "slave/http.hpp"
#include "slave/isolation_module.hpp"
#include "slave/state.hpp"

#include "common/attributes.hpp"
#include "common/resources.hpp"
#include "common/type_utils.hpp"

#include "files/files.hpp"

#include "messages/messages.hpp"

namespace mesos {
namespace internal {
namespace slave {

using namespace process;

// Some forward declarations.
struct Executor;
struct Framework;

class Slave : public ProtobufProcess<Slave>
{
public:
  Slave(const Resources& resources,
        bool local,
        IsolationModule* isolationModule,
        Files* files);

  Slave(const flags::Flags<logging::Flags, slave::Flags>& flags,
        bool local,
        IsolationModule *isolationModule,
        Files* files);

  virtual ~Slave();

  void shutdown();

  void newMasterDetected(const UPID& pid);
  void noMasterDetected();
  void masterDetectionFailure();
  void registered(const SlaveID& slaveId);
  void reregistered(const SlaveID& slaveId);
  void doReliableRegistration();
  void runTask(const FrameworkInfo& frameworkInfo,
               const FrameworkID& frameworkId,
               const std::string& pid,
               const TaskInfo& task);
  void killTask(const FrameworkID& frameworkId,
                const TaskID& taskId);
  void shutdownFramework(const FrameworkID& frameworkId);
  void schedulerMessage(const SlaveID& slaveId,
			const FrameworkID& frameworkId,
			const ExecutorID& executorId,
			const std::string& data);
  void updateFramework(const FrameworkID& frameworkId,
                       const std::string& pid);
  void statusUpdateAcknowledgement(const SlaveID& slaveId,
                                   const FrameworkID& frameworkId,
                                   const TaskID& taskId,
                                   const std::string& uuid);
  void registerExecutor(const FrameworkID& frameworkId,
                        const ExecutorID& executorId);
  void statusUpdate(const StatusUpdate& update);
  void executorMessage(const SlaveID& slaveId,
                       const FrameworkID& frameworkId,
                       const ExecutorID& executorId,
                       const std::string& data);
  void ping(const UPID& from, const std::string& body);

  void statusUpdateTimeout(const FrameworkID& frameworkId, const UUID& uuid);

  StatusUpdate createStatusUpdate(const TaskID& taskId,
                                  const ExecutorID& executorId,
                                  const FrameworkID& frameworkId,
                                  TaskState taskState,
                                  const std::string& message);

  void executorStarted(const FrameworkID& frameworkId,
                       const ExecutorID& executorId,
                       pid_t pid);

  void executorExited(const FrameworkID& frameworkId,
                      const ExecutorID& executorId,
                      int status);

  void transitionLiveTask(const TaskID& taskId,
                          const ExecutorID& executorId,
                          const FrameworkID& frameworkId,
                          bool command_executor,
                          int status);

  // NOTE: Pulled this to public to make it visible for testing.
  // Garbage collects the directories based on the current disk usage.
  // TODO(vinod): Instead of making this function public, we need to
  // mock both GarbageCollector (and pass it through slave's constructor)
  // and os calls.
  void _checkDiskUsage(const Future<Try<double> >& capacity);

protected:
  virtual void initialize();
  virtual void finalize();
  virtual void exited(const UPID& pid);

  void fileAttached(const Future<Nothing>& result);

  // Helper routine to lookup a framework.
  Framework* getFramework(const FrameworkID& frameworkId);

  // Shut down an executor. This is a two phase process. First, an
  // executor receives a shut down message (shut down phase), then
  // after a configurable timeout the slave actually forces a kill
  // (kill phase, via the isolation module) if the executor has not
  // exited.
  void shutdownExecutor(Framework* framework, Executor* executor);

  // Handle the second phase of shutting down an executor for those
  // executors that have not properly shutdown within a timeout.
  void shutdownExecutorTimeout(const FrameworkID& frameworkId,
                               const ExecutorID& executorId,
                               const UUID& uuid);

  // This function returns the max age of executor/slave directories allowed,
  // given a disk usage. This value could be used to tune gc.
  Duration age(double usage);

  // Checks the current disk usage and schedules for gc as necessary.
  void checkDiskUsage();

private:
  // HTTP handlers, friends of the slave in order to access state,
  // they get invoked from within the slave so there is no need to
  // use synchronization mechanisms to protect state.
  friend Future<process::http::Response> http::vars(
      const Slave& slave,
      const process::http::Request& request);

  friend Future<process::http::Response> http::json::stats(
      const Slave& slave,
      const process::http::Request& request);

  friend Future<process::http::Response> http::json::state(
      const Slave& slave,
      const process::http::Request& request);

  const flags::Flags<logging::Flags, slave::Flags> flags;

  bool local;

  SlaveID id;
  SlaveInfo info;

  UPID master;

  Resources resources;
  Attributes attributes;

  hashmap<FrameworkID, Framework*> frameworks;

  IsolationModule* isolationModule;
  Files* files;

  // Statistics (initialized in Slave::initialize).
  struct {
    uint64_t tasks[TaskState_ARRAYSIZE];
    uint64_t validStatusUpdates;
    uint64_t invalidStatusUpdates;
    uint64_t validFrameworkMessages;
    uint64_t invalidFrameworkMessages;
  } stats;

  double startTime;

  bool connected; // Flag to indicate if slave is registered.

  GarbageCollector gc;

  state::SlaveState state;
};

// Information describing an executor (goes away if executor crashes).
struct Executor
{
  Executor(const FrameworkID& _frameworkId,
           const ExecutorInfo& _info,
           const std::string& _directory)
    : id(_info.executor_id()),
      info(_info),
      frameworkId(_frameworkId),
      directory(_directory),
      uuid(UUID::random()),
      pid(UPID()),
      shutdown(false),
      resources(_info.resources()) {}

  ~Executor()
  {
    // Delete the tasks.
    foreachvalue (Task* task, launchedTasks) {
      delete task;
    }
  }

  Task* addTask(const TaskInfo& task)
  {
    // The master should enforce unique task IDs, but just in case
    // maybe we shouldn't make this a fatal error.
    CHECK(!launchedTasks.contains(task.task_id()));

    Task *t = new Task();
    t->mutable_framework_id()->MergeFrom(frameworkId);
    t->set_state(TASK_STAGING);
    t->set_name(task.name());
    t->mutable_task_id()->MergeFrom(task.task_id());
    t->mutable_slave_id()->MergeFrom(task.slave_id());
    t->mutable_resources()->MergeFrom(task.resources());

    if (!task.has_command()) {
      t->mutable_executor_id()->MergeFrom(id);
    }

    launchedTasks[task.task_id()] = t;
    resources += task.resources();
    return t;
  }

  void removeTask(const TaskID& taskId)
  {
    // Remove the task if it's queued.
    queuedTasks.erase(taskId);

    // Update the resources if it's been launched.
    if (launchedTasks.contains(taskId)) {
      Task* task = launchedTasks[taskId];
      foreach (const Resource& resource, task->resources()) {
        resources -= resource;
      }
      launchedTasks.erase(taskId);
      delete task;
    }
  }

  void updateTaskState(const TaskID& taskId, TaskState state)
  {
    if (launchedTasks.contains(taskId)) {
      launchedTasks[taskId]->set_state(state);
    }
  }

  const ExecutorID id;
  const ExecutorInfo info;

  const FrameworkID frameworkId;

  const std::string directory;

  const UUID uuid; // Distinguishes executor instances with same ExecutorID.

  UPID pid;

  bool shutdown; // Indicates if executor is being shut down.

  Resources resources; // Currently consumed resources.

  hashmap<TaskID, TaskInfo> queuedTasks;
  hashmap<TaskID, Task*> launchedTasks;
};

// Information about a framework.
struct Framework
{
  Framework(const FrameworkID& _id,
            const FrameworkInfo& _info,
            const UPID& _pid,
            const Flags& _flags)
    : id(_id),
      info(_info),
      pid(_pid),
      flags(_flags) {}

  ~Framework() {}

  // Returns an ExecutorInfo for a TaskInfo (possibly
  // constructing one if the task has a CommandInfo).
  ExecutorInfo getExecutorInfo(const TaskInfo& task)
  {
    CHECK(task.has_executor() != task.has_command());

    if (task.has_command()) {
      ExecutorInfo executor;

      // Prepare an executor id which includes information on the
      // command being launched.
      std::string id = "Task " + task.task_id().value() + " (";
      if (task.command().value().length() > 15) {
        id += task.command().value().substr(0, 12) + "...)";
      } else {
        id += task.command().value() + ")";
      }

      executor.mutable_executor_id()->set_value(id);

      // Now determine the path to the executor.
      Try<std::string> path = os::realpath(
          ::path::join(flags.launcher_dir, "mesos-executor"));

      if (path.isSome()) {
        executor.mutable_command()->set_value(path.get());
      } else {
        executor.mutable_command()->set_value(
            "echo '" + path.error() + "'; exit 1");
      }

      // TODO(benh): Set some resources for the executor so that a task
      // doesn't end up getting killed because the amount of resources of
      // the executor went over those allocated. Note that this might mean
      // that the number of resources on the machine will actually be
      // slightly oversubscribed, so we'll need to reevaluate with respect
      // to resources that can't be oversubscribed.
      return executor;
    }

    return task.executor();
  }

  Executor* createExecutor(const ExecutorInfo& executorInfo,
                           const std::string& directory)
  {
    Executor* executor = new Executor(id, executorInfo, directory);
    CHECK(!executors.contains(executorInfo.executor_id()));
    executors[executorInfo.executor_id()] = executor;
    return executor;
  }

  void destroyExecutor(const ExecutorID& executorId)
  {
    if (executors.contains(executorId)) {
      Executor* executor = executors[executorId];
      executors.erase(executorId);
      delete executor;
    }
  }

  Executor* getExecutor(const ExecutorID& executorId)
  {
    if (executors.contains(executorId)) {
      return executors[executorId];
    }

    return NULL;
  }

  Executor* getExecutor(const TaskID& taskId)
  {
    foreachvalue (Executor* executor, executors) {
      if (executor->queuedTasks.contains(taskId) ||
          executor->launchedTasks.contains(taskId)) {
        return executor;
      }
    }

    return NULL;
  }

  const FrameworkID id;
  const FrameworkInfo info;

  UPID pid;

  const Flags flags;

  // Current running executors.
  hashmap<ExecutorID, Executor*> executors;

  // Status updates keyed by uuid.
  hashmap<UUID, StatusUpdate> updates;
};

} // namespace slave {
} // namespace internal {
} // namespace mesos {

#endif // __SLAVE_HPP__
<commit_msg>Fixes a bug where tasks that don't have an executor were not getting their URIs or environment properly set up.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#ifndef __SLAVE_HPP__
#define __SLAVE_HPP__

#include <process/http.hpp>
#include <process/process.hpp>
#include <process/protobuf.hpp>

#include <stout/hashmap.hpp>
#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/uuid.hpp>

#include "slave/constants.hpp"
#include "slave/flags.hpp"
#include "slave/gc.hpp"
#include "slave/http.hpp"
#include "slave/isolation_module.hpp"
#include "slave/state.hpp"

#include "common/attributes.hpp"
#include "common/resources.hpp"
#include "common/type_utils.hpp"

#include "files/files.hpp"

#include "messages/messages.hpp"

namespace mesos {
namespace internal {
namespace slave {

using namespace process;

// Some forward declarations.
struct Executor;
struct Framework;

class Slave : public ProtobufProcess<Slave>
{
public:
  Slave(const Resources& resources,
        bool local,
        IsolationModule* isolationModule,
        Files* files);

  Slave(const flags::Flags<logging::Flags, slave::Flags>& flags,
        bool local,
        IsolationModule *isolationModule,
        Files* files);

  virtual ~Slave();

  void shutdown();

  void newMasterDetected(const UPID& pid);
  void noMasterDetected();
  void masterDetectionFailure();
  void registered(const SlaveID& slaveId);
  void reregistered(const SlaveID& slaveId);
  void doReliableRegistration();
  void runTask(const FrameworkInfo& frameworkInfo,
               const FrameworkID& frameworkId,
               const std::string& pid,
               const TaskInfo& task);
  void killTask(const FrameworkID& frameworkId,
                const TaskID& taskId);
  void shutdownFramework(const FrameworkID& frameworkId);
  void schedulerMessage(const SlaveID& slaveId,
			const FrameworkID& frameworkId,
			const ExecutorID& executorId,
			const std::string& data);
  void updateFramework(const FrameworkID& frameworkId,
                       const std::string& pid);
  void statusUpdateAcknowledgement(const SlaveID& slaveId,
                                   const FrameworkID& frameworkId,
                                   const TaskID& taskId,
                                   const std::string& uuid);
  void registerExecutor(const FrameworkID& frameworkId,
                        const ExecutorID& executorId);
  void statusUpdate(const StatusUpdate& update);
  void executorMessage(const SlaveID& slaveId,
                       const FrameworkID& frameworkId,
                       const ExecutorID& executorId,
                       const std::string& data);
  void ping(const UPID& from, const std::string& body);

  void statusUpdateTimeout(const FrameworkID& frameworkId, const UUID& uuid);

  StatusUpdate createStatusUpdate(const TaskID& taskId,
                                  const ExecutorID& executorId,
                                  const FrameworkID& frameworkId,
                                  TaskState taskState,
                                  const std::string& message);

  void executorStarted(const FrameworkID& frameworkId,
                       const ExecutorID& executorId,
                       pid_t pid);

  void executorExited(const FrameworkID& frameworkId,
                      const ExecutorID& executorId,
                      int status);

  void transitionLiveTask(const TaskID& taskId,
                          const ExecutorID& executorId,
                          const FrameworkID& frameworkId,
                          bool command_executor,
                          int status);

  // NOTE: Pulled this to public to make it visible for testing.
  // Garbage collects the directories based on the current disk usage.
  // TODO(vinod): Instead of making this function public, we need to
  // mock both GarbageCollector (and pass it through slave's constructor)
  // and os calls.
  void _checkDiskUsage(const Future<Try<double> >& capacity);

protected:
  virtual void initialize();
  virtual void finalize();
  virtual void exited(const UPID& pid);

  void fileAttached(const Future<Nothing>& result);

  // Helper routine to lookup a framework.
  Framework* getFramework(const FrameworkID& frameworkId);

  // Shut down an executor. This is a two phase process. First, an
  // executor receives a shut down message (shut down phase), then
  // after a configurable timeout the slave actually forces a kill
  // (kill phase, via the isolation module) if the executor has not
  // exited.
  void shutdownExecutor(Framework* framework, Executor* executor);

  // Handle the second phase of shutting down an executor for those
  // executors that have not properly shutdown within a timeout.
  void shutdownExecutorTimeout(const FrameworkID& frameworkId,
                               const ExecutorID& executorId,
                               const UUID& uuid);

  // This function returns the max age of executor/slave directories allowed,
  // given a disk usage. This value could be used to tune gc.
  Duration age(double usage);

  // Checks the current disk usage and schedules for gc as necessary.
  void checkDiskUsage();

private:
  // HTTP handlers, friends of the slave in order to access state,
  // they get invoked from within the slave so there is no need to
  // use synchronization mechanisms to protect state.
  friend Future<process::http::Response> http::vars(
      const Slave& slave,
      const process::http::Request& request);

  friend Future<process::http::Response> http::json::stats(
      const Slave& slave,
      const process::http::Request& request);

  friend Future<process::http::Response> http::json::state(
      const Slave& slave,
      const process::http::Request& request);

  const flags::Flags<logging::Flags, slave::Flags> flags;

  bool local;

  SlaveID id;
  SlaveInfo info;

  UPID master;

  Resources resources;
  Attributes attributes;

  hashmap<FrameworkID, Framework*> frameworks;

  IsolationModule* isolationModule;
  Files* files;

  // Statistics (initialized in Slave::initialize).
  struct {
    uint64_t tasks[TaskState_ARRAYSIZE];
    uint64_t validStatusUpdates;
    uint64_t invalidStatusUpdates;
    uint64_t validFrameworkMessages;
    uint64_t invalidFrameworkMessages;
  } stats;

  double startTime;

  bool connected; // Flag to indicate if slave is registered.

  GarbageCollector gc;

  state::SlaveState state;
};

// Information describing an executor (goes away if executor crashes).
struct Executor
{
  Executor(const FrameworkID& _frameworkId,
           const ExecutorInfo& _info,
           const std::string& _directory)
    : id(_info.executor_id()),
      info(_info),
      frameworkId(_frameworkId),
      directory(_directory),
      uuid(UUID::random()),
      pid(UPID()),
      shutdown(false),
      resources(_info.resources()) {}

  ~Executor()
  {
    // Delete the tasks.
    foreachvalue (Task* task, launchedTasks) {
      delete task;
    }
  }

  Task* addTask(const TaskInfo& task)
  {
    // The master should enforce unique task IDs, but just in case
    // maybe we shouldn't make this a fatal error.
    CHECK(!launchedTasks.contains(task.task_id()));

    Task *t = new Task();
    t->mutable_framework_id()->MergeFrom(frameworkId);
    t->set_state(TASK_STAGING);
    t->set_name(task.name());
    t->mutable_task_id()->MergeFrom(task.task_id());
    t->mutable_slave_id()->MergeFrom(task.slave_id());
    t->mutable_resources()->MergeFrom(task.resources());

    if (!task.has_command()) {
      t->mutable_executor_id()->MergeFrom(id);
    }

    launchedTasks[task.task_id()] = t;
    resources += task.resources();
    return t;
  }

  void removeTask(const TaskID& taskId)
  {
    // Remove the task if it's queued.
    queuedTasks.erase(taskId);

    // Update the resources if it's been launched.
    if (launchedTasks.contains(taskId)) {
      Task* task = launchedTasks[taskId];
      foreach (const Resource& resource, task->resources()) {
        resources -= resource;
      }
      launchedTasks.erase(taskId);
      delete task;
    }
  }

  void updateTaskState(const TaskID& taskId, TaskState state)
  {
    if (launchedTasks.contains(taskId)) {
      launchedTasks[taskId]->set_state(state);
    }
  }

  const ExecutorID id;
  const ExecutorInfo info;

  const FrameworkID frameworkId;

  const std::string directory;

  const UUID uuid; // Distinguishes executor instances with same ExecutorID.

  UPID pid;

  bool shutdown; // Indicates if executor is being shut down.

  Resources resources; // Currently consumed resources.

  hashmap<TaskID, TaskInfo> queuedTasks;
  hashmap<TaskID, Task*> launchedTasks;
};

// Information about a framework.
struct Framework
{
  Framework(const FrameworkID& _id,
            const FrameworkInfo& _info,
            const UPID& _pid,
            const Flags& _flags)
    : id(_id),
      info(_info),
      pid(_pid),
      flags(_flags) {}

  ~Framework() {}

  // Returns an ExecutorInfo for a TaskInfo (possibly
  // constructing one if the task has a CommandInfo).
  ExecutorInfo getExecutorInfo(const TaskInfo& task)
  {
    CHECK(task.has_executor() != task.has_command());

    if (task.has_command()) {
      ExecutorInfo executor;

      // Prepare an executor id which includes information on the
      // command being launched.
      std::string id = "Task " + task.task_id().value() + " (";
      if (task.command().value().length() > 15) {
        id += task.command().value().substr(0, 12) + "...)";
      } else {
        id += task.command().value() + ")";
      }

      executor.mutable_executor_id()->set_value(id);

      // Copy the CommandInfo to get the URIs and environment, but
      // update it to invoke 'mesos-executor' (unless we couldn't
      // resolve 'mesos-executor' via 'realpath', in which case just
      // echo the error and exit).
      executor.mutable_command()->MergeFrom(task.command());

      Try<std::string> path = os::realpath(
          path::join(flags.launcher_dir, "mesos-executor"));

      if (path.isSome()) {
        executor.mutable_command()->set_value(path.get());
      } else {
        executor.mutable_command()->set_value(
            "echo '" + path.error() + "'; exit 1");
      }

      // TODO(benh): Set some resources for the executor so that a task
      // doesn't end up getting killed because the amount of resources of
      // the executor went over those allocated. Note that this might mean
      // that the number of resources on the machine will actually be
      // slightly oversubscribed, so we'll need to reevaluate with respect
      // to resources that can't be oversubscribed.
      return executor;
    }

    return task.executor();
  }

  Executor* createExecutor(const ExecutorInfo& executorInfo,
                           const std::string& directory)
  {
    Executor* executor = new Executor(id, executorInfo, directory);
    CHECK(!executors.contains(executorInfo.executor_id()));
    executors[executorInfo.executor_id()] = executor;
    return executor;
  }

  void destroyExecutor(const ExecutorID& executorId)
  {
    if (executors.contains(executorId)) {
      Executor* executor = executors[executorId];
      executors.erase(executorId);
      delete executor;
    }
  }

  Executor* getExecutor(const ExecutorID& executorId)
  {
    if (executors.contains(executorId)) {
      return executors[executorId];
    }

    return NULL;
  }

  Executor* getExecutor(const TaskID& taskId)
  {
    foreachvalue (Executor* executor, executors) {
      if (executor->queuedTasks.contains(taskId) ||
          executor->launchedTasks.contains(taskId)) {
        return executor;
      }
    }

    return NULL;
  }

  const FrameworkID id;
  const FrameworkInfo info;

  UPID pid;

  const Flags flags;

  // Current running executors.
  hashmap<ExecutorID, Executor*> executors;

  // Status updates keyed by uuid.
  hashmap<UUID, StatusUpdate> updates;
};

} // namespace slave {
} // namespace internal {
} // namespace mesos {

#endif // __SLAVE_HPP__
<|endoftext|>


<commit_before>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2013 LiteIDE Team. All rights reserved.
**
** 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.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: editorutil.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "editorutil.h"

typedef void (*EnumEditorProc)(QTextCursor &cursor, QTextBlock &block, void *param);

void EditorUtil::EnumEditor(QPlainTextEdit *ed, EnumEditorProc proc, void *param)
{
    if (!ed) {
        return;
    }
    QTextCursor cur = ed->textCursor();
    cur.beginEditBlock();
    if (cur.hasSelection()) {
        QTextBlock begin = ed->document()->findBlock(cur.selectionStart());
        QTextBlock end = ed->document()->findBlock(cur.selectionEnd());
        if (end.position() == cur.selectionEnd()) {
            end = end.previous();
        }
        QTextBlock block = begin;
        do {
            if (block.text().length() > 0) {
                proc(cur,block,param);
            }
            block = block.next();
        } while(block.isValid() && block.position() <= end.position());
    } else {
        QTextBlock block = cur.block();
        proc(cur,block,param);
    }
    cur.endEditBlock();
    ed->setTextCursor(cur);
}

struct InsertHeadParam
{
    QString tag;
    bool blockStart;
};

static void insertHead(QTextCursor &cur, QTextBlock &block, void *param)
{
    InsertHeadParam *ip = (InsertHeadParam*)param;
    if (ip->blockStart) {
        cur.setPosition(block.position());
    } else {
        QString text = block.text();
        foreach(QChar c, text) {
            if (!c.isSpace()) {
                cur.setPosition(block.position()+text.indexOf(c));
                break;
            }
        }
    }
    cur.insertText(ip->tag);
}

struct RemoveHeadParam
{
    QStringList tags;
    bool blockStart;
};

struct SwitchHeadParam
{
    QString tagAdd;
    QStringList tagRemove;
    bool blockStart;
};

static void removeHead(QTextCursor &cur, QTextBlock &block, void *param)
{
    RemoveHeadParam *ip = (RemoveHeadParam*)param;
    if (ip->blockStart) {
        cur.setPosition(block.position());
    } else {
        QString text = block.text();
        foreach(QChar c, text) {
            if (!c.isSpace()) {
                cur.setPosition(block.position()+text.indexOf(c));
                break;
            }
        }
    }
    foreach (QString tag, ip->tags) {
        if (cur.block().text().startsWith(tag)) {
            cur.setPosition(block.position());
            cur.movePosition(QTextCursor::NextCharacter,
                                QTextCursor::KeepAnchor,
                                tag.length());
            cur.removeSelectedText();
            break;
        }
    }
}

static void switchHead(QTextCursor &cur, QTextBlock &block, void *param)
{
    SwitchHeadParam *ip = (SwitchHeadParam*)param;
    if (ip->blockStart) {
        cur.setPosition(block.position());
    } else {
        QString text = block.text();
        foreach(QChar c, text) {
            if (!c.isSpace()) {
                cur.setPosition(block.position()+text.indexOf(c));
                break;
            }
        }
    }
    foreach (QString tag, ip->tagRemove) {
        if (cur.block().text().startsWith(tag)) {
            cur.setPosition(block.position());
            cur.movePosition(QTextCursor::NextCharacter,
                                QTextCursor::KeepAnchor,
                                tag.length());
            cur.removeSelectedText();
            return;
        }
    }
    cur.insertText(ip->tagAdd);
}

void EditorUtil::InsertHead(QPlainTextEdit *ed, const QString &tag, bool blockStart)
{
    InsertHeadParam param = {tag,blockStart};
    EnumEditor(ed,&insertHead,&param);
}

void EditorUtil::RemoveHead(QPlainTextEdit *ed, const QStringList &tags, bool blockStart)
{
    RemoveHeadParam param = {tags,blockStart};
    EnumEditor(ed,&removeHead,&param);
}

void EditorUtil::SwitchHead(QPlainTextEdit *ed, const QString &tagAdd, const QStringList &tagRemove, bool blockStart)
{
    SwitchHeadParam param = {tagAdd,tagRemove,blockStart};
    EnumEditor(ed,&switchHead,&param);
}

void EditorUtil::MarkSelection(QPlainTextEdit *ed, const QString &mark1, const QString &mark2)
{
    if (!ed) {
        return;
    }
    QTextCursor cur = ed->textCursor();
    cur.beginEditBlock();
    if (cur.hasSelection()) {
        QTextBlock begin = ed->document()->findBlock(cur.selectionStart());
        QTextBlock end = ed->document()->findBlock(cur.selectionEnd());
        if (end.position() == cur.selectionEnd()) {
            end = end.previous();
        }
        int n1 = cur.selectionStart();
        int n2 = cur.selectionEnd();
        QTextBlock block = begin;
        do {
            int c1 = block.position();
            int c2 = c1+block.text().length();
            if (block.position() == begin.position() && c1 < n1) {
                c1 = n1;
            }
            if (c2 > n2) {
                c2 = n2;
            }
            if (c2 > c1) {
                if (!mark1.isEmpty()) {
                    cur.setPosition(c1);
                    cur.insertText(mark1);
                    n2 += mark1.length();
                }
                if (!mark2.isEmpty()) {
                    cur.setPosition(c2+mark1.length());
                    cur.insertText(mark2);
                    n2 += mark2.length();
                }
            }
            block = block.next();
        } while(block.isValid() && block.position() <= end.position());
    } else {
        int pos = cur.position();
        cur.insertText(mark1+mark2);
        cur.setPosition(pos+mark1.length());
    }
    cur.endEditBlock();
    ed->setTextCursor(cur);
}

void EditorUtil::MarkSelection(QPlainTextEdit *ed, const QString &mark)
{
    EditorUtil::MarkSelection(ed,mark,mark);
}

<commit_msg>update<commit_after>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2013 LiteIDE Team. All rights reserved.
**
** 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.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: editorutil.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "editorutil.h"
#include <QTextBlock>
#include <QTextCursor>
#include <QPlainTextEdit>

typedef void (*EnumEditorProc)(QTextCursor &cursor, QTextBlock &block, void *param);

void EditorUtil::EnumEditor(QPlainTextEdit *ed, EnumEditorProc proc, void *param)
{
    if (!ed) {
        return;
    }
    QTextCursor cur = ed->textCursor();
    cur.beginEditBlock();
    if (cur.hasSelection()) {
        QTextBlock begin = ed->document()->findBlock(cur.selectionStart());
        QTextBlock end = ed->document()->findBlock(cur.selectionEnd());
        if (end.position() == cur.selectionEnd()) {
            end = end.previous();
        }
        QTextBlock block = begin;
        do {
            if (block.text().length() > 0) {
                proc(cur,block,param);
            }
            block = block.next();
        } while(block.isValid() && block.position() <= end.position());
    } else {
        QTextBlock block = cur.block();
        proc(cur,block,param);
    }
    cur.endEditBlock();
    ed->setTextCursor(cur);
}

struct InsertHeadParam
{
    QString tag;
    bool blockStart;
};

static void insertHead(QTextCursor &cur, QTextBlock &block, void *param)
{
    InsertHeadParam *ip = (InsertHeadParam*)param;
    if (ip->blockStart) {
        cur.setPosition(block.position());
    } else {
        QString text = block.text();
        foreach(QChar c, text) {
            if (!c.isSpace()) {
                cur.setPosition(block.position()+text.indexOf(c));
                break;
            }
        }
    }
    cur.insertText(ip->tag);
}

struct RemoveHeadParam
{
    QStringList tags;
    bool blockStart;
};

struct SwitchHeadParam
{
    QString tagAdd;
    QStringList tagRemove;
    bool blockStart;
};

static void removeHead(QTextCursor &cur, QTextBlock &block, void *param)
{
    RemoveHeadParam *ip = (RemoveHeadParam*)param;
    if (ip->blockStart) {
        cur.setPosition(block.position());
    } else {
        QString text = block.text();
        foreach(QChar c, text) {
            if (!c.isSpace()) {
                cur.setPosition(block.position()+text.indexOf(c));
                break;
            }
        }
    }
    foreach (QString tag, ip->tags) {
        if (cur.block().text().startsWith(tag)) {
            cur.setPosition(block.position());
            cur.movePosition(QTextCursor::NextCharacter,
                                QTextCursor::KeepAnchor,
                                tag.length());
            cur.removeSelectedText();
            break;
        }
    }
}

static void switchHead(QTextCursor &cur, QTextBlock &block, void *param)
{
    SwitchHeadParam *ip = (SwitchHeadParam*)param;
    if (ip->blockStart) {
        cur.setPosition(block.position());
    } else {
        QString text = block.text();
        foreach(QChar c, text) {
            if (!c.isSpace()) {
                cur.setPosition(block.position()+text.indexOf(c));
                break;
            }
        }
    }
    foreach (QString tag, ip->tagRemove) {
        if (cur.block().text().startsWith(tag)) {
            cur.setPosition(block.position());
            cur.movePosition(QTextCursor::NextCharacter,
                                QTextCursor::KeepAnchor,
                                tag.length());
            cur.removeSelectedText();
            return;
        }
    }
    cur.insertText(ip->tagAdd);
}

void EditorUtil::InsertHead(QPlainTextEdit *ed, const QString &tag, bool blockStart)
{
    InsertHeadParam param = {tag,blockStart};
    EnumEditor(ed,&insertHead,&param);
}

void EditorUtil::RemoveHead(QPlainTextEdit *ed, const QStringList &tags, bool blockStart)
{
    RemoveHeadParam param = {tags,blockStart};
    EnumEditor(ed,&removeHead,&param);
}

void EditorUtil::SwitchHead(QPlainTextEdit *ed, const QString &tagAdd, const QStringList &tagRemove, bool blockStart)
{
    SwitchHeadParam param = {tagAdd,tagRemove,blockStart};
    EnumEditor(ed,&switchHead,&param);
}

void EditorUtil::MarkSelection(QPlainTextEdit *ed, const QString &mark1, const QString &mark2)
{
    if (!ed) {
        return;
    }
    QTextCursor cur = ed->textCursor();
    cur.beginEditBlock();
    if (cur.hasSelection()) {
        QTextBlock begin = ed->document()->findBlock(cur.selectionStart());
        QTextBlock end = ed->document()->findBlock(cur.selectionEnd());
        if (end.position() == cur.selectionEnd()) {
            end = end.previous();
        }
        int n1 = cur.selectionStart();
        int n2 = cur.selectionEnd();
        QTextBlock block = begin;
        do {
            int c1 = block.position();
            int c2 = c1+block.text().length();
            if (block.position() == begin.position() && c1 < n1) {
                c1 = n1;
            }
            if (c2 > n2) {
                c2 = n2;
            }
            if (c2 > c1) {
                if (!mark1.isEmpty()) {
                    cur.setPosition(c1);
                    cur.insertText(mark1);
                    n2 += mark1.length();
                }
                if (!mark2.isEmpty()) {
                    cur.setPosition(c2+mark1.length());
                    cur.insertText(mark2);
                    n2 += mark2.length();
                }
            }
            block = block.next();
        } while(block.isValid() && block.position() <= end.position());
    } else {
        int pos = cur.position();
        cur.insertText(mark1+mark2);
        cur.setPosition(pos+mark1.length());
    }
    cur.endEditBlock();
    ed->setTextCursor(cur);
}

void EditorUtil::MarkSelection(QPlainTextEdit *ed, const QString &mark)
{
    EditorUtil::MarkSelection(ed,mark,mark);
}

<|endoftext|>