<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <windows.ui.notifications.h>
#include <windows.data.xml.dom.h>
#include <wrl.h>
#include <wchar.h>
#include <vector>

#pragma comment(lib, "delayimp")
#pragma comment(lib, "runtimeobject")

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

class ToastNotificationHandler;

static wchar_t* sAppId = nullptr;
static std::vector<void*> sNotifications;

typedef bool (*EventCallback)();

class ToastNotificationHandler {
	typedef ABI::Windows::UI::Notifications::IToastNotification IToastNotification;
	typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs IToastDismissedEventArgs;
	typedef ABI::Windows::UI::Notifications::IToastNotificationManagerStatics IToastNotificationManagerStatics;
	typedef ABI::Windows::UI::Notifications::ToastTemplateType ToastTemplateType;
	typedef ABI::Windows::Data::Xml::Dom::IXmlNode IXmlNode;
	typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;

	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler;
	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler;

public:
	ToastNotificationHandler() : mTitle(nullptr), mMessage(nullptr), mName(nullptr), mActivateCallback(nullptr), mDismissCallback(nullptr)
	{
	}

	~ToastNotificationHandler();

	bool Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName);
	bool DisplayNotification(EventCallback aActivate, EventCallback aDismiss);
	bool CloseNotification();

	const wchar_t* GetName() const { return mName; }

private:
	ComPtr<IXmlDocument> ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType);
	bool CreateWindowsNotificationFromXml(IXmlDocument* aXml);

	HRESULT OnActivate(IToastNotification* aNotification, IInspectable* aInspectable);
	HRESULT OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aInspectable);

	ComPtr<IToastNotificationManagerStatics> mToastNotificationManagerStatics;
	ComPtr<IToastNotification> mNotification;
	ComPtr<IToastNotifier> mNotifier;
	HSTRING mTitle;
	HSTRING mMessage;
	wchar_t* mName;
	DWORD mThreadId;

	EventCallback mActivateCallback;
	EventCallback mDismissCallback;
};

ToastNotificationHandler::~ToastNotificationHandler()
{
	std::vector<void*>::iterator iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		if (*iter == this) {
			sNotifications.erase(iter);
			break;
		}
		iter++;
	}

	if (mTitle) {
		WindowsDeleteString(mTitle);
	}
	if (mMessage) {
		WindowsDeleteString(mMessage);
	}
	if (mName) {
		free(mName);
	}
}

bool
ToastNotificationHandler::Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName)
{
	HRESULT hr;
	hr = WindowsCreateString(aTitle, (UINT32)wcslen(aTitle), &mTitle);
	if (FAILED(hr)) {
		return false;
	}
	hr = WindowsCreateString(aMessage, (UINT32)wcslen(aMessage), &mMessage);
	if (FAILED(hr)) {
		return false;
	}
	if (aName) {
		mName = _wcsdup(aName);
		if (!mName) {
			return false;
		}
	}

	mThreadId = GetCurrentThreadId();

	return true;
}

static bool
SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml)
{
	ComPtr<IXmlText> inputText;
	HRESULT hr;
	hr = xml->CreateTextNode(inputString, &inputText);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> inputTextNode;
	hr = inputText.As(&inputTextNode);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> appendedChild;
	hr = node->AppendChild(inputTextNode.Get(), &appendedChild);
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

ComPtr<IXmlDocument>
ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType)
{
	HRESULT hr;
	hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), mToastNotificationManagerStatics.GetAddressOf());
	if (FAILED(hr)) {
		return nullptr;
	}

	ComPtr<IXmlDocument> toastXml;
	mToastNotificationManagerStatics->GetTemplateContent(templateType, &toastXml);
	return toastXml;
}

bool
ToastNotificationHandler::CreateWindowsNotificationFromXml(IXmlDocument* aXml)
{
	ComPtr<IToastNotificationFactory> factory;
	HRESULT hr;
	hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), factory.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}

	hr = factory->CreateToastNotification(aXml, &mNotification);
	if (FAILED(hr)) {
		return false;
	}

	if (mActivateCallback) {
		EventRegistrationToken activatedToken;
		hr = mNotification->add_Activated(Callback<ToastActivationHandler>(this, &ToastNotificationHandler::OnActivate).Get(), &activatedToken);
		if (FAILED(hr)) {
			return false;
		}
	}

	EventRegistrationToken dismissedToken;
	hr = mNotification->add_Dismissed(Callback<ToastDismissHandler>(this, &ToastNotificationHandler::OnDismiss).Get(), &dismissedToken);
	if (FAILED(hr)) {
		return false;
	}

	hr = mToastNotificationManagerStatics->CreateToastNotifierWithId(HStringReference(sAppId).Get(), mNotifier.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}
	hr = mNotifier->Show(mNotification.Get());
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

bool
ToastNotificationHandler::DisplayNotification(EventCallback aActivate, EventCallback aDismiss)
{
	ComPtr<IXmlDocument> toastXml = InitializeXmlForTemplate(ToastTemplateType::ToastTemplateType_ToastText03);
	HRESULT hr;

	ComPtr<IXmlNodeList> toastTextElements;
	hr = toastXml->GetElementsByTagName(HStringReference(L"text").Get(), &toastTextElements);
	if (FAILED(hr)) {
		return false;
	}

	ComPtr<IXmlNode> titleTextNodeRoot;
	hr = toastTextElements->Item(0, &titleTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> msgTextNodeRoot;
	hr = toastTextElements->Item(1, &msgTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}

	SetNodeValueString(mTitle, titleTextNodeRoot.Get(), toastXml.Get());
	SetNodeValueString(mMessage, msgTextNodeRoot.Get(), toastXml.Get());

	mActivateCallback = aActivate;
	mDismissCallback = aDismiss;

	return CreateWindowsNotificationFromXml(toastXml.Get());
}

bool
ToastNotificationHandler::CloseNotification()
{
	mNotifier->Hide(mNotification.Get());
	return true;
}

HRESULT
ToastNotificationHandler::OnActivate(IToastNotification* aNotification, IInspectable* aInspectable)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mActivateCallback) {
		mActivateCallback();
	}
	return S_OK;
}

HRESULT
ToastNotificationHandler::OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aArgs)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mDismissCallback) {
		mDismissCallback();
	}
	delete this;
	return S_OK;
}

extern "C"
bool WINAPI
SetAppId()
{
	if (!sAppId) {
		WCHAR wszFilename[MAX_PATH];
		GetModuleFileNameW(NULL, wszFilename, MAX_PATH);
		wchar_t* slash = wcsrchr(wszFilename, '\\');
		if (slash) {
			*slash = '\0';
		}

		HKEY key;
		if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Mozilla\\Firefox\\TaskBarIDs", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
			WCHAR value[MAX_PATH];
			DWORD type = REG_SZ;
			DWORD len = sizeof(value);
			if (RegQueryValueExW(key, wszFilename, NULL, &type, (LPBYTE) value, &len) == ERROR_SUCCESS) {
				sAppId = _wcsdup(value);
			}
			RegCloseKey(key);
		}
	}

	return !!sAppId;
}

// external API to show toast notification via JS-CTYPES
extern "C"
bool WINAPI
DisplayToastNotification(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName, void* aCallbackActive, void* aCallbackDismiss)
{
	if (!sAppId) {
		return false;
	}

	ToastNotificationHandler* handler = new ToastNotificationHandler();

	if (!handler->Init(aTitle, aMessage, aName)) {
		delete handler;
		return false;
	}

	if (!handler->DisplayNotification((EventCallback) aCallbackActive, (EventCallback) aCallbackDismiss)) {
		delete handler;
		return false;
	}

	sNotifications.push_back(handler);

	return true;
}

extern "C"
bool WINAPI
CloseToastNotification(const wchar_t* aName)
{
	std::vector<void*>::iterator iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		ToastNotificationHandler* handler = reinterpret_cast<ToastNotificationHandler*>(*iter);
		if (!wcscmp(handler->GetName(), aName)) {
			sNotifications.erase(iter);
			handler->CloseNotification();
			return true;
		}
		iter++;
	}

	return false;
}
<commit_msg>Fix crash when closing<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <windows.ui.notifications.h>
#include <windows.data.xml.dom.h>
#include <wrl.h>
#include <wchar.h>
#include <vector>

#pragma comment(lib, "delayimp")
#pragma comment(lib, "runtimeobject")

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

class ToastNotificationHandler;

static wchar_t* sAppId = nullptr;
static std::vector<ToastNotificationHandler*> sNotifications;

typedef bool (STDAPICALLTYPE *EventCallback)();

class ToastNotificationHandler {
	typedef ABI::Windows::UI::Notifications::IToastNotification IToastNotification;
	typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs IToastDismissedEventArgs;
	typedef ABI::Windows::UI::Notifications::IToastNotificationManagerStatics IToastNotificationManagerStatics;
	typedef ABI::Windows::UI::Notifications::ToastTemplateType ToastTemplateType;
	typedef ABI::Windows::Data::Xml::Dom::IXmlNode IXmlNode;
	typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;

	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler;
	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler;

public:
	ToastNotificationHandler() : mTitle(nullptr), mMessage(nullptr), mName(nullptr), mActivateCallback(nullptr), mDismissCallback(nullptr)
	{
	}

	~ToastNotificationHandler();

	bool Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName);
	bool DisplayNotification(EventCallback aActivate, EventCallback aDismiss);
	bool CloseNotification();

	const wchar_t* GetName() const { return mName; }

private:
	ComPtr<IXmlDocument> ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType);
	bool CreateWindowsNotificationFromXml(IXmlDocument* aXml);

	HRESULT OnActivate(IToastNotification* aNotification, IInspectable* aInspectable);
	HRESULT OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aInspectable);

	ComPtr<IToastNotificationManagerStatics> mToastNotificationManagerStatics;
	ComPtr<IToastNotification> mNotification;
	ComPtr<IToastNotifier> mNotifier;
	HSTRING mTitle;
	HSTRING mMessage;
	wchar_t* mName;
	DWORD mThreadId;

	EventCallback mActivateCallback;
	EventCallback mDismissCallback;
};

ToastNotificationHandler::~ToastNotificationHandler()
{
	std::vector<ToastNotificationHandler*>::iterator iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		if (*iter == this) {
			sNotifications.erase(iter);
			break;
		}
		iter++;
	}

	if (mTitle) {
		WindowsDeleteString(mTitle);
	}
	if (mMessage) {
		WindowsDeleteString(mMessage);
	}
	if (mName) {
		free(mName);
	}
}

bool
ToastNotificationHandler::Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName)
{
	HRESULT hr;
	hr = WindowsCreateString(aTitle, (UINT32)wcslen(aTitle), &mTitle);
	if (FAILED(hr)) {
		return false;
	}
	hr = WindowsCreateString(aMessage, (UINT32)wcslen(aMessage), &mMessage);
	if (FAILED(hr)) {
		return false;
	}
	if (aName) {
		mName = _wcsdup(aName);
		if (!mName) {
			return false;
		}
	}

	mThreadId = GetCurrentThreadId();

	return true;
}

static bool
SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml)
{
	ComPtr<IXmlText> inputText;
	HRESULT hr;
	hr = xml->CreateTextNode(inputString, &inputText);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> inputTextNode;
	hr = inputText.As(&inputTextNode);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> appendedChild;
	hr = node->AppendChild(inputTextNode.Get(), &appendedChild);
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

ComPtr<IXmlDocument>
ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType)
{
	HRESULT hr;
	hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), mToastNotificationManagerStatics.GetAddressOf());
	if (FAILED(hr)) {
		return nullptr;
	}

	ComPtr<IXmlDocument> toastXml;
	mToastNotificationManagerStatics->GetTemplateContent(templateType, &toastXml);
	return toastXml;
}

bool
ToastNotificationHandler::CreateWindowsNotificationFromXml(IXmlDocument* aXml)
{
	ComPtr<IToastNotificationFactory> factory;
	HRESULT hr;
	hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), factory.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}

	hr = factory->CreateToastNotification(aXml, &mNotification);
	if (FAILED(hr)) {
		return false;
	}

	if (mActivateCallback) {
		EventRegistrationToken activatedToken;
		hr = mNotification->add_Activated(Callback<ToastActivationHandler>(this, &ToastNotificationHandler::OnActivate).Get(), &activatedToken);
		if (FAILED(hr)) {
			return false;
		}
	}

	EventRegistrationToken dismissedToken;
	hr = mNotification->add_Dismissed(Callback<ToastDismissHandler>(this, &ToastNotificationHandler::OnDismiss).Get(), &dismissedToken);
	if (FAILED(hr)) {
		return false;
	}

	hr = mToastNotificationManagerStatics->CreateToastNotifierWithId(HStringReference(sAppId).Get(), mNotifier.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}
	hr = mNotifier->Show(mNotification.Get());
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

bool
ToastNotificationHandler::DisplayNotification(EventCallback aActivate, EventCallback aDismiss)
{
	ComPtr<IXmlDocument> toastXml = InitializeXmlForTemplate(ToastTemplateType::ToastTemplateType_ToastText03);
	HRESULT hr;

	ComPtr<IXmlNodeList> toastTextElements;
	hr = toastXml->GetElementsByTagName(HStringReference(L"text").Get(), &toastTextElements);
	if (FAILED(hr)) {
		return false;
	}

	ComPtr<IXmlNode> titleTextNodeRoot;
	hr = toastTextElements->Item(0, &titleTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> msgTextNodeRoot;
	hr = toastTextElements->Item(1, &msgTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}

	SetNodeValueString(mTitle, titleTextNodeRoot.Get(), toastXml.Get());
	SetNodeValueString(mMessage, msgTextNodeRoot.Get(), toastXml.Get());

	mActivateCallback = aActivate;
	mDismissCallback = aDismiss;

	return CreateWindowsNotificationFromXml(toastXml.Get());
}

bool
ToastNotificationHandler::CloseNotification()
{
	if (mNotifier && mNotification) {
		mNotifier->Hide(mNotification.Get());
	}
	return true;
}

HRESULT
ToastNotificationHandler::OnActivate(IToastNotification* aNotification, IInspectable* aInspectable)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mActivateCallback) {
		mActivateCallback();
	}
	return S_OK;
}

HRESULT
ToastNotificationHandler::OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aArgs)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mDismissCallback) {
		mDismissCallback();
	}
	delete this;
	return S_OK;
}

extern "C"
bool WINAPI
SetAppId()
{
	if (!sAppId) {
		WCHAR wszFilename[MAX_PATH];
		GetModuleFileNameW(NULL, wszFilename, MAX_PATH);
		wchar_t* slash = wcsrchr(wszFilename, '\\');
		if (slash) {
			*slash = '\0';
		}

		HKEY key;
		if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Mozilla\\Firefox\\TaskBarIDs", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
			WCHAR value[MAX_PATH];
			DWORD type = REG_SZ;
			DWORD len = sizeof(value);
			if (RegQueryValueExW(key, wszFilename, NULL, &type, (LPBYTE) value, &len) == ERROR_SUCCESS) {
				sAppId = _wcsdup(value);
			}
			RegCloseKey(key);
		}
	}

	return !!sAppId;
}

// external API to show toast notification via JS-CTYPES
extern "C"
bool WINAPI
DisplayToastNotification(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName, void* aCallbackActive, void* aCallbackDismiss)
{
	if (!sAppId) {
		return false;
	}

	ToastNotificationHandler* handler = new ToastNotificationHandler();

	if (!handler->Init(aTitle, aMessage, aName)) {
		delete handler;
		return false;
	}

	if (!handler->DisplayNotification((EventCallback) aCallbackActive, (EventCallback) aCallbackDismiss)) {
		delete handler;
		return false;
	}

	sNotifications.push_back(handler);

	return true;
}

extern "C"
bool WINAPI
CloseToastNotification(const wchar_t* aName)
{
	if (!aName) {
		return false;
	}
	std::vector<ToastNotificationHandler*>::iterator iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		ToastNotificationHandler* handler = *iter;
		if (handler) {
			if (!wcscmp(handler->GetName(), aName)) {
				sNotifications.erase(iter);
				handler->CloseNotification();
				delete handler;
				return true;
			}
		}
		iter++;
	}

	return false;
}
<|endoftext|>


<commit_before>#include "debugger.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtkmm.h>

class DebuggerWindow : public Gtk::Window
{
public:
	DebuggerWindow()
	{
		set_title("OSECPU Debugger");
	}
};

void* create_debugger_window_thread(void* data)
{
	OsecpuDebugger* debugger = (OsecpuDebugger*)data;
	Gtk::Main gtk(NULL, NULL);
	debugger->window = new DebuggerWindow();
	Gtk::Main::run(*(DebuggerWindow*)debugger->window);
}

extern "C" OsecpuDebugger* debugger_init(struct Osecpu* osecpu)
{
	OsecpuDebugger* debugger;
	debugger = (OsecpuDebugger*)malloc(sizeof(OsecpuDebugger));
	if (!debugger) return NULL;
	memset(debugger, 0, sizeof(OsecpuDebugger));
	debugger->osecpu = osecpu;

	pthread_create(&debugger->windowThread, NULL, create_debugger_window_thread, debugger);

	while (!debugger->window);
	((Gtk::Window*)debugger->window)->show_all_children();

	return debugger;
}

extern "C" void debugger_free(OsecpuDebugger* debugger)
{
	free(debugger);
}

extern "C" void debugger_open(OsecpuDebugger* debugger)
{
	char cmdbuf[1024];
	while (1) {
		printf("debug> ");
		fgets(cmdbuf, 1024, stdin);
		cmdbuf[strlen(cmdbuf)-1] = 0;
		if (strcmp(cmdbuf, "continue") == 0) {
			if (continue_osecpu(debugger->osecpu) == 2) {
				printf("breakpoint.\n");
				debugger_open(debugger);
			}
			return;
		} else if (strcmp(cmdbuf, "next") == 0) {
			do_next_instruction(debugger->osecpu);
			if (debugger->osecpu->pregisters[0x3f].p.code >= debugger->osecpu->codelen) {
				return;
			}
		} else if (strcmp(cmdbuf, "coredump") == 0) {
			coredump(debugger->osecpu);
		} else {
			printf("command: continue, next, coredump\n");
		}
	}
}

<commit_msg>Debugger window UI (1)<commit_after>#include "debugger.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtkmm.h>

class ControlWidget : public Gtk::HBox
{
	Gtk::Button button_continue_pause;
	Gtk::Button button_stepover;
public:
	ControlWidget() :
		button_continue_pause("Continue / Pause"),
		button_stepover("Stepover")
	{
		pack_start(button_continue_pause, Gtk::PACK_SHRINK);
		pack_start(button_stepover, Gtk::PACK_SHRINK);
	}
};

class RegistersWidget : public Gtk::VBox
{
	Gtk::Label label;
	Gtk::ScrolledWindow scrwin;
	Gtk::TreeView treeview;
public:
	RegistersWidget() : label("Registers", Gtk::ALIGN_START, Gtk::ALIGN_LEFT)
	{
		pack_start(label, Gtk::PACK_SHRINK);
		scrwin.add(treeview);
		pack_start(scrwin);
	}
};

class LabelsWidget : public Gtk::VBox
{
	Gtk::Label label;
	Gtk::ScrolledWindow scrwin;
	Gtk::TreeView treeview;
public:
	LabelsWidget() : label("Labels", Gtk::ALIGN_START, Gtk::ALIGN_LEFT)
	{
		pack_start(label, Gtk::PACK_SHRINK);
		scrwin.add(treeview);
		pack_start(scrwin);
	}
};

class CodeWidget : public Gtk::VBox
{
	Gtk::Label label;
	Gtk::ScrolledWindow scrwin;
	Gtk::TreeView treeview;
public:
	CodeWidget() : label("Code", Gtk::ALIGN_START, Gtk::ALIGN_LEFT)
	{
		pack_start(label, Gtk::PACK_SHRINK);
		scrwin.add(treeview);
		pack_start(scrwin);
	}
};

class DebuggerWindow : public Gtk::Window
{
	Gtk::VBox vbox, vbox_left, vbox_right;
	Gtk::HBox hbox;
	ControlWidget widget_control;
	RegistersWidget widget_registers;
	LabelsWidget widget_labels;
	CodeWidget widget_code;
public:
	DebuggerWindow()
	{
		set_title("OSECPU Debugger");
		vbox_left.pack_start(widget_control, Gtk::PACK_SHRINK);
		vbox_left.pack_start(widget_registers);
		vbox_left.pack_start(widget_labels);
		vbox_right.pack_start(widget_code);
		hbox.pack_start(vbox_left);
		hbox.pack_start(vbox_right);
		vbox.pack_start(hbox);
		add(vbox);
		show_all_children();
	}
};

void* create_debugger_window_thread(void* data)
{
	OsecpuDebugger* debugger = (OsecpuDebugger*)data;
	Gtk::Main gtk(NULL, NULL);
	debugger->window = new DebuggerWindow();
	Gtk::Main::run(*(DebuggerWindow*)debugger->window);
}

extern "C" OsecpuDebugger* debugger_init(struct Osecpu* osecpu)
{
	OsecpuDebugger* debugger;
	debugger = (OsecpuDebugger*)malloc(sizeof(OsecpuDebugger));
	if (!debugger) return NULL;
	memset(debugger, 0, sizeof(OsecpuDebugger));
	debugger->osecpu = osecpu;

	pthread_create(&debugger->windowThread, NULL, create_debugger_window_thread, debugger);

	while (!debugger->window);
	((Gtk::Window*)debugger->window)->show_all_children();

	return debugger;
}

extern "C" void debugger_free(OsecpuDebugger* debugger)
{
	free(debugger);
}

extern "C" void debugger_open(OsecpuDebugger* debugger)
{
	char cmdbuf[1024];
	while (1) {
		printf("debug> ");
		fgets(cmdbuf, 1024, stdin);
		cmdbuf[strlen(cmdbuf)-1] = 0;
		if (strcmp(cmdbuf, "continue") == 0) {
			if (continue_osecpu(debugger->osecpu) == 2) {
				printf("breakpoint.\n");
				debugger_open(debugger);
			}
			return;
		} else if (strcmp(cmdbuf, "next") == 0) {
			do_next_instruction(debugger->osecpu);
			if (debugger->osecpu->pregisters[0x3f].p.code >= debugger->osecpu->codelen) {
				return;
			}
		} else if (strcmp(cmdbuf, "coredump") == 0) {
			coredump(debugger->osecpu);
		} else {
			printf("command: continue, next, coredump\n");
		}
	}
}

<|endoftext|>


<commit_before>/*
 *  phdlog.cpp
 *  PHD Guiding
 *
 *  Created by Bret McKee
 *  Copyright (c) 2012 Bret McKee
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *    Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *    Neither the name of Bret McKee, Dad Dog Development,
 *     Craig Stark, Stark Labs nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "phd.h"

void DebugLog::InitVars(void)
{
    m_bEnabled = false;
    m_lastWriteTime = wxDateTime::UNow();
}

DebugLog::DebugLog(void)
{
    InitVars();
}

DebugLog::DebugLog(const char *pName, bool bEnabled = true)
{
    InitVars();

    Init(pName, bEnabled);
}

DebugLog::~DebugLog(void)
{
    wxFFile::Flush();
    wxFFile::Close();
}

bool DebugLog::Enable(bool bEnabled)
{
    bool prevState = m_bEnabled;

    m_bEnabled = bEnabled;

    return prevState;
}

bool DebugLog::Init(const char *pName, bool bEnable, bool bForceOpen)
{
    wxCriticalSectionLocker lock(m_criticalSection);

    if (m_bEnabled)
    {
        wxFFile::Flush();
        wxFFile::Close();

        m_bEnabled = false;
    }

    if (bEnable && (m_pPathName.IsEmpty() || bForceOpen))
    {
        wxDateTime now = wxDateTime::UNow();

        m_pPathName = GetLogDir() + PATHSEPSTR + "PHD2_DebugLog" + now.Format(_T("_%Y-%m-%d")) +  now.Format(_T("_%H%M%S"))+ ".txt";

        if (!wxFFile::Open(m_pPathName, "a"))
        {
            wxMessageBox(wxString::Format("unable to open file %s", m_pPathName));
        }
    }

    m_bEnabled = bEnable;

    return m_bEnabled;
}

bool DebugLog::ChangeDirLog(const wxString& newdir)
{
    bool bEnabled = IsEnabled();
    bool bOk = true;

    if (!SetLogDir(newdir))
    {
        wxMessageBox(wxString::Format("invalid folder name %s, debug log folder unchanged", newdir));
        bOk = false;
    }

    Init("debug", bEnabled, true);                // lots of side effects, but all good...
    return bOk;
}

wxString DebugLog::AddLine(const char *format, ...)
{
    va_list args;
    va_start(args, format);

    wxString ret = Write(wxString::FormatV(format, args) + "\n");

    va_end(args);

    return ret;
}

wxString DebugLog::AddBytes(const wxString& str, const unsigned char *pBytes, unsigned int count)
{
    wxString Line = str + " - ";

    for (unsigned int i=0; i < count; i++)
    {
        unsigned char ch = pBytes[i];
        Line += wxString::Format("%2.2X (%c) ", ch, isprint(ch) ? ch : '?');
    }

    return Write(Line + "\n");
}

bool DebugLog::Flush(void)
{
    bool bReturn = true;

    if (m_bEnabled)
    {
        wxCriticalSectionLocker lock(m_criticalSection);

        bReturn = wxFFile::Flush();
    }

    return bReturn;
}

wxString DebugLog::Write(const wxString& str)
{
    if (m_bEnabled)
    {
        wxCriticalSectionLocker lock(m_criticalSection);

        wxDateTime now = wxDateTime::UNow();
        wxTimeSpan deltaTime = now - m_lastWriteTime;
        m_lastWriteTime = now;
        wxString outputLine = wxString::Format("%s %s %d %s", now.Format("%H:%M:%S.%l"),
                                                              deltaTime.Format("%S.%l"),
                                                              wxThread::GetCurrentId(),
                                                              str);

        wxFFile::Write(outputLine);
#if defined(ALWAYS_FLUSH_DEBUGLOG)
        wxFFile::Flush();
#endif
#if defined(__WINDOWS__) && defined(_DEBUG)
        OutputDebugString(outputLine.c_str());
#endif
    }

    return str;
}

DebugLog& operator<< (DebugLog& out, const wxString &str)
{
    out.Write(str);
    return out;
}

DebugLog& operator<< (DebugLog& out, const char *str)
{
    out.Write(str);
    return out;
}

DebugLog& operator<< (DebugLog& out, const int i)
{
    out.Write(wxString::Format(_T("%d"), i));
    return out;
}

DebugLog& operator<< (DebugLog& out, const double d)
{
    out.Write(wxString::Format(_T("%f"), d));
    return out;
}
<commit_msg>fix display of thread id in debug log<commit_after>/*
 *  phdlog.cpp
 *  PHD Guiding
 *
 *  Created by Bret McKee
 *  Copyright (c) 2012 Bret McKee
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *    Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *    Neither the name of Bret McKee, Dad Dog Development,
 *     Craig Stark, Stark Labs nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "phd.h"

void DebugLog::InitVars(void)
{
    m_bEnabled = false;
    m_lastWriteTime = wxDateTime::UNow();
}

DebugLog::DebugLog(void)
{
    InitVars();
}

DebugLog::DebugLog(const char *pName, bool bEnabled = true)
{
    InitVars();

    Init(pName, bEnabled);
}

DebugLog::~DebugLog(void)
{
    wxFFile::Flush();
    wxFFile::Close();
}

bool DebugLog::Enable(bool bEnabled)
{
    bool prevState = m_bEnabled;

    m_bEnabled = bEnabled;

    return prevState;
}

bool DebugLog::Init(const char *pName, bool bEnable, bool bForceOpen)
{
    wxCriticalSectionLocker lock(m_criticalSection);

    if (m_bEnabled)
    {
        wxFFile::Flush();
        wxFFile::Close();

        m_bEnabled = false;
    }

    if (bEnable && (m_pPathName.IsEmpty() || bForceOpen))
    {
        wxDateTime now = wxDateTime::UNow();

        m_pPathName = GetLogDir() + PATHSEPSTR + "PHD2_DebugLog" + now.Format(_T("_%Y-%m-%d")) +  now.Format(_T("_%H%M%S"))+ ".txt";

        if (!wxFFile::Open(m_pPathName, "a"))
        {
            wxMessageBox(wxString::Format("unable to open file %s", m_pPathName));
        }
    }

    m_bEnabled = bEnable;

    return m_bEnabled;
}

bool DebugLog::ChangeDirLog(const wxString& newdir)
{
    bool bEnabled = IsEnabled();
    bool bOk = true;

    if (!SetLogDir(newdir))
    {
        wxMessageBox(wxString::Format("invalid folder name %s, debug log folder unchanged", newdir));
        bOk = false;
    }

    Init("debug", bEnabled, true);                // lots of side effects, but all good...
    return bOk;
}

wxString DebugLog::AddLine(const char *format, ...)
{
    va_list args;
    va_start(args, format);

    wxString ret = Write(wxString::FormatV(format, args) + "\n");

    va_end(args);

    return ret;
}

wxString DebugLog::AddBytes(const wxString& str, const unsigned char *pBytes, unsigned int count)
{
    wxString Line = str + " - ";

    for (unsigned int i=0; i < count; i++)
    {
        unsigned char ch = pBytes[i];
        Line += wxString::Format("%2.2X (%c) ", ch, isprint(ch) ? ch : '?');
    }

    return Write(Line + "\n");
}

bool DebugLog::Flush(void)
{
    bool bReturn = true;

    if (m_bEnabled)
    {
        wxCriticalSectionLocker lock(m_criticalSection);

        bReturn = wxFFile::Flush();
    }

    return bReturn;
}

wxString DebugLog::Write(const wxString& str)
{
    if (m_bEnabled)
    {
        wxCriticalSectionLocker lock(m_criticalSection);

        wxDateTime now = wxDateTime::UNow();
        wxTimeSpan deltaTime = now - m_lastWriteTime;
        m_lastWriteTime = now;
        wxString outputLine = wxString::Format("%s %s %lu %s", now.Format("%H:%M:%S.%l"),
                                                              deltaTime.Format("%S.%l"),
                                                              (unsigned long) wxThread::GetCurrentId(),
                                                              str);

        wxFFile::Write(outputLine);
#if defined(ALWAYS_FLUSH_DEBUGLOG)
        wxFFile::Flush();
#endif
#if defined(__WINDOWS__) && defined(_DEBUG)
        OutputDebugString(outputLine.c_str());
#endif
    }

    return str;
}

DebugLog& operator<< (DebugLog& out, const wxString &str)
{
    out.Write(str);
    return out;
}

DebugLog& operator<< (DebugLog& out, const char *str)
{
    out.Write(str);
    return out;
}

DebugLog& operator<< (DebugLog& out, const int i)
{
    out.Write(wxString::Format(_T("%d"), i));
    return out;
}

DebugLog& operator<< (DebugLog& out, const double d)
{
    out.Write(wxString::Format(_T("%f"), d));
    return out;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ifacecompare.hxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: fs $ $Date: 2000-12-13 10:37:19 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_FORMS_IFACECOMPARE_HXX_
#define _XMLOFF_FORMS_IFACECOMPARE_HXX_

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
#include <com/sun/star/drawing/XDrawPage.hpp>
#endif

//.........................................................................
namespace xmloff
{
//.........................................................................

    //=====================================================================
    //= OInterfaceCompare
    //=====================================================================
    /** is stl-compliant structure for comparing Reference< <iface> > instances
    */
    template < class IAFCE >
    struct OInterfaceCompare
        :public ::std::binary_function  <   ::com::sun::star::uno::Reference< IAFCE >
                                        ,   ::com::sun::star::uno::Reference< IAFCE >
                                        ,   bool
                                        >
    {
        bool operator() (const ::com::sun::star::uno::Reference< IAFCE >& lhs, const ::com::sun::star::uno::Reference< IAFCE >& rhs) const
        {
            return lhs.get() < rhs.get();
                // this does not make any sense if you see the semantics of the pointer returned by get:
                // It's a pointer to a point in memory where an interface implementation lies.
                // But for our purpose (provide a reliable less-operator which can be used with the STL), this is
                // sufficient ....
        }
    };

    typedef OInterfaceCompare< ::com::sun::star::beans::XPropertySet >  OPropertySetCompare;
    typedef OInterfaceCompare< ::com::sun::star::drawing::XDrawPage >   ODrawPageCompare;

//.........................................................................
}   // namespace xmloff
//.........................................................................

#endif // _XMLOFF_FORMS_IFACECOMPARE_HXX_

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *
 *  Revision 1.0 13.12.00 10:06:14  fs
 ************************************************************************/

<commit_msg>INTEGRATION: CWS ooo19126 (1.1.646); FILE MERGED 2005/09/05 14:39:00 rt 1.1.646.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ifacecompare.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 14:12:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_FORMS_IFACECOMPARE_HXX_
#define _XMLOFF_FORMS_IFACECOMPARE_HXX_

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
#include <com/sun/star/drawing/XDrawPage.hpp>
#endif

//.........................................................................
namespace xmloff
{
//.........................................................................

    //=====================================================================
    //= OInterfaceCompare
    //=====================================================================
    /** is stl-compliant structure for comparing Reference< <iface> > instances
    */
    template < class IAFCE >
    struct OInterfaceCompare
        :public ::std::binary_function  <   ::com::sun::star::uno::Reference< IAFCE >
                                        ,   ::com::sun::star::uno::Reference< IAFCE >
                                        ,   bool
                                        >
    {
        bool operator() (const ::com::sun::star::uno::Reference< IAFCE >& lhs, const ::com::sun::star::uno::Reference< IAFCE >& rhs) const
        {
            return lhs.get() < rhs.get();
                // this does not make any sense if you see the semantics of the pointer returned by get:
                // It's a pointer to a point in memory where an interface implementation lies.
                // But for our purpose (provide a reliable less-operator which can be used with the STL), this is
                // sufficient ....
        }
    };

    typedef OInterfaceCompare< ::com::sun::star::beans::XPropertySet >  OPropertySetCompare;
    typedef OInterfaceCompare< ::com::sun::star::drawing::XDrawPage >   ODrawPageCompare;

//.........................................................................
}   // namespace xmloff
//.........................................................................

#endif // _XMLOFF_FORMS_IFACECOMPARE_HXX_

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *  Revision 1.1.646.1  2005/09/05 14:39:00  rt
 *  #i54170# Change license header: remove SISSL
 *
 *  Revision 1.1  2000/12/13 10:37:19  fs
 *  initial checkin - helper class for build maps whichs keys are interface references
 *
 *
 *  Revision 1.0 13.12.00 10:06:14  fs
 ************************************************************************/

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: baslibnode.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2004-10-22 14:00:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SCRIPTING_BASLIBNODE_HXX
#include "baslibnode.hxx"
#endif

#ifndef SCRIPTING_BASMODNODE_HXX
#include "basmodnode.hxx"
#endif

#ifndef _COM_SUN_STAR_SCRIPT_BROWSE_BROWSENODETYPES_HPP_
#include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
#endif

#ifndef _BASMGR_HXX
#include <basic/basmgr.hxx>
#endif
#ifndef _SB_SBSTAR_HXX
#include <basic/sbstar.hxx>
#endif

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

//.........................................................................
namespace basprov
{
//.........................................................................

    // =============================================================================
    // BasicLibraryNodeImpl
    // =============================================================================

    BasicLibraryNodeImpl::BasicLibraryNodeImpl( const Reference< XComponentContext >& rxContext,
         const ::rtl::OUString& sScriptingContext, BasicManager* pBasicManager,
        const Reference< script::XLibraryContainer >& xLibContainer, const ::rtl::OUString& sLibName, bool isAppScript )
        :m_xContext( rxContext )
    ,m_sScriptingContext( sScriptingContext )
        ,m_pBasicManager( pBasicManager )
        ,m_xLibContainer( xLibContainer )
        ,m_sLibName( sLibName )
        ,m_bIsAppScript( isAppScript )
    {
        if ( m_xLibContainer.is() )
        {
            Any aElement = m_xLibContainer->getByName( m_sLibName );
            aElement >>= m_xLibrary;
        }
    }

    // -----------------------------------------------------------------------------

    BasicLibraryNodeImpl::~BasicLibraryNodeImpl()
    {
    }

    // -----------------------------------------------------------------------------
    // XBrowseNode
    // -----------------------------------------------------------------------------

    ::rtl::OUString BasicLibraryNodeImpl::getName(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( StarBASIC::GetGlobalMutex() );

        return m_sLibName;
    }

    // -----------------------------------------------------------------------------

    Sequence< Reference< browse::XBrowseNode > > BasicLibraryNodeImpl::getChildNodes(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( StarBASIC::GetGlobalMutex() );

        Sequence< Reference< browse::XBrowseNode > > aChildNodes;

        if ( m_xLibContainer.is() && m_xLibContainer->hasByName( m_sLibName ) && !m_xLibContainer->isLibraryLoaded( m_sLibName ) )
            m_xLibContainer->loadLibrary( m_sLibName );

        if ( m_pBasicManager )
        {
            StarBASIC* pBasic = m_pBasicManager->GetLib( m_sLibName );
            if ( pBasic && m_xLibrary.is() )
            {
                Sequence< ::rtl::OUString > aNames = m_xLibrary->getElementNames();
                sal_Int32 nCount = aNames.getLength();
                const ::rtl::OUString* pNames = aNames.getConstArray();
                aChildNodes.realloc( nCount );
                Reference< browse::XBrowseNode >* pChildNodes = aChildNodes.getArray();

                for ( sal_Int32 i = 0 ; i < nCount ; ++i )
                {
                    SbModule* pModule = pBasic->FindModule( pNames[i] );
                    if ( pModule )
                        pChildNodes[i] = static_cast< browse::XBrowseNode* >( new BasicModuleNodeImpl( m_xContext, m_sScriptingContext, pModule, m_bIsAppScript ) );
                }
            }
        }

        return aChildNodes;
    }

    // -----------------------------------------------------------------------------

    sal_Bool BasicLibraryNodeImpl::hasChildNodes(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( StarBASIC::GetGlobalMutex() );

        sal_Bool bReturn = sal_False;
        if ( m_xLibrary.is() )
            bReturn = m_xLibrary->hasElements();

        return bReturn;
    }

    // -----------------------------------------------------------------------------

    sal_Int16 BasicLibraryNodeImpl::getType(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( StarBASIC::GetGlobalMutex() );

        return browse::BrowseNodeTypes::CONTAINER;
    }

    // -----------------------------------------------------------------------------

//.........................................................................
}   // namespace basprov
//.........................................................................
<commit_msg>INTEGRATION: CWS tbe15 (1.6.12); FILE MERGED 2004/12/03 16:22:18 tbe 1.6.12.1: #i38139# Tools/Macro/Run Macro freezes office when Basic macro is already running<commit_after>/*************************************************************************
 *
 *  $RCSfile: baslibnode.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-13 17:42:17 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SCRIPTING_BASLIBNODE_HXX
#include "baslibnode.hxx"
#endif

#ifndef SCRIPTING_BASMODNODE_HXX
#include "basmodnode.hxx"
#endif

#ifndef _COM_SUN_STAR_SCRIPT_BROWSE_BROWSENODETYPES_HPP_
#include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
#endif

#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _BASMGR_HXX
#include <basic/basmgr.hxx>
#endif
#ifndef _SB_SBSTAR_HXX
#include <basic/sbstar.hxx>
#endif

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

//.........................................................................
namespace basprov
{
//.........................................................................

    // =============================================================================
    // BasicLibraryNodeImpl
    // =============================================================================

    BasicLibraryNodeImpl::BasicLibraryNodeImpl( const Reference< XComponentContext >& rxContext,
         const ::rtl::OUString& sScriptingContext, BasicManager* pBasicManager,
        const Reference< script::XLibraryContainer >& xLibContainer, const ::rtl::OUString& sLibName, bool isAppScript )
        :m_xContext( rxContext )
    ,m_sScriptingContext( sScriptingContext )
        ,m_pBasicManager( pBasicManager )
        ,m_xLibContainer( xLibContainer )
        ,m_sLibName( sLibName )
        ,m_bIsAppScript( isAppScript )
    {
        if ( m_xLibContainer.is() )
        {
            Any aElement = m_xLibContainer->getByName( m_sLibName );
            aElement >>= m_xLibrary;
        }
    }

    // -----------------------------------------------------------------------------

    BasicLibraryNodeImpl::~BasicLibraryNodeImpl()
    {
    }

    // -----------------------------------------------------------------------------
    // XBrowseNode
    // -----------------------------------------------------------------------------

    ::rtl::OUString BasicLibraryNodeImpl::getName(  ) throw (RuntimeException)
    {
        ::vos::OGuard aGuard( Application::GetSolarMutex() );

        return m_sLibName;
    }

    // -----------------------------------------------------------------------------

    Sequence< Reference< browse::XBrowseNode > > BasicLibraryNodeImpl::getChildNodes(  ) throw (RuntimeException)
    {
        ::vos::OGuard aGuard( Application::GetSolarMutex() );

        Sequence< Reference< browse::XBrowseNode > > aChildNodes;

        if ( m_xLibContainer.is() && m_xLibContainer->hasByName( m_sLibName ) && !m_xLibContainer->isLibraryLoaded( m_sLibName ) )
            m_xLibContainer->loadLibrary( m_sLibName );

        if ( m_pBasicManager )
        {
            StarBASIC* pBasic = m_pBasicManager->GetLib( m_sLibName );
            if ( pBasic && m_xLibrary.is() )
            {
                Sequence< ::rtl::OUString > aNames = m_xLibrary->getElementNames();
                sal_Int32 nCount = aNames.getLength();
                const ::rtl::OUString* pNames = aNames.getConstArray();
                aChildNodes.realloc( nCount );
                Reference< browse::XBrowseNode >* pChildNodes = aChildNodes.getArray();

                for ( sal_Int32 i = 0 ; i < nCount ; ++i )
                {
                    SbModule* pModule = pBasic->FindModule( pNames[i] );
                    if ( pModule )
                        pChildNodes[i] = static_cast< browse::XBrowseNode* >( new BasicModuleNodeImpl( m_xContext, m_sScriptingContext, pModule, m_bIsAppScript ) );
                }
            }
        }

        return aChildNodes;
    }

    // -----------------------------------------------------------------------------

    sal_Bool BasicLibraryNodeImpl::hasChildNodes(  ) throw (RuntimeException)
    {
        ::vos::OGuard aGuard( Application::GetSolarMutex() );

        sal_Bool bReturn = sal_False;
        if ( m_xLibrary.is() )
            bReturn = m_xLibrary->hasElements();

        return bReturn;
    }

    // -----------------------------------------------------------------------------

    sal_Int16 BasicLibraryNodeImpl::getType(  ) throw (RuntimeException)
    {
        ::vos::OGuard aGuard( Application::GetSolarMutex() );

        return browse::BrowseNodeTypes::CONTAINER;
    }

    // -----------------------------------------------------------------------------

//.........................................................................
}   // namespace basprov
//.........................................................................
<|endoftext|>


<commit_before><commit_msg>[NFC] Extend RDF docs with Dask backend<commit_after><|endoftext|>


<commit_before>#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sqlite3.h>
#include <map>
#include "udplogger.h"
#include "udploggerparselib.h"

/*
 * Structure that contains configuration information for the running instance
 * of this udploggerstats program.
 */
struct udploggerstats_configuration_t {
	sqlite3 *data_store;
} udploggerstats_conf;

int arguments_parse(int, char **);
void hit_statistics(struct log_entry_t *, time_t);
void sql_query(const char *, ...);
void status_statistics(struct log_entry_t *, time_t);
void usersex_statistics(struct log_entry_t *, time_t);
void usertype_statistics(struct log_entry_t *, time_t);

int main (int argc, char **argv)
{
	char *line = NULL;
	size_t line_buffer_length = 0;
	ssize_t line_length = 0;
	struct log_entry_t log_data;
	int result = 0;
	time_t timestamp = 0;

	result = arguments_parse(argc, argv);
	if (result <= 0)
	{
		return result;
	}

	while ((line_length = getline(&line, &line_buffer_length, stdin)) != -1)
	{
		parse_log_line(line, &log_data);

		/*
		 * Zero the tm_sec and tm_min fields of log_data.timestamp.  We only
		 * want granularity down to the hour.  Assign the timestamp local variable
		 * to be equivalent to the log_data.timestamp struct, except for stored as
		 * a time_t rather than a struct tm.
		 */
		log_data.timestamp.tm_sec = 0;
		log_data.timestamp.tm_min = 0;
		timestamp = mktime(&(log_data.timestamp));

		hit_statistics(&log_data, timestamp);
		status_statistics(&log_data, timestamp);
		usersex_statistics(&log_data, timestamp);
		usertype_statistics(&log_data, timestamp);
	}

	hit_statistics(NULL, 0);
	status_statistics(NULL, 0);
	usersex_statistics(NULL, 0);
	usertype_statistics(NULL, 0);

	sqlite3_close(udploggerstats_conf.data_store);
	return 0;
}

/**
 * arguments_parse(argc, argv)
 *
 * Utility function to parse the passed in arguments using getopt; also responsible for sanity-checking
 * any passed-in values and ensuring that the program's configuration is sane before returning (i.e.
 * using default values).
 **/
int arguments_parse(int argc, char **argv)
{
	int i;
	static struct option long_options[] =
	{
		{"database", required_argument, 0, 'd'},
		{"help", no_argument, 0, 'h'},
		{"version", no_argument, 0, 'v'},
		{0, 0, 0, 0}
	};
	int result;

	/* Initialize our configuration to the default settings. */
	udploggerstats_conf.data_store = NULL;

	while (1)
	{
		i = getopt_long(argc, argv, "d:hv", long_options, NULL);
		if (i == -1)
		{
			break;
		}
		switch (i)
		{
			case 'd':
				result = sqlite3_open(optarg, &(udploggerstats_conf.data_store));
				if (result != SQLITE_OK)
				{
					printf("udploggerstats.cc unable to open sqlite database '%s': %s\n", optarg, sqlite3_errmsg(udploggerstats_conf.data_store));
					udploggerstats_conf.data_store = NULL;
					return -1;
				}
				else
				{
					#ifdef __DEBUG__
						printf("udploggerstats.cc debug: opened sqlite database '%s' as data store\n", optarg);
					#endif
				}
				break;
			case 'h':
				printf("Usage: udploggerstats [OPTIONS]\n");
				printf("\n");
				printf("  -d, --database <db path>                       use <db path> as the sqlite data store for statistic storage\n");
				printf("  -h, --help                                     display this help and exit\n");
				printf("  -v, --version                                  display udploggerstats version and exit\n");
				printf("\n");
				return 0;
			case 'v':
				printf("udploggerstats.cc revision r%d\n", REVISION);
				return 0;
		}
	}

	return 1;
}

void hit_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<char *, long unsigned int> hit_map_t;
	typedef std::map<time_t, hit_map_t> timestamp_hit_map_t;
	static timestamp_hit_map_t hit_maps;

	if (data != NULL)
	{
		hit_maps[timestamp]["hits"]++;
		hit_maps[timestamp]["bytes_incoming"] += data->bytes_incoming;
		hit_maps[timestamp]["bytes_outgoing"] += data->bytes_outgoing;
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS hit_statistics ( timestamp INTEGER, hits INTEGER, bytes_incoming INTEGER, bytes_outgoing INTEGER, PRIMARY KEY (timestamp) );");

	for (timestamp_hit_map_t::const_iterator i = hit_maps.begin(); i != hit_maps.end(); i++)
	{
		timestamp = i->first;
		hit_map_t hit_map = i->second;

		sql_query("INSERT OR IGNORE INTO hit_statistics ( timestamp, hits, bytes_incoming, bytes_outgoing ) VALUES ( %ld, 0, 0, 0 );", timestamp);
		sql_query("UPDATE hit_statistics SET hits = hits + %lu, bytes_incoming = bytes_incoming + %lu, bytes_outgoing = bytes_outgoing + %lu WHERE timestamp = %ld;", hit_map["hits"], hit_map["bytes_incoming"], hit_map["bytes_outgoing"], timestamp);

		#ifdef __DEBUG__
			for (hit_map_t::const_iterator j = hit_map.begin(); j != hit_map.end(); j++)
			{
				printf("udploggerstats.cc debug: hit_maps[%ld].%s => %lu\n", timestamp, j->first, j->second);
			}
		#endif
	}
}

void sql_query(const char *sql_fmt, ...)
{
	va_list ap;
	int result = 0;
	char *sql = NULL;
	int sql_size = 200; /* Guess that we will not need more than 200 bytes to properly render sql_fmt. */
	char *sqlite_errmsg = NULL;

	if (udploggerstats_conf.data_store == NULL)
	{
		return;
	}

	while (1)
	{
		if ((sql = (char *)calloc(sql_size, sizeof(char))) == NULL)
		{
			fprintf(stderr, "udploggerstats.cc could not allocate %d bytes for sql query string\n", sql_size);
			return;
		}

		/* Attempt to render sql_fmt in the memory pointed to by sql. */
		va_start(ap, sql_fmt);
		result = vsnprintf(sql, sql_size, sql_fmt, ap);
		va_end(ap);

		if ((result > -1) && (result < sql_size))
		{
			/* We rendered the string successfully. */
			break;
		}

		/* We failed to render the string, try again with more space. */
		if (result > -1)
		{
			sql_size = result + 1; /* glibc 2.1 - use exactly as much memory as we need. */
		}
		else
		{
			sql_size *= 2; /* glibc 2.0 - double the amount of memory that we attempt to use. */
		}
		free(sql);
		sql = NULL;
	}

	#ifdef __DEBUG__
		printf("udploggerstats.cc debug: SQL format '%s' was successfully rendered to '%s'.\n", sql_fmt, sql);
	#endif

	result = sqlite3_exec(udploggerstats_conf.data_store, sql, NULL, NULL, &sqlite_errmsg);
	if (result != SQLITE_OK)
	{
		fprintf(stderr, "udploggerstats.cc SQL query: %s\n", sql);
		fprintf(stderr, "udploggerstats.cc SQL error: %s\n", sqlite_errmsg);
	}
	if (sqlite_errmsg != NULL)
	{
		sqlite3_free(sqlite_errmsg);
		sqlite_errmsg = NULL;
	}
	free(sql);
}

void status_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<short unsigned int, long unsigned int> status_map_t;
	typedef std::map<time_t, status_map_t> timestamp_status_map_t;
	static timestamp_status_map_t status_maps;

	if (data != NULL)
	{
		status_maps[timestamp][data->status]++;
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS status_statistics ( timestamp INTEGER, status INTEGER, count INTEGER, PRIMARY KEY (timestamp, status) );");

	for (timestamp_status_map_t::const_iterator i = status_maps.begin(); i != status_maps.end(); i++)
	{
		timestamp = i->first;
		status_map_t status_map = i->second;

		for (status_map_t::const_iterator j = status_map.begin(); j != status_map.end(); j++)
		{
			short unsigned int status = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO status_statistics ( timestamp, status, count ) VALUES ( %ld, %hu, 0 );", timestamp, status);
			sql_query("UPDATE status_statistics SET count = count + %lu WHERE timestamp = %ld AND status = %hu;", count, timestamp, status);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: status_maps[%ld].%hu => %lu\n", timestamp, status, count);
			#endif
		}
	}
}

void usersex_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<char *, long unsigned int> usersex_map_t;
	typedef std::map<time_t, usersex_map_t> timestamp_usersex_map_t;
	static timestamp_usersex_map_t usersex_maps;

	if (data != NULL)
	{
		switch (data->nexopia_usersex)
		{
			case sex_male:
				usersex_maps[timestamp]["male"]++;
				break;
			case sex_female:
				usersex_maps[timestamp]["female"]++;
				break;
			default:
				usersex_maps[timestamp]["unknown"]++;
				break;
		}
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS usersex_statistics ( timestamp INTEGER, sex TEXT, count INTEGER, PRIMARY KEY (timestamp, sex) );");

	for (timestamp_usersex_map_t::const_iterator i = usersex_maps.begin(); i != usersex_maps.end(); i++)
	{
		timestamp = i->first;
		usersex_map_t usersex_map = i->second;

		for (usersex_map_t::const_iterator j = usersex_map.begin(); j != usersex_map.end(); j++)
		{
			char *sex = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO usersex_statistics ( timestamp, sex, count ) VALUES ( %ld, '%s', 0 );", timestamp, sex);
			sql_query("UPDATE usersex_statistics SET count = count + %lu WHERE timestamp = %ld AND sex = '%s';", count, timestamp, sex);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: usersex_maps[%ld].%s => %lu\n", timestamp, sex, count);
			#endif
		}
	}
}

void usertype_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<char *, long unsigned int> usertype_map_t;
	typedef std::map<time_t, usertype_map_t> timestamp_usertype_map_t;
	static timestamp_usertype_map_t usertype_maps;

	if (data != NULL)
	{
		switch (data->nexopia_usertype)
		{
			case usertype_plus:
				usertype_maps[timestamp]["plus"]++;
				break;
			case usertype_user:
				usertype_maps[timestamp]["user"]++;
				break;
			case usertype_anon:
				usertype_maps[timestamp]["anon"]++;
				break;
			default:
				usertype_maps[timestamp]["unknown"]++;
				break;
		}
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS usertype_statistics ( timestamp INTEGER, type TEXT, count INTEGER, PRIMARY KEY (timestamp, type) );");

	for (timestamp_usertype_map_t::const_iterator i = usertype_maps.begin(); i != usertype_maps.end(); i++)
	{
		timestamp = i->first;
		usertype_map_t usertype_map = i->second;

		for (usertype_map_t::const_iterator j = usertype_map.begin(); j != usertype_map.end(); j++)
		{
			char *type = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO usertype_statistics ( timestamp, type, count ) VALUES ( %ld, '%s', 0 );", timestamp, type);
			sql_query("UPDATE usertype_statistics SET count = count + %lu WHERE timestamp = %ld AND type = '%s';", count, timestamp, type);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: usertype_maps[%ld].%s => %lu\n", timestamp, type, count);
			#endif
		}
	}
}
<commit_msg>* Add time_used statistics to udploggerstats.<commit_after>#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sqlite3.h>
#include <map>
#include "udplogger.h"
#include "udploggerparselib.h"

/*
 * Structure that contains configuration information for the running instance
 * of this udploggerstats program.
 */
struct udploggerstats_configuration_t {
	sqlite3 *data_store;
} udploggerstats_conf;

int arguments_parse(int, char **);
void hit_statistics(struct log_entry_t *, time_t);
void sql_query(const char *, ...);
void status_statistics(struct log_entry_t *, time_t);
void time_used_statistics(struct log_entry_t *, time_t);
void usersex_statistics(struct log_entry_t *, time_t);
void usertype_statistics(struct log_entry_t *, time_t);

int main (int argc, char **argv)
{
	char *line = NULL;
	size_t line_buffer_length = 0;
	ssize_t line_length = 0;
	struct log_entry_t log_data;
	int result = 0;
	time_t timestamp = 0;

	result = arguments_parse(argc, argv);
	if (result <= 0)
	{
		return result;
	}

	while ((line_length = getline(&line, &line_buffer_length, stdin)) != -1)
	{
		parse_log_line(line, &log_data);

		/*
		 * Zero the tm_sec and tm_min fields of log_data.timestamp.  We only
		 * want granularity down to the hour.  Assign the timestamp local variable
		 * to be equivalent to the log_data.timestamp struct, except for stored as
		 * a time_t rather than a struct tm.
		 */
		log_data.timestamp.tm_sec = 0;
		log_data.timestamp.tm_min = 0;
		timestamp = mktime(&(log_data.timestamp));

		hit_statistics(&log_data, timestamp);
		status_statistics(&log_data, timestamp);
		time_used_statistics(&log_data, timestamp);
		usersex_statistics(&log_data, timestamp);
		usertype_statistics(&log_data, timestamp);
	}

	hit_statistics(NULL, 0);
	status_statistics(NULL, 0);
	time_used_statistics(NULL, 0);
	usersex_statistics(NULL, 0);
	usertype_statistics(NULL, 0);

	sqlite3_close(udploggerstats_conf.data_store);
	return 0;
}

/**
 * arguments_parse(argc, argv)
 *
 * Utility function to parse the passed in arguments using getopt; also responsible for sanity-checking
 * any passed-in values and ensuring that the program's configuration is sane before returning (i.e.
 * using default values).
 **/
int arguments_parse(int argc, char **argv)
{
	int i;
	static struct option long_options[] =
	{
		{"database", required_argument, 0, 'd'},
		{"help", no_argument, 0, 'h'},
		{"version", no_argument, 0, 'v'},
		{0, 0, 0, 0}
	};
	int result;

	/* Initialize our configuration to the default settings. */
	udploggerstats_conf.data_store = NULL;

	while (1)
	{
		i = getopt_long(argc, argv, "d:hv", long_options, NULL);
		if (i == -1)
		{
			break;
		}
		switch (i)
		{
			case 'd':
				result = sqlite3_open(optarg, &(udploggerstats_conf.data_store));
				if (result != SQLITE_OK)
				{
					printf("udploggerstats.cc unable to open sqlite database '%s': %s\n", optarg, sqlite3_errmsg(udploggerstats_conf.data_store));
					udploggerstats_conf.data_store = NULL;
					return -1;
				}
				else
				{
					#ifdef __DEBUG__
						printf("udploggerstats.cc debug: opened sqlite database '%s' as data store\n", optarg);
					#endif
				}
				break;
			case 'h':
				printf("Usage: udploggerstats [OPTIONS]\n");
				printf("\n");
				printf("  -d, --database <db path>                       use <db path> as the sqlite data store for statistic storage\n");
				printf("  -h, --help                                     display this help and exit\n");
				printf("  -v, --version                                  display udploggerstats version and exit\n");
				printf("\n");
				return 0;
			case 'v':
				printf("udploggerstats.cc revision r%d\n", REVISION);
				return 0;
		}
	}

	return 1;
}

void hit_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<char *, long unsigned int> hit_map_t;
	typedef std::map<time_t, hit_map_t> timestamp_hit_map_t;
	static timestamp_hit_map_t hit_maps;

	if (data != NULL)
	{
		hit_maps[timestamp]["hits"]++;
		hit_maps[timestamp]["bytes_incoming"] += data->bytes_incoming;
		hit_maps[timestamp]["bytes_outgoing"] += data->bytes_outgoing;
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS hit_statistics ( timestamp INTEGER, hits INTEGER, bytes_incoming INTEGER, bytes_outgoing INTEGER, PRIMARY KEY (timestamp) );");

	for (timestamp_hit_map_t::const_iterator i = hit_maps.begin(); i != hit_maps.end(); i++)
	{
		timestamp = i->first;
		hit_map_t hit_map = i->second;

		sql_query("INSERT OR IGNORE INTO hit_statistics ( timestamp, hits, bytes_incoming, bytes_outgoing ) VALUES ( %ld, 0, 0, 0 );", timestamp);
		sql_query("UPDATE hit_statistics SET hits = hits + %lu, bytes_incoming = bytes_incoming + %lu, bytes_outgoing = bytes_outgoing + %lu WHERE timestamp = %ld;", hit_map["hits"], hit_map["bytes_incoming"], hit_map["bytes_outgoing"], timestamp);

		#ifdef __DEBUG__
			for (hit_map_t::const_iterator j = hit_map.begin(); j != hit_map.end(); j++)
			{
				printf("udploggerstats.cc debug: hit_maps[%ld].%s => %lu\n", timestamp, j->first, j->second);
			}
		#endif
	}
}

void sql_query(const char *sql_fmt, ...)
{
	va_list ap;
	int result = 0;
	char *sql = NULL;
	int sql_size = 200; /* Guess that we will not need more than 200 bytes to properly render sql_fmt. */
	char *sqlite_errmsg = NULL;

	if (udploggerstats_conf.data_store == NULL)
	{
		return;
	}

	while (1)
	{
		if ((sql = (char *)calloc(sql_size, sizeof(char))) == NULL)
		{
			fprintf(stderr, "udploggerstats.cc could not allocate %d bytes for sql query string\n", sql_size);
			return;
		}

		/* Attempt to render sql_fmt in the memory pointed to by sql. */
		va_start(ap, sql_fmt);
		result = vsnprintf(sql, sql_size, sql_fmt, ap);
		va_end(ap);

		if ((result > -1) && (result < sql_size))
		{
			/* We rendered the string successfully. */
			break;
		}

		/* We failed to render the string, try again with more space. */
		if (result > -1)
		{
			sql_size = result + 1; /* glibc 2.1 - use exactly as much memory as we need. */
		}
		else
		{
			sql_size *= 2; /* glibc 2.0 - double the amount of memory that we attempt to use. */
		}
		free(sql);
		sql = NULL;
	}

	#ifdef __DEBUG__
		printf("udploggerstats.cc debug: SQL format '%s' was successfully rendered to '%s'.\n", sql_fmt, sql);
	#endif

	result = sqlite3_exec(udploggerstats_conf.data_store, sql, NULL, NULL, &sqlite_errmsg);
	if (result != SQLITE_OK)
	{
		fprintf(stderr, "udploggerstats.cc SQL query: %s\n", sql);
		fprintf(stderr, "udploggerstats.cc SQL error: %s\n", sqlite_errmsg);
	}
	if (sqlite_errmsg != NULL)
	{
		sqlite3_free(sqlite_errmsg);
		sqlite_errmsg = NULL;
	}
	free(sql);
}

void status_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<short unsigned int, long unsigned int> status_map_t;
	typedef std::map<time_t, status_map_t> timestamp_status_map_t;
	static timestamp_status_map_t status_maps;

	if (data != NULL)
	{
		status_maps[timestamp][data->status]++;
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS status_statistics ( timestamp INTEGER, status INTEGER, count INTEGER, PRIMARY KEY (timestamp, status) );");

	for (timestamp_status_map_t::const_iterator i = status_maps.begin(); i != status_maps.end(); i++)
	{
		timestamp = i->first;
		status_map_t status_map = i->second;

		for (status_map_t::const_iterator j = status_map.begin(); j != status_map.end(); j++)
		{
			short unsigned int status = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO status_statistics ( timestamp, status, count ) VALUES ( %ld, %hu, 0 );", timestamp, status);
			sql_query("UPDATE status_statistics SET count = count + %lu WHERE timestamp = %ld AND status = %hu;", count, timestamp, status);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: status_maps[%ld].%hu => %lu\n", timestamp, status, count);
			#endif
		}
	}
}

void time_used_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<short int, long unsigned int> time_used_map_t;
	typedef std::map<time_t, time_used_map_t> timestamp_time_used_map_t;
	static timestamp_time_used_map_t time_used_maps;

	if (data != NULL)
	{
		if (data->time_used > 10)
		{
			/* -1 is used to represent time used of >= 11.  This is non-obvious,
			 * but then again no other value that I can think of _would_
			 * be obvious. */
			time_used_maps[timestamp][-1]++;
		}
		else
		{
			time_used_maps[timestamp][data->time_used]++;
		}
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS time_used_statistics ( timestamp INTEGER, time_used INTEGER, count INTEGER, PRIMARY KEY (timestamp, time_used) );");

	for (timestamp_time_used_map_t::const_iterator i = time_used_maps.begin(); i != time_used_maps.end(); i++)
	{
		timestamp = i->first;
		time_used_map_t time_used_map = i->second;

		for (time_used_map_t::const_iterator j = time_used_map.begin(); j != time_used_map.end(); j++)
		{
			short int time_used = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO time_used_statistics ( timestamp, time_used, count ) VALUES ( %ld, %hd, 0 );", timestamp, time_used);
			sql_query("UPDATE time_used_statistics SET count = count + %lu WHERE timestamp = %ld AND status = %hd;", count, timestamp, time_used);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: time_used_maps[%ld].%hd => %lu\n", timestamp, time_used, count);
			#endif
		}
	}
}

void usersex_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<char *, long unsigned int> usersex_map_t;
	typedef std::map<time_t, usersex_map_t> timestamp_usersex_map_t;
	static timestamp_usersex_map_t usersex_maps;

	if (data != NULL)
	{
		switch (data->nexopia_usersex)
		{
			case sex_male:
				usersex_maps[timestamp]["male"]++;
				break;
			case sex_female:
				usersex_maps[timestamp]["female"]++;
				break;
			default:
				usersex_maps[timestamp]["unknown"]++;
				break;
		}
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS usersex_statistics ( timestamp INTEGER, sex TEXT, count INTEGER, PRIMARY KEY (timestamp, sex) );");

	for (timestamp_usersex_map_t::const_iterator i = usersex_maps.begin(); i != usersex_maps.end(); i++)
	{
		timestamp = i->first;
		usersex_map_t usersex_map = i->second;

		for (usersex_map_t::const_iterator j = usersex_map.begin(); j != usersex_map.end(); j++)
		{
			char *sex = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO usersex_statistics ( timestamp, sex, count ) VALUES ( %ld, '%s', 0 );", timestamp, sex);
			sql_query("UPDATE usersex_statistics SET count = count + %lu WHERE timestamp = %ld AND sex = '%s';", count, timestamp, sex);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: usersex_maps[%ld].%s => %lu\n", timestamp, sex, count);
			#endif
		}
	}
}

void usertype_statistics(struct log_entry_t *data, time_t timestamp)
{
	typedef std::map<char *, long unsigned int> usertype_map_t;
	typedef std::map<time_t, usertype_map_t> timestamp_usertype_map_t;
	static timestamp_usertype_map_t usertype_maps;

	if (data != NULL)
	{
		switch (data->nexopia_usertype)
		{
			case usertype_plus:
				usertype_maps[timestamp]["plus"]++;
				break;
			case usertype_user:
				usertype_maps[timestamp]["user"]++;
				break;
			case usertype_anon:
				usertype_maps[timestamp]["anon"]++;
				break;
			default:
				usertype_maps[timestamp]["unknown"]++;
				break;
		}
		return;
	}

	sql_query("CREATE TABLE IF NOT EXISTS usertype_statistics ( timestamp INTEGER, type TEXT, count INTEGER, PRIMARY KEY (timestamp, type) );");

	for (timestamp_usertype_map_t::const_iterator i = usertype_maps.begin(); i != usertype_maps.end(); i++)
	{
		timestamp = i->first;
		usertype_map_t usertype_map = i->second;

		for (usertype_map_t::const_iterator j = usertype_map.begin(); j != usertype_map.end(); j++)
		{
			char *type = j->first;
			long unsigned int count = j->second;

			sql_query("INSERT OR IGNORE INTO usertype_statistics ( timestamp, type, count ) VALUES ( %ld, '%s', 0 );", timestamp, type);
			sql_query("UPDATE usertype_statistics SET count = count + %lu WHERE timestamp = %ld AND type = '%s';", count, timestamp, type);

			#ifdef __DEBUG__
				printf("udploggerstats.cc debug: usertype_maps[%ld].%s => %lu\n", timestamp, type, count);
			#endif
		}
	}
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "logging.h"

#ifndef LOG_FILE_NAME
#define LOG_FILE_NAME "output"
#endif  // LOG_FILE_NAME

void InitLog(int shell_verbose, int log_verbose) {
  namespace expressions = boost::log::expressions;
  namespace sinks = boost::log::sinks;
  namespace keywords = boost::log::keywords;
  namespace trivial = boost::log::trivial;
  namespace attributes = boost::log::attributes;
  boost::shared_ptr<boost::log::core> log_core_ = boost::log::core::get();
#ifdef LOG_TO_FILE
  // init sink1
  typedef sinks::synchronous_sink<sinks::text_file_backend> TextSink;
  boost::shared_ptr<sinks::text_file_backend> backend1 =
    boost::make_shared<sinks::text_file_backend>(
      // log filename pattern
      keywords::file_name = std::string(LOG_FILE_NAME) +
                            "_%Y-%m-%d_%H-%M-%S.%N.log",
      // rotate log when reaching 16MiB
      keywords::rotation_size = 16 * 1024 * 1024,
      // or at midnight
      keywords::time_based_rotation =
        sinks::file::rotation_at_time_point(0, 0, 0),
      // keep at least 3GiB free space
      keywords::min_free_space = 3 * 1024 * 1024);
  backend1->auto_flush(true);
  boost::shared_ptr<TextSink> sink1(new TextSink(backend1));
  sink1->set_formatter(
    expressions::format("%1%\t%2%\t%3%\t%4%:\n\t%5%")
    % expressions::format_date_time<boost::posix_time::ptime>("TimeStamp",
        "%Y-%m-%d %H:%M:%S")
    % expressions::attr<trivial::severity_level>("Severity")
    % expressions::attr<attributes::current_thread_id::value_type>("ThreadID")
    % expressions::format_named_scope("Scopes",
                                      boost::log::keywords::format = "%n (%f:%l)",
                                      boost::log::keywords::iteration = expressions::forward,
                                      boost::log::keywords::depth = 2)
    % expressions::smessage
  );

  if (log_verbose > 0) {
    sink1->set_filter(trivial::severity >= log_verbose);
  }

  log_core_->add_sink(sink1);
#endif
  // init sink2
  typedef sinks::synchronous_sink<sinks::text_ostream_backend> StreamSink;
  boost::shared_ptr<StreamSink> sink2 = boost::make_shared<StreamSink>();
  sink2->set_formatter(
    expressions::format("%1%: %2%")
    % expressions::format_date_time<boost::posix_time::ptime>("TimeStamp",
        "%H:%M:%S")
    % expressions::smessage
  );
  boost::shared_ptr<std::ostream> stream(&std::clog, boost::empty_deleter());
  sink2->locked_backend()->add_stream(stream);

  if (shell_verbose > 0) {
    sink2->set_filter(trivial::severity >= shell_verbose);
  }

  log_core_->add_sink(sink2);
  boost::log::add_common_attributes();
  log_core_->add_global_attribute("Scopes", attributes::named_scope());
}

void DeInitLog() {
  boost::log::core::get()->remove_all_sinks();
}
<commit_msg>Simpler file log.<commit_after>#include "stdafx.h"
#include "logging.h"

#ifndef LOG_FILE_NAME
#define LOG_FILE_NAME "output"
#endif  // LOG_FILE_NAME

void InitLog(int shell_verbose, int log_verbose) {
  namespace expressions = boost::log::expressions;
  namespace sinks = boost::log::sinks;
  namespace keywords = boost::log::keywords;
  namespace trivial = boost::log::trivial;
  namespace attributes = boost::log::attributes;
  boost::shared_ptr<boost::log::core> log_core_ = boost::log::core::get();
#ifdef LOG_TO_FILE
  // init sink1
  typedef sinks::synchronous_sink<sinks::text_file_backend> TextSink;
  boost::shared_ptr<sinks::text_file_backend> backend1 =
    boost::make_shared<sinks::text_file_backend>(
      // log filename pattern
      keywords::file_name = std::string(LOG_FILE_NAME) +
                            "_%Y-%m-%d_%H-%M-%S.%N.log",
      // rotate log when reaching 16MiB
      keywords::rotation_size = 16 * 1024 * 1024,
      // or at midnight
      keywords::time_based_rotation =
        sinks::file::rotation_at_time_point(0, 0, 0),
      // keep at least 3GiB free space
      keywords::min_free_space = 3 * 1024 * 1024);
  backend1->auto_flush(true);
  boost::shared_ptr<TextSink> sink1(new TextSink(backend1));
  sink1->set_formatter(
    expressions::format("%1%\t%2%:\t%3%")
    % expressions::format_date_time<boost::posix_time::ptime>("TimeStamp",
        "%Y-%m-%d %H:%M:%S")
    % expressions::attr<trivial::severity_level>("Severity")
    % expressions::smessage
    //expressions::format("%1%\t%2%\t%3%\t%4%:\n\t%5%")
    //% expressions::format_date_time<boost::posix_time::ptime>("TimeStamp",
    //    "%Y-%m-%d %H:%M:%S")
    //% expressions::attr<trivial::severity_level>("Severity")
    //% expressions::attr<attributes::current_thread_id::value_type>("ThreadID")
    //% expressions::format_named_scope("Scopes",
    //                                  boost::log::keywords::format = "%n (%f:%l)",
    //                                  boost::log::keywords::iteration = expressions::forward,
    //                                  boost::log::keywords::depth = 2)
    //% expressions::smessage
  );

  if (log_verbose > 0) {
    sink1->set_filter(trivial::severity >= log_verbose);
  }

  log_core_->add_sink(sink1);
#endif
  // init sink2
  typedef sinks::synchronous_sink<sinks::text_ostream_backend> StreamSink;
  boost::shared_ptr<StreamSink> sink2 = boost::make_shared<StreamSink>();
  sink2->set_formatter(
    expressions::format("%1%: %2%")
    % expressions::format_date_time<boost::posix_time::ptime>("TimeStamp",
        "%H:%M:%S")
    % expressions::smessage
  );
  boost::shared_ptr<std::ostream> stream(&std::clog, boost::empty_deleter());
  sink2->locked_backend()->add_stream(stream);

  if (shell_verbose > 0) {
    sink2->set_filter(trivial::severity >= shell_verbose);
  }

  log_core_->add_sink(sink2);
  boost::log::add_common_attributes();
  log_core_->add_global_attribute("Scopes", attributes::named_scope());
}

void DeInitLog() {
  boost::log::core::get()->remove_all_sinks();
}
<|endoftext|>