<commit_before>/*
 * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "tvgSvgCssStyle.h"

/************************************************************************/
/* Internal Class Implementation                                        */
/************************************************************************/

static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
{
    if (from == nullptr) return;
    //Copy the properties of 'from' only if they were explicitly set (not the default ones).
    if (from->curColorSet && !((int)to->flags & (int)SvgStyleFlags::Color)) {
        to->color = from->color;
        to->curColorSet = true;
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Color);
    }
    //Fill
    if (((int)from->fill.flags & (int)SvgFillFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Fill)) {
        to->fill.paint.color = from->fill.paint.color;
        to->fill.paint.none = from->fill.paint.none;
        to->fill.paint.curColor = from->fill.paint.curColor;
        if (from->fill.paint.url) to->fill.paint.url = strdup(from->fill.paint.url);
        to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
    }
    if (((int)from->fill.flags & (int)SvgFillFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::FillOpacity)) {
        to->fill.opacity = from->fill.opacity;
        to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Opacity);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillOpacity);
    }
    if (((int)from->fill.flags & (int)SvgFillFlags::FillRule) && !((int)to->flags & (int)SvgStyleFlags::FillRule)) {
        to->fill.fillRule = from->fill.fillRule;
        to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::FillRule);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillRule);
    }
    //Stroke
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Stroke)) {
        to->stroke.paint.color = from->stroke.paint.color;
        to->stroke.paint.none = from->stroke.paint.none;
        to->stroke.paint.curColor = from->stroke.paint.curColor;
        if (from->stroke.paint.url) to->stroke.paint.url = strdup(from->stroke.paint.url);
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::StrokeOpacity)) {
        to->stroke.opacity = from->stroke.opacity;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Opacity);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeOpacity);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width) && !((int)to->flags & (int)SvgStyleFlags::StrokeWidth)) {
        to->stroke.width = from->stroke.width;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Width);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeWidth);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash) && !((int)to->flags & (int)SvgStyleFlags::StrokeDashArray)) {
        if (from->stroke.dash.array.count > 0) {
            to->stroke.dash.array.clear();
            to->stroke.dash.array.reserve(from->stroke.dash.array.count);
            for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
                to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
            }
            to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Dash);
            to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeDashArray);
        }
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineCap)) {
        to->stroke.cap = from->stroke.cap;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Cap);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineCap);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineJoin)) {
        to->stroke.join = from->stroke.join;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Join);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineJoin);
    }
    //Opacity
    //TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
    if (from->opacity < 255 && !((int)to->flags & (int)SvgStyleFlags::Opacity)) {
        to->opacity = from->opacity;
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Opacity);
    }
}

/************************************************************************/
/* External Class Implementation                                        */
/************************************************************************/

void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
{
    //Copy matrix attribute
    if (from->transform && !((int)to->style->flags & (int)SvgStyleFlags::Transform)) {
        to->transform = (Matrix*)malloc(sizeof(Matrix));
        if (to->transform) {
            *to->transform = *from->transform;
            to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)SvgStyleFlags::Transform);
        }
    }
    //Copy style attribute
    _copyStyle(to->style, from->style);

    if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
    if (from->style->mask.url) to->style->mask.url = strdup(from->style->mask.url);
}

SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type)
{
    if (!style) return nullptr;

    auto child = style->child.data;
    for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
        if ((*child)->type == type) {
            if ((!title && !(*child)->id) || (title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
        }
    }
    return nullptr;
}

SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
{
    if (!style) return nullptr;

    auto child = style->child.data;
    for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
        if ((*child)->type == SvgNodeType::CssStyle) {
            if ((title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
        }
    }
    return nullptr;
}

void cssUpdateStyle(SvgNode* doc, SvgNode* style)
{
    if (doc->child.count > 0) {
        auto child = doc->child.data;
        for (uint32_t i = 0; i < doc->child.count; ++i, ++child) {
            if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
                cssCopyStyleAttr(*child, cssNode);
            }
            if (auto cssNode = cssFindStyleNode(style, nullptr)) {
                cssCopyStyleAttr(*child, cssNode);
            }
            cssUpdateStyle(*child, style);
        }
    }
}

void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style)
{
    for (uint32_t i = 0; i < postponeds.count; ++i) {
        auto nodeIdPair = postponeds.data[i];

        //css styling: tag.name has higher priority than .name
        if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id, nodeIdPair.node->type)) {
            cssCopyStyleAttr(nodeIdPair.node, cssNode);
        }
        if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id)) {
            cssCopyStyleAttr(nodeIdPair.node, cssNode);
        }
    }
}<commit_msg>thorvg: Fix MinGW build by adding explicit `<cstring>` include<commit_after>/*
 * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "tvgSvgCssStyle.h"

#include <cstring>

/************************************************************************/
/* Internal Class Implementation                                        */
/************************************************************************/

static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
{
    if (from == nullptr) return;
    //Copy the properties of 'from' only if they were explicitly set (not the default ones).
    if (from->curColorSet && !((int)to->flags & (int)SvgStyleFlags::Color)) {
        to->color = from->color;
        to->curColorSet = true;
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Color);
    }
    //Fill
    if (((int)from->fill.flags & (int)SvgFillFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Fill)) {
        to->fill.paint.color = from->fill.paint.color;
        to->fill.paint.none = from->fill.paint.none;
        to->fill.paint.curColor = from->fill.paint.curColor;
        if (from->fill.paint.url) to->fill.paint.url = strdup(from->fill.paint.url);
        to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
    }
    if (((int)from->fill.flags & (int)SvgFillFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::FillOpacity)) {
        to->fill.opacity = from->fill.opacity;
        to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Opacity);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillOpacity);
    }
    if (((int)from->fill.flags & (int)SvgFillFlags::FillRule) && !((int)to->flags & (int)SvgStyleFlags::FillRule)) {
        to->fill.fillRule = from->fill.fillRule;
        to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::FillRule);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillRule);
    }
    //Stroke
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Stroke)) {
        to->stroke.paint.color = from->stroke.paint.color;
        to->stroke.paint.none = from->stroke.paint.none;
        to->stroke.paint.curColor = from->stroke.paint.curColor;
        if (from->stroke.paint.url) to->stroke.paint.url = strdup(from->stroke.paint.url);
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::StrokeOpacity)) {
        to->stroke.opacity = from->stroke.opacity;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Opacity);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeOpacity);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width) && !((int)to->flags & (int)SvgStyleFlags::StrokeWidth)) {
        to->stroke.width = from->stroke.width;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Width);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeWidth);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash) && !((int)to->flags & (int)SvgStyleFlags::StrokeDashArray)) {
        if (from->stroke.dash.array.count > 0) {
            to->stroke.dash.array.clear();
            to->stroke.dash.array.reserve(from->stroke.dash.array.count);
            for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
                to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
            }
            to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Dash);
            to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeDashArray);
        }
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineCap)) {
        to->stroke.cap = from->stroke.cap;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Cap);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineCap);
    }
    if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineJoin)) {
        to->stroke.join = from->stroke.join;
        to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Join);
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineJoin);
    }
    //Opacity
    //TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
    if (from->opacity < 255 && !((int)to->flags & (int)SvgStyleFlags::Opacity)) {
        to->opacity = from->opacity;
        to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Opacity);
    }
}

/************************************************************************/
/* External Class Implementation                                        */
/************************************************************************/

void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
{
    //Copy matrix attribute
    if (from->transform && !((int)to->style->flags & (int)SvgStyleFlags::Transform)) {
        to->transform = (Matrix*)malloc(sizeof(Matrix));
        if (to->transform) {
            *to->transform = *from->transform;
            to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)SvgStyleFlags::Transform);
        }
    }
    //Copy style attribute
    _copyStyle(to->style, from->style);

    if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
    if (from->style->mask.url) to->style->mask.url = strdup(from->style->mask.url);
}

SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type)
{
    if (!style) return nullptr;

    auto child = style->child.data;
    for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
        if ((*child)->type == type) {
            if ((!title && !(*child)->id) || (title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
        }
    }
    return nullptr;
}

SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
{
    if (!style) return nullptr;

    auto child = style->child.data;
    for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
        if ((*child)->type == SvgNodeType::CssStyle) {
            if ((title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
        }
    }
    return nullptr;
}

void cssUpdateStyle(SvgNode* doc, SvgNode* style)
{
    if (doc->child.count > 0) {
        auto child = doc->child.data;
        for (uint32_t i = 0; i < doc->child.count; ++i, ++child) {
            if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
                cssCopyStyleAttr(*child, cssNode);
            }
            if (auto cssNode = cssFindStyleNode(style, nullptr)) {
                cssCopyStyleAttr(*child, cssNode);
            }
            cssUpdateStyle(*child, style);
        }
    }
}

void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style)
{
    for (uint32_t i = 0; i < postponeds.count; ++i) {
        auto nodeIdPair = postponeds.data[i];

        //css styling: tag.name has higher priority than .name
        if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id, nodeIdPair.node->type)) {
            cssCopyStyleAttr(nodeIdPair.node, cssNode);
        }
        if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id)) {
            cssCopyStyleAttr(nodeIdPair.node, cssNode);
        }
    }
}
<|endoftext|>


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

#include "PyEvents.h"
#include "PyBZFlag.h"

namespace Python
{

void
PythonHandler::emit (PyObject *arglist, int event)
{
	PyObject *listeners = parent->GetListeners (event);

	if (listeners == NULL || !PyList_Check(listeners)) {
		// FIXME - throw error
		fprintf (stderr, "tick listeners is not a list!\n");
		return;
	}

	// Call out
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "%d listener is not callable\n", event);
			Py_DECREF (arglist);
			return;
		}
		PyErr_Clear ();
		PyEval_CallObject (handler, arglist);
		if (PyErr_Occurred ()) {
			PyErr_Print ();
			return;
		}
	}
}

void
CaptureHandler::process (bz_EventData *eventData)
{
	bz_CTFCaptureEventData *ced = (bz_CTFCaptureEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iii(fff)fd",
			ced->teamCaped,
			ced->teamCaping,
			ced->playerCaping,
			ced->pos[0],
			ced->pos[1],
			ced->pos[2],
			ced->rot,
			ced->time);
	emit (arglist, bz_eCaptureEvent);
	Py_DECREF (arglist);
}

void
JoinHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->AddPlayer (pjped->playerID);

	emit (NULL /* FIXME */, bz_ePlayerJoinEvent);
}

void
PartHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->RemovePlayer (pjped->playerID);

	emit (NULL /* FIXME */, bz_ePlayerPartEvent);
}

void
TickHandler::process (bz_EventData *eventData)
{
	bz_TickEventData *ted = (bz_TickEventData*) eventData;

	PyObject *arglist = Py_BuildValue ("(d)", ted->time);
	emit (arglist, bz_eTickEvent);
	Py_DECREF (arglist);
}

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

#include "PyEvents.h"
#include "PyBZFlag.h"

namespace Python
{

void
PythonHandler::emit (PyObject *arglist, int event)
{
	PyObject *listeners = parent->GetListeners (event);

	if (listeners == NULL || !PyList_Check(listeners)) {
		// FIXME - throw error
		fprintf (stderr, "tick listeners is not a list!\n");
		return;
	}

	// Call out
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "%d listener is not callable\n", event);
			Py_DECREF (arglist);
			return;
		}
		PyErr_Clear ();
		PyEval_CallObject (handler, arglist);
		if (PyErr_Occurred ()) {
			PyErr_Print ();
			return;
		}
	}
}

void
CaptureHandler::process (bz_EventData *eventData)
{
	bz_CTFCaptureEventData *ced = (bz_CTFCaptureEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iii(fff)fd",
			ced->teamCaped,
			ced->teamCaping,
			ced->playerCaping,
			ced->pos[0],
			ced->pos[1],
			ced->pos[2],
			ced->rot,
			ced->time);
	emit (arglist, bz_eCaptureEvent);
	Py_DECREF (arglist);
}

void
DieHandler::process (bz_EventData *eventData)
{
	bz_PlayerDieEventData *pded = (bz_PlayerDieEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("iiiis(fff)fd",
			pded->playerID,
			pded->teamID,
			pded->killerID,
			pded->killerTeamID,
			pded->flagKilledWith.c_str(),
			pded->pos[0],
			pded->pos[1],
			pded->pos[2],
			pded->rot,
			pded->time);
	emit (arglist, bz_ePlayerDieEvent);
	Py_DECREF (arglist);
}

void
JoinHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->AddPlayer (pjped->playerID);

	emit (NULL /* FIXME */, bz_ePlayerJoinEvent);
}

void
PartHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->RemovePlayer (pjped->playerID);

	emit (NULL /* FIXME */, bz_ePlayerPartEvent);
}

void
TickHandler::process (bz_EventData *eventData)
{
	bz_TickEventData *ted = (bz_TickEventData*) eventData;

	PyObject *arglist = Py_BuildValue ("(d)", ted->time);
	emit (arglist, bz_eTickEvent);
	Py_DECREF (arglist);
}

};
<|endoftext|>


<commit_before>#include "kernel.h"
#include "storage.h"
#include "arch/dev/Display.h"
#include "sampling.h"

#include <cassert>
#include <algorithm>
#include <cstdarg>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <set>
#include <map>
#include <cstdio>

using namespace std;

namespace Simulator
{

//
// Process class
//

std::string Process::GetName() const
{
    return GetObject()->GetFQN() + ":" + m_name;
}

void Process::Deactivate()
{
    // A process can be sensitive to multiple objects, so we only remove it from the list
    // if the count becomes zero
    if (--m_activations == 0)
    {
        // Remove the handle node from the list
        *m_pPrev = m_next;
        if (m_next != NULL) {
            m_next->m_pPrev = m_pPrev;
        }
        m_state = STATE_IDLE;
    }
}

std::set<const Process*> Process::m_registry;

Process::Process(Object& parent, const string& name, const delegate& delegate)
    : m_name(name), m_delegate(delegate), m_state(STATE_IDLE), m_activations(0), m_stalls(0)
{
    m_registry.insert(this);
    RegisterSampleVariable(m_stalls, parent.GetFQN() + ':' + name + ":stalls", SVC_CUMULATIVE);
    RegisterSampleVariable(m_state, parent.GetFQN() + ':' + name + ":state", SVC_LEVEL);
}

Process::~Process()
{
    m_registry.erase(this);
}

//
// Object class
//
Object::Object(const std::string& name, Clock& clock)
    : m_parent(NULL), m_name(name), m_fqn(name), m_clock(clock), m_kernel(clock.GetKernel())
{
}

Object::Object(const std::string& name, Object& parent)
    : m_parent(&parent),
      m_name(name),
      m_fqn(parent.GetFQN().empty() ? name : (parent.GetFQN() + '.' + name)),
      m_clock(parent.m_clock),
      m_kernel(m_clock.GetKernel())
{
    // Add ourself to the parent's children array
    parent.m_children.push_back(this);
}

Object::Object(const std::string& name, Object& parent, Clock& clock)
    : m_parent(&parent),
      m_name(name),
      m_fqn(parent.GetFQN().empty() ? name : (parent.GetFQN() + '.' + name)),
      m_clock(clock),
      m_kernel(clock.GetKernel())
{
    // Add ourself to the parent's children array
    parent.m_children.push_back(this);
}

Object::~Object()
{
    if (m_parent != NULL)
    {
        // Remove ourself from the parent's children array
        for (vector<Object*>::iterator p = m_parent->m_children.begin(); p != m_parent->m_children.end(); ++p)
        {
            if (*p == this)
            {
                m_parent->m_children.erase(p);
                break;
            }
        }
    }
}

void Object::OutputWrite_(const char* msg, ...) const
{
    va_list args;

    fprintf(stderr, "[%08lld:%s] o ", m_kernel.GetCycleNo(), GetFQN().c_str());
    va_start(args, msg);
    vfprintf(stderr, msg, args);
    va_end(args);
    fputc('\n', stderr);
}

void Object::DeadlockWrite_(const char* msg, ...) const
{
    va_list args;

    fprintf(stderr, "[%08lld:%s] d (%s) ", m_kernel.GetCycleNo(), GetFQN().c_str(), m_kernel.GetActiveProcess()->GetName().c_str());
    va_start(args, msg);
    vfprintf(stderr, msg, args);
    va_end(args);
    fputc('\n', stderr);
}

void Object::DebugSimWrite_(const char* msg, ...) const
{
    va_list args;

    fprintf(stderr, "[%08lld:%s] ", m_kernel.GetCycleNo(), GetFQN().c_str());
    va_start(args, msg);
    vfprintf(stderr, msg, args);
    va_end(args);
    fputc('\n', stderr);
}

//
// Kernel class
//
void Kernel::Abort()
{
    m_aborted = true;
}

// Returns the Greatest Common Denominator of a and b.
static unsigned long long gcd(unsigned long long a, unsigned long long b)
{
    // Euclid's algorithm
    while (b != 0){
        unsigned long long t = b;
        b = a % b;
        a = t;
    }
    return a;
}

// Returns the Lowest Common Multiple of a and b.
unsigned long long lcm(unsigned long long a, unsigned long long b)
{
    return (a * b / gcd(a,b));
}

Clock& Kernel::CreateClock(unsigned long frequency)
{
    // We only allow creating clocks before the simulation starts
    assert(m_cycle == 0);

    // Gotta be at least 1 MHz
    assert(frequency > 0);
    frequency = std::max(1UL, frequency);

    /*
     Calculate new master frequency:
     If we have clocks of frequency [f_1, ..., f_n], we want a frequency
     that allows every cycle time to be an integer multiple of the master
     cycle time (e.g., a 300 MHz and 400 MHz clock would create a master
     clock of 1200 MHz, where the 300 MHz clock ticks once every 4 cycles
     and the 400 MHz clock ticks once every 3 cycles).

     This is simply equalizing fractions. e.g., 1/300 and 1/400 becomes
     4/1200 and 3/1200.

     Also, see if we already have this clock.
    */
    unsigned long long master_freq = 1;
    for (std::vector<Clock*>::const_iterator p = m_clocks.begin(); p != m_clocks.end(); ++p)
    {
        if ((*p)->m_frequency == frequency)
        {
            // We already have this clock, no need to calculate anything.
            return **p;
        }

        // Find Least Common Multiplier of master_freq and this clock's frequency.
        master_freq = lcm(master_freq, (*p)->m_frequency);
    }
    master_freq = lcm(master_freq, frequency);

    if (m_master_freq != master_freq)
    {
        // The master frequency changed, update the clock periods
        m_master_freq = master_freq;
        for (std::vector<Clock*>::const_iterator p = m_clocks.begin(); p != m_clocks.end(); ++p)
        {
            assert(m_master_freq % (*p)->m_frequency == 0);
            (*p)->m_period = m_master_freq / (*p)->m_frequency;
        }
    }
    assert(m_master_freq % frequency == 0);

    m_clocks.push_back(new Clock(*this, frequency, m_master_freq / frequency));
    return *m_clocks.back();
}

RunState Kernel::Step(CycleNo cycles)
{
    try
    {
        // Time to simulate until
        const CycleNo endcycle = (cycles == INFINITE_CYCLES) ? cycles : m_cycle + cycles;

        if (m_cycle == 0)
        {
            // Update any changed storages.
            // This is just to effect the initialization writes,
            // in order to activate the initial processes.
            UpdateStorages();
        }

        // Advance time to the first clock to run.
        if (m_activeClocks != NULL)
        {
            assert(m_activeClocks->m_cycle >= m_cycle);
            m_cycle = m_activeClocks->m_cycle;
        }

        m_aborted = false;
        bool idle = false;
        while (!m_aborted && !idle && (endcycle == INFINITE_CYCLES || m_cycle < endcycle))
        {
            // We start each cycle being idle, and see if we did something this cycle
            idle = true;

            //
            // Acquire phase
            //
            m_phase = PHASE_ACQUIRE;
            for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
            {
                for (Process* process = clock->m_activeProcesses; process != NULL; process = process->m_next)
                {
                    m_process   = process;

                    // This process begins the cycle
                    // This is a purely administrative function and has no simulation effect.
                    process->OnBeginCycle();

                    // If we fail in the acquire stage, don't bother with the check and commit stages
                    Result result = process->m_delegate();
                    if (result == SUCCESS)
                    {
                        process->m_state = STATE_RUNNING;
                    }
                    else
                    {
                        assert(result == FAILED);
                        process->m_state = STATE_DEADLOCK;
                        ++process->m_stalls;
                    }
                }
            }

            //
            // Arbitrate phase
            //
            for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
            {
                for (Arbitrator* arbitrator = clock->m_activeArbitrators; arbitrator != NULL; arbitrator = arbitrator->m_next)
                {
                    arbitrator->OnArbitrate();
                    arbitrator->m_activated = false;
                }
                clock->m_activeArbitrators = NULL;
            }

            //
            // Commit phase
            //
            for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
            {
                for (Process* process = clock->m_activeProcesses; process != NULL; process = process->m_next)
                {
                    if (process->m_state != STATE_DEADLOCK)
                    {
                        m_process   = process;
                        m_phase     = PHASE_CHECK;

                        Result result = process->m_delegate();
                        if (result == SUCCESS)
                        {
                            // This process is done this cycle.
                            // This is a purely administrative function and has no simulation effect.
                            // We call this before the COMMIT phase, so that if this produces an error,
                            // we can still inspect the state that caused it.
                            process->OnEndCycle();

                            m_phase = PHASE_COMMIT;
                            result = process->m_delegate();

                            // If the CHECK succeeded, the COMMIT cannot fail
                            assert(result == SUCCESS);
                            process->m_state = STATE_RUNNING;

                            // We've done something -- we're not idle
                            idle = false;
                        }
                        else
                        {
                            // If a process has nothing to do (DELAYED) it shouldn't have been
                            // called in the first place.
                            assert(result == FAILED);
                            process->m_state = STATE_DEADLOCK;
                        }
                    }
                }
            }

            // Process the requested storage updates
            // This can activate or deactivate processes due to changes in storages
            // made by processes run in this cycle.
            if (UpdateStorages())
            {
                // We've update at least one storage
                idle = false;
            }

            if (idle)
            {
                // We haven't done anything this cycle. Check if there are clocks scheduled
                // for cycles in the future. If so, we want to still advance the simulation.
                for (Clock* clock = m_activeClocks; clock != NULL; clock = clock->m_next)
                {
                    if (clock->m_cycle > m_cycle)
                    {
                        idle = false;
                        break;
                    }
                }
            }

            if (Display::GetDisplay())
                Display::GetDisplay()->OnCycle(m_cycle);

            if (!idle)
            {
                // Advance the simulation

                // Update the clocks
                for (Clock *next, *clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = next)
                {
                    next = clock->m_next;

                    // We ran this clock, remove it from the queue
                    m_activeClocks = clock->m_next;
                    clock->m_activated = false;

                    assert(clock->m_activeArbitrators == NULL);

                    if (clock->m_activeProcesses != NULL || clock->m_activeStorages != NULL)
                    {
                        // This clock still has active components, reschedule it
                        ActivateClock(*clock);
                    }
                }

                // Advance time to first clock to run
                if (m_activeClocks != NULL)
                {
                    assert(m_activeClocks->m_cycle > m_cycle);
                    m_cycle = m_activeClocks->m_cycle;
                }
            }
        }

        // In case we overshot the end with the last update
        m_cycle = std::min(m_cycle, endcycle);

        return (m_aborted)
            ? STATE_ABORTED
            : idle ? STATE_IDLE : STATE_RUNNING;
    }
    catch (SimulationException& e)
    {
        // Add information about what component/state we were executing
        stringstream details;
        details << "While executing process " << m_process->GetName() << endl
                << "At master cycle " << m_cycle << endl;
        e.AddDetails(details.str());
        throw;
    }
}

void Kernel::ActivateClock(Clock& clock)
{
    if (!clock.m_activated)
    {
        // Calculate new activation time for clock
        clock.m_cycle = (m_cycle / clock.m_period) * clock.m_period + clock.m_period;

        // Insert clock into list based on activation time (earliest in front)
        Clock **before = &m_activeClocks, *after = m_activeClocks;
        while (after != NULL && after->m_cycle < clock.m_cycle)
        {
            before = &after->m_next;
            after  = after->m_next;
        }
        *before = &clock;
        clock.m_next = after;
        clock.m_activated = true;
    }
}

bool Kernel::UpdateStorages()
{
    bool updated = false;
    for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
    {
        for (Storage *s = clock->m_activeStorages; s != NULL; s = s->m_next)
        {
            s->Update();
            s->m_activated = false;
            updated = true;
        }
        clock->m_activeStorages = NULL;
    }
    return updated;
}

void Clock::ActivateProcess(Process& process)
{
    if (++process.m_activations == 1)
    {
        // First time this process has been activated, queue it
        process.m_next  = m_activeProcesses;
        process.m_pPrev = &m_activeProcesses;
        if (process.m_next != NULL) {
            process.m_next->m_pPrev = &process.m_next;
        }
        m_activeProcesses = &process;
        process.m_state = STATE_ACTIVE;

        m_kernel.ActivateClock(*this);
    }
}

void Kernel::SetDebugMode(int flags)
{
    m_debugMode = flags;
}

void Kernel::ToggleDebugMode(int flags)
{
    m_debugMode ^= flags;
}

Kernel::Kernel(SymbolTable& symtable, BreakPoints& breakpoints)
 : m_debugMode(0),
   m_cycle(0),
   m_symtable(symtable),
   m_breakpoints(breakpoints),
   m_phase(PHASE_COMMIT),
   m_master_freq(0),
   m_process(NULL),
   m_activeClocks(NULL)
{
    RegisterSampleVariable(m_cycle, "kernel.cycle", SVC_CUMULATIVE);
    RegisterSampleVariable(m_phase, "kernel.phase", SVC_STATE);
}

Kernel::~Kernel()
{
    for (size_t i = 0; i < m_clocks.size(); ++i)
    {
        delete m_clocks[i];
    }
}

}
<commit_msg>[mgsim] Ensure that all trace messages use the same tabs; include process names always when available.<commit_after>#include "kernel.h"
#include "storage.h"
#include "arch/dev/Display.h"
#include "sampling.h"

#include <cassert>
#include <algorithm>
#include <cstdarg>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <set>
#include <map>
#include <cstdio>

using namespace std;

namespace Simulator
{

//
// Process class
//

std::string Process::GetName() const
{
    return GetObject()->GetFQN() + ":" + m_name;
}

void Process::Deactivate()
{
    // A process can be sensitive to multiple objects, so we only remove it from the list
    // if the count becomes zero
    if (--m_activations == 0)
    {
        // Remove the handle node from the list
        *m_pPrev = m_next;
        if (m_next != NULL) {
            m_next->m_pPrev = m_pPrev;
        }
        m_state = STATE_IDLE;
    }
}

std::set<const Process*> Process::m_registry;

Process::Process(Object& parent, const string& name, const delegate& delegate)
    : m_name(name), m_delegate(delegate), m_state(STATE_IDLE), m_activations(0), m_stalls(0)
{
    m_registry.insert(this);
    RegisterSampleVariable(m_stalls, parent.GetFQN() + ':' + name + ":stalls", SVC_CUMULATIVE);
    RegisterSampleVariable(m_state, parent.GetFQN() + ':' + name + ":state", SVC_LEVEL);
}

Process::~Process()
{
    m_registry.erase(this);
}

//
// Object class
//
Object::Object(const std::string& name, Clock& clock)
    : m_parent(NULL), m_name(name), m_fqn(name), m_clock(clock), m_kernel(clock.GetKernel())
{
}

Object::Object(const std::string& name, Object& parent)
    : m_parent(&parent),
      m_name(name),
      m_fqn(parent.GetFQN().empty() ? name : (parent.GetFQN() + '.' + name)),
      m_clock(parent.m_clock),
      m_kernel(m_clock.GetKernel())
{
    // Add ourself to the parent's children array
    parent.m_children.push_back(this);
}

Object::Object(const std::string& name, Object& parent, Clock& clock)
    : m_parent(&parent),
      m_name(name),
      m_fqn(parent.GetFQN().empty() ? name : (parent.GetFQN() + '.' + name)),
      m_clock(clock),
      m_kernel(clock.GetKernel())
{
    // Add ourself to the parent's children array
    parent.m_children.push_back(this);
}

Object::~Object()
{
    if (m_parent != NULL)
    {
        // Remove ourself from the parent's children array
        for (vector<Object*>::iterator p = m_parent->m_children.begin(); p != m_parent->m_children.end(); ++p)
        {
            if (*p == this)
            {
                m_parent->m_children.erase(p);
                break;
            }
        }
    }
}

void Object::OutputWrite_(const char* msg, ...) const
{
    va_list args;

    fprintf(stderr, "[%08lld:%s]\t\to ", m_kernel.GetCycleNo(), GetFQN().c_str());
    va_start(args, msg);
    vfprintf(stderr, msg, args);
    va_end(args);
    fputc('\n', stderr);
}

void Object::DeadlockWrite_(const char* msg, ...) const
{
    va_list args;

    fprintf(stderr, "[%08lld:%s]\t(%s)\td ", m_kernel.GetCycleNo(), GetFQN().c_str(), m_kernel.GetActiveProcess()->GetName().c_str());
    va_start(args, msg);
    vfprintf(stderr, msg, args);
    va_end(args);
    fputc('\n', stderr);
}

void Object::DebugSimWrite_(const char* msg, ...) const
{
    va_list args;

    fprintf(stderr, "[%08lld:%s]\t", m_kernel.GetCycleNo(), GetFQN().c_str());
    const Process *p = m_kernel.GetActiveProcess();
    if (p)
        fprintf(stderr, "(%s)", p->GetName().c_str());
    fputc('\t', stderr);
    va_start(args, msg);
    vfprintf(stderr, msg, args);
    va_end(args);
    fputc('\n', stderr);
}

//
// Kernel class
//
void Kernel::Abort()
{
    m_aborted = true;
}

// Returns the Greatest Common Denominator of a and b.
static unsigned long long gcd(unsigned long long a, unsigned long long b)
{
    // Euclid's algorithm
    while (b != 0){
        unsigned long long t = b;
        b = a % b;
        a = t;
    }
    return a;
}

// Returns the Lowest Common Multiple of a and b.
unsigned long long lcm(unsigned long long a, unsigned long long b)
{
    return (a * b / gcd(a,b));
}

Clock& Kernel::CreateClock(unsigned long frequency)
{
    // We only allow creating clocks before the simulation starts
    assert(m_cycle == 0);

    // Gotta be at least 1 MHz
    assert(frequency > 0);
    frequency = std::max(1UL, frequency);

    /*
     Calculate new master frequency:
     If we have clocks of frequency [f_1, ..., f_n], we want a frequency
     that allows every cycle time to be an integer multiple of the master
     cycle time (e.g., a 300 MHz and 400 MHz clock would create a master
     clock of 1200 MHz, where the 300 MHz clock ticks once every 4 cycles
     and the 400 MHz clock ticks once every 3 cycles).

     This is simply equalizing fractions. e.g., 1/300 and 1/400 becomes
     4/1200 and 3/1200.

     Also, see if we already have this clock.
    */
    unsigned long long master_freq = 1;
    for (std::vector<Clock*>::const_iterator p = m_clocks.begin(); p != m_clocks.end(); ++p)
    {
        if ((*p)->m_frequency == frequency)
        {
            // We already have this clock, no need to calculate anything.
            return **p;
        }

        // Find Least Common Multiplier of master_freq and this clock's frequency.
        master_freq = lcm(master_freq, (*p)->m_frequency);
    }
    master_freq = lcm(master_freq, frequency);

    if (m_master_freq != master_freq)
    {
        // The master frequency changed, update the clock periods
        m_master_freq = master_freq;
        for (std::vector<Clock*>::const_iterator p = m_clocks.begin(); p != m_clocks.end(); ++p)
        {
            assert(m_master_freq % (*p)->m_frequency == 0);
            (*p)->m_period = m_master_freq / (*p)->m_frequency;
        }
    }
    assert(m_master_freq % frequency == 0);

    m_clocks.push_back(new Clock(*this, frequency, m_master_freq / frequency));
    return *m_clocks.back();
}

RunState Kernel::Step(CycleNo cycles)
{
    try
    {
        // Time to simulate until
        const CycleNo endcycle = (cycles == INFINITE_CYCLES) ? cycles : m_cycle + cycles;

        if (m_cycle == 0)
        {
            // Update any changed storages.
            // This is just to effect the initialization writes,
            // in order to activate the initial processes.
            UpdateStorages();
        }

        // Advance time to the first clock to run.
        if (m_activeClocks != NULL)
        {
            assert(m_activeClocks->m_cycle >= m_cycle);
            m_cycle = m_activeClocks->m_cycle;
        }

        m_aborted = false;
        bool idle = false;
        while (!m_aborted && !idle && (endcycle == INFINITE_CYCLES || m_cycle < endcycle))
        {
            // We start each cycle being idle, and see if we did something this cycle
            idle = true;

            //
            // Acquire phase
            //
            m_phase = PHASE_ACQUIRE;
            for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
            {
                for (Process* process = clock->m_activeProcesses; process != NULL; process = process->m_next)
                {
                    m_process   = process;

                    // This process begins the cycle
                    // This is a purely administrative function and has no simulation effect.
                    process->OnBeginCycle();

                    // If we fail in the acquire stage, don't bother with the check and commit stages
                    Result result = process->m_delegate();
                    if (result == SUCCESS)
                    {
                        process->m_state = STATE_RUNNING;
                    }
                    else
                    {
                        assert(result == FAILED);
                        process->m_state = STATE_DEADLOCK;
                        ++process->m_stalls;
                    }
                }
            }

            //
            // Arbitrate phase
            //
            for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
            {
                for (Arbitrator* arbitrator = clock->m_activeArbitrators; arbitrator != NULL; arbitrator = arbitrator->m_next)
                {
                    arbitrator->OnArbitrate();
                    arbitrator->m_activated = false;
                }
                clock->m_activeArbitrators = NULL;
            }

            //
            // Commit phase
            //
            for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
            {
                for (Process* process = clock->m_activeProcesses; process != NULL; process = process->m_next)
                {
                    if (process->m_state != STATE_DEADLOCK)
                    {
                        m_process   = process;
                        m_phase     = PHASE_CHECK;

                        Result result = process->m_delegate();
                        if (result == SUCCESS)
                        {
                            // This process is done this cycle.
                            // This is a purely administrative function and has no simulation effect.
                            // We call this before the COMMIT phase, so that if this produces an error,
                            // we can still inspect the state that caused it.
                            process->OnEndCycle();

                            m_phase = PHASE_COMMIT;
                            result = process->m_delegate();

                            // If the CHECK succeeded, the COMMIT cannot fail
                            assert(result == SUCCESS);
                            process->m_state = STATE_RUNNING;

                            // We've done something -- we're not idle
                            idle = false;
                        }
                        else
                        {
                            // If a process has nothing to do (DELAYED) it shouldn't have been
                            // called in the first place.
                            assert(result == FAILED);
                            process->m_state = STATE_DEADLOCK;
                        }
                    }
                }
            }

            // Process the requested storage updates
            // This can activate or deactivate processes due to changes in storages
            // made by processes run in this cycle.
            if (UpdateStorages())
            {
                // We've update at least one storage
                idle = false;
            }

            if (idle)
            {
                // We haven't done anything this cycle. Check if there are clocks scheduled
                // for cycles in the future. If so, we want to still advance the simulation.
                for (Clock* clock = m_activeClocks; clock != NULL; clock = clock->m_next)
                {
                    if (clock->m_cycle > m_cycle)
                    {
                        idle = false;
                        break;
                    }
                }
            }

            if (Display::GetDisplay())
                Display::GetDisplay()->OnCycle(m_cycle);

            if (!idle)
            {
                // Advance the simulation

                // Update the clocks
                for (Clock *next, *clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = next)
                {
                    next = clock->m_next;

                    // We ran this clock, remove it from the queue
                    m_activeClocks = clock->m_next;
                    clock->m_activated = false;

                    assert(clock->m_activeArbitrators == NULL);

                    if (clock->m_activeProcesses != NULL || clock->m_activeStorages != NULL)
                    {
                        // This clock still has active components, reschedule it
                        ActivateClock(*clock);
                    }
                }

                // Advance time to first clock to run
                if (m_activeClocks != NULL)
                {
                    assert(m_activeClocks->m_cycle > m_cycle);
                    m_cycle = m_activeClocks->m_cycle;
                }
            }
        }

        // In case we overshot the end with the last update
        m_cycle = std::min(m_cycle, endcycle);

        return (m_aborted)
            ? STATE_ABORTED
            : idle ? STATE_IDLE : STATE_RUNNING;
    }
    catch (SimulationException& e)
    {
        // Add information about what component/state we were executing
        stringstream details;
        details << "While executing process " << m_process->GetName() << endl
                << "At master cycle " << m_cycle << endl;
        e.AddDetails(details.str());
        throw;
    }
}

void Kernel::ActivateClock(Clock& clock)
{
    if (!clock.m_activated)
    {
        // Calculate new activation time for clock
        clock.m_cycle = (m_cycle / clock.m_period) * clock.m_period + clock.m_period;

        // Insert clock into list based on activation time (earliest in front)
        Clock **before = &m_activeClocks, *after = m_activeClocks;
        while (after != NULL && after->m_cycle < clock.m_cycle)
        {
            before = &after->m_next;
            after  = after->m_next;
        }
        *before = &clock;
        clock.m_next = after;
        clock.m_activated = true;
    }
}

bool Kernel::UpdateStorages()
{
    bool updated = false;
    for (Clock* clock = m_activeClocks; clock != NULL && m_cycle == clock->m_cycle; clock = clock->m_next)
    {
        for (Storage *s = clock->m_activeStorages; s != NULL; s = s->m_next)
        {
            s->Update();
            s->m_activated = false;
            updated = true;
        }
        clock->m_activeStorages = NULL;
    }
    return updated;
}

void Clock::ActivateProcess(Process& process)
{
    if (++process.m_activations == 1)
    {
        // First time this process has been activated, queue it
        process.m_next  = m_activeProcesses;
        process.m_pPrev = &m_activeProcesses;
        if (process.m_next != NULL) {
            process.m_next->m_pPrev = &process.m_next;
        }
        m_activeProcesses = &process;
        process.m_state = STATE_ACTIVE;

        m_kernel.ActivateClock(*this);
    }
}

void Kernel::SetDebugMode(int flags)
{
    m_debugMode = flags;
}

void Kernel::ToggleDebugMode(int flags)
{
    m_debugMode ^= flags;
}

Kernel::Kernel(SymbolTable& symtable, BreakPoints& breakpoints)
 : m_debugMode(0),
   m_cycle(0),
   m_symtable(symtable),
   m_breakpoints(breakpoints),
   m_phase(PHASE_COMMIT),
   m_master_freq(0),
   m_process(NULL),
   m_activeClocks(NULL)
{
    RegisterSampleVariable(m_cycle, "kernel.cycle", SVC_CUMULATIVE);
    RegisterSampleVariable(m_phase, "kernel.phase", SVC_STATE);
}

Kernel::~Kernel()
{
    for (size_t i = 0; i < m_clocks.size(); ++i)
    {
        delete m_clocks[i];
    }
}

}
<|endoftext|>


<commit_before>#include <sys/stat.h>
#include <float.h>

#include <iostream> // for standard output
#include <fstream> // for file input
#include <iomanip> // some nice printing functions
using namespace std;

#include <eigen3/Eigen/Dense> // linear algebra library
using namespace Eigen;

#include <boost/algorithm/string.hpp> // string manipulation library
#include <boost/program_options.hpp> // options parsing library
namespace po = boost::program_options;

#include "constants.h"
#include "qp-math.h"
#include "nv-math.h"
#include "printing.h"
#include "gates.h"

// random double from 0 to 1
inline double rnd(){ return std::rand()/(double)RAND_MAX; }

int main(int arg_num, const char *arg_vec[]) {

  // -----------------------------------------------------------------------------------------
  // Parse and process input options
  // -----------------------------------------------------------------------------------------

  // define parameters
  int cell_radius;
  double c13_abundance;
  string lattice_file = "lattice-cr[cell_radius]-s[seed].txt";

  uint max_cluster_size;
  int ms;
  double Bz_in_gauss;

  bool perform_scan;
  uint scan_bins;
  double f_DD;
  uint k_DD_int;
  double scan_time_in_ms;
  string larmor_file = "larmor-cr[cell_radius]-s[seed]-[ms].txt";
  string scan_file = "scan-cr[cell_radius]-s[seed]-[ms].txt";

  string output_dir;
  int seed;

  // define options
  po::options_description options("allowed options", 90);
  options.add_options()
    ("help,h", "produce help message")
    ("cell_radius", po::value<int>(&cell_radius)->default_value(6),
     "number of unit cells to simulate out from the NV center (along cell axes)")
    ("c13_abundance", po::value<double>(&c13_abundance)->default_value(0.0107,"0.0107"),
     "relative isotopic abundance of C-13")
    ("lattice_file", po::value<string>(&lattice_file),
     "specify file defining system configuration")

    ("max_cluster_size", po::value<uint>(&max_cluster_size)->default_value(6),
     "maximum allowable size of C-13 clusters")
    ("ms", po::value<int>(&ms)->default_value(1),
     "NV center spin state used with |0> for an effective two-level system (must be +/-1)")
    ("Bz", po::value<double>(&Bz_in_gauss)->default_value(140.1,"140.1"),
     "strength of static magnetic field along the NV axis (in gauss)")

    ("scan", po::value<bool>(&perform_scan)->default_value(true),
     "perform coherence scan of effective larmor frequencies?")
    ("scan_bins", po::value<uint>(&scan_bins)->default_value(200),
     "number of bins in coherence scanning range")
    ("f_DD", po::value<double>(&f_DD)->default_value(0.06,"0.06"),
     "magnitude of fourier component used in coherence scanning")
    ("k_DD", po::value<uint>(&k_DD_int)->default_value(1),
     "resonance harmonic used in coherence scanning (must be 1 or 3)")
    ("scan_time", po::value<double>(&scan_time_in_ms)->default_value(1,"1"),
     "time for each coherence measurement (in milliseconds)")

    ("output_dir", po::value<string>(&output_dir)->default_value("./data"),
     "directory for storing data")
    ("seed", po::value<int>(&seed)->default_value(1),
     "seed for random number generator (must be >=1)")
    ;

  // collect inputs
  po::variables_map inputs;
  po::store(parse_command_line(arg_num, arg_vec, options), inputs);
  po::notify(inputs);

  // if requested, print help text
  if(inputs.count("help")){
    cout << options;
    return 0;
  }

  // print summary of inputs
  if(arg_num > 1){
    printf("------------------------------------------------------------------\n");
    printf("running %s with parameters:\n", arg_vec[0]);
    for(int i = 1; i < arg_num; i++) {
      if(arg_vec[i][0] == '-') printf("\n");
      printf("%s ", arg_vec[i]);
    }
    printf("\n------------------------------------------------------------------\n\n");
  }

  bool set_cell_radius = !inputs["cell_radius"].defaulted();
  bool set_c13_abundance = !inputs["c13_abundance"].defaulted();
  bool input_lattice = inputs.count("lattice_file");

  // run a sanity check on inputs
  assert(cell_radius > 0);
  assert(c13_abundance >= 0 && c13_abundance <= 1);

  assert(ms == 1 || ms == -1);
  assert(Bz_in_gauss >= 0);

  if(perform_scan){
    assert(scan_bins > 0);
    assert((f_DD > 0) && (f_DD < 1));
    assert((k_DD_int == 1) || (k_DD_int == 3));
    assert(scan_time_in_ms > 0);
  }

  assert(!(input_lattice && set_cell_radius));
  assert(!(input_lattice && set_c13_abundance));

  assert(seed > 0);

  string lattice_path;
  if(input_lattice){
    lattice_path = lattice_file;
    // check that the given input file exists
    if(access(lattice_path.c_str(),F_OK) == -1){
      printf("file does not exist: %s\n",lattice_file.c_str());
      return 1;
    }
  } else{ // if !input_lattice
    boost::replace_all(lattice_file, "[cell_radius]", to_string(cell_radius));
    boost::replace_all(lattice_file, "[seed]", to_string(seed));
    lattice_path = output_dir+"/"+lattice_file;
  }

  printf("total number of lattice sites: %d\n", int(pow(2*cell_radius,3)*cell_sites.size()));

  boost::replace_all(larmor_file, "[cell_radius]", to_string(cell_radius));
  boost::replace_all(larmor_file, "[seed]", to_string(seed));
  boost::replace_all(larmor_file, "[ms]", (ms > 0)?"up":"dn");
  string larmor_path = output_dir+"/"+larmor_file;

  boost::replace_all(scan_file, "[cell_radius]", to_string(cell_radius));
  boost::replace_all(scan_file, "[seed]", to_string(seed));
  boost::replace_all(scan_file, "[ms]", (ms > 0)?"up":"dn");
  string scan_path = output_dir+"/"+scan_file;

  // set variables based on iputs
  double Bz = Bz_in_gauss*gauss;
  harmonic k_DD;
  if(k_DD_int == 1) k_DD = first;
  if(k_DD_int == 3) k_DD = third;
  double scan_time = scan_time_in_ms*1e-3;

  srand(seed); // initialize random number generator
  mkdir(output_dir.c_str(),0777); // create data directory

  // -----------------------------------------------------------------------------------------
  // Construct spin lattice
  // -----------------------------------------------------------------------------------------

  // vector of C-13 nuclei
  vector<spin> nuclei;

  if(!input_lattice){

    // set positions of C-13 nuclei at lattice sites
    Vector3d cell_pos; // position of unit cell indexed by i,j,k
    for(int i = -cell_radius; i < cell_radius; i++){ // loop over all unit cell indices
      cell_pos(0) = i;
      for(int j = -cell_radius; j < cell_radius; j++){
        cell_pos(1) = j;
        for(int k = -cell_radius; k < cell_radius; k++){
          cell_pos(2) = k;
          for(uint ls = 0; ls < cell_sites.size(); ls++){ // loop over sites in unit cell
            if(rnd() <= c13_abundance){ // if we pass a check for C-13 isotopic abundance
              nuclei.push_back(spin(cell_pos+cell_sites.at(ls),gC13,s_vec));
            }
          }
        }
      }
    }

    // remove any C-13 atoms at the NV lattice sites
    nuclei.erase(remove(nuclei.begin(), nuclei.end(), spin(n.pos,gC13,s_vec)),
                 nuclei.end());
    nuclei.erase(remove(nuclei.begin(), nuclei.end(), spin(e(ms).pos,gC13,s_vec)),
                 nuclei.end());

    // write cell radius and C-13 positions to file
    ofstream lattice(lattice_path);
    lattice << "# cell_radius: " << cell_radius << endl;
    for(uint n = 0; n < nuclei.size(); n++){
      lattice << nuclei.at(n).pos(0) << ' '
             << nuclei.at(n).pos(1) << ' '
             << nuclei.at(n).pos(2) << endl;
    }
    lattice.close();

  } else { // if input_lattice

    string line;
    ifstream lattice(lattice_path);

    // get cell_radius
    getline(lattice,line,' ');
    getline(lattice,line,' ');
    getline(lattice,line);
    cell_radius = stoi(line);

    // get C-13 positions
    double x,y,z;
    while(getline(lattice,line,' ')){
      x = stod(line);
      getline(lattice,line,' ');
      y = stod(line);
      getline(lattice,line);
      z = stod(line);
      nuclei.push_back(spin((Vector3d() << x,y,z).finished(),gC13,s_vec));
    }
    lattice.close();

  }

  // assert that no C-13 spins lie at the NV lattice sites
  if(in_vector(spin(n.pos,gC13,s_vec),nuclei)
     || in_vector(spin(e(ms).pos,gC13,s_vec),nuclei)){
    printf("we have a C-13 nucleus at one of the NV lattice sites!\n");
    return 2;
  }

  // -----------------------------------------------------------------------------------------
  // Cluster C-13 nuclei
  // -----------------------------------------------------------------------------------------

  double cluster_coupling_guess = 100;
  double dcc_cutoff = 1e-5;

  // get cluster_coupling for which the largest cluster size is >= max_cluster_size
  double cluster_coupling = find_target_coupling(nuclei,max_cluster_size,
                                                 cluster_coupling_guess,dcc_cutoff);
  vector<vector<spin>> clusters = get_clusters(nuclei,cluster_coupling);

  // if largest cluster size > max_cluster_size,
  //   which can occur because it is impossible to exactly match max_cluster_size,
  //   find largest cluster_coupling for which the largest cluster size is < max_cluster_size
  if(largest_cluster_size(clusters) > max_cluster_size){
    int cluster_size_target
      = largest_cluster_size(get_clusters(nuclei,cluster_coupling+dcc_cutoff));
    cluster_coupling = find_target_coupling(nuclei,cluster_size_target,
                                            cluster_coupling,dcc_cutoff);
    clusters = get_clusters(nuclei,cluster_coupling);
  }

  printf("\n");
  printf("%d nuclei grouped into %d clusters\n",nuclei.size(),clusters.size());
  printf("largest cluster size: %d\n",largest_cluster_size(clusters));
  printf("cluster coupling factor: %g Hz\n\n",cluster_coupling);
  printf("\n");

  // -----------------------------------------------------------------------------------------
  // Coherence scan
  // -----------------------------------------------------------------------------------------

  if(perform_scan){

    // idenfy effictive larmor frequencies and NV coupling strengths
    VectorXd w_larmor = VectorXd::Zero(nuclei.size());
    VectorXd A_perp = VectorXd::Zero(nuclei.size());

    double w_max = 0, w_min = DBL_MAX;
    for(uint n = 0; n < nuclei.size(); n++){
      Vector3d A_n = A(nuclei.at(n),ms);
      w_larmor(n) = effective_larmor(nuclei.at(n),Bz*zhat,A_n,ms);
      A_perp(n) = (A_n-dot(A_n,zhat)*zhat).norm();

      if(w_larmor(n) < w_min) w_min = w_larmor(n);
      if(w_larmor(n) > w_max) w_max = w_larmor(n);
    }

    ofstream larmor(larmor_path);
    larmor << "# f_DD: " << f_DD << endl;
    larmor << "# k_DD: " << k_DD_int << endl;
    larmor << "# w A_perp" << endl;
    for(uint n = 0; n < nuclei.size(); n++){
      larmor << w_larmor(n) << " " << A_perp(n) << endl;
    }
    larmor.close();

    // perform coherence scan
    printf("beginning coherence scan\n");
    VectorXd w_scan = VectorXd::Zero(scan_bins);
    VectorXd coherence = VectorXd::Zero(scan_bins);

    double w_range = w_max - w_min;
    double w_start = w_min - w_range/10;
    double w_end = w_max + w_range/10;
    for(uint i = 0; i < scan_bins; i++){
      w_scan(i) = w_start + i*(w_end-w_start)/scan_bins;
      coherence(i) =
        coherence_measurement(ms, clusters, w_scan(i), k_DD, f_DD, Bz, scan_time);
      printf("(%d/%d) %g %g\n",i+1,scan_bins,w_scan(i),coherence(i));
    }

    ofstream scan(scan_path);
    scan << "# f_DD: " << f_DD << endl;
    scan << "# k_DD: " << k_DD_int << endl;
    scan << "# w L" << endl;
    for(uint i = 0; i < scan_bins; i++){
      scan << w_scan(i) << " " << coherence(i) << endl;
    }
    scan.close();
  }

}

<commit_msg>changed output formatting<commit_after>#include <sys/stat.h>
#include <float.h>

#include <iostream> // for standard output
#include <fstream> // for file input
#include <iomanip> // some nice printing functions
using namespace std;

#include <eigen3/Eigen/Dense> // linear algebra library
using namespace Eigen;

#include <boost/algorithm/string.hpp> // string manipulation library
#include <boost/program_options.hpp> // options parsing library
namespace po = boost::program_options;

#include "constants.h"
#include "qp-math.h"
#include "nv-math.h"
#include "printing.h"
#include "gates.h"

// random double from 0 to 1
inline double rnd(){ return std::rand()/(double)RAND_MAX; }

int main(int arg_num, const char *arg_vec[]) {

  // -----------------------------------------------------------------------------------------
  // Parse and process input options
  // -----------------------------------------------------------------------------------------

  // define parameters
  int cell_radius;
  double c13_abundance;
  string lattice_file = "lattice-cr[cell_radius]-s[seed].txt";

  int max_cluster_size;
  int ms;
  double Bz_in_gauss;

  bool perform_scan;
  int scan_bins;
  double f_DD;
  uint k_DD_int;
  double scan_time_in_ms;
  string larmor_file = "larmor-cr[cell_radius]-s[seed]-[ms].txt";
  string scan_file = "scan-cr[cell_radius]-s[seed]-[ms].txt";

  string output_dir;
  int seed;

  // define options
  po::options_description options("allowed options", 95);
  options.add_options()
    ("help,h", "produce help message")
    ("cell_radius", po::value<int>(&cell_radius)->default_value(6),
     "number of unit cells to simulate out from the NV center (along cell axes)")
    ("c13_abundance", po::value<double>(&c13_abundance)->default_value(0.0107,"0.0107"),
     "relative isotopic abundance of C-13")
    ("lattice_file", po::value<string>(&lattice_file),
     "specify file defining system configuration")

    ("max_cluster_size", po::value<int>(&max_cluster_size)->default_value(6),
     "maximum allowable size of C-13 clusters")
    ("ms", po::value<int>(&ms)->default_value(1),
     "NV center spin state used with |0> for an effective two-level system (+/-1)")
    ("Bz", po::value<double>(&Bz_in_gauss)->default_value(140.1,"140.1"),
     "strength of static magnetic field along the NV axis (in gauss)")

    ("scan", po::value<bool>(&perform_scan)->default_value(false),
     "perform coherence scan of effective larmor frequencies?")
    ("scan_bins", po::value<int>(&scan_bins)->default_value(200),
     "number of bins in coherence scanning range")
    ("f_DD", po::value<double>(&f_DD)->default_value(0.06,"0.06"),
     "magnitude of fourier component used in coherence scanning")
    ("k_DD", po::value<uint>(&k_DD_int)->default_value(1),
     "resonance harmonic used in coherence scanning (1 or 3)")
    ("scan_time", po::value<double>(&scan_time_in_ms)->default_value(1),
     "time for each coherence measurement (in milliseconds)")

    ("output_dir", po::value<string>(&output_dir)->default_value("./data"),
     "directory for storing data")
    ("seed", po::value<int>(&seed)->default_value(1),
     "seed for random number generator (>=1)")
    ;

  // collect inputs
  po::variables_map inputs;
  po::store(parse_command_line(arg_num, arg_vec, options), inputs);
  po::notify(inputs);

  // if requested, print help text
  if(inputs.count("help")){
    cout << options;
    return 0;
  }

  // print summary of inputs
  if(arg_num > 1){
    cout << "------------------------------------------------------------------" << endl;
    cout << "running " << arg_vec[0] << " with parameters:" << endl;
    for(int i = 1; i < arg_num; i++) {
      if(arg_vec[i][0] == '-') cout << endl;
      cout << arg_vec[i] << " ";
    }
    cout << endl;
    cout << "------------------------------------------------------------------" << endl;
    cout << endl;
  }

  bool set_cell_radius = !inputs["cell_radius"].defaulted();
  bool set_c13_abundance = !inputs["c13_abundance"].defaulted();
  bool input_lattice = inputs.count("lattice_file");

  // run a sanity check on inputs
  assert(cell_radius > 0);
  assert(c13_abundance >= 0 && c13_abundance <= 1);
  assert(!(input_lattice && set_cell_radius));
  assert(!(input_lattice && set_c13_abundance));

  assert(max_cluster_size > 0);
  assert(ms == 1 || ms == -1);
  assert(Bz_in_gauss >= 0);

  if(perform_scan){
    assert(scan_bins > 0);
    assert((f_DD > 0) && (f_DD < 1));
    assert((k_DD_int == 1) || (k_DD_int == 3));
    assert(scan_time_in_ms > 0);
  }

  assert(seed > 0);

  string lattice_path;
  if(input_lattice){
    lattice_path = lattice_file;
    // check that the given input file exists
    if(access(lattice_path.c_str(),F_OK) == -1){
      cout << "file does not exist: " << lattice_file << endl;
      return 1;
    }
  } else{ // if !input_lattice
    boost::replace_all(lattice_file, "[cell_radius]", to_string(cell_radius));
    boost::replace_all(lattice_file, "[seed]", to_string(seed));
    lattice_path = output_dir+"/"+lattice_file;
  }

  cout << "total number of lattice sites: " << int(pow(2*cell_radius,3)*cell_sites.size());
  cout << endl << endl;

  boost::replace_all(larmor_file, "[cell_radius]", to_string(cell_radius));
  boost::replace_all(larmor_file, "[seed]", to_string(seed));
  boost::replace_all(larmor_file, "[ms]", (ms > 0)?"up":"dn");
  string larmor_path = output_dir+"/"+larmor_file;

  boost::replace_all(scan_file, "[cell_radius]", to_string(cell_radius));
  boost::replace_all(scan_file, "[seed]", to_string(seed));
  boost::replace_all(scan_file, "[ms]", (ms > 0)?"up":"dn");
  string scan_path = output_dir+"/"+scan_file;

  // set variables based on iputs
  double Bz = Bz_in_gauss*gauss;
  harmonic k_DD;
  if(k_DD_int == 1) k_DD = first;
  if(k_DD_int == 3) k_DD = third;
  double scan_time = scan_time_in_ms*1e-3;

  srand(seed); // initialize random number generator
  mkdir(output_dir.c_str(),0777); // create data directory

  // -----------------------------------------------------------------------------------------
  // Construct spin lattice
  // -----------------------------------------------------------------------------------------

  // vector of C-13 nuclei
  vector<spin> nuclei;

  if(!input_lattice){

    // set positions of C-13 nuclei at lattice sites
    Vector3d cell_pos; // position of unit cell indexed by i,j,k
    for(int i = -cell_radius; i < cell_radius; i++){ // loop over all unit cell indices
      cell_pos(0) = i;
      for(int j = -cell_radius; j < cell_radius; j++){
        cell_pos(1) = j;
        for(int k = -cell_radius; k < cell_radius; k++){
          cell_pos(2) = k;
          for(uint ls = 0; ls < cell_sites.size(); ls++){ // loop over sites in unit cell
            if(rnd() <= c13_abundance){ // if we pass a check for C-13 isotopic abundance
              nuclei.push_back(spin(cell_pos+cell_sites.at(ls),gC13,s_vec));
            }
          }
        }
      }
    }

    // remove any C-13 atoms at the NV lattice sites
    nuclei.erase(remove(nuclei.begin(), nuclei.end(), spin(n.pos,gC13,s_vec)),
                 nuclei.end());
    nuclei.erase(remove(nuclei.begin(), nuclei.end(), spin(e(ms).pos,gC13,s_vec)),
                 nuclei.end());

    // write cell radius and C-13 positions to file
    ofstream lattice(lattice_path);
    lattice << "# cell_radius: " << cell_radius << endl;
    for(uint n = 0; n < nuclei.size(); n++){
      lattice << nuclei.at(n).pos(0) << ' '
             << nuclei.at(n).pos(1) << ' '
             << nuclei.at(n).pos(2) << endl;
    }
    lattice.close();

  } else { // if input_lattice

    string line;
    ifstream lattice(lattice_path);

    // get cell_radius
    getline(lattice,line,' ');
    getline(lattice,line,' ');
    getline(lattice,line);
    cell_radius = stoi(line);

    // get C-13 positions
    double x,y,z;
    while(getline(lattice,line,' ')){
      x = stod(line);
      getline(lattice,line,' ');
      y = stod(line);
      getline(lattice,line);
      z = stod(line);
      nuclei.push_back(spin((Vector3d() << x,y,z).finished(),gC13,s_vec));
    }
    lattice.close();

  }

  // assert that no C-13 spins lie at the NV lattice sites
  if(in_vector(spin(n.pos,gC13,s_vec),nuclei)
     || in_vector(spin(e(ms).pos,gC13,s_vec),nuclei)){
    cout << "we have a C-13 nucleus at one of the NV lattice sites!" << endl;
    return 2;
  }

  // -----------------------------------------------------------------------------------------
  // Cluster C-13 nuclei
  // -----------------------------------------------------------------------------------------

  double cluster_coupling_guess = 100;
  double dcc_cutoff = 1e-5;

  // get cluster_coupling for which the largest cluster size is >= max_cluster_size
  double cluster_coupling = find_target_coupling(nuclei,max_cluster_size,
                                                 cluster_coupling_guess,dcc_cutoff);
  vector<vector<spin>> clusters = get_clusters(nuclei,cluster_coupling);

  // if largest cluster size > max_cluster_size,
  //   which can occur because it is impossible to exactly match max_cluster_size,
  //   find largest cluster_coupling for which the largest cluster size is < max_cluster_size
  if(largest_cluster_size(clusters) > max_cluster_size){
    int cluster_size_target
      = largest_cluster_size(get_clusters(nuclei,cluster_coupling+dcc_cutoff));
    cluster_coupling = find_target_coupling(nuclei,cluster_size_target,
                                            cluster_coupling,dcc_cutoff);
    clusters = get_clusters(nuclei,cluster_coupling);
  }

  cout << nuclei.size() << " nuclei grouped into " << clusters.size() << " clusters" << endl;
  cout << "largest cluster size: " << largest_cluster_size(clusters) << endl;
  cout << "cluster coupling factor: " << cluster_coupling << " Hz" << endl;
  cout << endl;

  // -----------------------------------------------------------------------------------------
  // Coherence scan
  // -----------------------------------------------------------------------------------------

  if(perform_scan){

    // idenfy effictive larmor frequencies and NV coupling strengths
    VectorXd w_larmor = VectorXd::Zero(nuclei.size());
    VectorXd A_perp = VectorXd::Zero(nuclei.size());

    double w_max = 0, w_min = DBL_MAX;
    for(uint n = 0; n < nuclei.size(); n++){
      Vector3d A_n = A(nuclei.at(n),ms);
      w_larmor(n) = effective_larmor(nuclei.at(n),Bz*zhat,A_n,ms);
      A_perp(n) = (A_n-dot(A_n,zhat)*zhat).norm();

      if(w_larmor(n) < w_min) w_min = w_larmor(n);
      if(w_larmor(n) > w_max) w_max = w_larmor(n);
    }

    ofstream larmor(larmor_path);
    larmor << "# f_DD: " << f_DD << endl;
    larmor << "# k_DD: " << k_DD_int << endl;
    larmor << "# w A_perp" << endl;
    for(uint n = 0; n < nuclei.size(); n++){
      larmor << w_larmor(n) << " " << A_perp(n) << endl;
    }
    larmor.close();

    // perform coherence scan
    cout << "beginning coherence scan" << endl;
    VectorXd w_scan = VectorXd::Zero(scan_bins);
    VectorXd coherence = VectorXd::Zero(scan_bins);

    double w_range = w_max - w_min;
    double w_start = w_min - w_range/10;
    double w_end = w_max + w_range/10;
    for(uint i = 0; i < scan_bins; i++){
      w_scan(i) = w_start + i*(w_end-w_start)/scan_bins;
      coherence(i) =
        coherence_measurement(ms, clusters, w_scan(i), k_DD, f_DD, Bz, scan_time);
      cout << "(" << i+1 << "/" << scan_bins << ") "
           << w_scan(i) << " " << coherence(i) << endl;
    }

    ofstream scan(scan_path);
    scan << "# f_DD: " << f_DD << endl;
    scan << "# k_DD: " << k_DD_int << endl;
    scan << "# w L" << endl;
    for(uint i = 0; i < scan_bins; i++){
      scan << w_scan(i) << " " << coherence(i) << endl;
    }
    scan.close();

  }

}

<|endoftext|>


<commit_before>//===-- cc1_main.cpp - Clang CC1 Driver -----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1 functionality, which implements the
// core compiler functionality along with a number of additional tools for
// demonstration and testing purposes.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/CC1Options.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/OptTable.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
#include <cstdio>
using namespace clang;

//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//

void LLVMErrorHandler(void *UserData, const std::string &Message) {
  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
  using namespace clang::frontend;

  switch (CI.getFrontendOpts().ProgramAction) {
  default:
    llvm_unreachable("Invalid program action!");

  case ASTDump:                return new ASTDumpAction();
  case ASTPrint:               return new ASTPrintAction();
  case ASTPrintXML:            return new ASTPrintXMLAction();
  case ASTView:                return new ASTViewAction();
  case DumpRawTokens:          return new DumpRawTokensAction();
  case DumpRecordLayouts:      return new DumpRecordAction();
  case DumpTokens:             return new DumpTokensAction();
  case EmitAssembly:           return new EmitAssemblyAction();
  case EmitBC:                 return new EmitBCAction();
  case EmitHTML:               return new HTMLPrintAction();
  case EmitLLVM:               return new EmitLLVMAction();
  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
  case EmitObj:                return new EmitObjAction();
  case FixIt:                  return new FixItAction();
  case GeneratePCH:            return new GeneratePCHAction();
  case GeneratePTH:            return new GeneratePTHAction();
  case InheritanceView:        return new InheritanceViewAction();
  case ParseNoop:              return new ParseOnlyAction();
  case ParsePrintCallbacks:    return new PrintParseAction();
  case ParseSyntaxOnly:        return new SyntaxOnlyAction();

  case PluginAction: {
    if (CI.getFrontendOpts().ActionName == "help") {
      llvm::errs() << "clang -cc1 plugins:\n";
      for (FrontendPluginRegistry::iterator it =
             FrontendPluginRegistry::begin(),
             ie = FrontendPluginRegistry::end();
           it != ie; ++it)
        llvm::errs() << "  " << it->getName() << " - " << it->getDesc() << "\n";
      return 0;
    }

    for (FrontendPluginRegistry::iterator it =
           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
         it != ie; ++it) {
      if (it->getName() == CI.getFrontendOpts().ActionName)
        return it->instantiate();
    }

    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
      << CI.getFrontendOpts().ActionName;
    return 0;
  }

  case PrintDeclContext:       return new DeclContextPrintAction();
  case PrintPreprocessedInput: return new PrintPreprocessedAction();
  case RewriteMacros:          return new RewriteMacrosAction();
  case RewriteObjC:            return new RewriteObjCAction();
  case RewriteTest:            return new RewriteTestAction();
  case RunAnalysis:            return new AnalysisAction();
  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
  }
}

static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
  // Create the underlying action.
  FrontendAction *Act = CreateFrontendBaseAction(CI);
  if (!Act)
    return 0;

  // If there are any AST files to merge, create a frontend action
  // adaptor to perform the merge.
  if (!CI.getFrontendOpts().ASTMergeFiles.empty())
    Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
                             CI.getFrontendOpts().ASTMergeFiles.size());

  return Act;
}

// FIXME: Define the need for this testing away.
static int cc1_test(Diagnostic &Diags,
                    const char **ArgBegin, const char **ArgEnd) {
  using namespace clang::driver;

  llvm::errs() << "cc1 argv:";
  for (const char **i = ArgBegin; i != ArgEnd; ++i)
    llvm::errs() << " \"" << *i << '"';
  llvm::errs() << "\n";

  // Parse the arguments.
  OptTable *Opts = createCC1OptTable();
  unsigned MissingArgIndex, MissingArgCount;
  InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd,
                                       MissingArgIndex, MissingArgCount);

  // Check for missing argument error.
  if (MissingArgCount)
    Diags.Report(clang::diag::err_drv_missing_argument)
      << Args->getArgString(MissingArgIndex) << MissingArgCount;

  // Dump the parsed arguments.
  llvm::errs() << "cc1 parsed options:\n";
  for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
       it != ie; ++it)
    (*it)->dump();

  // Create a compiler invocation.
  llvm::errs() << "cc1 creating invocation.\n";
  CompilerInvocation Invocation;
  CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags);

  // Convert the invocation back to argument strings.
  std::vector<std::string> InvocationArgs;
  Invocation.toArgs(InvocationArgs);

  // Dump the converted arguments.
  llvm::SmallVector<const char*, 32> Invocation2Args;
  llvm::errs() << "invocation argv :";
  for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) {
    Invocation2Args.push_back(InvocationArgs[i].c_str());
    llvm::errs() << " \"" << InvocationArgs[i] << '"';
  }
  llvm::errs() << "\n";

  // Convert those arguments to another invocation, and check that we got the
  // same thing.
  CompilerInvocation Invocation2;
  CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
                                     Invocation2Args.end(), Diags);

  // FIXME: Implement CompilerInvocation comparison.
  if (true) {
    //llvm::errs() << "warning: Invocations differ!\n";

    std::vector<std::string> Invocation2Args;
    Invocation2.toArgs(Invocation2Args);
    llvm::errs() << "invocation2 argv:";
    for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i)
      llvm::errs() << " \"" << Invocation2Args[i] << '"';
    llvm::errs() << "\n";
  }

  return 0;
}

int cc1_main(const char **ArgBegin, const char **ArgEnd,
             const char *Argv0, void *MainAddr) {
  CompilerInstance Clang;

  Clang.setLLVMContext(new llvm::LLVMContext);

  // Run clang -cc1 test.
  if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
    TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
    Diagnostic Diags(&DiagClient);
    return cc1_test(Diags, ArgBegin + 1, ArgEnd);
  }

  // Initialize targets first, so that --version shows registered targets.
  llvm::InitializeAllTargets();
  llvm::InitializeAllAsmPrinters();

  // Buffer diagnostics from argument parsing so that we can output them using a
  // well formed diagnostic object.
  TextDiagnosticBuffer DiagsBuffer;
  Diagnostic Diags(&DiagsBuffer);
  CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd,
                                     Diags);

  // Infer the builtin include path if unspecified.
  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
      Clang.getHeaderSearchOpts().ResourceDir.empty())
    Clang.getHeaderSearchOpts().ResourceDir =
      CompilerInvocation::GetResourcesPath(Argv0, MainAddr);

  // Honor -help.
  if (Clang.getFrontendOpts().ShowHelp) {
    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1",
                    "LLVM 'Clang' Compiler: http://clang.llvm.org");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Clang.getFrontendOpts().ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Create the actual diagnostics engine.
  Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
  if (!Clang.hasDiagnostics())
    return 1;

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  llvm::llvm_install_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang.getDiagnostics()));

  DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics());

  // Load any requested plugins.
  for (unsigned i = 0,
         e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) {
    const std::string &Path = Clang.getFrontendOpts().Plugins[i];
    std::string Error;
    if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
      Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
  }

  // If there were errors in processing arguments, don't do anything else.
  bool Success = false;
  if (!Clang.getDiagnostics().getNumErrors()) {
    // Create and execute the frontend action.
    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
    if (Act)
      Success = Clang.ExecuteAction(*Act);
  }

  // Managed static deconstruction. Useful for making things like
  // -time-passes usable.
  llvm::llvm_shutdown();

  return !Success;
}
<commit_msg>Remove unused includes.<commit_after>//===-- cc1_main.cpp - Clang CC1 Driver -----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1 functionality, which implements the
// core compiler functionality along with a number of additional tools for
// demonstration and testing purposes.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/CC1Options.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/OptTable.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Target/TargetSelect.h"
#include <cstdio>
using namespace clang;

//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//

void LLVMErrorHandler(void *UserData, const std::string &Message) {
  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
  using namespace clang::frontend;

  switch (CI.getFrontendOpts().ProgramAction) {
  default:
    llvm_unreachable("Invalid program action!");

  case ASTDump:                return new ASTDumpAction();
  case ASTPrint:               return new ASTPrintAction();
  case ASTPrintXML:            return new ASTPrintXMLAction();
  case ASTView:                return new ASTViewAction();
  case DumpRawTokens:          return new DumpRawTokensAction();
  case DumpRecordLayouts:      return new DumpRecordAction();
  case DumpTokens:             return new DumpTokensAction();
  case EmitAssembly:           return new EmitAssemblyAction();
  case EmitBC:                 return new EmitBCAction();
  case EmitHTML:               return new HTMLPrintAction();
  case EmitLLVM:               return new EmitLLVMAction();
  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
  case EmitObj:                return new EmitObjAction();
  case FixIt:                  return new FixItAction();
  case GeneratePCH:            return new GeneratePCHAction();
  case GeneratePTH:            return new GeneratePTHAction();
  case InheritanceView:        return new InheritanceViewAction();
  case ParseNoop:              return new ParseOnlyAction();
  case ParsePrintCallbacks:    return new PrintParseAction();
  case ParseSyntaxOnly:        return new SyntaxOnlyAction();

  case PluginAction: {
    if (CI.getFrontendOpts().ActionName == "help") {
      llvm::errs() << "clang -cc1 plugins:\n";
      for (FrontendPluginRegistry::iterator it =
             FrontendPluginRegistry::begin(),
             ie = FrontendPluginRegistry::end();
           it != ie; ++it)
        llvm::errs() << "  " << it->getName() << " - " << it->getDesc() << "\n";
      return 0;
    }

    for (FrontendPluginRegistry::iterator it =
           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
         it != ie; ++it) {
      if (it->getName() == CI.getFrontendOpts().ActionName)
        return it->instantiate();
    }

    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
      << CI.getFrontendOpts().ActionName;
    return 0;
  }

  case PrintDeclContext:       return new DeclContextPrintAction();
  case PrintPreprocessedInput: return new PrintPreprocessedAction();
  case RewriteMacros:          return new RewriteMacrosAction();
  case RewriteObjC:            return new RewriteObjCAction();
  case RewriteTest:            return new RewriteTestAction();
  case RunAnalysis:            return new AnalysisAction();
  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
  }
}

static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
  // Create the underlying action.
  FrontendAction *Act = CreateFrontendBaseAction(CI);
  if (!Act)
    return 0;

  // If there are any AST files to merge, create a frontend action
  // adaptor to perform the merge.
  if (!CI.getFrontendOpts().ASTMergeFiles.empty())
    Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
                             CI.getFrontendOpts().ASTMergeFiles.size());

  return Act;
}

// FIXME: Define the need for this testing away.
static int cc1_test(Diagnostic &Diags,
                    const char **ArgBegin, const char **ArgEnd) {
  using namespace clang::driver;

  llvm::errs() << "cc1 argv:";
  for (const char **i = ArgBegin; i != ArgEnd; ++i)
    llvm::errs() << " \"" << *i << '"';
  llvm::errs() << "\n";

  // Parse the arguments.
  OptTable *Opts = createCC1OptTable();
  unsigned MissingArgIndex, MissingArgCount;
  InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd,
                                       MissingArgIndex, MissingArgCount);

  // Check for missing argument error.
  if (MissingArgCount)
    Diags.Report(clang::diag::err_drv_missing_argument)
      << Args->getArgString(MissingArgIndex) << MissingArgCount;

  // Dump the parsed arguments.
  llvm::errs() << "cc1 parsed options:\n";
  for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
       it != ie; ++it)
    (*it)->dump();

  // Create a compiler invocation.
  llvm::errs() << "cc1 creating invocation.\n";
  CompilerInvocation Invocation;
  CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags);

  // Convert the invocation back to argument strings.
  std::vector<std::string> InvocationArgs;
  Invocation.toArgs(InvocationArgs);

  // Dump the converted arguments.
  llvm::SmallVector<const char*, 32> Invocation2Args;
  llvm::errs() << "invocation argv :";
  for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) {
    Invocation2Args.push_back(InvocationArgs[i].c_str());
    llvm::errs() << " \"" << InvocationArgs[i] << '"';
  }
  llvm::errs() << "\n";

  // Convert those arguments to another invocation, and check that we got the
  // same thing.
  CompilerInvocation Invocation2;
  CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
                                     Invocation2Args.end(), Diags);

  // FIXME: Implement CompilerInvocation comparison.
  if (true) {
    //llvm::errs() << "warning: Invocations differ!\n";

    std::vector<std::string> Invocation2Args;
    Invocation2.toArgs(Invocation2Args);
    llvm::errs() << "invocation2 argv:";
    for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i)
      llvm::errs() << " \"" << Invocation2Args[i] << '"';
    llvm::errs() << "\n";
  }

  return 0;
}

int cc1_main(const char **ArgBegin, const char **ArgEnd,
             const char *Argv0, void *MainAddr) {
  CompilerInstance Clang;

  Clang.setLLVMContext(new llvm::LLVMContext);

  // Run clang -cc1 test.
  if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
    TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
    Diagnostic Diags(&DiagClient);
    return cc1_test(Diags, ArgBegin + 1, ArgEnd);
  }

  // Initialize targets first, so that --version shows registered targets.
  llvm::InitializeAllTargets();
  llvm::InitializeAllAsmPrinters();

  // Buffer diagnostics from argument parsing so that we can output them using a
  // well formed diagnostic object.
  TextDiagnosticBuffer DiagsBuffer;
  Diagnostic Diags(&DiagsBuffer);
  CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd,
                                     Diags);

  // Infer the builtin include path if unspecified.
  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
      Clang.getHeaderSearchOpts().ResourceDir.empty())
    Clang.getHeaderSearchOpts().ResourceDir =
      CompilerInvocation::GetResourcesPath(Argv0, MainAddr);

  // Honor -help.
  if (Clang.getFrontendOpts().ShowHelp) {
    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1",
                    "LLVM 'Clang' Compiler: http://clang.llvm.org");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Clang.getFrontendOpts().ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Create the actual diagnostics engine.
  Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
  if (!Clang.hasDiagnostics())
    return 1;

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  llvm::llvm_install_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang.getDiagnostics()));

  DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics());

  // Load any requested plugins.
  for (unsigned i = 0,
         e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) {
    const std::string &Path = Clang.getFrontendOpts().Plugins[i];
    std::string Error;
    if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
      Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
  }

  // If there were errors in processing arguments, don't do anything else.
  bool Success = false;
  if (!Clang.getDiagnostics().getNumErrors()) {
    // Create and execute the frontend action.
    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
    if (Act)
      Success = Clang.ExecuteAction(*Act);
  }

  // Managed static deconstruction. Useful for making things like
  // -time-passes usable.
  llvm::llvm_shutdown();

  return !Success;
}
<|endoftext|>