<commit_before>#include <fstream>
#include <iostream>
#include <chrono>
#include <cstdio>
#include <string>
#include <vector>
#include <sdbusplus/vtable.hpp>
#include <systemd/sd-bus.h>
#include <systemd/sd-journal.h>
#include "elog-lookup.cpp"
#include "config.h"
#include "elog_entry.hpp"
#include "log.hpp"
#include "log_manager.hpp"

namespace phosphor
{
namespace logging
{

void Manager::commit(uint64_t transactionId, std::string errMsg)
{
    // TODO Change /tmp path to a permanent location on flash
    constexpr const auto path = "/tmp/elog";
    constexpr const auto transactionIdVar = "TRANSACTION_ID";

    std::string filename{};
    filename.append(path);
    // TODO Create error logs in their own separate dir once permanent location
    // on flash is determined. Ex: ../transactionId/1
    std::ofstream efile;
    efile.open(filename);
    efile << "{" << std::endl;

    sd_journal *j = nullptr;
    int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
    if (rc < 0)
    {
        logging::log<logging::level::ERR>("Failed to open journal",
                           logging::entry("DESCRIPTION=%s", strerror(-rc)));
        return;
    }

    std::string transactionIdStr = std::to_string(transactionId);
    std::vector<std::string> metalist = g_errMetaMap[errMsg];
    std::vector<std::string> additionalData;

    // Read the journal from the end to get the most recent entry first.
    // The result from the sd_journal_get_data() is of the form VARIABLE=value.
    SD_JOURNAL_FOREACH_BACKWARDS(j)
    {
        const char *data = nullptr;
        size_t length = 0;

        // Look for the transaction id metadata variable
        rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
                                &length);
        if (rc < 0)
        {
            // This journal entry does not have the transaction id,
            // continue to next entry
            continue;
        }

        std::string result(data);
        if (result.find(transactionIdStr) == std::string::npos)
        {
            // Requested transaction id  not found,
            // continue to next journal entry.
            continue;
        }
        // Match found, write to file
        // TODO This is a draft format based on the redfish event logs written
        // in json, the final openbmc format is to be determined
        efile << "\t{" << std::endl;
        efile << "\t\"@" << data << "\"," << std::endl;

        // Include the journal message
        rc = sd_journal_get_data(j, "MESSAGE", (const void **)&data, &length);
        if (rc < 0)
        {
            continue;
        }

        efile << "\t\"@" << data << "\"," << std::endl;

        // Search for the metadata variables in the current journal entry
        for (auto metaVarStr : metalist)
        {
            rc = sd_journal_get_data(j, metaVarStr.c_str(),
                                    (const void **)&data, &length);
            if (rc < 0)
            {
                // Not found, continue to next metadata variable
                logging::log<logging::level::INFO>("Failed to find metadata",
                        logging::entry("META_FIELD=%s", metaVarStr.c_str()));
                continue;
            }

            // Metatdata variable found, write to file
            additionalData.push_back(std::string(data));
            efile << "\t\"@" << data << "\"," << std::endl;
        }
        efile << "\t}" << std::endl;

        // TODO Break only once all metadata fields have been found. Implement
        // once this function reads the metadata fields from the header file.
        break;
    }
    sd_journal_close(j);

    // Create error Entry dbus object
    entryId++;
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::system_clock::now().time_since_epoch()).count();
    auto objPath =  std::string(OBJ_ENTRY) + '/' +
            std::to_string(entryId);
    entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
            busLog,
            objPath,
            entryId,
            ms, // Milliseconds since 1970
            (Entry::Level)g_errLevelMap[errMsg],
            std::move(errMsg),
            std::move(additionalData))));

    efile << "}" << std::endl;
    efile.close();
    return;
}

} // namespace logging
} // namepsace phosphor
<commit_msg>Add HostEvent support to Commit interface<commit_after>#include <fstream>
#include <iostream>
#include <chrono>
#include <cstdio>
#include <string>
#include <vector>
#include <sdbusplus/vtable.hpp>
#include <systemd/sd-bus.h>
#include <systemd/sd-journal.h>
#include "elog-lookup.cpp"
#include "elog-errors-HostEvent.hpp"
#include "config.h"
#include "elog_entry.hpp"
#include "log.hpp"
#include "log_manager.hpp"

namespace phosphor
{
namespace logging
{

void Manager::commit(uint64_t transactionId, std::string errMsg)
{
    // TODO Change /tmp path to a permanent location on flash
    constexpr const auto path = "/tmp/elog";
    constexpr const auto transactionIdVar = "TRANSACTION_ID";

    std::string filename{};
    filename.append(path);
    // TODO Create error logs in their own separate dir once permanent location
    // on flash is determined. Ex: ../transactionId/1
    std::ofstream efile;
    efile.open(filename);
    efile << "{" << std::endl;

    sd_journal *j = nullptr;
    int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
    if (rc < 0)
    {
        logging::log<logging::level::ERR>("Failed to open journal",
                           logging::entry("DESCRIPTION=%s", strerror(-rc)));
        return;
    }

    std::string transactionIdStr = std::to_string(transactionId);
    std::vector<std::string> metalist = g_errMetaMap[errMsg];
    std::vector<std::string> metalistHostEvent = g_errMetaMapHostEvent[errMsg];
    std::vector<std::string> additionalData;

    // Read the journal from the end to get the most recent entry first.
    // The result from the sd_journal_get_data() is of the form VARIABLE=value.
    SD_JOURNAL_FOREACH_BACKWARDS(j)
    {
        const char *data = nullptr;
        size_t length = 0;

        // Look for the transaction id metadata variable
        rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
                                &length);
        if (rc < 0)
        {
            // This journal entry does not have the transaction id,
            // continue to next entry
            continue;
        }

        std::string result(data);
        if (result.find(transactionIdStr) == std::string::npos)
        {
            // Requested transaction id  not found,
            // continue to next journal entry.
            continue;
        }
        // Match found, write to file
        // TODO This is a draft format based on the redfish event logs written
        // in json, the final openbmc format is to be determined
        efile << "\t{" << std::endl;
        efile << "\t\"@" << data << "\"," << std::endl;

        // Include the journal message
        rc = sd_journal_get_data(j, "MESSAGE", (const void **)&data, &length);
        if (rc < 0)
        {
            continue;
        }

        efile << "\t\"@" << data << "\"," << std::endl;

        // Search for the metadata variables in the current journal entry
        for (auto metaVarStr : metalist)
        {
            rc = sd_journal_get_data(j, metaVarStr.c_str(),
                                    (const void **)&data, &length);
            if (rc < 0)
            {
                // Not found, continue to next metadata variable
                logging::log<logging::level::INFO>("Failed to find metadata",
                        logging::entry("META_FIELD=%s", metaVarStr.c_str()));
                continue;
            }

            // Metatdata variable found, write to file
            additionalData.push_back(std::string(data));
            efile << "\t\"@" << data << "\"," << std::endl;
        }
        efile << "\t}" << std::endl;

        // TODO Remove once host event error header file is auto-generated.
        // Tracking with issue openbmc/phosphor-logging#4
        for (auto metaVarStrHostEvent : metalistHostEvent)
        {
            rc = sd_journal_get_data(j, metaVarStrHostEvent.c_str(),
                                    (const void **)&data, &length);
            if (rc < 0)
            {
                // Not found, continue to next metadata variable
                logging::log<logging::level::INFO>("Failed to find metadata",
                        logging::entry("META_FIELD=%s",
                        metaVarStrHostEvent.c_str()));
                continue;
            }

            // Metatdata variable found, write to file
            additionalData.push_back(std::string(data));
            efile << "\t\"@" << data << "\"," << std::endl;
        }

        // TODO Break only once all metadata fields have been found. Implement
        // once this function reads the metadata fields from the header file.
        break;
    }
    sd_journal_close(j);

    // Create error Entry dbus object
    entryId++;
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::system_clock::now().time_since_epoch()).count();
    auto objPath =  std::string(OBJ_ENTRY) + '/' +
            std::to_string(entryId);
    entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
            busLog,
            objPath,
            entryId,
            ms, // Milliseconds since 1970
            (Entry::Level)g_errLevelMap[errMsg],
            std::move(errMsg),
            std::move(additionalData))));

    efile << "}" << std::endl;
    efile.close();
    return;
}

} // namespace logging
} // namepsace phosphor
<|endoftext|>


<commit_before>/* RTcmix - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <RTcmixMIDI.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <Option.h>

// if INBUF_SIZE is 0, PortMidi uses a default value
#define INBUF_SIZE		0
#define MSG_QUEUE_SIZE	32

enum {
	kQuitMsg = 0
};

RTcmixMIDI::RTcmixMIDI()
	: _instream(NULL), _outstream(NULL), _active(false)
{
	clear();
}

RTcmixMIDI::~RTcmixMIDI()
{
	if (_mainToMIDI) {
		long msg = kQuitMsg;
		Pm_Enqueue(_mainToMIDI, &msg);

		// wait for acknowlegement
		int spin;
		do {
			spin = Pm_Dequeue(_MIDIToMain, &msg);
		} while (spin == 0);
	}

	Pt_Stop();	// stop timer
	if (_instream)
		Pm_Close(_instream);
	if (_outstream)
		Pm_Close(_outstream);

	Pm_QueueDestroy(_mainToMIDI);
	Pm_QueueDestroy(_MIDIToMain);

	Pm_Terminate();
}

int RTcmixMIDI::init()
{
	_MIDIToMain = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(long));
	_mainToMIDI = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(long));
	if (_mainToMIDI == NULL || _MIDIToMain == NULL) {
		fprintf(stderr, "Could not create MIDI message queues.\n");
		return -1;
	}

	// Start the timer before starting MIDI I/O.  The timer runs the callback
	// function every SLEEP_MSEC milliseconds.
	Pt_Start(SLEEP_MSEC, &_processMIDI, this);

	Pm_Initialize();

	int id = 0;
	const char *devname = Option::midiInDevice();
	if (strlen(devname)) {
		const int numdev = Pm_CountDevices();
		for ( ; id < numdev; id++) {
			const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
			if (info->input) {
				if (strcmp(info->name, devname) == 0)
					break;
			}
		}
		if (id == 0 || id == numdev) {
			fprintf(stderr, "WARNING: no match for MIDI input device \"%s\""
							" ... using default.\n", devname);
			id = Pm_GetDefaultInputDeviceID();
		}
	}
	else {
		fprintf(stderr, "WARNING: using default MIDI input device.\n");
		id = Pm_GetDefaultInputDeviceID();
	}
	const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
	if (info == NULL) {
		fprintf(stderr, "Could not open MIDI input device %d.\n", id);
		return -1;
	}

	PmError err = Pm_OpenInput(&_instream, id, NULL, INBUF_SIZE, NULL, NULL);
	if (err != pmNoError) {
		fprintf(stderr, "Could not open MIDI input stream: %s.\n",
									Pm_GetErrorText(err));
		return -1;
	}

	Pm_SetFilter(_instream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);

	// Empty buffer after setting filter, in case anything got through before.
	PmEvent buffer;
	while (Pm_Poll(_instream))
		Pm_Read(_instream, &buffer, 1);

	// enable processing in MIDI thread (_processMIDI)
	active(true);

	return 0;
}

void RTcmixMIDI::clear()
{
	for (int chan = 0; chan < 16; chan++) {
		_noteonpitch[chan] = INVALID_MIDIVAL;
		_noteonvel[chan] = INVALID_MIDIVAL;
		_noteoffpitch[chan] = INVALID_MIDIVAL;
		_noteoffvel[chan] = INVALID_MIDIVAL;
		_bend[chan] = INVALID_MIDIVAL;
		_program[chan] = INVALID_MIDIVAL;
		_chanpress[chan] = INVALID_MIDIVAL;
		for (int i = 0; i < 128; i++) {
			_control[chan][i] = INVALID_MIDIVAL;
			_polypress[chan][i] = INVALID_MIDIVAL;
		}
	}
}

// FIXME: These should really pass a message from _processMIDI thread to
// main thread.  Presumably the scheduler would call
// RTcmixMIDI::checkMIDITrigger, which would dequeue such messages and
// take appropriate action, starting or stopping notes.  If instead we
// call a registered callback here, then it will be running from within
// the _processMIDI thread!  Not what we want.
// Since RTcmixMIDI is supposed to be dynamically loaded, how would scheduler
// know if and what to call?
void RTcmixMIDI::noteOnTrigger(int chan, int pitch, int velocity)
{
#ifdef NOTYET
// NB: queue elem must be struct instead of long, so as to encode message
// type plus 3 ints (for chan, pitch, vel)
	Pm_Enqueue(_mainToMIDI, &msg);
#endif
}

void RTcmixMIDI::noteOffTrigger(int chan, int pitch, int velocity)
{
}

// -------------------------------------------------------------------- dump ---
// Just for debugging.

const char *RTcmixMIDI::getValueString(const int val)
{
	if (val == INVALID_MIDIVAL)
		return "--";

	static char buf[16];
	snprintf(buf, 16, "%d", val);
	return buf;
}

void RTcmixMIDI::dump()
{
	printf("\nDumping current MIDI state...\n");
	for (int chan = 0; chan < 16; chan++) {
		printf("---------------------------------------- Channel %d\n", chan + 1);
		printf("   Bend:\t%s\n", getValueString(_bend[chan]));
		printf("   Program:\t%s\n", getValueString(_program[chan]));
		printf("   ChanPress:\t%s\n", getValueString(_chanpress[chan]));
		printf("   NoteOnPitch:\t%s\n", getValueString(_noteonpitch[chan]));
		printf("   NoteOnVel:\t%s\n", getValueString(_noteonvel[chan]));
		printf("   NoteOffPitch:\t%s\n", getValueString(_noteoffpitch[chan]));
		printf("   NoteOffVel:\t%s\n", getValueString(_noteoffvel[chan]));
		printf("   Control:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_control[chan][i]));
		printf("   PolyPress:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_polypress[chan][i]));
		printf("\n");
	}
}

// ------------------------------------------------------------ _processMIDI ---

enum {
	kNoteOff = 0x80,
	kNoteOn = 0x90,
	kPolyPress = 0xA0,
	kControl = 0xB0,
	kProgram = 0xC0,
	kChanPress = 0xD0,
	kPitchBend = 0xE0,
	kSystem = 0xF0
} StatusByte;

// This is called from the MIDI worker thread.  The RTcmixMIDI object, held by
// main thread, communicates with this worker thread by passing messages
// back and forth.
void RTcmixMIDI::_processMIDI(PtTimestamp timestamp, void *context)
{
	RTcmixMIDI *obj = (RTcmixMIDI *) context;

	// Check for messages from object.
	PmError result;
	do {
		long msg;
		result = Pm_Dequeue(obj->mainToMIDI(), &msg);
		if (result) {
			if (msg == kQuitMsg) {
				// acknowledge receipt of quit message
				Pm_Enqueue(obj->MIDIToMain(), &msg);
				obj->active(false);
				return;
			}
		}
	} while (result);

	// Don't poll MIDI until initialization completes.  We still listen for
	// object messages, in case RTcmixMIDI::init fails and dtor is then called.
	if (!obj->active())
		return;

	// See if there is any MIDI input to process.
	do {
		result = Pm_Poll(obj->instream());
		if (result) {
			PmEvent buffer;

			if (Pm_Read(obj->instream(), &buffer, 1) == pmBufferOverflow)
				continue;

			// Unless there was overflow, we should have a message now.
			const long status = Pm_MessageStatus(buffer.message);
			const long data1 = Pm_MessageData1(buffer.message);
			const long data2 = Pm_MessageData2(buffer.message);

			const long chan = status & 0x0F;

			switch (status & 0xF0) {
				case kNoteOn:
					if (data2 > 0) {
						obj->setNoteOnPitch(chan, data1);
						obj->setNoteOnVel(chan, data2);
						obj->noteOnTrigger(chan, data1, data2);
					}
					else {	// note on w/ vel=0 is logically a note off
						obj->setNoteOffPitch(chan, data1);
						obj->setNoteOffVel(chan, data2);
						obj->noteOffTrigger(chan, data1, data2);
					}
					break;
				case kNoteOff:
					obj->setNoteOffPitch(chan, data1);
					obj->setNoteOffVel(chan, data2);
					obj->noteOffTrigger(chan, data1, data2);
					break;
				case kPolyPress:
					obj->setPolyPress(chan, data1, data2);
					break;
				case kControl:
					obj->setControl(chan, data1, data2);
					break;
				case kProgram:
					obj->setProgram(chan, data1);
					break;
				case kChanPress:
					obj->setChanPress(chan, data1);
					break;
				case kPitchBend:
					obj->setBend(chan, ((data2 << 7) + data1) - 8192);
					break;
				case kSystem:
				default:
//					printf("0x%.2x, %ld, %ld\n", (u_char) status, data1, data2);
					break;
			}
		}
	} while (result);
}

RTcmixMIDI *createMIDIPort()
{
	RTcmixMIDI *midiport = new RTcmixMIDI();
	if (midiport) {
		if (midiport->init() == -1) {
			delete midiport;
			return NULL;
		}
	}

	return midiport;
}

<commit_msg>More prelim work on note triggering.<commit_after>/* RTcmix - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <RTcmixMIDI.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <Option.h>

// if INBUF_SIZE is 0, PortMidi uses a default value
#define INBUF_SIZE		0
#define MSG_QUEUE_SIZE	32		// NB: sets number of notes queued for scheduler

typedef enum {
	kQuitMsg = 0,
	kNoteOnMsg,
	kNoteOffMsg
} RTMQMessageType;

typedef struct {
	RTMQMessageType type;
	int data0;
	int data1;
	int data2;
} RTMQMessage;

RTcmixMIDI::RTcmixMIDI()
	: _instream(NULL), _outstream(NULL), _active(false)
{
	clear();
}

RTcmixMIDI::~RTcmixMIDI()
{
	if (_mainToMIDI) {
		RTMQMessage msg;
		msg.type = kQuitMsg;
		Pm_Enqueue(_mainToMIDI, &msg);

		// wait for acknowlegement
		int spin;
		do {
			spin = Pm_Dequeue(_MIDIToMain, &msg);
		} while (spin == 0);
	}

	Pt_Stop();	// stop timer
	if (_instream)
		Pm_Close(_instream);
	if (_outstream)
		Pm_Close(_outstream);

	Pm_QueueDestroy(_mainToMIDI);
	Pm_QueueDestroy(_MIDIToMain);

	Pm_Terminate();
}

RTcmixMIDI *createMIDIPort()
{
	RTcmixMIDI *midiport = new RTcmixMIDI();
	if (midiport) {
		if (midiport->init() == -1) {
			delete midiport;
			return NULL;
		}
	}

	return midiport;
}

int RTcmixMIDI::init()
{
	_MIDIToMain = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(RTMQMessage));
	_mainToMIDI = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(RTMQMessage));
	if (_mainToMIDI == NULL || _MIDIToMain == NULL) {
		fprintf(stderr, "Could not create MIDI message queues.\n");
		return -1;
	}

	// Start the timer before starting MIDI I/O.  The timer runs the callback
	// function every SLEEP_MSEC milliseconds.
	Pt_Start(SLEEP_MSEC, &_processMIDI, this);

	Pm_Initialize();

	int id = 0;
	const char *devname = Option::midiInDevice();
	if (strlen(devname)) {
		const int numdev = Pm_CountDevices();
		for ( ; id < numdev; id++) {
			const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
			if (info->input) {
				if (strcmp(info->name, devname) == 0)
					break;
			}
		}
		if (id == 0 || id == numdev) {
			fprintf(stderr, "WARNING: no match for MIDI input device \"%s\""
							" ... using default.\n", devname);
			id = Pm_GetDefaultInputDeviceID();
		}
	}
	else {
		fprintf(stderr, "WARNING: using default MIDI input device.\n");
		id = Pm_GetDefaultInputDeviceID();
	}
	const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
	if (info == NULL) {
		fprintf(stderr, "Could not open MIDI input device %d.\n", id);
		return -1;
	}

	PmError err = Pm_OpenInput(&_instream, id, NULL, INBUF_SIZE, NULL, NULL);
	if (err != pmNoError) {
		fprintf(stderr, "Could not open MIDI input stream: %s.\n",
									Pm_GetErrorText(err));
		return -1;
	}

	Pm_SetFilter(_instream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);

	// Empty buffer after setting filter, in case anything got through before.
	PmEvent buffer;
	while (Pm_Poll(_instream))
		Pm_Read(_instream, &buffer, 1);

	// enable processing in MIDI thread (_processMIDI)
	active(true);

	return 0;
}

void RTcmixMIDI::clear()
{
	for (int chan = 0; chan < 16; chan++) {
		_noteonpitch[chan] = INVALID_MIDIVAL;
		_noteonvel[chan] = INVALID_MIDIVAL;
		_noteoffpitch[chan] = INVALID_MIDIVAL;
		_noteoffvel[chan] = INVALID_MIDIVAL;
		_bend[chan] = INVALID_MIDIVAL;
		_program[chan] = INVALID_MIDIVAL;
		_chanpress[chan] = INVALID_MIDIVAL;
		for (int i = 0; i < 128; i++) {
			_control[chan][i] = INVALID_MIDIVAL;
			_polypress[chan][i] = INVALID_MIDIVAL;
		}
	}
}

// -------------------------------------------------------------------- dump ---
// Just for debugging.

const char *RTcmixMIDI::getValueString(const int val)
{
	if (val == INVALID_MIDIVAL)
		return "--";

	static char buf[16];
	snprintf(buf, 16, "%d", val);
	return buf;
}

void RTcmixMIDI::dump()
{
	printf("\nDumping current MIDI state...\n");
	for (int chan = 0; chan < 16; chan++) {
		printf("---------------------------------------- Channel %d\n", chan + 1);
		printf("   Bend:\t%s\n", getValueString(_bend[chan]));
		printf("   Program:\t%s\n", getValueString(_program[chan]));
		printf("   ChanPress:\t%s\n", getValueString(_chanpress[chan]));
		printf("   NoteOnPitch:\t%s\n", getValueString(_noteonpitch[chan]));
		printf("   NoteOnVel:\t%s\n", getValueString(_noteonvel[chan]));
		printf("   NoteOffPitch:\t%s\n", getValueString(_noteoffpitch[chan]));
		printf("   NoteOffVel:\t%s\n", getValueString(_noteoffvel[chan]));
		printf("   Control:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_control[chan][i]));
		printf("   PolyPress:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_polypress[chan][i]));
		printf("\n");
	}
}

// ------------------------------------------------------------ _processMIDI ---

enum {
	kNoteOff = 0x80,
	kNoteOn = 0x90,
	kPolyPress = 0xA0,
	kControl = 0xB0,
	kProgram = 0xC0,
	kChanPress = 0xD0,
	kPitchBend = 0xE0,
	kSystem = 0xF0
} StatusByte;

// This is called from the MIDI worker thread.  The RTcmixMIDI object, held by
// main thread, communicates with this worker thread by passing messages
// back and forth.
void RTcmixMIDI::_processMIDI(PtTimestamp timestamp, void *context)
{
	RTcmixMIDI *obj = (RTcmixMIDI *) context;

	// Check for messages from object.
	PmError result;
	do {
		RTMQMessage msg;
		result = Pm_Dequeue(obj->mainToMIDI(), &msg);
		if (result) {
			if (msg.type == kQuitMsg) {
				// acknowledge receipt of quit message
				Pm_Enqueue(obj->MIDIToMain(), &msg);
				obj->active(false);
				return;
			}
		}
	} while (result);

	// Don't poll MIDI until initialization completes.  We still listen for
	// object messages, in case RTcmixMIDI::init fails and dtor is then called.
	if (!obj->active())
		return;

	// See if there is any MIDI input to process.
	do {
		result = Pm_Poll(obj->instream());
		if (result) {
			PmEvent buffer;

			if (Pm_Read(obj->instream(), &buffer, 1) == pmBufferOverflow)
				continue;

			// Unless there was overflow, we should have a message now.
			const long status = Pm_MessageStatus(buffer.message);
			const long data1 = Pm_MessageData1(buffer.message);
			const long data2 = Pm_MessageData2(buffer.message);

			const long chan = status & 0x0F;

			switch (status & 0xF0) {
				case kNoteOn:
					if (data2 > 0) {
						obj->setNoteOnPitch(chan, data1);
						obj->setNoteOnVel(chan, data2);
						obj->noteOnTrigger(chan, data1, data2);
					}
					else {	// note on w/ vel=0 is logically a note off
						obj->setNoteOffPitch(chan, data1);
						obj->setNoteOffVel(chan, data2);
						obj->noteOffTrigger(chan, data1, data2);
					}
					break;
				case kNoteOff:
					obj->setNoteOffPitch(chan, data1);
					obj->setNoteOffVel(chan, data2);
					obj->noteOffTrigger(chan, data1, data2);
					break;
				case kPolyPress:
					obj->setPolyPress(chan, data1, data2);
					break;
				case kControl:
					obj->setControl(chan, data1, data2);
					break;
				case kProgram:
					obj->setProgram(chan, data1);
					break;
				case kChanPress:
					obj->setChanPress(chan, data1);
					break;
				case kPitchBend:
					obj->setBend(chan, ((data2 << 7) + data1) - 8192);
					break;
				case kSystem:
				default:
//					printf("0x%.2x, %ld, %ld\n", (u_char) status, data1, data2);
					break;
			}
		}
	} while (result);
}

// These functions pass a message, from the MIDI worker thread to the main
// thread, containing the data for a new noteon or noteoff event.  If we
// were to act on that data directly here, by calling a scheduler function,
// then the note would be running within the MIDI worker thread!  Not what
// we want.

// FIXME: Presumably the scheduler would call RTcmixMIDI::checkMIDITrigger,
// which would dequeue such messages and take appropriate action, starting or
// stopping notes.  Since RTcmixMIDI is supposed to be dynamically loaded, how
// would scheduler know if and what to call?

void RTcmixMIDI::noteOnTrigger(int chan, int pitch, int velocity)
{
	RTMQMessage msg;
	msg.type = kNoteOnMsg;
	msg.data0 = chan;
	msg.data1 = pitch;
	msg.data2 = velocity;
	Pm_Enqueue(_MIDIToMain, &msg);
}

void RTcmixMIDI::noteOffTrigger(int chan, int pitch, int velocity)
{
	RTMQMessage msg;
	msg.type = kNoteOffMsg;
	msg.data0 = chan;
	msg.data1 = pitch;
	msg.data2 = velocity;
	Pm_Enqueue(_MIDIToMain, &msg);
}

<|endoftext|>


<commit_before><commit_msg>Use separate code path for loading prefabs from assetlibrary<commit_after><|endoftext|>


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

#include "IECore/ObjectVector.h"

#include "boost/lexical_cast.hpp"
#include "boost/format.hpp"

using namespace IECore;

const unsigned int ObjectVector::m_ioVersion = 1;

IE_CORE_DEFINEOBJECTTYPEDESCRIPTION( ObjectVector );

ObjectVector::ObjectVector()
{
}

ObjectVector::~ObjectVector()
{
}

ObjectVector::MemberContainer &ObjectVector::members()
{
	return m_members;
}

const ObjectVector::MemberContainer &ObjectVector::members() const
{
	return m_members;
}

void ObjectVector::copyFrom( ConstObjectPtr other, CopyContext *context )
{
	Object::copyFrom( other, context );
	const ObjectVector *tOther = static_cast<const ObjectVector *>( other.get() );
	m_members.resize( tOther->m_members.size() );
	for( unsigned i=0; i<m_members.size(); i++ )
	{
		if( !tOther->m_members[i] )
		{
			m_members[i] = 0;
		}
		else
		{
			m_members[i] = context->copy<Object>( tOther->m_members[i] );
		}
	}
}

void ObjectVector::save( SaveContext *context ) const
{
	Object::save( context );
	IndexedIOInterfacePtr container = context->container( staticTypeName(), m_ioVersion );

	container->write( "size", m_members.size() );

	container->mkdir( "members" );
	container->chdir( "members" );

		unsigned i=0;
		for( MemberContainer::const_iterator it=m_members.begin(); it!=m_members.end(); it++ )
		{
			if( *it )
			{
				std::string name = str( boost::format( "%d" ) % i );
				context->save( *it, container, name );
			}
			i++;
		}

	container->chdir( ".." );
}

void ObjectVector::load( LoadContextPtr context )
{
	Object::load( context );
	unsigned int v = m_ioVersion;
	IndexedIOInterfacePtr container = context->container( staticTypeName(), v );

	MemberContainer::size_type size = m_members.size();
	container->read( "size", size );

	m_members.resize( size );
	std::fill( m_members.begin(), m_members.end(), (IECore::Object*)0 );

	container->chdir( "members" );

		IndexedIO::EntryList l = container->ls();
		for( IndexedIO::EntryList::const_iterator it=l.begin(); it!=l.end(); it++ )
		{
			MemberContainer::size_type i = boost::lexical_cast<MemberContainer::size_type>( it->id() );
			m_members[i] = context->load<Object>( container, it->id() );
		}

	container->chdir( ".." );

}

bool ObjectVector::isEqualTo( ConstObjectPtr other ) const
{
	if( !Object::isEqualTo( other ) )
	{
		return false;
	}
	ObjectVector::ConstPtr tOther = boost::static_pointer_cast<const ObjectVector>( other );
	if( m_members.size()!=tOther->m_members.size() )
	{
		return false;
	}
	for( MemberContainer::size_type i=0; i<m_members.size(); i++ )
	{
		if( m_members[i] )
		{
			if( !m_members[i]->isEqualTo( tOther->m_members[i] ) )
			{
				return false;
			}
		}
		else
		{
			if( tOther->m_members[i] )
			{
				return false;
			}
		}
	}
	return true;
}

void ObjectVector::memoryUsage( Object::MemoryAccumulator &a ) const
{
	Object::memoryUsage( a );
	for( MemberContainer::const_iterator it=m_members.begin(); it!=m_members.end(); it++ )
	{
		if( *it )
		{
			a.accumulate( *it );
		}
	}
}
<commit_msg>Fixed IO to build on the mac.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2008, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/ObjectVector.h"

#include "boost/lexical_cast.hpp"
#include "boost/format.hpp"

using namespace IECore;

const unsigned int ObjectVector::m_ioVersion = 1;

IE_CORE_DEFINEOBJECTTYPEDESCRIPTION( ObjectVector );

ObjectVector::ObjectVector()
{
}

ObjectVector::~ObjectVector()
{
}

ObjectVector::MemberContainer &ObjectVector::members()
{
	return m_members;
}

const ObjectVector::MemberContainer &ObjectVector::members() const
{
	return m_members;
}

void ObjectVector::copyFrom( ConstObjectPtr other, CopyContext *context )
{
	Object::copyFrom( other, context );
	const ObjectVector *tOther = static_cast<const ObjectVector *>( other.get() );
	m_members.resize( tOther->m_members.size() );
	for( unsigned i=0; i<m_members.size(); i++ )
	{
		if( !tOther->m_members[i] )
		{
			m_members[i] = 0;
		}
		else
		{
			m_members[i] = context->copy<Object>( tOther->m_members[i] );
		}
	}
}

void ObjectVector::save( SaveContext *context ) const
{
	Object::save( context );
	IndexedIOInterfacePtr container = context->container( staticTypeName(), m_ioVersion );

	unsigned int size = m_members.size();
	container->write( "size", size );

	container->mkdir( "members" );
	container->chdir( "members" );

		unsigned i=0;
		for( MemberContainer::const_iterator it=m_members.begin(); it!=m_members.end(); it++ )
		{
			if( *it )
			{
				std::string name = str( boost::format( "%d" ) % i );
				context->save( *it, container, name );
			}
			i++;
		}

	container->chdir( ".." );
}

void ObjectVector::load( LoadContextPtr context )
{
	Object::load( context );
	unsigned int v = m_ioVersion;
	IndexedIOInterfacePtr container = context->container( staticTypeName(), v );

	unsigned int size = 0;
	container->read( "size", size );

	m_members.resize( size );
	std::fill( m_members.begin(), m_members.end(), (IECore::Object*)0 );

	container->chdir( "members" );

		IndexedIO::EntryList l = container->ls();
		for( IndexedIO::EntryList::const_iterator it=l.begin(); it!=l.end(); it++ )
		{
			MemberContainer::size_type i = boost::lexical_cast<MemberContainer::size_type>( it->id() );
			m_members[i] = context->load<Object>( container, it->id() );
		}

	container->chdir( ".." );

}

bool ObjectVector::isEqualTo( ConstObjectPtr other ) const
{
	if( !Object::isEqualTo( other ) )
	{
		return false;
	}
	ObjectVector::ConstPtr tOther = boost::static_pointer_cast<const ObjectVector>( other );
	if( m_members.size()!=tOther->m_members.size() )
	{
		return false;
	}
	for( MemberContainer::size_type i=0; i<m_members.size(); i++ )
	{
		if( m_members[i] )
		{
			if( !m_members[i]->isEqualTo( tOther->m_members[i] ) )
			{
				return false;
			}
		}
		else
		{
			if( tOther->m_members[i] )
			{
				return false;
			}
		}
	}
	return true;
}

void ObjectVector::memoryUsage( Object::MemoryAccumulator &a ) const
{
	Object::memoryUsage( a );
	for( MemberContainer::const_iterator it=m_members.begin(); it!=m_members.end(); it++ )
	{
		if( *it )
		{
			a.accumulate( *it );
		}
	}
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

const LexerModule *LexerModule::base = 0;
int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;

LexerModule::LexerModule(int language_, LexerFunction fnLexer_,
	const char *languageName_, LexerFunction fnFolder_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	languageName(languageName_) {
	next = base;
	base = this;
	if (language == SCLEX_AUTOMATIC) {
		language = nextLanguage;
		nextLanguage++;
	}
}

const LexerModule *LexerModule::Find(int language) {
	const LexerModule *lm = base;
	while (lm) {
		if (lm->language == language) {
			return lm;
		}
		lm = lm->next;
	}
	return 0;
}

const LexerModule *LexerModule::Find(const char *languageName) {
	if (languageName) {
		const LexerModule *lm = base;
		while (lm) {
			if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) {
				return lm;
			}
			lm = lm->next;
		}
	}
	return 0;
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc-1, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}

static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
                            Accessor &styler) {
	// Null language means all style bytes are 0 so just mark the end - no need to fill in.
	if (length > 0) {
		styler.StartAt(startPos + length - 1);
		styler.StartSegment(startPos + length - 1);
		styler.ColourTo(startPos + length - 1, 0);
	}
}

LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");

#ifdef __vms
#define LINK_LEXERS
#endif

#ifdef LINK_LEXERS

// The following code forces a reference to all of the Scintilla lexers.
// If we don't do something like this, then the linker tends to "optimize"
// them away. (eric@sourcegear.com)

// Taken from wxWindow's stc.cpp. Walter.

int wxForceScintillaLexers(void) {
	return Scintilla_LinkLexers();
}

int Scintilla_LinkLexers() {
  extern LexerModule lmAda;
  extern LexerModule lmAVE;
  extern LexerModule lmBaan;
  extern LexerModule lmBatch;
  extern LexerModule lmConf;
  extern LexerModule lmCPP;
  extern LexerModule lmDiff;
  extern LexerModule lmEiffel;
  extern LexerModule lmEiffelkw;
  extern LexerModule lmErrorList;
  extern LexerModule lmHTML;
  extern LexerModule lmLatex;
  extern LexerModule lmLISP;
  extern LexerModule lmLua;
  extern LexerModule lmMake;
  extern LexerModule lmMatlab;
  extern LexerModule lmPascal;
  extern LexerModule lmPerl;
  extern LexerModule lmProps;
  extern LexerModule lmPython;
  extern LexerModule lmRuby;
  extern LexerModule lmSQL;
  extern LexerModule lmVB;
  extern LexerModule lmXML;
  extern LexerModule lmBullant;

  if (
      &lmAda
      && &lmAVE
      && &lmBaan
      && &lmConf
      && &lmDiff
      && &lmLatex
      && &lmPascal
      && &lmCPP
      && &lmHTML
      && &lmXML
      && &lmProps
      && &lmErrorList
      && &lmMake
      && &lmMatlab
      && &lmBatch
      && &lmPerl
      && &lmPython
      && &lmSQL
      && &lmVB
      && &lmRuby
      && &lmEiffel
      && &lmEiffelkw
      && &lmLISP
      && &lmLua
      && &lmNull
      && &lmBullant
      )
    {
      return 1;
    }
  else
    {
      return 0;
    }
}
#endif
<commit_msg>Changed back to lexing full length rather than 1 less.<commit_after>// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

const LexerModule *LexerModule::base = 0;
int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;

LexerModule::LexerModule(int language_, LexerFunction fnLexer_,
	const char *languageName_, LexerFunction fnFolder_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	languageName(languageName_) {
	next = base;
	base = this;
	if (language == SCLEX_AUTOMATIC) {
		language = nextLanguage;
		nextLanguage++;
	}
}

const LexerModule *LexerModule::Find(int language) {
	const LexerModule *lm = base;
	while (lm) {
		if (lm->language == language) {
			return lm;
		}
		lm = lm->next;
	}
	return 0;
}

const LexerModule *LexerModule::Find(const char *languageName) {
	if (languageName) {
		const LexerModule *lm = base;
		while (lm) {
			if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) {
				return lm;
			}
			lm = lm->next;
		}
	}
	return 0;
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}

static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
                            Accessor &styler) {
	// Null language means all style bytes are 0 so just mark the end - no need to fill in.
	if (length > 0) {
		styler.StartAt(startPos + length - 1);
		styler.StartSegment(startPos + length - 1);
		styler.ColourTo(startPos + length - 1, 0);
	}
}

LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");

#ifdef __vms
#define LINK_LEXERS
#endif

#ifdef LINK_LEXERS

// The following code forces a reference to all of the Scintilla lexers.
// If we don't do something like this, then the linker tends to "optimize"
// them away. (eric@sourcegear.com)

// Taken from wxWindow's stc.cpp. Walter.

int wxForceScintillaLexers(void) {
	return Scintilla_LinkLexers();
}

int Scintilla_LinkLexers() {
  extern LexerModule lmAda;
  extern LexerModule lmAVE;
  extern LexerModule lmBaan;
  extern LexerModule lmBatch;
  extern LexerModule lmConf;
  extern LexerModule lmCPP;
  extern LexerModule lmDiff;
  extern LexerModule lmEiffel;
  extern LexerModule lmEiffelkw;
  extern LexerModule lmErrorList;
  extern LexerModule lmHTML;
  extern LexerModule lmLatex;
  extern LexerModule lmLISP;
  extern LexerModule lmLua;
  extern LexerModule lmMake;
  extern LexerModule lmMatlab;
  extern LexerModule lmPascal;
  extern LexerModule lmPerl;
  extern LexerModule lmProps;
  extern LexerModule lmPython;
  extern LexerModule lmRuby;
  extern LexerModule lmSQL;
  extern LexerModule lmVB;
  extern LexerModule lmXML;
  extern LexerModule lmBullant;

  if (
      &lmAda
      && &lmAVE
      && &lmBaan
      && &lmConf
      && &lmDiff
      && &lmLatex
      && &lmPascal
      && &lmCPP
      && &lmHTML
      && &lmXML
      && &lmProps
      && &lmErrorList
      && &lmMake
      && &lmMatlab
      && &lmBatch
      && &lmPerl
      && &lmPython
      && &lmSQL
      && &lmVB
      && &lmRuby
      && &lmEiffel
      && &lmEiffelkw
      && &lmLISP
      && &lmLua
      && &lmNull
      && &lmBullant
      )
    {
      return 1;
    }
  else
    {
      return 0;
    }
}
#endif
<|endoftext|>


<commit_before><commit_msg>Added missing dummy return statements.<commit_after><|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkBitmapProcShader.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkPixelRef.h"

bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
    switch (bm.config()) {
        case SkBitmap::kA8_Config:
        case SkBitmap::kRGB_565_Config:
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
    //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
                return true;
        default:
            break;
    }
    return false;
}

SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy) {
    fRawBitmap = src;
    fState.fTileModeX = (uint8_t)tmx;
    fState.fTileModeY = (uint8_t)tmy;
    fFlags = 0; // computed in setContext
}

SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer) {
    buffer.readBitmap(&fRawBitmap);
    fState.fTileModeX = buffer.readUInt();
    fState.fTileModeY = buffer.readUInt();
    fFlags = 0; // computed in setContext
}

void SkBitmapProcShader::beginSession() {
    this->INHERITED::beginSession();

    fRawBitmap.lockPixels();
}

void SkBitmapProcShader::endSession() {
    fRawBitmap.unlockPixels();

    this->INHERITED::endSession();
}

SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
                                                   SkMatrix* texM,
                                                   TileMode xy[]) const {
    if (texture) {
        *texture = fRawBitmap;
    }
    if (texM) {
        texM->reset();
    }
    if (xy) {
        xy[0] = (TileMode)fState.fTileModeX;
        xy[1] = (TileMode)fState.fTileModeY;
    }
    return kDefault_BitmapType;
}

void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);

    buffer.writeBitmap(fRawBitmap);
    buffer.writeUInt(fState.fTileModeX);
    buffer.writeUInt(fState.fTileModeY);
}

static bool only_scale_and_translate(const SkMatrix& matrix) {
    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    return (matrix.getType() & ~mask) == 0;
}

bool SkBitmapProcShader::isOpaque() const {
    return fRawBitmap.isOpaque();
}

bool SkBitmapProcShader::setContext(const SkBitmap& device,
                                    const SkPaint& paint,
                                    const SkMatrix& matrix) {
    // do this first, so we have a correct inverse matrix
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    fState.fOrigBitmap = fRawBitmap;
    fState.fOrigBitmap.lockPixels();
    if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
        fState.fOrigBitmap.unlockPixels();
        return false;
    }

    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
        return false;
    }

    const SkBitmap& bitmap = *fState.fBitmap;
    bool bitmapIsOpaque = bitmap.isOpaque();

    // update fFlags
    uint32_t flags = 0;
    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
        flags |= kOpaqueAlpha_Flag;
    }

    switch (bitmap.config()) {
        case SkBitmap::kRGB_565_Config:
            flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
            break;
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
            if (bitmapIsOpaque) {
                flags |= kHasSpan16_Flag;
            }
            break;
        case SkBitmap::kA8_Config:
            break;  // never set kHasSpan16_Flag
        default:
            break;
    }

    if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
        // gradients can auto-dither in their 16bit sampler, but we don't so
        // we clear the flag here.
        flags &= ~kHasSpan16_Flag;
    }

    // if we're only 1-pixel heigh, and we don't rotate, then we can claim this
    if (1 == bitmap.height() &&
            only_scale_and_translate(this->getTotalInverse())) {
        flags |= kConstInY32_Flag;
        if (flags & kHasSpan16_Flag) {
            flags |= kConstInY16_Flag;
        }
    }

    fFlags = flags;
    return true;
}

#define BUF_MAX     128

#define TEST_BUFFER_OVERRITEx

#ifdef TEST_BUFFER_OVERRITE
    #define TEST_BUFFER_EXTRA   32
    #define TEST_PATTERN    0x88888888
#else
    #define TEST_BUFFER_EXTRA   0
#endif

void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc32()) {
        state.getShaderProc32()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
    int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        SkASSERT(n > 0 && n < BUF_MAX*2);
#ifdef TEST_BUFFER_OVERRITE
        for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
            buffer[BUF_MAX + i] = TEST_PATTERN;
        }
#endif
        mproc(state, buffer, n, x, y);
#ifdef TEST_BUFFER_OVERRITE
        for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
            SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
        }
#endif
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        SkASSERT(count > 0);
        x += n;
        dstC += n;
    }
}

SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
    if (fState.getShaderProc32()) {
        *ctx = &fState;
        return (ShadeProc)fState.getShaderProc32();
    }
    return NULL;
}

void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc16()) {
        state.getShaderProc16()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
    int max = fState.maxCountForBufferSize(sizeof(buffer));

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        mproc(state, buffer, n, x, y);
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        x += n;
        dstC += n;
    }
}

///////////////////////////////////////////////////////////////////////////////

#include "SkUnPreMultiply.h"
#include "SkColorShader.h"
#include "SkEmptyShader.h"

// returns true and set color if the bitmap can be drawn as a single color
// (for efficiency)
static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
    if (1 != bm.width() || 1 != bm.height()) {
        return false;
    }

    SkAutoLockPixels alp(bm);
    if (!bm.readyToDraw()) {
        return false;
    }

    switch (bm.config()) {
        case SkBitmap::kARGB_8888_Config:
            *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
            return true;
        case SkBitmap::kRGB_565_Config:
            *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
            return true;
        case SkBitmap::kIndex8_Config:
            *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
            return true;
        default: // just skip the other configs for now
            break;
    }
    return false;
}

#include "SkTemplatesPriv.h"

static bool bitmapIsTooBig(const SkBitmap& bm) {
    // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
    // communicates between its matrix-proc and its sampler-proc. Until we can
    // widen that, we have to reject bitmaps that are larger.
    //
    const int maxSize = 65535;

    return bm.width() > maxSize || bm.height() > maxSize;
}

SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy,
                                       void* storage, size_t storageSize) {
    SkShader* shader;
    SkColor color;
    if (src.isNull() || bitmapIsTooBig(src)) {
        SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
    }
    else if (canUseColorShader(src, &color)) {
        SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
                              (color));
    } else {
        SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
                              storageSize, (src, tmx, tmy));
    }
    return shader;
}

///////////////////////////////////////////////////////////////////////////////

static const char* gTileModeName[] = {
    "clamp", "repeat", "mirror"
};

bool SkBitmapProcShader::toDumpString(SkString* str) const {
    str->printf("BitmapShader: [%d %d %d",
                fRawBitmap.width(), fRawBitmap.height(),
                fRawBitmap.bytesPerPixel());

    // add the pixelref
    SkPixelRef* pr = fRawBitmap.pixelRef();
    if (pr) {
        const char* uri = pr->getURI();
        if (uri) {
            str->appendf(" \"%s\"", uri);
        }
    }

    // add the (optional) matrix
    {
        if (this->hasLocalMatrix()) {
            SkString info;
            this->getLocalMatrix().toDumpString(&info);
            str->appendf(" %s", info.c_str());
        }
    }

    str->appendf(" [%s %s]]",
                 gTileModeName[fState.fTileModeX],
                 gTileModeName[fState.fTileModeY]);
    return true;
}

<commit_msg>mark our unflattened bitmap as immutable (just as picture deserialization does)<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkBitmapProcShader.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkPixelRef.h"

bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
    switch (bm.config()) {
        case SkBitmap::kA8_Config:
        case SkBitmap::kRGB_565_Config:
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
    //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
                return true;
        default:
            break;
    }
    return false;
}

SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy) {
    fRawBitmap = src;
    fState.fTileModeX = (uint8_t)tmx;
    fState.fTileModeY = (uint8_t)tmy;
    fFlags = 0; // computed in setContext
}

SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer) {
    buffer.readBitmap(&fRawBitmap);
    fRawBitmap.setImmutable();
    fState.fTileModeX = buffer.readUInt();
    fState.fTileModeY = buffer.readUInt();
    fFlags = 0; // computed in setContext
}

void SkBitmapProcShader::beginSession() {
    this->INHERITED::beginSession();

    fRawBitmap.lockPixels();
}

void SkBitmapProcShader::endSession() {
    fRawBitmap.unlockPixels();

    this->INHERITED::endSession();
}

SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
                                                   SkMatrix* texM,
                                                   TileMode xy[]) const {
    if (texture) {
        *texture = fRawBitmap;
    }
    if (texM) {
        texM->reset();
    }
    if (xy) {
        xy[0] = (TileMode)fState.fTileModeX;
        xy[1] = (TileMode)fState.fTileModeY;
    }
    return kDefault_BitmapType;
}

void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);

    buffer.writeBitmap(fRawBitmap);
    buffer.writeUInt(fState.fTileModeX);
    buffer.writeUInt(fState.fTileModeY);
}

static bool only_scale_and_translate(const SkMatrix& matrix) {
    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    return (matrix.getType() & ~mask) == 0;
}

bool SkBitmapProcShader::isOpaque() const {
    return fRawBitmap.isOpaque();
}

bool SkBitmapProcShader::setContext(const SkBitmap& device,
                                    const SkPaint& paint,
                                    const SkMatrix& matrix) {
    // do this first, so we have a correct inverse matrix
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    fState.fOrigBitmap = fRawBitmap;
    fState.fOrigBitmap.lockPixels();
    if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
        fState.fOrigBitmap.unlockPixels();
        return false;
    }

    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
        return false;
    }

    const SkBitmap& bitmap = *fState.fBitmap;
    bool bitmapIsOpaque = bitmap.isOpaque();

    // update fFlags
    uint32_t flags = 0;
    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
        flags |= kOpaqueAlpha_Flag;
    }

    switch (bitmap.config()) {
        case SkBitmap::kRGB_565_Config:
            flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
            break;
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
            if (bitmapIsOpaque) {
                flags |= kHasSpan16_Flag;
            }
            break;
        case SkBitmap::kA8_Config:
            break;  // never set kHasSpan16_Flag
        default:
            break;
    }

    if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
        // gradients can auto-dither in their 16bit sampler, but we don't so
        // we clear the flag here.
        flags &= ~kHasSpan16_Flag;
    }

    // if we're only 1-pixel heigh, and we don't rotate, then we can claim this
    if (1 == bitmap.height() &&
            only_scale_and_translate(this->getTotalInverse())) {
        flags |= kConstInY32_Flag;
        if (flags & kHasSpan16_Flag) {
            flags |= kConstInY16_Flag;
        }
    }

    fFlags = flags;
    return true;
}

#define BUF_MAX     128

#define TEST_BUFFER_OVERRITEx

#ifdef TEST_BUFFER_OVERRITE
    #define TEST_BUFFER_EXTRA   32
    #define TEST_PATTERN    0x88888888
#else
    #define TEST_BUFFER_EXTRA   0
#endif

void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc32()) {
        state.getShaderProc32()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
    int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        SkASSERT(n > 0 && n < BUF_MAX*2);
#ifdef TEST_BUFFER_OVERRITE
        for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
            buffer[BUF_MAX + i] = TEST_PATTERN;
        }
#endif
        mproc(state, buffer, n, x, y);
#ifdef TEST_BUFFER_OVERRITE
        for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
            SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
        }
#endif
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        SkASSERT(count > 0);
        x += n;
        dstC += n;
    }
}

SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
    if (fState.getShaderProc32()) {
        *ctx = &fState;
        return (ShadeProc)fState.getShaderProc32();
    }
    return NULL;
}

void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc16()) {
        state.getShaderProc16()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
    int max = fState.maxCountForBufferSize(sizeof(buffer));

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        mproc(state, buffer, n, x, y);
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        x += n;
        dstC += n;
    }
}

///////////////////////////////////////////////////////////////////////////////

#include "SkUnPreMultiply.h"
#include "SkColorShader.h"
#include "SkEmptyShader.h"

// returns true and set color if the bitmap can be drawn as a single color
// (for efficiency)
static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
    if (1 != bm.width() || 1 != bm.height()) {
        return false;
    }

    SkAutoLockPixels alp(bm);
    if (!bm.readyToDraw()) {
        return false;
    }

    switch (bm.config()) {
        case SkBitmap::kARGB_8888_Config:
            *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
            return true;
        case SkBitmap::kRGB_565_Config:
            *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
            return true;
        case SkBitmap::kIndex8_Config:
            *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
            return true;
        default: // just skip the other configs for now
            break;
    }
    return false;
}

#include "SkTemplatesPriv.h"

static bool bitmapIsTooBig(const SkBitmap& bm) {
    // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
    // communicates between its matrix-proc and its sampler-proc. Until we can
    // widen that, we have to reject bitmaps that are larger.
    //
    const int maxSize = 65535;

    return bm.width() > maxSize || bm.height() > maxSize;
}

SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy,
                                       void* storage, size_t storageSize) {
    SkShader* shader;
    SkColor color;
    if (src.isNull() || bitmapIsTooBig(src)) {
        SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
    }
    else if (canUseColorShader(src, &color)) {
        SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
                              (color));
    } else {
        SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
                              storageSize, (src, tmx, tmy));
    }
    return shader;
}

///////////////////////////////////////////////////////////////////////////////

static const char* gTileModeName[] = {
    "clamp", "repeat", "mirror"
};

bool SkBitmapProcShader::toDumpString(SkString* str) const {
    str->printf("BitmapShader: [%d %d %d",
                fRawBitmap.width(), fRawBitmap.height(),
                fRawBitmap.bytesPerPixel());

    // add the pixelref
    SkPixelRef* pr = fRawBitmap.pixelRef();
    if (pr) {
        const char* uri = pr->getURI();
        if (uri) {
            str->appendf(" \"%s\"", uri);
        }
    }

    // add the (optional) matrix
    {
        if (this->hasLocalMatrix()) {
            SkString info;
            this->getLocalMatrix().toDumpString(&info);
            str->appendf(" %s", info.c_str());
        }
    }

    str->appendf(" [%s %s]]",
                 gTileModeName[fState.fTileModeX],
                 gTileModeName[fState.fTileModeY]);
    return true;
}

<|endoftext|>


<commit_before>/*
 * Use and distribution licensed under the Apache license version 2.
 *
 * See the COPYING file in the root project directory for full text.
 */

#include "sqltoast.h"

#include "parser/error.h"
#include "parser/parse.h"

namespace sqltoast {

// <insert statement> ::= INSERT INTO <table name> <insert columns and source>
//
// <insert columns and source> ::=
//     [ <left paren> <insert column list> <right paren> ] <query expression>
//     | DEFAULT VALUES
//
// <insert column list> ::= <column name list>
bool parse_insert(
        parse_context_t& ctx,
        token_t& cur_tok,
        std::unique_ptr<statement_t>& out) {
    lexer_t& lex = ctx.lexer;
    parse_position_t start = ctx.lexer.cursor;
    lexeme_t table_name;
    symbol_t cur_sym;
    std::vector<lexeme_t> col_list;

    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_INSERT) {
        ctx.lexer.cursor = start;
        return false;
    }
    cur_tok = lex.next();
    goto expect_into;
expect_into:
    // We get here after successfully finding INSERT. We now need to find the
    // INTO symbol.
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_INTO)
        goto err_expect_into;
    cur_tok = lex.next();
    goto expect_identifier;
err_expect_into:
    expect_error(ctx, SYMBOL_INTO);
    return false;
expect_identifier:
    // We get here after successfully finding INSERT followed by INTO. We
    // now need to find the table identifier
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_IDENTIFIER)
        goto err_expect_identifier;
    table_name = cur_tok.lexeme;
    cur_tok = lex.next();
    goto insert_col_list_or_default_values;
err_expect_identifier:
    expect_error(ctx, SYMBOL_IDENTIFIER);
    return false;
insert_col_list_or_default_values:
    cur_sym = cur_tok.symbol;
    if (cur_sym == SYMBOL_DEFAULT) {
        cur_tok = lex.next();
        goto expect_default_values;
    } else if (cur_sym == SYMBOL_LPAREN) {
        cur_tok = lex.next();
        goto process_column_list_item;
    }
    goto err_expect_lparen_or_default;
err_expect_lparen_or_default:
    expect_any_error(ctx, {SYMBOL_DEFAULT, SYMBOL_LPAREN});
    return false;
expect_default_values:
    // We get here after successfully finding DEFAULT, which must be followed
    // by the VALUES symbol
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_VALUES)
        goto err_expect_values;
    cur_tok = lex.next();
    goto statement_ending;
err_expect_values:
    expect_error(ctx, SYMBOL_VALUES);
    return false;
process_column_list_item:
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_IDENTIFIER)
        goto err_expect_identifier;
    col_list.emplace_back(cur_tok.lexeme);
    cur_tok = lex.next();
    cur_sym = cur_tok.symbol;
    if (cur_sym == SYMBOL_COMMA) {
        cur_tok = lex.next();
        goto process_column_list_item;
    } else if (cur_sym == SYMBOL_RPAREN) {
        cur_tok = lex.next();
        goto statement_ending;
    }
    goto err_expect_comma_or_rparen;
err_expect_comma_or_rparen:
    expect_any_error(ctx, {SYMBOL_COMMA, SYMBOL_RPAREN});
    return false;
statement_ending:
    // We get here after successfully parsing the <table name> element,
    // which must be followed by the <insert columns and source> element
    // behaviour clause>
    cur_sym = cur_tok.symbol;
    if (cur_sym == SYMBOL_SEMICOLON || cur_sym == SYMBOL_EOS) {
        goto push_statement;
    }
    expect_any_error(ctx, {SYMBOL_EOS, SYMBOL_SEMICOLON});
    return false;
push_statement:
    if (ctx.opts.disable_statement_construction)
        return true;
    if (col_list.empty())
        out = std::make_unique<insert_t>(table_name);
    else
        out = std::make_unique<insert_t>(table_name, col_list);
    return true;
}

} // namespace sqltoast
<commit_msg>Support not having a column list or default values<commit_after>/*
 * Use and distribution licensed under the Apache license version 2.
 *
 * See the COPYING file in the root project directory for full text.
 */

#include "sqltoast.h"

#include "parser/error.h"
#include "parser/parse.h"

namespace sqltoast {

// <insert statement> ::= INSERT INTO <table name> <insert columns and source>
//
// <insert columns and source> ::=
//     [ <left paren> <insert column list> <right paren> ] <query expression>
//     | DEFAULT VALUES
//
// <insert column list> ::= <column name list>
bool parse_insert(
        parse_context_t& ctx,
        token_t& cur_tok,
        std::unique_ptr<statement_t>& out) {
    lexer_t& lex = ctx.lexer;
    parse_position_t start = ctx.lexer.cursor;
    lexeme_t table_name;
    symbol_t cur_sym;
    std::vector<lexeme_t> col_list;

    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_INSERT) {
        ctx.lexer.cursor = start;
        return false;
    }
    cur_tok = lex.next();
    goto expect_into;
expect_into:
    // We get here after successfully finding INSERT. We now need to find the
    // INTO symbol.
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_INTO)
        goto err_expect_into;
    cur_tok = lex.next();
    goto expect_identifier;
err_expect_into:
    expect_error(ctx, SYMBOL_INTO);
    return false;
expect_identifier:
    // We get here after successfully finding INSERT followed by INTO. We
    // now need to find the table identifier
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_IDENTIFIER)
        goto err_expect_identifier;
    table_name = cur_tok.lexeme;
    cur_tok = lex.next();
    goto opt_col_list_or_default_values;
err_expect_identifier:
    expect_error(ctx, SYMBOL_IDENTIFIER);
    return false;
opt_col_list_or_default_values:
    cur_sym = cur_tok.symbol;
    if (cur_sym == SYMBOL_DEFAULT) {
        cur_tok = lex.next();
        goto expect_default_values;
    } else if (cur_sym == SYMBOL_LPAREN) {
        cur_tok = lex.next();
        goto process_column_list_item;
    } else if (cur_sym == SYMBOL_VALUES) {
        cur_tok = lex.next();
        goto statement_ending;
    }
    goto err_expect_lparen_values_or_default;
err_expect_lparen_values_or_default:
    expect_any_error(ctx, {SYMBOL_DEFAULT, SYMBOL_VALUES, SYMBOL_LPAREN});
    return false;
expect_default_values:
    // We get here after successfully finding DEFAULT, which must be followed
    // by the VALUES symbol
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_VALUES)
        goto err_expect_values;
    cur_tok = lex.next();
    goto statement_ending;
err_expect_values:
    expect_error(ctx, SYMBOL_VALUES);
    return false;
process_column_list_item:
    cur_sym = cur_tok.symbol;
    if (cur_sym != SYMBOL_IDENTIFIER)
        goto err_expect_identifier;
    col_list.emplace_back(cur_tok.lexeme);
    cur_tok = lex.next();
    cur_sym = cur_tok.symbol;
    if (cur_sym == SYMBOL_COMMA) {
        cur_tok = lex.next();
        goto process_column_list_item;
    } else if (cur_sym == SYMBOL_RPAREN) {
        cur_tok = lex.next();
        goto statement_ending;
    }
    goto err_expect_comma_or_rparen;
err_expect_comma_or_rparen:
    expect_any_error(ctx, {SYMBOL_COMMA, SYMBOL_RPAREN});
    return false;
statement_ending:
    // We get here after successfully parsing the <table name> element,
    // which must be followed by the <insert columns and source> element
    // behaviour clause>
    cur_sym = cur_tok.symbol;
    if (cur_sym == SYMBOL_SEMICOLON || cur_sym == SYMBOL_EOS) {
        goto push_statement;
    }
    expect_any_error(ctx, {SYMBOL_EOS, SYMBOL_SEMICOLON});
    return false;
push_statement:
    if (ctx.opts.disable_statement_construction)
        return true;
    if (col_list.empty())
        out = std::make_unique<insert_t>(table_name);
    else
        out = std::make_unique<insert_t>(table_name, col_list);
    return true;
}

} // namespace sqltoast
<|endoftext|>


<commit_before>/*
 * DesktopMain.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

// TODO: test on other platforms

// TODO: make sure file assocs still open in existing (.R)

// TODO: open -a RStudio on the Mac

#include <QtGui>
#include <QtWebKit>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>

#include <core/Log.hpp>

#include <core/system/FileScanner.hpp>
#include <core/Error.hpp>
#include <core/FileInfo.hpp>
#include <core/FilePath.hpp>
#include <core/SafeConvert.hpp>
#include <core/StringUtils.hpp>
#include <core/system/System.hpp>
#include <core/system/Environment.hpp>
#include <core/r_util/RProjectFile.hpp>

#include "DesktopApplicationLaunch.hpp"
#include "DesktopSlotBinders.hpp"
#include "DesktopDetectRHome.hpp"
#include "DesktopOptions.hpp"
#include "DesktopUtils.hpp"
#include "DesktopSessionLauncher.hpp"

QProcess* pRSessionProcess;
QString sharedSecret;

using namespace core;
using namespace desktop;

namespace {

void initializeSharedSecret()
{
   sharedSecret = QString::number(rand())
                  + QString::number(rand())
                  + QString::number(rand());
   std::string value = sharedSecret.toUtf8().constData();
   core::system::setenv("RS_SHARED_SECRET", value);
}

void initializeWorkingDirectory(int argc,
                                char* argv[],
                                const QString& filename)
{
   // calculate what our initial working directory should be
   std::string workingDir;

   // if there is a filename passed to us then use it's path
   if (filename != QString())
   {
      FilePath filePath(filename.toUtf8().constData());
      if (filePath.exists())
      {
         if (filePath.isDirectory())
            workingDir = filePath.absolutePath();
         else
            workingDir = filePath.parent().absolutePath();
      }
   }

   // do additinal detection if necessary
   if (workingDir.empty())
   {
      // get current path
      FilePath currentPath = FilePath::safeCurrentPath(
                                       core::system::userHomePath());

#if defined(_WIN32) || defined(__APPLE__)

      // detect whether we were launched from the system application menu
      // (e.g. Dock, Program File icon, etc.). we do this by checking
      // whether the executable path is within the current path. if we
      // weren't launched from the system app menu that set the initial
      // wd to the current path

      FilePath exePath;
      Error error = core::system::executablePath(argc, argv, &exePath);
      if (!error)
      {
         if (!exePath.isWithin(currentPath))
            workingDir = currentPath.absolutePath();
      }
      else
      {
         LOG_ERROR(error);
      }

#else

      // on linux we take the current working dir if we were launched
      // from within a terminal
      if (core::system::stdoutIsTerminal())
      {
         workingDir = currentPath.absolutePath();
      }

#endif

   }

   // set the working dir if we have one
   if (!workingDir.empty())
      core::system::setenv("RS_INITIAL_WD", workingDir);
}

void setInitialProject(const FilePath& projectFile, QString* pFilename)
{
   core::system::setenv("RS_INITIAL_PROJECT", projectFile.absolutePath());
   pFilename->clear();
}

void initializeStartupEnvironment(QString* pFilename)
{
   // if the filename ends with .RData or .rda then this is an
   // environment file. if it ends with .Rproj then it is
   // a project file. we handle both cases by setting an environment
   // var and then resetting the pFilename so it isn't processed
   // using the standard open file logic
   FilePath filePath(pFilename->toUtf8().constData());
   if (filePath.exists())
   {
      std::string ext = filePath.extensionLowerCase();

      // if it is a directory or just an .rdata file then we can see
      // whether there is a project file we can automatically attach to
      if (filePath.isDirectory())
      {
         FilePath projectFile = r_util::projectFromDirectory(filePath);
         if (!projectFile.empty())
         {
            setInitialProject(projectFile, pFilename);
         }
      }
      else if (ext == ".rproj")
      {
         setInitialProject(filePath, pFilename);
      }
      else if (ext == ".rdata" || ext == ".rda")
      {
         core::system::setenv("RS_INITIAL_ENV", filePath.absolutePath());
         pFilename->clear();
      }

   }
}

QString verifyAndNormalizeFilename(QString filename)
{
   if (filename.isNull() || filename.isEmpty())
      return QString();

   QFileInfo fileInfo(filename);
   if (fileInfo.exists())
      return fileInfo.absoluteFilePath();
   else
      return QString();
}

bool isNonProjectFilename(QString filename)
{
   if (filename.isNull() || filename.isEmpty())
      return false;

   FilePath filePath(filename.toUtf8().constData());
   return filePath.exists() && filePath.extensionLowerCase() != ".rproj";
}

bool dummy(const FileInfo& file)
{
   return true;
}

} // anonymous namespace

int main(int argc, char* argv[])
{
   core::system::initHook();

   try
   {
      QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

      // initialize log
      FilePath userHomePath = core::system::userHomePath("R_USER|HOME");
      FilePath logPath = core::system::userSettingsPath(
            userHomePath,
            "RStudio-Desktop").childPath("log");
      core::system::initializeLog("rdesktop",
                                  core::system::kLogLevelWarning,
                                  logPath);

      boost::scoped_ptr<QApplication> pApp;
      boost::scoped_ptr<ApplicationLaunch> pAppLaunch;
      ApplicationLaunch::init(QString::fromAscii("RStudio"),
                              argc,
                              argv,
                              &pApp,
                              &pAppLaunch);

      // determine the filename that was passed to us
      QString filename;
#ifdef __APPLE__
      // get filename from OpenFile apple-event (pump to ensure delivery)
      pApp->processEvents();
      filename = verifyAndNormalizeFilename(
                              pAppLaunch->startupOpenFileRequest());
#endif
      // allow all platforms (including OSX) to check the command line.
      // we include OSX because the way Qt handles apple events is to
      // re-route them to the first instance to register for events. in
      // this case (for projects) we use this to initiate a launch
      // of the application with the project filename on the command line
      if (filename.isEmpty())
      {
         // get filename from command line arguments
         if (pApp->arguments().size() > 1)
            filename = verifyAndNormalizeFilename(pApp->arguments().last());
      }

      // if we have a filename and it is NOT a project file then see
      // if we can open it within an existing instance
      if (isNonProjectFilename(filename))
      {
         if (pAppLaunch->sendMessage(filename))
            return 0;
      }

      pApp->setAttribute(Qt::AA_MacDontSwapCtrlAndMeta);

      initializeSharedSecret();
      initializeWorkingDirectory(argc, argv, filename);
      initializeStartupEnvironment(&filename);

      Options& options = desktop::options();
      if (!prepareEnvironment(options))
         return 1;

      // get install path
      FilePath installPath;
      Error error = core::system::installPath("..", argc, argv, &installPath);
      if (error)
      {
         LOG_ERROR(error);
         return EXIT_FAILURE;
      }

#ifdef _WIN32
      RVersion version = detectRVersion(false);
#endif

      // calculate paths to config file and rsession
      FilePath confPath, sessionPath;

      // check for debug configuration
#ifndef NDEBUG
      FilePath currentPath = FilePath::safeCurrentPath(installPath);
      if (currentPath.complete("conf/rdesktop-dev.conf").exists())
      {
         confPath = currentPath.complete("conf/rdesktop-dev.conf");
         sessionPath = currentPath.complete("session/rsession");
#ifdef _WIN32
         if (version.architecture() == ArchX64)
            sessionPath = installPath.complete("x64/rsession");
#endif
      }
#endif

      // if there is no conf path then release mode
      if (confPath.empty())
      {
         // default session path (then tweak)
         sessionPath = installPath.complete("bin/rsession");

         // check for win64 binary on windows
#ifdef _WIN32
         if (version.architecture() == ArchX64)
            sessionPath = installPath.complete("bin/x64/rsession");
#endif

         // check for running in a bundle on OSX
#ifdef __APPLE__
         if (installPath.complete("Info.plist").exists())
            sessionPath = installPath.complete("MacOS/rsession");
#endif
      }
      core::system::fixupExecutablePath(&sessionPath);

      // launch session
      SessionLauncher sessionLauncher(sessionPath, confPath);
      error = sessionLauncher.launchFirstSession(filename, pAppLaunch.get());
      if (!error)
      {
         int result = pApp->exec();

         sessionLauncher.cleanupAtExit();

         options.cleanUpScratchTempDir();

         return result;
      }
      else
      {
         LOG_ERROR(error);

         // These calls to processEvents() seem to be necessary to get
         // readAllStandardError to work.
         pApp->processEvents();
         pApp->processEvents();
         pApp->processEvents();

         QMessageBox errorMsg(safeMessageBoxIcon(QMessageBox::Critical),
                              QString::fromUtf8("RStudio"),
                              sessionLauncher.launchFailedErrorMessage());
         errorMsg.addButton(new QPushButton(QString::fromUtf8("OK")),
                            QMessageBox::AcceptRole);
         errorMsg.show();

         pApp->exec();

         return EXIT_FAILURE;
      }
   }
   CATCH_UNEXPECTED_EXCEPTION
}
<commit_msg>update todos<commit_after>/*
 * DesktopMain.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

// TODO: test on other platforms

// TODO: make sure file assocs still open in existing (.R)

//  - Mac: yes (binds to any running instance)

//  - Windows/Ubuntu:
//             only when first instances was opened with assoc
//             (sendMessage has side effect of becoming server).
//             after this it appears to use a stack of most recently opened

// TODO: windows: access denied to removing the session src database

// TODO: open project in new window command

// TODO: open -a RStudio on the Mac (test on other system)

#include <QtGui>
#include <QtWebKit>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>

#include <core/Log.hpp>

#include <core/system/FileScanner.hpp>
#include <core/Error.hpp>
#include <core/FileInfo.hpp>
#include <core/FilePath.hpp>
#include <core/SafeConvert.hpp>
#include <core/StringUtils.hpp>
#include <core/system/System.hpp>
#include <core/system/Environment.hpp>
#include <core/r_util/RProjectFile.hpp>

#include "DesktopApplicationLaunch.hpp"
#include "DesktopSlotBinders.hpp"
#include "DesktopDetectRHome.hpp"
#include "DesktopOptions.hpp"
#include "DesktopUtils.hpp"
#include "DesktopSessionLauncher.hpp"

QProcess* pRSessionProcess;
QString sharedSecret;

using namespace core;
using namespace desktop;

namespace {

void initializeSharedSecret()
{
   sharedSecret = QString::number(rand())
                  + QString::number(rand())
                  + QString::number(rand());
   std::string value = sharedSecret.toUtf8().constData();
   core::system::setenv("RS_SHARED_SECRET", value);
}

void initializeWorkingDirectory(int argc,
                                char* argv[],
                                const QString& filename)
{
   // calculate what our initial working directory should be
   std::string workingDir;

   // if there is a filename passed to us then use it's path
   if (filename != QString())
   {
      FilePath filePath(filename.toUtf8().constData());
      if (filePath.exists())
      {
         if (filePath.isDirectory())
            workingDir = filePath.absolutePath();
         else
            workingDir = filePath.parent().absolutePath();
      }
   }

   // do additinal detection if necessary
   if (workingDir.empty())
   {
      // get current path
      FilePath currentPath = FilePath::safeCurrentPath(
                                       core::system::userHomePath());

#if defined(_WIN32) || defined(__APPLE__)

      // detect whether we were launched from the system application menu
      // (e.g. Dock, Program File icon, etc.). we do this by checking
      // whether the executable path is within the current path. if we
      // weren't launched from the system app menu that set the initial
      // wd to the current path

      FilePath exePath;
      Error error = core::system::executablePath(argc, argv, &exePath);
      if (!error)
      {
         if (!exePath.isWithin(currentPath))
            workingDir = currentPath.absolutePath();
      }
      else
      {
         LOG_ERROR(error);
      }

#else

      // on linux we take the current working dir if we were launched
      // from within a terminal
      if (core::system::stdoutIsTerminal())
      {
         workingDir = currentPath.absolutePath();
      }

#endif

   }

   // set the working dir if we have one
   if (!workingDir.empty())
      core::system::setenv("RS_INITIAL_WD", workingDir);
}

void setInitialProject(const FilePath& projectFile, QString* pFilename)
{
   core::system::setenv("RS_INITIAL_PROJECT", projectFile.absolutePath());
   pFilename->clear();
}

void initializeStartupEnvironment(QString* pFilename)
{
   // if the filename ends with .RData or .rda then this is an
   // environment file. if it ends with .Rproj then it is
   // a project file. we handle both cases by setting an environment
   // var and then resetting the pFilename so it isn't processed
   // using the standard open file logic
   FilePath filePath(pFilename->toUtf8().constData());
   if (filePath.exists())
   {
      std::string ext = filePath.extensionLowerCase();

      // if it is a directory or just an .rdata file then we can see
      // whether there is a project file we can automatically attach to
      if (filePath.isDirectory())
      {
         FilePath projectFile = r_util::projectFromDirectory(filePath);
         if (!projectFile.empty())
         {
            setInitialProject(projectFile, pFilename);
         }
      }
      else if (ext == ".rproj")
      {
         setInitialProject(filePath, pFilename);
      }
      else if (ext == ".rdata" || ext == ".rda")
      {
         core::system::setenv("RS_INITIAL_ENV", filePath.absolutePath());
         pFilename->clear();
      }

   }
}

QString verifyAndNormalizeFilename(QString filename)
{
   if (filename.isNull() || filename.isEmpty())
      return QString();

   QFileInfo fileInfo(filename);
   if (fileInfo.exists())
      return fileInfo.absoluteFilePath();
   else
      return QString();
}

bool isNonProjectFilename(QString filename)
{
   if (filename.isNull() || filename.isEmpty())
      return false;

   FilePath filePath(filename.toUtf8().constData());
   return filePath.exists() && filePath.extensionLowerCase() != ".rproj";
}

bool dummy(const FileInfo& file)
{
   return true;
}

} // anonymous namespace

int main(int argc, char* argv[])
{
   core::system::initHook();

   try
   {
      QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

      // initialize log
      FilePath userHomePath = core::system::userHomePath("R_USER|HOME");
      FilePath logPath = core::system::userSettingsPath(
            userHomePath,
            "RStudio-Desktop").childPath("log");
      core::system::initializeLog("rdesktop",
                                  core::system::kLogLevelWarning,
                                  logPath);

      boost::scoped_ptr<QApplication> pApp;
      boost::scoped_ptr<ApplicationLaunch> pAppLaunch;
      ApplicationLaunch::init(QString::fromAscii("RStudio"),
                              argc,
                              argv,
                              &pApp,
                              &pAppLaunch);

      // determine the filename that was passed to us
      QString filename;
#ifdef __APPLE__
      // get filename from OpenFile apple-event (pump to ensure delivery)
      pApp->processEvents();
      filename = verifyAndNormalizeFilename(
                              pAppLaunch->startupOpenFileRequest());
#endif
      // allow all platforms (including OSX) to check the command line.
      // we include OSX because the way Qt handles apple events is to
      // re-route them to the first instance to register for events. in
      // this case (for projects) we use this to initiate a launch
      // of the application with the project filename on the command line
      if (filename.isEmpty())
      {
         // get filename from command line arguments
         if (pApp->arguments().size() > 1)
            filename = verifyAndNormalizeFilename(pApp->arguments().last());
      }

      // if we have a filename and it is NOT a project file then see
      // if we can open it within an existing instance
      if (isNonProjectFilename(filename))
      {
         if (pAppLaunch->sendMessage(filename))
            return 0;
      }

      pApp->setAttribute(Qt::AA_MacDontSwapCtrlAndMeta);

      initializeSharedSecret();
      initializeWorkingDirectory(argc, argv, filename);
      initializeStartupEnvironment(&filename);

      Options& options = desktop::options();
      if (!prepareEnvironment(options))
         return 1;

      // get install path
      FilePath installPath;
      Error error = core::system::installPath("..", argc, argv, &installPath);
      if (error)
      {
         LOG_ERROR(error);
         return EXIT_FAILURE;
      }

#ifdef _WIN32
      RVersion version = detectRVersion(false);
#endif

      // calculate paths to config file and rsession
      FilePath confPath, sessionPath;

      // check for debug configuration
#ifndef NDEBUG
      FilePath currentPath = FilePath::safeCurrentPath(installPath);
      if (currentPath.complete("conf/rdesktop-dev.conf").exists())
      {
         confPath = currentPath.complete("conf/rdesktop-dev.conf");
         sessionPath = currentPath.complete("session/rsession");
#ifdef _WIN32
         if (version.architecture() == ArchX64)
            sessionPath = installPath.complete("x64/rsession");
#endif
      }
#endif

      // if there is no conf path then release mode
      if (confPath.empty())
      {
         // default session path (then tweak)
         sessionPath = installPath.complete("bin/rsession");

         // check for win64 binary on windows
#ifdef _WIN32
         if (version.architecture() == ArchX64)
            sessionPath = installPath.complete("bin/x64/rsession");
#endif

         // check for running in a bundle on OSX
#ifdef __APPLE__
         if (installPath.complete("Info.plist").exists())
            sessionPath = installPath.complete("MacOS/rsession");
#endif
      }
      core::system::fixupExecutablePath(&sessionPath);

      // launch session
      SessionLauncher sessionLauncher(sessionPath, confPath);
      error = sessionLauncher.launchFirstSession(filename, pAppLaunch.get());
      if (!error)
      {
         int result = pApp->exec();

         sessionLauncher.cleanupAtExit();

         options.cleanUpScratchTempDir();

         return result;
      }
      else
      {
         LOG_ERROR(error);

         // These calls to processEvents() seem to be necessary to get
         // readAllStandardError to work.
         pApp->processEvents();
         pApp->processEvents();
         pApp->processEvents();

         QMessageBox errorMsg(safeMessageBoxIcon(QMessageBox::Critical),
                              QString::fromUtf8("RStudio"),
                              sessionLauncher.launchFailedErrorMessage());
         errorMsg.addButton(new QPushButton(QString::fromUtf8("OK")),
                            QMessageBox::AcceptRole);
         errorMsg.show();

         pApp->exec();

         return EXIT_FAILURE;
      }
   }
   CATCH_UNEXPECTED_EXCEPTION
}
<|endoftext|>