<commit_before>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "PoolAllocator.h"

//--- standard modules used ----------------------------------------------------
#include "ITOString.h"
#include "MemHeader.h"
#include "SysLog.h"

//--- c-library modules used ---------------------------------------------------
#include <stdlib.h>

#if !defined(__SUNPRO_CC) ||  __SUNPRO_CC < 0x500
extern void *operator new(size_t size, void *vp);
#if defined(WIN32) && (_MSC_VER >= 1200) // VC6 or greater
extern void operator delete(void *ptr, void *vp);
#endif
extern void operator delete(void *ptr);
#endif

//---- PoolAllocator ------------------------------------------
struct PoolBucket {
	u_long fSize;
	u_long fUsableSize;
	void *fFirstFree;
};

PoolAllocator::PoolAllocator(long poolid, u_long poolSize, u_long maxPoolBuckets) : Allocator(poolid), fNumOfPoolBucketSizes(maxPoolBuckets)
{
	fAllocSz = poolSize * 1024;
	fPoolMemory = ::calloc(fAllocSz, 1);
	fPoolBuckets = (PoolBucket *)::calloc(fNumOfPoolBucketSizes + 1, sizeof(PoolBucket));

	if (!fPoolMemory || !fPoolBuckets) {
		static const char crashmsg[] = "FATAL: PoolAllocator::PoolAllocator calloc failed. I will crash :-(\n";
		SysLog::WriteToStderr(crashmsg, sizeof(crashmsg));

		// We might never see the following because we have no memory.
		String msg("PoolAllocator: ");
		msg << "allocation of PoolStorage: " << (long)poolSize << ", " << (long)maxPoolBuckets << " failed";
		SysLog::Error(msg);
		Unref(); // signal allocation failure
		return;
	}
	Initialize();

#ifdef MEM_DEBUG
	fPoolTracker.SetId(poolid);
	fExcessTracker.SetId(poolid);
#endif
}

long PoolAllocator::SetId(long lId)
{
#ifdef MEM_DEBUG
	fPoolTracker.SetId(lId);
	fExcessTracker.SetId(lId);
#endif
	return Allocator::SetId(lId);
}

void PoolAllocator::Initialize()
{
	// initialize data structures used by the allocator
	long sz = 16;

	for (long i = 0; i < (long)fNumOfPoolBucketSizes; i++) {
		fPoolBuckets[i].fSize = sz;
		fPoolBuckets[i].fUsableSize = sz - MemoryHeader::AlignedSize();	// optimization
		fPoolBuckets[i].fFirstFree = NULL;

		sz *= 2;
	}
	fPoolBuckets[fNumOfPoolBucketSizes].fSize = 0;
	fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree = ((char *)fPoolMemory) + fAllocSz;
}

PoolAllocator::~PoolAllocator()
{
#ifdef MEM_DEBUG
	MemTrackStat(fPoolTracker);
	if (fPoolTracker.CurrentlyAllocated() != 0) {
		SysLog::Error(String("deleted PoolAllocator [") << GetId() << "] " << (long)this << " was still in use!");
	}
#endif
	::free(fPoolBuckets);
	::free(fPoolMemory);
}

void PoolAllocator::Free(void *vp)
{
	MemoryHeader *header = RealMemStart(vp);

	if ( header ) {
		if (header->fState == MemoryHeader::eUsed ) {	// most likely case first
			// recycle into pool
			PoolBucket *bucket = FindBucketBySize( header->fSize + MemoryHeader::AlignedSize());

			if ( bucket ) {
				Assert(header->fSize + MemoryHeader::AlignedSize() == bucket->fSize);

				MemTrackFree(fPoolTracker, header->fSize);
				InsertFreeHeaderIntoBucket(header, bucket);
			} else {
				SysLog::Error("bucket not found!");
				Assert(0);
			}
		} else if ( header->fState == MemoryHeader::eUsedNotPooled ) {
			MemTrackFree(fExcessTracker, header->fSize);
			::free(header);
		} else  {
			// something wrong happened, double free
			SysLog::Error("wrong header status");
			Assert(0);
		}
	} else {
		// something wrong, either 0 ptr, invalid pointer or corrupted memory
		Assert(0 == vp);
	}
}

// users of sizeHint pay a price for optimal sizing...
size_t PoolAllocator::SizeHint(size_t size)
{
	PoolBucket *bucket = FindBucketBySize(size);
	if (bucket) {
		return bucket->fSize;
	} else {
		return size;
	}
}

void *PoolAllocator::Alloc(u_long allocSize)
{
	// allocSize includes the size of the necessary MemoryHeader!

	PoolBucket *bucket = FindBucketBySize(allocSize);
	// assume we found the order or can't fit it into order
	if ( bucket ) {
		if ( bucket->fFirstFree ) {
			// we have a bucket to reuse
			MemoryHeader *mh =  RemoveHeaderFromBucket(bucket) ;
			MemTrackAlloc(fPoolTracker, mh->fSize);
			return ExtMemStart(mh);
		} else {
			void *lastFree = fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree;

			if ( ((char *)lastFree - (char *)fPoolMemory) > (long)bucket->fSize) {	// bucket size fits into long
				// we have enough free pool memory to satisfy the request
				MemoryHeader *mh = MakeHeaderFromBucket(bucket, lastFree);
				fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree = mh;

				MemTrackAlloc(fPoolTracker, mh->fSize);
				return ExtMemStart( mh );
			} else {
				// try to split a larger bucket
				PoolBucket *requestedBucket = bucket;
				while ( bucket && !bucket->fFirstFree ) {
					bucket++;    // get next larger available bucket
				}

				if ( bucket && bucket->fFirstFree && bucket->fSize > 0 ) {
					// split larger bucket
					MemoryHeader *mh = RemoveHeaderFromBucket(bucket);

					long nbuckets = bucket->fSize / requestedBucket->fSize;
					char *buketEnd = ((char *)mh) + requestedBucket->fSize * nbuckets;
					Assert((char *)mh + mh->fSize + MemoryHeader::AlignedSize() == buketEnd);

					for (long i = 0; i < nbuckets; i++) {
						// create new buckets of requested size
						mh = MakeHeaderFromBucket(requestedBucket, buketEnd);
						buketEnd -= requestedBucket->fSize;
						InsertFreeHeaderIntoBucket(mh, requestedBucket);
					}
					// we have a bucket to reuse
					mh =  RemoveHeaderFromBucket(requestedBucket) ;

					MemTrackAlloc(fPoolTracker, mh->fSize);
					return ExtMemStart(mh);
				}
			}
		}
	}
	// last resort
	// we are out of pool memory at the moment
	// or have a larger piece of memory requested than largest pool bucket
	void *vp = ::calloc(allocSize, 1);
	if (vp) {
		// keep some statistic
		MemoryHeader *mh = new(vp) MemoryHeader(allocSize - MemoryHeader::AlignedSize(),
												MemoryHeader::eUsedNotPooled);
		MemTrackAlloc(fExcessTracker, mh->fSize);
		SysLog::WriteToStderr("|", 1); // visually mark pool overflow
		return ExtMemStart(mh);
	}
	static const char crashmsg[] = "FATAL: PoolAllocator::Alloc [global memory] calloc failed. I will crash :-(\n";
	SysLog::WriteToStderr(crashmsg, sizeof(crashmsg));

	return 0;
}

MemoryHeader *PoolAllocator::RemoveHeaderFromBucket(PoolBucket *bucket)
{
	MemoryHeader *mh = (MemoryHeader *)bucket->fFirstFree;
	Assert(mh->fMagic == MemoryHeader::gcMagic);
	mh->fState = MemoryHeader::eUsed;
	bucket->fFirstFree = mh->fNext;
	return mh;
}

MemoryHeader *PoolAllocator::MakeHeaderFromBucket(PoolBucket *bucket, void *lastFree)
{
	// create header from bucket
	lastFree = ((char *)lastFree - bucket->fSize);
	Assert(((char *)lastFree - (char *)fPoolMemory) >= 0 );
	MemoryHeader *mh = new(lastFree) MemoryHeader(bucket->fUsableSize, MemoryHeader::eUsed);
	return mh;
}

void PoolAllocator::InsertFreeHeaderIntoBucket(MemoryHeader *mh, PoolBucket *bucket)
{
	Assert(mh->fMagic == MemoryHeader::gcMagic);
	mh->fState = MemoryHeader::eFree;
	mh->fNext = (MemoryHeader *)bucket->fFirstFree;
	bucket->fFirstFree = mh;
}

PoolBucket *PoolAllocator::FindBucketBySize( u_long allocSize)
{
	// find smallest bucket suitable to store allocSize
	for (u_long order = 0; order < fNumOfPoolBucketSizes; order++) {
		if (fPoolBuckets[order].fSize >= allocSize ) { // yeah it fits
			return fPoolBuckets + order;
		}
	}
	return 0;
}

#ifdef MEM_DEBUG
void PoolAllocator::PrintStatistic()
{
	MemTrackStat(fPoolTracker);
	MemTrackStat(fExcessTracker);
}

l_long PoolAllocator::CurrentlyAllocated()
{
	return fPoolTracker.CurrentlyAllocated() + fExcessTracker.CurrentlyAllocated();
}
#endif

void PoolAllocator::Refresh()
{
#ifdef MEM_DEBUG
	if (fPoolTracker.CurrentlyAllocated() != 0) {
		String strMsg(Storage::Global());
		strMsg << "PoolAllocator [" << GetId() << "] is still in use: " << (long)fPoolTracker.CurrentlyAllocated();
		SysLog::Error(strMsg);
		PrintStatistic();
	} else {
		// reinitialize pool
		Initialize();
	}

	if (fExcessTracker.CurrentlyAllocated() != 0) {
		String strMsg(Storage::Global());
		strMsg << "PoolAllocator [" << GetId() << "] is still using global memory: " << (long)fExcessTracker.CurrentlyAllocated();
		SysLog::Error(strMsg);
	}
#else
	// reinitialize pool
	Initialize();
#endif
}
<commit_msg>also printing excess memory usage in dtor<commit_after>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "PoolAllocator.h"

//--- standard modules used ----------------------------------------------------
#include "ITOString.h"
#include "MemHeader.h"
#include "SysLog.h"

//--- c-library modules used ---------------------------------------------------
#include <stdlib.h>

#if !defined(__SUNPRO_CC) ||  __SUNPRO_CC < 0x500
extern void *operator new(size_t size, void *vp);
#if defined(WIN32) && (_MSC_VER >= 1200) // VC6 or greater
extern void operator delete(void *ptr, void *vp);
#endif
extern void operator delete(void *ptr);
#endif

//---- PoolAllocator ------------------------------------------
struct PoolBucket {
	u_long fSize;
	u_long fUsableSize;
	void *fFirstFree;
};

PoolAllocator::PoolAllocator(long poolid, u_long poolSize, u_long maxPoolBuckets)
	: Allocator(poolid)
	, fNumOfPoolBucketSizes(maxPoolBuckets)
	MemTrackInit(fPoolTracker)
	MemTrackInit(fExcessTracker)
{
	fAllocSz = poolSize * 1024;
	fPoolMemory = ::calloc(fAllocSz, 1);
	fPoolBuckets = (PoolBucket *)::calloc(fNumOfPoolBucketSizes + 1, sizeof(PoolBucket));

	if (!fPoolMemory || !fPoolBuckets) {
		static const char crashmsg[] = "FATAL: PoolAllocator::PoolAllocator calloc failed. I will crash :-(\n";
		SysLog::WriteToStderr(crashmsg, sizeof(crashmsg));

		// We might never see the following because we have no memory.
		String msg("PoolAllocator: ");
		msg << "allocation of PoolStorage: " << (long)poolSize << ", " << (long)maxPoolBuckets << " failed";
		SysLog::Error(msg);
		Unref(); // signal allocation failure
		return;
	}
	Initialize();

#ifdef MEM_DEBUG
	fPoolTracker.SetId(poolid);
	fExcessTracker.SetId(poolid);
#endif
}

long PoolAllocator::SetId(long lId)
{
#ifdef MEM_DEBUG
	fPoolTracker.SetId(lId);
	fExcessTracker.SetId(lId);
#endif
	return Allocator::SetId(lId);
}

void PoolAllocator::Initialize()
{
	// initialize data structures used by the allocator
	long sz = 16;

	for (long i = 0; i < (long)fNumOfPoolBucketSizes; i++) {
		fPoolBuckets[i].fSize = sz;
		fPoolBuckets[i].fUsableSize = sz - MemoryHeader::AlignedSize();	// optimization
		fPoolBuckets[i].fFirstFree = NULL;

		sz *= 2;
	}
	fPoolBuckets[fNumOfPoolBucketSizes].fSize = 0;
	fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree = ((char *)fPoolMemory) + fAllocSz;
}

PoolAllocator::~PoolAllocator()
{
#ifdef MEM_DEBUG
	{
		MemTrackStat(fPoolTracker);
	} {
		// caution: must use scoping because tracking would increase fPoolTrackers allocated count!
		MemTrackStat(fExcessTracker);
	}
	if (fPoolTracker.CurrentlyAllocated() != 0) {
		SysLog::Error(String("deleted PoolAllocator [") << GetId() << "] " << (long)this << " was still in use!");
	}
#endif
	::free(fPoolBuckets);
	::free(fPoolMemory);
}

void PoolAllocator::Free(void *vp)
{
	MemoryHeader *header = RealMemStart(vp);

	if ( header ) {
		if (header->fState == MemoryHeader::eUsed ) {	// most likely case first
			// recycle into pool
			PoolBucket *bucket = FindBucketBySize( header->fSize + MemoryHeader::AlignedSize());

			if ( bucket ) {
				Assert(header->fSize + MemoryHeader::AlignedSize() == bucket->fSize);

				MemTrackFree(fPoolTracker, header->fSize);
				InsertFreeHeaderIntoBucket(header, bucket);
			} else {
				SysLog::Error("bucket not found!");
				Assert(0);
			}
		} else if ( header->fState == MemoryHeader::eUsedNotPooled ) {
			MemTrackFree(fExcessTracker, header->fSize);
			::free(header);
		} else  {
			// something wrong happened, double free
			SysLog::Error("wrong header status");
			Assert(0);
		}
	} else {
		// something wrong, either 0 ptr, invalid pointer or corrupted memory
		Assert(0 == vp);
	}
}

// users of sizeHint pay a price for optimal sizing...
size_t PoolAllocator::SizeHint(size_t size)
{
	PoolBucket *bucket = FindBucketBySize(size);
	if (bucket) {
		return bucket->fSize;
	} else {
		return size;
	}
}

void *PoolAllocator::Alloc(u_long allocSize)
{
	// allocSize includes the size of the necessary MemoryHeader!

	PoolBucket *bucket = FindBucketBySize(allocSize);
	// assume we found the order or can't fit it into order
	if ( bucket ) {
		if ( bucket->fFirstFree ) {
			// we have a bucket to reuse
			MemoryHeader *mh =  RemoveHeaderFromBucket(bucket) ;
			MemTrackAlloc(fPoolTracker, mh->fSize);
			return ExtMemStart(mh);
		} else {
			void *lastFree = fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree;

			if ( ((char *)lastFree - (char *)fPoolMemory) > (long)bucket->fSize) {	// bucket size fits into long
				// we have enough free pool memory to satisfy the request
				MemoryHeader *mh = MakeHeaderFromBucket(bucket, lastFree);
				fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree = mh;

				MemTrackAlloc(fPoolTracker, mh->fSize);
				return ExtMemStart( mh );
			} else {
				// try to split a larger bucket
				PoolBucket *requestedBucket = bucket;
				while ( bucket && !bucket->fFirstFree ) {
					bucket++;    // get next larger available bucket
				}

				if ( bucket && bucket->fFirstFree && bucket->fSize > 0 ) {
					// split larger bucket
					MemoryHeader *mh = RemoveHeaderFromBucket(bucket);

					long nbuckets = bucket->fSize / requestedBucket->fSize;
					char *buketEnd = ((char *)mh) + requestedBucket->fSize * nbuckets;
					Assert((char *)mh + mh->fSize + MemoryHeader::AlignedSize() == buketEnd);

					for (long i = 0; i < nbuckets; i++) {
						// create new buckets of requested size
						mh = MakeHeaderFromBucket(requestedBucket, buketEnd);
						buketEnd -= requestedBucket->fSize;
						InsertFreeHeaderIntoBucket(mh, requestedBucket);
					}
					// we have a bucket to reuse
					mh =  RemoveHeaderFromBucket(requestedBucket) ;

					MemTrackAlloc(fPoolTracker, mh->fSize);
					return ExtMemStart(mh);
				}
			}
		}
	}
	// last resort
	// we are out of pool memory at the moment
	// or have a larger piece of memory requested than largest pool bucket
	void *vp = ::calloc(allocSize, 1);
	if (vp) {
		// keep some statistic
		MemoryHeader *mh = new(vp) MemoryHeader(allocSize - MemoryHeader::AlignedSize(),
												MemoryHeader::eUsedNotPooled);
		MemTrackAlloc(fExcessTracker, mh->fSize);
		SysLog::WriteToStderr("|", 1); // visually mark pool overflow
		return ExtMemStart(mh);
	}
	static const char crashmsg[] = "FATAL: PoolAllocator::Alloc [global memory] calloc failed. I will crash :-(\n";
	SysLog::WriteToStderr(crashmsg, sizeof(crashmsg));

	return 0;
}

MemoryHeader *PoolAllocator::RemoveHeaderFromBucket(PoolBucket *bucket)
{
	MemoryHeader *mh = (MemoryHeader *)bucket->fFirstFree;
	Assert(mh->fMagic == MemoryHeader::gcMagic);
	mh->fState = MemoryHeader::eUsed;
	bucket->fFirstFree = mh->fNext;
	return mh;
}

MemoryHeader *PoolAllocator::MakeHeaderFromBucket(PoolBucket *bucket, void *lastFree)
{
	// create header from bucket
	lastFree = ((char *)lastFree - bucket->fSize);
	Assert(((char *)lastFree - (char *)fPoolMemory) >= 0 );
	MemoryHeader *mh = new(lastFree) MemoryHeader(bucket->fUsableSize, MemoryHeader::eUsed);
	return mh;
}

void PoolAllocator::InsertFreeHeaderIntoBucket(MemoryHeader *mh, PoolBucket *bucket)
{
	Assert(mh->fMagic == MemoryHeader::gcMagic);
	mh->fState = MemoryHeader::eFree;
	mh->fNext = (MemoryHeader *)bucket->fFirstFree;
	bucket->fFirstFree = mh;
}

PoolBucket *PoolAllocator::FindBucketBySize( u_long allocSize)
{
	// find smallest bucket suitable to store allocSize
	for (u_long order = 0; order < fNumOfPoolBucketSizes; order++) {
		if (fPoolBuckets[order].fSize >= allocSize ) { // yeah it fits
			return fPoolBuckets + order;
		}
	}
	return 0;
}

#ifdef MEM_DEBUG
void PoolAllocator::PrintStatistic()
{
	MemTrackStat(fPoolTracker);
	MemTrackStat(fExcessTracker);
}

l_long PoolAllocator::CurrentlyAllocated()
{
	return fPoolTracker.CurrentlyAllocated() + fExcessTracker.CurrentlyAllocated();
}
#endif

void PoolAllocator::Refresh()
{
#ifdef MEM_DEBUG
	if (fPoolTracker.CurrentlyAllocated() != 0) {
		String strMsg(Storage::Global());
		strMsg << "PoolAllocator [" << GetId() << "] is still in use: " << (long)fPoolTracker.CurrentlyAllocated();
		SysLog::Error(strMsg);
		PrintStatistic();
	} else {
		// reinitialize pool
		Initialize();
	}

	if (fExcessTracker.CurrentlyAllocated() != 0) {
		String strMsg(Storage::Global());
		strMsg << "PoolAllocator [" << GetId() << "] is still using global memory: " << (long)fExcessTracker.CurrentlyAllocated();
		SysLog::Error(strMsg);
	}
#else
	// reinitialize pool
	Initialize();
#endif
}
<|endoftext|>


<commit_before>#include "Element.h"
#include "Feeder.h"
#include "IfBlock.h"
#include "Import.h"
#include "Pipeline.h"
#include "Andline.h"
#include "CommandLine.h"
using namespace std;

IfBlock::IfBlock(Feeder *f, Environment *env) : Element(f,env)
{
}

IfBlock::~IfBlock()
{
}

/* IfBlock means an if-then-else chunk in usual programing languages.
 * ex)

? commandline1	    <- if
	commandline2
| commandline2	    <- else if
	commandline3
| otherwise	       <- else
	commandline4

commandline5	      <- out of if block

The other purpose to use IfBlock is the cancel of exit statuses

? seq '1' '1000000000' >>= head

Though the head command invokes SIGPIPE error of the seq command,
"|" cancels this failure in this case.
However, this technique should be carefully used.
 */
bool IfBlock::parse(void)
{
	m_feeder->getPos(&m_start_line, &m_start_char);

	int indent = m_feeder->countIndent();

	m_feeder->blank();
	// detect the first condition
	if(! m_feeder->str("?")){
		m_feeder->setPos(m_start_line, m_start_char);
		return false;
	}

	while(1){
		// condition -> many (pipeline or commandline) -> condition ->...
		if(m_feeder->str("otherwise")){
			m_nodes.push_back(NULL); // dummy

		}else if(add(new Pipeline(m_feeder,m_env))){
			((Pipeline *)m_nodes.back())->setIfFlag();
		}else{
			m_feeder->setPos(m_start_line, m_start_char);
			return false;
		}

		while(m_feeder->blankLine()){}

		m_is_cond_node.push_back(true);

		int sub_indent = m_feeder->countIndent();
		// end of the if block
		if(sub_indent < indent)
			break;

		// found another condition
		if( indent == sub_indent){
			m_feeder->blank();
			if(m_feeder->str("?")){
				// another condition
				continue;
			}else{
				break; // end of the if block
			}
		}

		// attempt to search procedures related to the condition
		while(sub_indent > indent){
			m_feeder->blank();

			if(add(new IfBlock(m_feeder,m_env))
				|| add(new Pipeline(m_feeder,m_env))){

				m_is_cond_node.push_back(false);
				while(m_feeder->blankLine()){}
				sub_indent = m_feeder->countIndent();
			}else{
				m_feeder->setPos(m_start_line, m_start_char);
				return false;
			}
		}

		// after procedures related to the condition
		if(sub_indent < indent){
			m_feeder->getPos(&m_end_line, &m_end_char);
			break;
		}

		m_feeder->getPos(&m_end_line, &m_end_char);
		// next condition
		m_feeder->blank();
		// detect the first condition
		if(! m_feeder->str("|")){
			m_feeder->setPos(m_end_line, m_end_char);
			break;
		}
	}
	m_feeder->getPos(&m_end_line, &m_end_char);

	return true;
}

int IfBlock::exec(void)
{
	if(m_nodes.size() != m_is_cond_node.size()){
		m_error_msg = "BUG: IfBlock internal error";
		throw this;
	}

	int exit_status = 0;
	bool skip = false;
	bool match = false;
	for(int i=0;i< (int)m_nodes.size();i++){
		if(m_is_cond_node[i]){ // cond node
			if(match) // already matched
				break;

			if(m_nodes[i] == NULL || m_nodes[i]->exec() == 0){
				match = true;
				skip = false;
			}else
				skip = true;

		}else{ // other node
			if(!skip)
				m_nodes[i]->exec();
		}
	}
/*
	for(auto &c : m_nodes){
	}
*/
	return exit_status;
}
<commit_msg>Rename another x2 header file for Linux<commit_after>#include "Element.h"
#include "Feeder.h"
#include "IfBlock.h"
#include "Import.h"
#include "Pipeline.h"
#include "AndLine.h"
#include "CommandLine.h"
using namespace std;

IfBlock::IfBlock(Feeder *f, Environment *env) : Element(f,env)
{
}

IfBlock::~IfBlock()
{
}

/* IfBlock means an if-then-else chunk in usual programing languages.
 * ex)

? commandline1	    <- if
	commandline2
| commandline2	    <- else if
	commandline3
| otherwise	       <- else
	commandline4

commandline5	      <- out of if block

The other purpose to use IfBlock is the cancel of exit statuses

? seq '1' '1000000000' >>= head

Though the head command invokes SIGPIPE error of the seq command,
"|" cancels this failure in this case.
However, this technique should be carefully used.
 */
bool IfBlock::parse(void)
{
	m_feeder->getPos(&m_start_line, &m_start_char);

	int indent = m_feeder->countIndent();

	m_feeder->blank();
	// detect the first condition
	if(! m_feeder->str("?")){
		m_feeder->setPos(m_start_line, m_start_char);
		return false;
	}

	while(1){
		// condition -> many (pipeline or commandline) -> condition ->...
		if(m_feeder->str("otherwise")){
			m_nodes.push_back(NULL); // dummy

		}else if(add(new Pipeline(m_feeder,m_env))){
			((Pipeline *)m_nodes.back())->setIfFlag();
		}else{
			m_feeder->setPos(m_start_line, m_start_char);
			return false;
		}

		while(m_feeder->blankLine()){}

		m_is_cond_node.push_back(true);

		int sub_indent = m_feeder->countIndent();
		// end of the if block
		if(sub_indent < indent)
			break;

		// found another condition
		if( indent == sub_indent){
			m_feeder->blank();
			if(m_feeder->str("?")){
				// another condition
				continue;
			}else{
				break; // end of the if block
			}
		}

		// attempt to search procedures related to the condition
		while(sub_indent > indent){
			m_feeder->blank();

			if(add(new IfBlock(m_feeder,m_env))
				|| add(new Pipeline(m_feeder,m_env))){

				m_is_cond_node.push_back(false);
				while(m_feeder->blankLine()){}
				sub_indent = m_feeder->countIndent();
			}else{
				m_feeder->setPos(m_start_line, m_start_char);
				return false;
			}
		}

		// after procedures related to the condition
		if(sub_indent < indent){
			m_feeder->getPos(&m_end_line, &m_end_char);
			break;
		}

		m_feeder->getPos(&m_end_line, &m_end_char);
		// next condition
		m_feeder->blank();
		// detect the first condition
		if(! m_feeder->str("|")){
			m_feeder->setPos(m_end_line, m_end_char);
			break;
		}
	}
	m_feeder->getPos(&m_end_line, &m_end_char);

	return true;
}

int IfBlock::exec(void)
{
	if(m_nodes.size() != m_is_cond_node.size()){
		m_error_msg = "BUG: IfBlock internal error";
		throw this;
	}

	int exit_status = 0;
	bool skip = false;
	bool match = false;
	for(int i=0;i< (int)m_nodes.size();i++){
		if(m_is_cond_node[i]){ // cond node
			if(match) // already matched
				break;

			if(m_nodes[i] == NULL || m_nodes[i]->exec() == 0){
				match = true;
				skip = false;
			}else
				skip = true;

		}else{ // other node
			if(!skip)
				m_nodes[i]->exec();
		}
	}
/*
	for(auto &c : m_nodes){
	}
*/
	return exit_status;
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 ***************************************************************************/

#include "PkExample.h"

#include <ActionButton>
#include <ActionButtons>
#include <Context>
#include <Auth>
#include <QDebug>

using namespace PolkitQt;

PkExample::PkExample(QMainWindow *parent)
        : QMainWindow(parent)
{
    setupUi(this);

    ActionButton *bt;

    // Here we create an ActionButton that is a subclass of Action
    // allways pass a QAbstractButton pointer and action id
    // You can change the action id later if you want
    bt = new ActionButton(playPB, "org.qt.policykit.examples.play", this);
    // Here we are setting the text to all four states an action might have
    bt->setText("Play!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    // As ActionButton is also an Action we cast it to add to menu
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    // this signal is emitted when the user click on the action,
    // it will only happen if it was inserted in a QMenu or a QToolBar
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    // This signal was propagated from the QAbstractButton just for
    // convenience in this case we don't have any benefit but the code
    // look cleaner
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    // this is the Action activated signal, it is always emmited whenever
    // someone click and get authorized to do the action
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButton(cryPB, "org.qt.policykit.examples.cry", this);
    bt->setText("Cry!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    // This action is more customized
    bt = new ActionButton(kickPB, "org.qt.policykit.examples.kick", this);
    bt->setText("Kick... (long)");
    // here we set the behavior of PolKitResul = No
    bt->setNoVisible(true);
    bt->setNoEnabled(true);
    bt->setNoText("Kick (long)");
    bt->setNoIcon(QPixmap(":/Icons/custom-no.png"));
    bt->setNoToolTip("If your admin wasn't annoying, you could do this");
    // here we set the behavior of PolKitResul = Auth
    bt->setAuthVisible(true);
    bt->setAuthEnabled(true);
    bt->setAuthText("Kick... (long)");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    bt->setAuthToolTip("Only card carrying tweakers can do this!");
    // here we set the behavior of PolKitResul = Yes
    bt->setYesVisible(true);
    bt->setYesEnabled(true);
    bt->setYesText("Kick! (long)");
    bt->setYesIcon(QPixmap(":/Icons/custom-yes.png"));
    bt->setYesToolTip("Go ahead, kick kick kick!");

    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButton(deletePB, "org.qt.policykit.examples.delete", this);
    bt->setText("Delete!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButton(bleedPB, "org.qt.policykit.examples.bleed", this);
    bt->setText("Bleed!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButtons(QList<QAbstractButton*>() << listenPB << listenCB,
                           "org.qt.policykit.examples.listen", this);
    bt->setIcon(QPixmap(":/Icons/action-locked.png"));
    bt->setYesIcon(QPixmap(":/Icons/action-unlocked.png"));
    bt->setText("Click to make changes...");
    // this example is pretty diferent, here we have a checkable
    // QAbstractButton, the setCheckable(true) was set in the ui
    // file so you can see that there is no need to call
    // bt->setCheckable(true);
    // if you want a simple Action checkable you can do as
    // of above.
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)),
            this, SLOT(activateCheckableAction()));
    // We have here a separated slot cause we want to revoke the
    // action.
    // Be sure not to cast sender to Action if you do so
    // you will call the wrong activate slot and it won't work
    // well with checkable actions
    connect(bt, SIGNAL(clicked(QAbstractButton*, bool)),
            this, SLOT(activateCheckableAction()));
    connect(bt, SIGNAL(activated()),
            this, SLOT(actionActivated()));
}

PkExample::~PkExample()
{
}

void PkExample::activateAction()
{
    // Here we cast the sender() to an Action and call activate()
    // on it.
    // Be careful in doing the same for ActionButton won't work as expected
    // as action->activate() is calling Action::activate() and
    // not ActionButton::activate which are different.
    // You can cast then to ActionButton but be carefull
    // an Action casted to ActionButton may crash you app
    Action *action = qobject_cast<Action*>(sender());
    // calling activate with winId() makes the auth dialog
    // be correct parented with your application.
    action->activate(winId());
}

// activateCheckableAction is only here to revoke the action
// As the slot above you might not need both of them, just
// connect to the activat slot of an Action or ActionButton
void PkExample::activateCheckableAction()
{
    // Here we cast the sender() to an ActionButton and call activate()
    // on it.
    // You will probable want to connect it derectly to your app,
    // here we do this way since we want to revoke the action
    // if we are granted it
    ActionButton *action = qobject_cast<ActionButton*>(sender());
    if (action->isAllowed()) {
        action->revoke();
    } else {
        // calling activate with winId() makes the auth dialog
        // be correct parented with your application.
        action->activate();
    }
}

void PkExample::actionActivated()
{
    // This slot is called whenever an action is allowed
    // here you will do your dirt job by calling a helper application
    // that might erase your hardrive ;)
    Action *action = qobject_cast<Action*>(sender());

    // here we don't want to do nothing if the action is listen
    if (action->is("org.qt.policykit.examples.listen")) {
        qDebug() << "toggled for: org.qt.policykit.examples.listen";
        return;
    }

    // As debug message says we are pretending to be the mechanism for the
    // following action, here you will actually call your DBus helper that
    // will run as root (setuid is not needed, see DBus docs).
    // In the helper application you will issue isCallerAuthorized,
    // passing the action id, the caller pid (which DBus will tell you) and
    // revokeIfOneShot = true as OneShot actions requires that the helper
    // revoke it after it sees that it's possible to do it, otherwise it
    // will work forever AND THAT IS NOT WHAT you want! If it's is simple
    // don't use oneShot in you .policy file ;)
    qDebug() << "pretending to be the mechanism for action:" << action->actionId();

    // note how we pass true to revokeIfOneShot - this is because we're
    // pretending to be the mechanism
    PolKitResult result;
    result == Auth::isCallerAuthorized(action->actionId(), static_cast<uint>(QCoreApplication::applicationPid()), true);
    if (result == POLKIT_RESULT_YES) {
        // in the helper you will do the action
        qDebug() << "caller is authorized to do:" << action->actionId();
    } else {
        // OR return false to the caller then the caller can ask for an auth dialog
        // or do anything else
        qDebug() << "caller is NOT authorized to do:" << action->actionId();
    }
}
<commit_msg>Fixing typo (== vs =) in the example<commit_after>/***************************************************************************
 *   Copyright (C) 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 ***************************************************************************/

#include "PkExample.h"

#include <ActionButton>
#include <ActionButtons>
#include <Context>
#include <Auth>
#include <QDebug>

using namespace PolkitQt;

PkExample::PkExample(QMainWindow *parent)
        : QMainWindow(parent)
{
    setupUi(this);

    ActionButton *bt;

    // Here we create an ActionButton that is a subclass of Action
    // always pass a QAbstractButton pointer and action id
    // You can change the action id later if you want
    bt = new ActionButton(playPB, "org.qt.policykit.examples.play", this);
    // Here we are setting the text to all four states an action might have
    bt->setText("Play!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    // As ActionButton is also an Action we cast it to add to menu
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    // this signal is emitted when the user click on the action,
    // it will only happen if it was inserted in a QMenu or a QToolBar
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    // This signal was propagated from the QAbstractButton just for
    // convenience in this case we don't have any benefit but the code
    // look cleaner
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    // this is the Action activated signal, it is always emmited whenever
    // someone click and get authorized to do the action
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButton(cryPB, "org.qt.policykit.examples.cry", this);
    bt->setText("Cry!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    // This action is more customized
    bt = new ActionButton(kickPB, "org.qt.policykit.examples.kick", this);
    bt->setText("Kick... (long)");
    // here we set the behavior of PolKitResul = No
    bt->setNoVisible(true);
    bt->setNoEnabled(true);
    bt->setNoText("Kick (long)");
    bt->setNoIcon(QPixmap(":/Icons/custom-no.png"));
    bt->setNoToolTip("If your admin wasn't annoying, you could do this");
    // here we set the behavior of PolKitResul = Auth
    bt->setAuthVisible(true);
    bt->setAuthEnabled(true);
    bt->setAuthText("Kick... (long)");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    bt->setAuthToolTip("Only card carrying tweakers can do this!");
    // here we set the behavior of PolKitResul = Yes
    bt->setYesVisible(true);
    bt->setYesEnabled(true);
    bt->setYesText("Kick! (long)");
    bt->setYesIcon(QPixmap(":/Icons/custom-yes.png"));
    bt->setYesToolTip("Go ahead, kick kick kick!");

    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButton(deletePB, "org.qt.policykit.examples.delete", this);
    bt->setText("Delete!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButton(bleedPB, "org.qt.policykit.examples.bleed", this);
    bt->setText("Bleed!");
    bt->setAuthIcon(QPixmap(":/Icons/action-locked-default.png"));
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
    connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
    connect(bt, SIGNAL(activated()), this, SLOT(actionActivated()));

    bt = new ActionButtons(QList<QAbstractButton*>() << listenPB << listenCB,
                           "org.qt.policykit.examples.listen", this);
    bt->setIcon(QPixmap(":/Icons/action-locked.png"));
    bt->setYesIcon(QPixmap(":/Icons/action-unlocked.png"));
    bt->setText("Click to make changes...");
    // this example is pretty diferent, here we have a checkable
    // QAbstractButton, the setCheckable(true) was set in the ui
    // file so you can see that there is no need to call
    // bt->setCheckable(true);
    // if you want a simple Action checkable you can do as
    // of above.
    menuActions->addAction(qobject_cast<Action*>(bt));
    toolBar->addAction(qobject_cast<Action*>(bt));
    connect(bt, SIGNAL(triggered(bool)),
            this, SLOT(activateCheckableAction()));
    // We have here a separated slot cause we want to revoke the
    // action.
    // Be sure not to cast sender to Action if you do so
    // you will call the wrong activate slot and it won't work
    // well with checkable actions
    connect(bt, SIGNAL(clicked(QAbstractButton*, bool)),
            this, SLOT(activateCheckableAction()));
    connect(bt, SIGNAL(activated()),
            this, SLOT(actionActivated()));
}

PkExample::~PkExample()
{
}

void PkExample::activateAction()
{
    // Here we cast the sender() to an Action and call activate()
    // on it.
    // Be careful in doing the same for ActionButton won't work as expected
    // as action->activate() is calling Action::activate() and
    // not ActionButton::activate which are different.
    // You can cast then to ActionButton but be carefull
    // an Action casted to ActionButton may crash you app
    Action *action = qobject_cast<Action*>(sender());
    // calling activate with winId() makes the auth dialog
    // be correct parented with your application.
    action->activate(winId());
}

// activateCheckableAction is only here to revoke the action
// As the slot above you might not need both of them, just
// connect to the activat slot of an Action or ActionButton
void PkExample::activateCheckableAction()
{
    // Here we cast the sender() to an ActionButton and call activate()
    // on it.
    // You will probable want to connect it derectly to your app,
    // here we do this way since we want to revoke the action
    // if we are granted it
    ActionButton *action = qobject_cast<ActionButton*>(sender());
    if (action->isAllowed()) {
        action->revoke();
    } else {
        // calling activate with winId() makes the auth dialog
        // be correct parented with your application.
        action->activate();
    }
}

void PkExample::actionActivated()
{
    // This slot is called whenever an action is allowed
    // here you will do your dirt job by calling a helper application
    // that might erase your hardrive ;)
    Action *action = qobject_cast<Action*>(sender());

    // here we don't want to do nothing if the action is listen
    if (action->is("org.qt.policykit.examples.listen")) {
        qDebug() << "toggled for: org.qt.policykit.examples.listen";
        return;
    }

    // As debug message says we are pretending to be the mechanism for the
    // following action, here you will actually call your DBus helper that
    // will run as root (setuid is not needed, see DBus docs).
    // In the helper application you will issue isCallerAuthorized,
    // passing the action id, the caller pid (which DBus will tell you) and
    // revokeIfOneShot = true as OneShot actions requires that the helper
    // revoke it after it sees that it's possible to do it, otherwise it
    // will work forever AND THAT IS NOT WHAT you want! If it's is simple
    // don't use oneShot in you .policy file ;)
    qDebug() << "pretending to be the mechanism for action:" << action->actionId();

    // note how we pass true to revokeIfOneShot - this is because we're
    // pretending to be the mechanism
    PolKitResult result;
    result = Auth::isCallerAuthorized(action->actionId(), static_cast<uint>(QCoreApplication::applicationPid()), true);
    if (result == POLKIT_RESULT_YES) {
        // in the helper you will do the action
        qDebug() << "caller is authorized to do:" << action->actionId();
    } else {
        // OR return false to the caller then the caller can ask for an auth dialog
        // or do anything else
        qDebug() << "caller is NOT authorized to do:" << action->actionId();
    }
}
<|endoftext|>


<commit_before>/*
    Crystal Space Vector class
    Copyright (C) 1998,1999 by Andrew Zabolotny <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdlib.h>
#include <string.h>
#include "sysdef.h"
#define CS_DISABLE_MODULE_LOCKING
#include "cscom/com.h"
#undef  CS_DISABLE_MODULE_LOCKING
#include "csutil/csvector.h"

csVector::csVector (int ilimit, int ithreshold)
{
  root = (csSome *)malloc ((limit = ilimit) * sizeof (csSome));
  count = 0; threshold = ithreshold;
}

csVector::~csVector ()
{
//not much sense to call DeleteAll () since even for inherited classes
//anyway will be called csVector::FreeItem which is empty.
//DeleteAll ();
  if (root) free (root);
}

void csVector::DeleteAll ()
{
  int idx;
  for (idx = count - 1; idx >= 0; idx--)
    if (!FreeItem (root [idx]))
      break;
  SetLength (idx + 1);
  while (idx >= 0)
    Delete (idx--);
}

void csVector::SetLength (int n)
{
  count = n;
  if ((n > limit) || ((limit > threshold) && (n < limit - threshold)))
  {
    n = ((n + threshold - 1) / threshold) * threshold;
    root = n ? (csSome *)realloc (root, n * sizeof (csSome)) : NULL;
    limit = n;
  }
}

bool csVector::FreeItem (csSome Item)
{
  (void)Item;
  return true;
}

bool csVector::Delete (int n)
{
  if (n < count)
  {
    if (!FreeItem (root [n]))
      return false;
    int ncount = count - 1;
    memmove (&root [n], &root [n + 1], (ncount - n) * sizeof (csSome));
    SetLength (ncount);
    return true;
  }
  else
    return false;
}

bool csVector::Insert (int n, csSome Item)
{
  if (n <= count)
  {
    SetLength (count + 1);
    memmove (&root [n + 1], &root [n], (count - n) * sizeof (csSome));
    root [n] = Item;
    return true;
  }
  else
   return false;
}

int csVector::Find (csSome which) const
{
  for (int i = 0; i < Length (); i++)
    if (root [i] == which)
      return i;
  return -1;
}

int csVector::FindKey (csConstSome Key, int Mode) const
{
  for (int i = 0; i < Length (); i++)
    if (CompareKey (root [i], Key, Mode) == 0)
      return i;
  return -1;
}

int csVector::FindSortedKey (csConstSome Key, int Mode) const
{
  int l = 0, r = Length () - 1;
  while (l <= r)
  {
    int m = (l + r) / 2;
    int cmp = CompareKey (root [m], Key, Mode);

    if (cmp == 0)
      return m;
    else if (cmp < 0)
      l = m + 1;
    else
      r = m - 1;
  }
  return -1;
}

void csVector::QuickSort (int Left, int Right, int Mode)
{
recurse:
  int i = Left, j = Right;
  int x = (Left + Right) / 2;
  do
  {
    while ((i != x) && (Compare (Get (i), Get (x), Mode) < 0))
      i++;
    while ((j != x) && (Compare (Get (j), Get (x), Mode) > 0))
      j--;
    if (i < j)
    {
      Exchange (i, j);
      if (x == i)
        x = j;
      else if (x == j)
        x = i;
    }
    if (i <= j)
    {
      i++;
      if (j > Left)
        j--;
    }
  } while (i <= j);

  if (j - Left < Right - i)
  {
    if (Left < j)
      QuickSort (Left, j, Mode);
    if (i < Right)
    {
      Left = i;
      goto recurse;
    }
  }
  else
  {
    if (i < Right)
      QuickSort (i, Right, Mode);
    if (Left < j)
    {
      Right = j;
      goto recurse;
    }
  }
}

int csVector::Compare (csSome Item1, csSome Item2, int Mode) const
{
  (void)Mode;
  return ((int)Item1 > (int)Item2) ? +1 : ((int)Item1 == (int)Item2) ? 0 : -1;
}

int csVector::CompareKey (csSome Item, csConstSome Key, int Mode) const
{
  (void)Mode;
  return (Item > Key) ? +1 : (Item == Key) ? 0 : -1;
}
<commit_msg>Removed COM junk.<commit_after>/*
    Crystal Space Vector class
    Copyright (C) 1998,1999 by Andrew Zabolotny <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdlib.h>
#include <string.h>
#include "sysdef.h"
#include "csutil/csvector.h"

csVector::csVector (int ilimit, int ithreshold)
{
  root = (csSome *)malloc ((limit = ilimit) * sizeof (csSome));
  count = 0; threshold = ithreshold;
}

csVector::~csVector ()
{
//not much sense to call DeleteAll () since even for inherited classes
//anyway will be called csVector::FreeItem which is empty.
//DeleteAll ();
  if (root) free (root);
}

void csVector::DeleteAll ()
{
  int idx;
  for (idx = count - 1; idx >= 0; idx--)
    if (!FreeItem (root [idx]))
      break;
  SetLength (idx + 1);
  while (idx >= 0)
    Delete (idx--);
}

void csVector::SetLength (int n)
{
  count = n;
  if ((n > limit) || ((limit > threshold) && (n < limit - threshold)))
  {
    n = ((n + threshold - 1) / threshold) * threshold;
    root = n ? (csSome *)realloc (root, n * sizeof (csSome)) : NULL;
    limit = n;
  }
}

bool csVector::FreeItem (csSome Item)
{
  (void)Item;
  return true;
}

bool csVector::Delete (int n)
{
  if (n < count)
  {
    if (!FreeItem (root [n]))
      return false;
    int ncount = count - 1;
    memmove (&root [n], &root [n + 1], (ncount - n) * sizeof (csSome));
    SetLength (ncount);
    return true;
  }
  else
    return false;
}

bool csVector::Insert (int n, csSome Item)
{
  if (n <= count)
  {
    SetLength (count + 1);
    memmove (&root [n + 1], &root [n], (count - n) * sizeof (csSome));
    root [n] = Item;
    return true;
  }
  else
   return false;
}

int csVector::Find (csSome which) const
{
  for (int i = 0; i < Length (); i++)
    if (root [i] == which)
      return i;
  return -1;
}

int csVector::FindKey (csConstSome Key, int Mode) const
{
  for (int i = 0; i < Length (); i++)
    if (CompareKey (root [i], Key, Mode) == 0)
      return i;
  return -1;
}

int csVector::FindSortedKey (csConstSome Key, int Mode) const
{
  int l = 0, r = Length () - 1;
  while (l <= r)
  {
    int m = (l + r) / 2;
    int cmp = CompareKey (root [m], Key, Mode);

    if (cmp == 0)
      return m;
    else if (cmp < 0)
      l = m + 1;
    else
      r = m - 1;
  }
  return -1;
}

void csVector::QuickSort (int Left, int Right, int Mode)
{
recurse:
  int i = Left, j = Right;
  int x = (Left + Right) / 2;
  do
  {
    while ((i != x) && (Compare (Get (i), Get (x), Mode) < 0))
      i++;
    while ((j != x) && (Compare (Get (j), Get (x), Mode) > 0))
      j--;
    if (i < j)
    {
      Exchange (i, j);
      if (x == i)
        x = j;
      else if (x == j)
        x = i;
    }
    if (i <= j)
    {
      i++;
      if (j > Left)
        j--;
    }
  } while (i <= j);

  if (j - Left < Right - i)
  {
    if (Left < j)
      QuickSort (Left, j, Mode);
    if (i < Right)
    {
      Left = i;
      goto recurse;
    }
  }
  else
  {
    if (i < Right)
      QuickSort (i, Right, Mode);
    if (Left < j)
    {
      Right = j;
      goto recurse;
    }
  }
}

int csVector::Compare (csSome Item1, csSome Item2, int Mode) const
{
  (void)Mode;
  return ((int)Item1 > (int)Item2) ? +1 : ((int)Item1 == (int)Item2) ? 0 : -1;
}

int csVector::CompareKey (csSome Item, csConstSome Key, int Mode) const
{
  (void)Mode;
  return (Item > Key) ? +1 : (Item == Key) ? 0 : -1;
}
<|endoftext|>


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

#ifndef _SB_HXX
#define _SB_HXX

#ifndef _SBERRORS_HXX
 #include "sberrors.hxx"
#endif

#include <sbdef.hxx>
#include <sbmeth.hxx>
#include <sbmod.hxx>
#include <sbprop.hxx>
#include <sbstar.hxx>

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

#ifndef _SB_HXX
#define _SB_HXX

#ifndef _SBERRORS_HXX
 #include "sberrors.hxx"
#endif

#include <sbdef.hxx>
#include <sbmeth.hxx>
#include <sbmod.hxx>
#include <sbprop.hxx>
#include <sbstar.hxx>

#endif
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file transform.inl
 *  \brief Inline file for transform.h
 */

#pragma once

#include <thrust/detail/device/cuda/vectorize.h>
#include <thrust/detail/device/dereference.h>

namespace thrust
{

namespace detail
{

namespace device
{

namespace detail
{

//////////////
// Functors //
//////////////

template <typename InputIterator, typename OutputIterator, typename UnaryFunction>
struct unary_transform_functor
{
    InputIterator first;
    OutputIterator result;
    UnaryFunction unary_op;

    unary_transform_functor(InputIterator _first, OutputIterator _result, UnaryFunction _unary_op)
        : first(_first), result(_result), unary_op(_unary_op) {}

    template <typename IntegerType>
         __device__
        void operator()(const IntegerType& i)
        {
            // result[i] = unary_op(first[i]);
            thrust::detail::device::dereference(result, i) = unary_op(thrust::detail::device::dereference(first, i));
        }
}; // end unary_transform_functor

template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryFunction>
struct binary_transform_functor
{
    InputIterator1 first1;
    InputIterator2 first2;
    OutputIterator result;
    BinaryFunction binary_op;

    binary_transform_functor(InputIterator1 _first1, InputIterator2 _first2, OutputIterator _result, BinaryFunction _binary_op)
        : first1(_first1), first2(_first2), result(_result), binary_op(_binary_op) {}

    template <typename IntegerType>
        __device__
        void operator()(const IntegerType& i)
        {
            // result[i] = binary_op(first1[i], first2[i]);
            thrust::detail::device::dereference(result, i) = binary_op(thrust::detail::device::dereference(first1, i), thrust::detail::device::dereference(first2, i));
        }
}; // end binary_transform_functor

template <typename InputIterator1, typename InputIterator2, typename ForwardIterator, typename UnaryFunction, typename Predicate>
struct unary_transform_if_functor
{
    InputIterator1 first;
    InputIterator2 stencil;
    ForwardIterator result;
    UnaryFunction unary_op;
    Predicate pred;

    unary_transform_if_functor(InputIterator1 _first, InputIterator2 _stencil, ForwardIterator _result, UnaryFunction _unary_op, Predicate _pred)
        : first(_first), stencil(_stencil), result(_result), unary_op(_unary_op), pred(_pred) {}

    template <typename IntegerType>
        __device__
        void operator()(const IntegerType& i)
        {
            // if(pred(stencil[i]))
            //     result[i] = unary_op(first[i]);
            if(pred(thrust::detail::device::dereference(stencil, i)))
                thrust::detail::device::dereference(result, i) = unary_op(thrust::detail::device::dereference(first, i));
        }
}; // end unary_transform_if_functor

template <typename InputIterator1, typename InputIterator2, typename InputIterator3,
          typename ForwardIterator, typename BinaryFunction, typename Predicate>
struct binary_transform_if_functor
{
    InputIterator1 first1;
    InputIterator2 first2;
    InputIterator3 stencil;
    ForwardIterator result;
    BinaryFunction binary_op;
    Predicate pred;

    binary_transform_if_functor(InputIterator1 _first1, InputIterator2 _first2, InputIterator2 _stencil,
                                ForwardIterator _result, BinaryFunction _binary_op, Predicate _pred)
        : first1(_first1), first2(_first2), stencil(_stencil), result(_result), binary_op(_binary_op), pred(_pred) {}
    template <typename IntegerType>
        __device__
        void operator()(const IntegerType& i)
        {
            // if(pred(stencil[i]))
            //     result[i] = binary_op(first1[i], first2[i]);
            if(pred(thrust::detail::device::dereference(stencil, i)))
                thrust::detail::device::dereference(result, i) = binary_op(thrust::detail::device::dereference(first1, i), thrust::detail::device::dereference(first2, i));
        }
}; // end binary_transform_if_functor

} // end namespace detail

template<typename InputIterator,
         typename OutputIterator,
         typename UnaryFunction>
  OutputIterator transform(InputIterator first, InputIterator last,
                           OutputIterator result,
                           UnaryFunction unary_op)
{
    detail::unary_transform_functor<InputIterator,OutputIterator,UnaryFunction> func(first, result, unary_op);
    thrust::detail::device::cuda::vectorize(last - first, func);
    return result + (last - first); // return the end of the output sequence
} // end transform()

template<typename InputIterator1,
         typename InputIterator2,
         typename OutputIterator,
         typename BinaryFunction>
  OutputIterator transform(InputIterator1 first1, InputIterator1 last1,
                           InputIterator2 first2,
                           OutputIterator result,
                           BinaryFunction binary_op)
{
    detail::binary_transform_functor<InputIterator1,InputIterator2,OutputIterator,BinaryFunction> func(first1, first2, result, binary_op);
    thrust::detail::device::cuda::vectorize(last1 - first1, func);
    return result + (last1 - first1); // return the end of the output sequence
} // end transform()

template<typename InputIterator1,
         typename InputIterator2,
         typename ForwardIterator,
         typename UnaryFunction,
         typename Predicate>
  ForwardIterator transform_if(InputIterator1 first, InputIterator1 last,
                               InputIterator2 stencil,
                               ForwardIterator result,
                               UnaryFunction unary_op,
                               Predicate pred)
{
    detail::unary_transform_if_functor<InputIterator1,InputIterator2,ForwardIterator,UnaryFunction,Predicate> func(first, stencil, result, unary_op, pred);
    thrust::detail::device::cuda::vectorize(last - first, func);
    return result + (last - first); // return the end of the output sequence
} // end transform_if()

template<typename InputIterator1,
         typename InputIterator2,
         typename InputIterator3,
         typename ForwardIterator,
         typename BinaryFunction,
         typename Predicate>
  ForwardIterator transform_if(InputIterator1 first1, InputIterator1 last1,
                               InputIterator2 first2,
                               InputIterator3 stencil,
                               ForwardIterator result,
                               BinaryFunction binary_op,
                               Predicate pred)
{
    detail::binary_transform_if_functor<InputIterator1,InputIterator2,InputIterator3,ForwardIterator,BinaryFunction,Predicate> func(first1, first2, stencil, result, binary_op, pred);
    thrust::detail::device::cuda::vectorize(last1 - first1, func);
    return result + (last1 - first1); // return the end of the output sequence
} // end transform_if()

} // end namespace device

} // end detail

} // end thrust

<commit_msg>Implement device transform with device for_each.<commit_after>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file transform.inl
 *  \brief Inline file for transform.h
 */

#pragma once

#include <thrust/detail/device/cuda/vectorize.h>
#include <thrust/detail/device/dereference.h>
#include <thrust/for_each.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>

namespace thrust
{

namespace detail
{

namespace device
{

namespace detail
{

//////////////
// Functors //
//////////////

template <typename UnaryFunction>
struct unary_transform_functor
{
  UnaryFunction f;

  unary_transform_functor(UnaryFunction f_)
    :f(f_)
  {}

  template<typename Tuple>
  __device__
  void operator()(Tuple t)
  {
    thrust::get<1>(t) = f(thrust::get<0>(t));
  }
}; // end unary_transform_functor

template <typename BinaryFunction>
struct binary_transform_functor
{
  BinaryFunction f;

  binary_transform_functor(BinaryFunction f_)
    :f(f_)
  {}

  template <typename Tuple>
  __device__
  void operator()(Tuple t)
  {
    thrust::get<2>(t) = f(thrust::get<0>(t), thrust::get<1>(t));
  }
}; // end binary_transform_functor

template <typename UnaryFunction, typename Predicate>
struct unary_transform_if_functor
{
  UnaryFunction unary_op;
  Predicate pred;

  unary_transform_if_functor(UnaryFunction _unary_op, Predicate _pred)
    : unary_op(_unary_op), pred(_pred) {}

  template <typename Tuple>
  __device__
  void operator()(Tuple t)
  {
    if(pred(thrust::get<1>(t)))
      thrust::get<2>(t) = unary_op(thrust::get<0>(t));
  }
}; // end unary_transform_if_functor

template <typename BinaryFunction, typename Predicate>
struct binary_transform_if_functor
{
  BinaryFunction binary_op;
  Predicate pred;

  binary_transform_if_functor(BinaryFunction _binary_op, Predicate _pred)
    : binary_op(_binary_op), pred(_pred) {}

  template <typename Tuple>
  __device__
  void operator()(Tuple t)
  {
    if(pred(thrust::get<2>(t)))
      thrust::get<3>(t) = binary_op(thrust::get<0>(t), thrust::get<1>(t));
  }
}; // end binary_transform_if_functor

} // end namespace detail

template<typename InputIterator,
         typename OutputIterator,
         typename UnaryFunction>
  OutputIterator transform(InputIterator first, InputIterator last,
                           OutputIterator result,
                           UnaryFunction unary_op)
{
  detail::unary_transform_functor<UnaryFunction> func(unary_op);

  thrust::detail::device::for_each(thrust::make_zip_iterator(thrust::make_tuple(first, result)),
                                   thrust::make_zip_iterator(thrust::make_tuple(last, result + (last - first))),
                                   func);

  return result + (last - first); // return the end of the output sequence
} // end transform()

template<typename InputIterator1,
         typename InputIterator2,
         typename OutputIterator,
         typename BinaryFunction>
  OutputIterator transform(InputIterator1 first1, InputIterator1 last1,
                           InputIterator2 first2,
                           OutputIterator result,
                           BinaryFunction binary_op)
{
  detail::binary_transform_functor<BinaryFunction> func(binary_op);

  thrust::detail::device::for_each(thrust::make_zip_iterator(thrust::make_tuple(first1, first2, result)),
                                   thrust::make_zip_iterator(thrust::make_tuple(last1,  first2 + (last1 - first1), result + (last1 - first1))),
                                   func);

  return result + (last1 - first1); // return the end of the output sequence
} // end transform()

template<typename InputIterator1,
         typename InputIterator2,
         typename ForwardIterator,
         typename UnaryFunction,
         typename Predicate>
  ForwardIterator transform_if(InputIterator1 first, InputIterator1 last,
                               InputIterator2 stencil,
                               ForwardIterator result,
                               UnaryFunction unary_op,
                               Predicate pred)
{
  detail::unary_transform_if_functor<UnaryFunction,Predicate> func(unary_op, pred);

  thrust::detail::device::for_each(thrust::make_zip_iterator(thrust::make_tuple(first, stencil, result)),
                                   thrust::make_zip_iterator(thrust::make_tuple(last,  stencil + (last - first), result + (last - first))),
                                   func);

  return result + (last - first); // return the end of the output sequence
} // end transform_if()

template<typename InputIterator1,
         typename InputIterator2,
         typename InputIterator3,
         typename ForwardIterator,
         typename BinaryFunction,
         typename Predicate>
  ForwardIterator transform_if(InputIterator1 first1, InputIterator1 last1,
                               InputIterator2 first2,
                               InputIterator3 stencil,
                               ForwardIterator result,
                               BinaryFunction binary_op,
                               Predicate pred)
{
  detail::binary_transform_if_functor<BinaryFunction,Predicate> func(binary_op, pred);

  thrust::detail::device::for_each(thrust::make_zip_iterator(thrust::make_tuple(first1, first2, stencil, result)),
                                   thrust::make_zip_iterator(thrust::make_tuple(last1,  first2 + (last1 - first1), stencil + (last1 - first1), result + (last1 - first1))),
                                   func);

  return result + (last1 - first1); // return the end of the output sequence
} // end transform_if()

} // end namespace device

} // end detail

} // end thrust

<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2008 Sacha Schutz <istdasklar@free.fr>
 * Copyright (C) 2008 Olivier Gueudelot <gueudelotolive@gmail.com>
 * Copyright (C) 2008 Charles Huet <packadal@gmail.com>
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "texture.h"

#include "math.h"

#include <QtGui/QImage>
#include <QtCore/QUrl>

using namespace GluonGraphics;

class Texture::Private
{
    public:
        QImage image;
};

Texture::Texture( QObject* parent )
    : QObject( parent ), d( new Private )
{

}

Texture::~Texture()
{
    delete d;
}

bool Texture::load( const QUrl& url )
{
    // TODO: Add support for non-2D textures and non-RGBA colour formats. Also, find a way
    // around the nasty const_cast .
    d->image.load( url.toLocalFile() );

    return false;
}

QImage Texture::image() const
{
    return d->image;
}

#include "texture.moc"
<commit_msg>Graphics: Make the Texture class work.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2008 Sacha Schutz <istdasklar@free.fr>
 * Copyright (C) 2008 Olivier Gueudelot <gueudelotolive@gmail.com>
 * Copyright (C) 2008 Charles Huet <packadal@gmail.com>
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "texture.h"

#include <core/debughelper.h>

#include "math.h"

#include <QtGui/QImage>
#include <QtCore/QUrl>
#include "manager.h"
#include "backend.h"
#include "texturedata.h"

using namespace GluonGraphics;

class Texture::Private
{
    public:
        QImage image;
        TextureData* data;
};

Texture::Texture( QObject* parent )
    : QObject( parent ), d( new Private )
{
    d->data = Manager::instance()->backend()->createTextureData();
}

Texture::~Texture()
{
    delete d->data;
    delete d;
}

bool Texture::load( const QUrl& url )
{
    //TODO: Add support for non-2D textures and non-RGBA colour formats.
    if( !d->image.load( url.toLocalFile() ) )
    {
        DEBUG_TEXT2( "Failed to load texture %1", url.toLocalFile() );
        return false;
    }

    //Ensure we have 32-bit ARGB data
    if( d->image.format() != QImage::Format_ARGB32 )
        d->image = d->image.convertToFormat( QImage::Format_ARGB32 );

    const int width = d->image.width();
    const int height = d->image.height();

    //TODO: Support big endian (?)
    //Convert ARGB to RGBA
    for( int y = 0; y < height; ++y )
    {
        uint* line = reinterpret_cast< uint* >( d->image.scanLine( y ) );
        for( int x = 0; x < width; ++x )
        {
            line[x] = ((line[x] << 16) & 0xff0000) | ((line[x] >> 16) & 0xff) | (line[x] & 0xff00ff00);
        }
    }

    //Mirror it since Qt uses different coords.
    d->image = d->image.mirrored();

    //Finally, load it into GPU memory.
    d->data->setData( d->image.width(), d->image.height(), d->image.bits() );

    return true;
}

QImage Texture::image() const
{
    return d->image;
}

#include "texture.moc"
<|endoftext|>


<commit_before>//
//  bootstrap.cpp
//  Parse
//
//  Created by Andrew Hunter on 21/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "bootstrap.h"

#include "Dfa/ndfa_regex.h"
#include "ContextFree/item.h"
#include "Lr/weak_symbols.h"
#include "Lr/ignored_symbols.h"
#include "Lr/lalr_builder.h"

using namespace dfa;
using namespace contextfree;
using namespace lr;
using namespace language;

/// \brief Adds a new terminal item to an NDFA, and to this object
contextfree::item_container bootstrap::add_terminal(dfa::ndfa_regex* ndfa, const std::wstring& name, const std::wstring& regex) {
    // Add to the terminal dictionary
    int termIdentifier = m_Terminals.symbol_for_name(name);

    if (termIdentifier == -1) {
        termIdentifier = m_Terminals.add_symbol(name);
    }

    // Add to the DFA
    ndfa->add_regex(0, regex, termIdentifier);

    // Return a new container
    return item_container(new terminal(termIdentifier), true);
}

/// \brief Creates the lexer for the language
dfa::ndfa* bootstrap::create_dfa() {
    // Create the NDFA (which we'll eventually turn into the lexer)
    ndfa_regex* languageNdfa = new ndfa_regex();

    // The weak keywords
    t.language          = add_terminal(languageNdfa, L"language", L"language");
    t.grammar           = add_terminal(languageNdfa, L"grammar", L"grammar");
    t.lexersymbols      = add_terminal(languageNdfa, L"lexer-symbols", L"lexer-symbols");
    t.lexer             = add_terminal(languageNdfa, L"lexer", L"lexer");
    t.weaklexer         = add_terminal(languageNdfa, L"weaklexer", L"weaklexer");
    t.ignore            = add_terminal(languageNdfa, L"ignore", L"ignore");
    t.keywords          = add_terminal(languageNdfa, L"keywords", L"keywords");

    // Single character elements (these are also weak)
	t.equals            = add_terminal(languageNdfa, L"'='", L"\\=");
    t.question          = add_terminal(languageNdfa, L"'?'", L"\\?");
    t.plus              = add_terminal(languageNdfa, L"'+'", L"\\+");
    t.star              = add_terminal(languageNdfa, L"'*'", L"\\*");
    t.colon             = add_terminal(languageNdfa, L"':'", L"\\:");
    t.openparen         = add_terminal(languageNdfa, L"'('", L"\\(");
    t.closeparen        = add_terminal(languageNdfa, L"')'", L"\\)");
    t.opencurly         = add_terminal(languageNdfa, L"'{'", L"\\{");
    t.closecurly        = add_terminal(languageNdfa, L"'}'", L"\\}");
    t.dot               = add_terminal(languageNdfa, L"'.'", L"\\.");
    t.pipe              = add_terminal(languageNdfa, L"'|'", L"\\|");

    // The lexical constructs
    t.identifier        = add_terminal(languageNdfa, L"identifier", L"[A-Za-z\\-][A-Za-z\\-0-9]*");
    t.nonterminal       = add_terminal(languageNdfa, L"nonterminal", L"\\<[A-Za-z\\-][A-Za-z\\-0-9]*\\>");
    t.regex             = add_terminal(languageNdfa, L"regex", L"/([^/]|(\\\\/))*/");
    t.string            = add_terminal(languageNdfa, L"string", L"\"([^\"]|(\\\"))*\"");
    t.character         = add_terminal(languageNdfa, L"character", L"'(.|(\\\\.))'");

    // Ignored elements
    t.newline           = add_terminal(languageNdfa, L"newline", L"[\n\r]");
    t.whitespace        = add_terminal(languageNdfa, L"whitespace", L"[ \t]+");
    t.comment           = add_terminal(languageNdfa, L"comment", L"//[^\n\r]*");

    // Build into a DFA
    ndfa* uniqueSyms = languageNdfa->to_ndfa_with_unique_symbols();
    delete languageNdfa;

    ndfa* result = uniqueSyms->to_dfa();
    delete uniqueSyms;

    return result;
}

/// \brief Creates the grammar for the language
contextfree::grammar* bootstrap::create_grammar() {
    // Create a new grammar
    grammar* result = new grammar();

    // Generate nonterminals
    nt.parser_language          = result->get_nonterminal(L"Parser-Language");
    nt.toplevel_block           = result->get_nonterminal(L"TopLevel-Block");
    nt.language_block           = result->get_nonterminal(L"Language-Block");
    nt.language_inherits        = result->get_nonterminal(L"Language-Inherits");
    nt.language_definition      = result->get_nonterminal(L"Language-Definition");
    nt.lexer_symbols_definition = result->get_nonterminal(L"Lexer-Symbols-Definition");
    nt.lexer_definition         = result->get_nonterminal(L"Lexer-Definition");
    nt.ignore_definition        = result->get_nonterminal(L"Ignore-Definition");
    nt.keywords_definition      = result->get_nonterminal(L"Keywords-Definition");
    nt.keyword_definition       = result->get_nonterminal(L"Keyword-Definition");
    nt.weak_symbols_definition  = result->get_nonterminal(L"Weak-Symbols-Definition");
    nt.lexeme_definition        = result->get_nonterminal(L"Lexeme-Definition");
    nt.grammar_definition       = result->get_nonterminal(L"Grammar-Definition");
    nt.nonterminal_definition   = result->get_nonterminal(L"Nonterminal-Definition");
    nt.production               = result->get_nonterminal(L"Production");
    nt.ebnf_item                = result->get_nonterminal(L"Ebnf-Item");
    nt.simple_ebnf_item         = result->get_nonterminal(L"Simple-Ebnf-Item");
    nt.nonterminal              = result->get_nonterminal(L"Nonterminal");
    nt.terminal                 = result->get_nonterminal(L"Terminal");
    nt.basic_terminal           = result->get_nonterminal(L"Basic-Terminal");

    // Generate productions
    ebnf_repeating_optional listToplevel;
    (*listToplevel.get_rule()) << nt.toplevel_block;
    ((*result) += L"Parser-Language") << listToplevel;

    // Top level block (language)
    ((*result) += L"TopLevel-Block") << nt.language_block;

    // Language block ('language x (: y) { ... }
    ebnf_optional           optionalLanguageInherits;
    ebnf_repeating_optional listLanguageDefinition;
    (*optionalLanguageInherits.get_rule()) << nt.language_inherits;
    (*listLanguageDefinition.get_rule()) << nt.language_definition;
    ((*result) += L"Language-Block") << t.language << t.identifier << optionalLanguageInherits << t.opencurly << listLanguageDefinition << t.closecurly;

    ((*result) += L"Language-Inherits") << t.colon << t.identifier;

    // Types of definition within a language block
    ((*result) += L"Language-Definition") << nt.lexer_symbols_definition;
    ((*result) += L"Language-Definition") << nt.lexer_definition;
    ((*result) += L"Language-Definition") << nt.ignore_definition;
    ((*result) += L"Language-Definition") << nt.weak_symbols_definition;
    ((*result) += L"Language-Definition") << nt.keywords_definition;
    ((*result) += L"Language-Definition") << nt.grammar_definition;

    // Some simple definitions
    ebnf_repeating_optional lexemeList;
    ebnf_repeating_optional keywordDefinitionList;
    ebnf_repeating_optional lexemeOrIdentifierList;
    ebnf_alternate          lexemeOrIdentifier;

    (*lexemeList.get_rule()) << nt.lexeme_definition;
    (*lexemeOrIdentifier.get_rule()) << nt.lexeme_definition;
    (*lexemeOrIdentifier.add_rule()) << t.identifier;
    (*lexemeOrIdentifierList.get_rule()) << lexemeOrIdentifier;
    (*keywordDefinitionList.get_rule()) << nt.keyword_definition;

    ((*result) += L"Lexer-Symbols-Definition") << t.lexersymbols << t.opencurly << lexemeList << t.closecurly;
    ((*result) += L"Lexer-Definition") << t.lexer << t.opencurly << lexemeList << t.closecurly;
    ((*result) += L"Ignore-Definition") << t.ignore << t.opencurly << lexemeOrIdentifierList << t.closecurly;
    ((*result) += L"Keywords-Definition") << t.keywords << t.opencurly << keywordDefinitionList << t.closecurly;
    ((*result) += L"Keyword-Definition") << t.identifier;
    ((*result) += L"Keyword-Definition") << t.identifier << t.equals << t.string;
    ((*result) += L"Keyword-Definition") << t.identifier << t.equals << t.character;
    ((*result) += L"Weak-Symbols-Definition") << t.weaklexer << t.opencurly << lexemeList << t.closecurly;
    ((*result) += L"Lexeme-Definition") << t.identifier << t.equals << t.regex;
    ((*result) += L"Lexeme-Definition") << t.identifier << t.equals << t.identifier << t.dot << t.identifier;

    // Definitions for a grammar
    ebnf_repeating_optional nonterminalDefinitionList;
    ebnf_repeating_optional orProductionList;
    ebnf_repeating_optional ebnfItemList;
    ebnf_repeating_optional simpleEbnfItemList;

    (*nonterminalDefinitionList.get_rule()) << nt.nonterminal_definition;
    (*orProductionList.get_rule()) << t.pipe << nt.production;
    (*ebnfItemList.get_rule()) << nt.ebnf_item;
    (*simpleEbnfItemList.get_rule()) << nt.simple_ebnf_item;

    ((*result) += L"Grammar-Definition") << t.grammar << t.opencurly << nonterminalDefinitionList << t.closecurly;

    ((*result) += L"Nonterminal-Definition") << t.nonterminal << t.equals << nt.production << orProductionList;
    // (Not supporting the inheritance forms of these in the bootstrap language)

    // Productions
    ((*result) += L"Production") << simpleEbnfItemList;

    ((*result) += L"Ebnf-Item") << nt.simple_ebnf_item;
    ((*result) += L"Ebnf-Item") << nt.simple_ebnf_item << t.pipe << nt.simple_ebnf_item;

    ((*result) += L"Simple-Ebnf-Item") << nt.nonterminal;
    ((*result) += L"Simple-Ebnf-Item") << nt.terminal;
    ((*result) += L"Simple-Ebnf-Item") << nt.simple_ebnf_item << t.star;
    ((*result) += L"Simple-Ebnf-Item") << nt.simple_ebnf_item << t.plus;
    ((*result) += L"Simple-Ebnf-Item") << nt.simple_ebnf_item << t.question;
    ((*result) += L"Simple-Ebnf-Item") << t.openparen << ebnfItemList << t.closeparen;

    ((*result) += L"Nonterminal") << t.nonterminal;

    ((*result) += L"Terminal") << nt.basic_terminal;
    ((*result) += L"Basic-Terminal") << t.identifier;
    ((*result) += L"Basic-Terminal") << t.string;
    ((*result) += L"Basic-Terminal") << t.character;

    // Return the new grammar
    return result;
}

/// \brief Constructs the bootstrap language
bootstrap::bootstrap() {
    // Create the DFA for this language
    ndfa* dfa = create_dfa();

    // Create the grammar for this language
    m_Grammar = create_grammar();

    // Set up the list of 'weak symbols'
    weak_symbols weak;

    // All of the keywords are weak
    item_set weaklings;

    weaklings.insert(t.language);
    weaklings.insert(t.grammar);
    weaklings.insert(t.lexersymbols);
    weaklings.insert(t.lexer);
    weaklings.insert(t.ignore);
    weaklings.insert(t.keywords);

    weak.add_symbols(*dfa, weaklings, m_Terminals);

    // Set up the list of ignored symbols
    ignored_symbols ignore;

    ignore.add_item(t.newline);
    ignore.add_item(t.whitespace);
    ignore.add_item(t.comment);

    // Create the lexer for this language
    m_Lexer = new dfa::lexer(*dfa);

    // No longer need the DFA at this point
    delete dfa;

    // Build the parser
    m_Builder = new lalr_builder(*m_Grammar, m_Terminals);

    m_Builder->add_rewriter(weak);
    m_Builder->add_rewriter(ignore);

    m_Builder->add_initial_state(nt.parser_language);

    // Finish up the parser
    m_Builder->complete_parser();

    // TODO: log information about shift/reduce and reduce/reduce conflicts

    // Turn into the finished parser
    m_Parser = new ast_parser(*m_Builder);
}

/// \brief Destructor
bootstrap::~bootstrap() {
    delete m_Lexer;
    delete m_Grammar;
    delete m_Builder;
    delete m_Parser;
}
<commit_msg>Resolved the ambiguities in the parser.<commit_after>//
//  bootstrap.cpp
//  Parse
//
//  Created by Andrew Hunter on 21/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "bootstrap.h"

#include "Dfa/ndfa_regex.h"
#include "ContextFree/item.h"
#include "Lr/weak_symbols.h"
#include "Lr/ignored_symbols.h"
#include "Lr/lalr_builder.h"

using namespace dfa;
using namespace contextfree;
using namespace lr;
using namespace language;

/// \brief Adds a new terminal item to an NDFA, and to this object
contextfree::item_container bootstrap::add_terminal(dfa::ndfa_regex* ndfa, const std::wstring& name, const std::wstring& regex) {
    // Add to the terminal dictionary
    int termIdentifier = m_Terminals.symbol_for_name(name);

    if (termIdentifier == -1) {
        termIdentifier = m_Terminals.add_symbol(name);
    }

    // Add to the DFA
    ndfa->add_regex(0, regex, termIdentifier);

    // Return a new container
    return item_container(new terminal(termIdentifier), true);
}

/// \brief Creates the lexer for the language
dfa::ndfa* bootstrap::create_dfa() {
    // Create the NDFA (which we'll eventually turn into the lexer)
    ndfa_regex* languageNdfa = new ndfa_regex();

    // The weak keywords
    t.language          = add_terminal(languageNdfa, L"language", L"language");
    t.grammar           = add_terminal(languageNdfa, L"grammar", L"grammar");
    t.lexersymbols      = add_terminal(languageNdfa, L"lexer-symbols", L"lexer-symbols");
    t.lexer             = add_terminal(languageNdfa, L"lexer", L"lexer");
    t.weaklexer         = add_terminal(languageNdfa, L"weaklexer", L"weaklexer");
    t.ignore            = add_terminal(languageNdfa, L"ignore", L"ignore");
    t.keywords          = add_terminal(languageNdfa, L"keywords", L"keywords");

    // Single character elements (these are also weak)
	t.equals            = add_terminal(languageNdfa, L"'='", L"\\=");
    t.question          = add_terminal(languageNdfa, L"'?'", L"\\?");
    t.plus              = add_terminal(languageNdfa, L"'+'", L"\\+");
    t.star              = add_terminal(languageNdfa, L"'*'", L"\\*");
    t.colon             = add_terminal(languageNdfa, L"':'", L"\\:");
    t.openparen         = add_terminal(languageNdfa, L"'('", L"\\(");
    t.closeparen        = add_terminal(languageNdfa, L"')'", L"\\)");
    t.opencurly         = add_terminal(languageNdfa, L"'{'", L"\\{");
    t.closecurly        = add_terminal(languageNdfa, L"'}'", L"\\}");
    t.dot               = add_terminal(languageNdfa, L"'.'", L"\\.");
    t.pipe              = add_terminal(languageNdfa, L"'|'", L"\\|");

    // The lexical constructs
    t.identifier        = add_terminal(languageNdfa, L"identifier", L"[A-Za-z\\-][A-Za-z\\-0-9]*");
    t.nonterminal       = add_terminal(languageNdfa, L"nonterminal", L"\\<[A-Za-z\\-][A-Za-z\\-0-9]*\\>");
    t.regex             = add_terminal(languageNdfa, L"regex", L"/([^/]|(\\\\/))*/");
    t.string            = add_terminal(languageNdfa, L"string", L"\"([^\"]|(\\\"))*\"");
    t.character         = add_terminal(languageNdfa, L"character", L"'(.|(\\\\.))'");

    // Ignored elements
    t.newline           = add_terminal(languageNdfa, L"newline", L"[\n\r]");
    t.whitespace        = add_terminal(languageNdfa, L"whitespace", L"[ \t]+");
    t.comment           = add_terminal(languageNdfa, L"comment", L"//[^\n\r]*");

    // Build into a DFA
    ndfa* uniqueSyms = languageNdfa->to_ndfa_with_unique_symbols();
    delete languageNdfa;

    ndfa* result = uniqueSyms->to_dfa();
    delete uniqueSyms;

    return result;
}

/// \brief Creates the grammar for the language
contextfree::grammar* bootstrap::create_grammar() {
    // Create a new grammar
    grammar* result = new grammar();

    // Generate nonterminals
    nt.parser_language          = result->get_nonterminal(L"Parser-Language");
    nt.toplevel_block           = result->get_nonterminal(L"TopLevel-Block");
    nt.language_block           = result->get_nonterminal(L"Language-Block");
    nt.language_inherits        = result->get_nonterminal(L"Language-Inherits");
    nt.language_definition      = result->get_nonterminal(L"Language-Definition");
    nt.lexer_symbols_definition = result->get_nonterminal(L"Lexer-Symbols-Definition");
    nt.lexer_definition         = result->get_nonterminal(L"Lexer-Definition");
    nt.ignore_definition        = result->get_nonterminal(L"Ignore-Definition");
    nt.keywords_definition      = result->get_nonterminal(L"Keywords-Definition");
    nt.keyword_definition       = result->get_nonterminal(L"Keyword-Definition");
    nt.weak_symbols_definition  = result->get_nonterminal(L"Weak-Symbols-Definition");
    nt.lexeme_definition        = result->get_nonterminal(L"Lexeme-Definition");
    nt.grammar_definition       = result->get_nonterminal(L"Grammar-Definition");
    nt.nonterminal_definition   = result->get_nonterminal(L"Nonterminal-Definition");
    nt.production               = result->get_nonterminal(L"Production");
    nt.ebnf_item                = result->get_nonterminal(L"Ebnf-Item");
    nt.simple_ebnf_item         = result->get_nonterminal(L"Simple-Ebnf-Item");
    nt.nonterminal              = result->get_nonterminal(L"Nonterminal");
    nt.terminal                 = result->get_nonterminal(L"Terminal");
    nt.basic_terminal           = result->get_nonterminal(L"Basic-Terminal");

    // Generate productions
    ebnf_repeating_optional listToplevel;
    (*listToplevel.get_rule()) << nt.toplevel_block;
    ((*result) += L"Parser-Language") << listToplevel;

    // Top level block (language)
    ((*result) += L"TopLevel-Block") << nt.language_block;

    // Language block ('language x (: y) { ... }
    ebnf_optional           optionalLanguageInherits;
    ebnf_repeating_optional listLanguageDefinition;
    (*optionalLanguageInherits.get_rule()) << nt.language_inherits;
    (*listLanguageDefinition.get_rule()) << nt.language_definition;
    ((*result) += L"Language-Block") << t.language << t.identifier << optionalLanguageInherits << t.opencurly << listLanguageDefinition << t.closecurly;

    ((*result) += L"Language-Inherits") << t.colon << t.identifier;

    // Types of definition within a language block
    ((*result) += L"Language-Definition") << nt.lexer_symbols_definition;
    ((*result) += L"Language-Definition") << nt.lexer_definition;
    ((*result) += L"Language-Definition") << nt.ignore_definition;
    ((*result) += L"Language-Definition") << nt.weak_symbols_definition;
    ((*result) += L"Language-Definition") << nt.keywords_definition;
    ((*result) += L"Language-Definition") << nt.grammar_definition;

    // Some simple definitions
    ebnf_repeating_optional lexemeList;
    ebnf_repeating_optional keywordDefinitionList;
    ebnf_repeating_optional lexemeOrIdentifierList;
    ebnf_alternate          lexemeOrIdentifier;

    (*lexemeList.get_rule()) << nt.lexeme_definition;
    (*lexemeOrIdentifier.get_rule()) << nt.lexeme_definition;
    (*lexemeOrIdentifier.add_rule()) << t.identifier;
    (*lexemeOrIdentifierList.get_rule()) << lexemeOrIdentifier;
    (*keywordDefinitionList.get_rule()) << nt.keyword_definition;

    ((*result) += L"Lexer-Symbols-Definition") << t.lexersymbols << t.opencurly << lexemeList << t.closecurly;
    ((*result) += L"Lexer-Definition") << t.lexer << t.opencurly << lexemeList << t.closecurly;
    ((*result) += L"Ignore-Definition") << t.ignore << t.opencurly << lexemeOrIdentifierList << t.closecurly;
    ((*result) += L"Keywords-Definition") << t.keywords << t.opencurly << keywordDefinitionList << t.closecurly;
    ((*result) += L"Keyword-Definition") << t.identifier;
    ((*result) += L"Keyword-Definition") << t.identifier << t.equals << t.string;
    ((*result) += L"Keyword-Definition") << t.identifier << t.equals << t.character;
    ((*result) += L"Weak-Symbols-Definition") << t.weaklexer << t.opencurly << lexemeList << t.closecurly;
    ((*result) += L"Lexeme-Definition") << t.identifier << t.equals << t.regex;
    ((*result) += L"Lexeme-Definition") << t.identifier << t.equals << t.identifier << t.dot << t.identifier;

    // Definitions for a grammar
    ebnf_optional           nonterminalDefinitionList;
    ebnf_repeating_optional orProductionList;
    ebnf_repeating_optional equalsProductionList;
    ebnf_repeating_optional ebnfItemList;
    ebnf_repeating_optional simpleEbnfItemList;

    (*nonterminalDefinitionList.get_rule()) << nt.nonterminal_definition;
    (*orProductionList.get_rule()) << t.pipe << nt.production;
    (*equalsProductionList.get_rule()) << t.equals << nt.production;
    (*ebnfItemList.get_rule()) << nt.ebnf_item;
    (*simpleEbnfItemList.get_rule()) << nt.simple_ebnf_item;

    // In the bootstrap language, we only actually support one nonterminal definition: this is because we have
    // to resolve the conflict where Simple-Ebnf-Item can reduce to a nonterminal, but if the nonterminal is followed
    // by an '=', it's actually a new production. This is resolved with a guard in the 'real' language definition.
    //
    // The AST needs to be massaged to remove the final nonterminal from the last 'or' rule and add it before the
    // equals. This is annoying, but it resolves the ambiguity with a LALR(1) parser.
    ((*result) += L"Grammar-Definition") << t.grammar << t.opencurly << nonterminalDefinitionList << t.closecurly;

    ((*result) += L"Nonterminal-Definition") << t.nonterminal << t.equals << nt.production << orProductionList << equalsProductionList;
    // (Not supporting the inheritance forms of these in the bootstrap language)

    // Productions
    ((*result) += L"Production") << simpleEbnfItemList;

    ((*result) += L"Ebnf-Item") << nt.simple_ebnf_item;
    ((*result) += L"Ebnf-Item") << nt.simple_ebnf_item << t.pipe << nt.simple_ebnf_item;

    ((*result) += L"Simple-Ebnf-Item") << nt.nonterminal;
    ((*result) += L"Simple-Ebnf-Item") << nt.terminal;
    ((*result) += L"Simple-Ebnf-Item") << t.openparen << ebnfItemList << t.closeparen;
    ((*result) += L"Simple-Ebnf-Item") << nt.nonterminal << t.star;
    ((*result) += L"Simple-Ebnf-Item") << nt.nonterminal << t.plus;
    ((*result) += L"Simple-Ebnf-Item") << nt.nonterminal << t.question;

    ((*result) += L"Nonterminal") << t.nonterminal;

    ((*result) += L"Terminal") << nt.basic_terminal;
    ((*result) += L"Basic-Terminal") << t.identifier;
    ((*result) += L"Basic-Terminal") << t.string;
    ((*result) += L"Basic-Terminal") << t.character;

    // Return the new grammar
    return result;
}

/// \brief Constructs the bootstrap language
bootstrap::bootstrap() {
    // Create the DFA for this language
    ndfa* dfa = create_dfa();

    // Create the grammar for this language
    m_Grammar = create_grammar();

    // Set up the list of 'weak symbols'
    weak_symbols weak;

    // All of the keywords are weak
    item_set weaklings;

    weaklings.insert(t.language);
    weaklings.insert(t.grammar);
    weaklings.insert(t.lexersymbols);
    weaklings.insert(t.lexer);
    weaklings.insert(t.ignore);
    weaklings.insert(t.keywords);

    weak.add_symbols(*dfa, weaklings, m_Terminals);

    // Set up the list of ignored symbols
    ignored_symbols ignore;

    ignore.add_item(t.newline);
    ignore.add_item(t.whitespace);
    ignore.add_item(t.comment);

    // Create the lexer for this language
    m_Lexer = new dfa::lexer(*dfa);

    // No longer need the DFA at this point
    delete dfa;

    // Build the parser
    m_Builder = new lalr_builder(*m_Grammar, m_Terminals);

    m_Builder->add_rewriter(weak);
    m_Builder->add_rewriter(ignore);

    m_Builder->add_initial_state(nt.parser_language);

    // Finish up the parser
    m_Builder->complete_parser();

    // TODO: log information about shift/reduce and reduce/reduce conflicts

    // Turn into the finished parser
    m_Parser = new ast_parser(*m_Builder);
}

/// \brief Destructor
bootstrap::~bootstrap() {
    delete m_Lexer;
    delete m_Grammar;
    delete m_Builder;
    delete m_Parser;
}
<|endoftext|>