<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2015-2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "random.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "serialize.h" // for begin_ptr(vec)
#include "util.h" // for LOG()
#include "utilstrencodings.h" // for GetTime()

#include <limits>
#include <stdlib.h>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <linux/random.h>
#include <sys/syscall.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LOGA("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER *)&nCounter);
#else
    timeval t;
    gettimeofday(&t, nullptr);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void *)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true)
    {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, begin_ptr(vData), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS)
    {
        RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
        memory_cleanse(begin_ptr(vData), nSize);
        LOG(RAND, "%s: %lu bytes\n", __func__, nSize);
    }
    else
    {
        static bool warned = false; // Warn only once
        if (!warned)
        {
            LOGA("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#ifdef WIN32
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret)
    {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret)
    {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES)
    {
        RandFailure();
    }
#elif defined(HAVE_GETENTROPY)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0)
    {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do
    {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0)
        {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1)
    {
        RandFailure();
    }
    int have = 0;
    do
    {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES)
        {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
#endif
}

void GetRandBytes(unsigned char *buf, int num)
{
    if (RAND_bytes(buf, num) != 1)
    {
        RandFailure();
    }
}

void GetStrongRandBytes(unsigned char *out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Produce output
    hasher.Finalize(buf);
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do
    {
        GetRandBytes((unsigned char *)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax) { return GetRand(nMax); }
uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char *)&hash, sizeof(hash));
    return hash;
}

FastRandomContext::FastRandomContext(bool fDeterministic)
{
    bitbuf_size = 0;
    // The seed values have some unlikely fixed points which we avoid.
    if (fDeterministic)
    {
        Rz = Rw = 11;
    }
    else
    {
        uint32_t tmp;
        do
        {
            GetRandBytes((unsigned char *)&tmp, 4);
        } while (tmp == 0 || tmp == 0x9068ffffU);
        Rz = tmp;
        do
        {
            GetRandBytes((unsigned char *)&tmp, 4);
        } while (tmp == 0 || tmp == 0x464fffffU);
        Rw = tmp;
    }
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do
    {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x = 0; x < NUM_OS_RANDOM_BYTES; ++x)
        {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x = 0; x < NUM_OS_RANDOM_BYTES; ++x)
        {
            if (overwritten[x])
            {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}
<commit_msg>random: Add fallback if getrandom syscall not available<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2015-2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "random.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "serialize.h" // for begin_ptr(vec)
#include "util.h" // for LOG()
#include "utilstrencodings.h" // for GetTime()

#include <limits>
#include <stdlib.h>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <linux/random.h>
#include <sys/syscall.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LOGA("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER *)&nCounter);
#else
    timeval t;
    gettimeofday(&t, nullptr);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void *)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true)
    {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, begin_ptr(vData), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS)
    {
        RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
        memory_cleanse(begin_ptr(vData), nSize);
        LOG(RAND, "%s: %lu bytes\n", __func__, nSize);
    }
    else
    {
        static bool warned = false; // Warn only once
        if (!warned)
        {
            LOGA("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
 * compatible way to get cryptographic randomness on UNIX-ish platforms.
 */
void GetDevURandom(unsigned char *ent32)
{
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1)
    {
        RandFailure();
    }
    int have = 0;
    do
    {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES)
        {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
}
#endif

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#ifdef WIN32
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret)
    {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret)
    {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
    if (rv != NUM_OS_RANDOM_BYTES)
    {
        if (rv < 0 && errno == ENOSYS)
        {
            /* Fallback for kernel <3.17: the return value will be -1 and errno
             * ENOSYS if the syscall is not available, in that case fall back
             * to /dev/urandom.
             */
            GetDevURandom(ent32);
        }
        else
        {
            RandFailure();
        }
    }
#elif defined(HAVE_GETENTROPY)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0)
    {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do
    {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0)
        {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    GetDevURandom(ent32);
#endif
}

void GetRandBytes(unsigned char *buf, int num)
{
    if (RAND_bytes(buf, num) != 1)
    {
        RandFailure();
    }
}

void GetStrongRandBytes(unsigned char *out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Produce output
    hasher.Finalize(buf);
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do
    {
        GetRandBytes((unsigned char *)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax) { return GetRand(nMax); }
uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char *)&hash, sizeof(hash));
    return hash;
}

FastRandomContext::FastRandomContext(bool fDeterministic)
{
    bitbuf_size = 0;
    // The seed values have some unlikely fixed points which we avoid.
    if (fDeterministic)
    {
        Rz = Rw = 11;
    }
    else
    {
        uint32_t tmp;
        do
        {
            GetRandBytes((unsigned char *)&tmp, 4);
        } while (tmp == 0 || tmp == 0x9068ffffU);
        Rz = tmp;
        do
        {
            GetRandBytes((unsigned char *)&tmp, 4);
        } while (tmp == 0 || tmp == 0x464fffffU);
        Rw = tmp;
    }
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do
    {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x = 0; x < NUM_OS_RANDOM_BYTES; ++x)
        {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x = 0; x < NUM_OS_RANDOM_BYTES; ++x)
        {
            if (overwritten[x])
            {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "startd.h"

void
check_perms()
{
	struct stat st;
	mode_t mode;

	if (stat(exec_path, &st) < 0) {
		EXCEPT("stat exec path");
	}

	if ((st.st_mode & 0777) != 0777) {
		dprintf(D_FULLDEBUG, "Changing permission on %s\n", exec_path);
		mode = st.st_mode | 0777;
		if (chmod(exec_path, mode) < 0) {
			EXCEPT("chmod exec path");
		}
	}
}

void
cleanup_execute_dir(int pid)
{
	char buf[2048];

#if defined(WIN32)
	if( pid ) {
		sprintf( buf, "rmdir /s /q %.256s\\dir_%d",
				 exec_path, pid );
	} else {
		sprintf( buf, "rmdir /s /q %.256s\\dir_*",
				 exec_path );
	}
	system( buf );
#else
	if( pid ) {
		sprintf( buf, "/bin/rm -rf %.256s/dir_%d",
				exec_path, pid );
	} else {
		sprintf( buf, "/bin/rm -rf %.256s/condor_exec* %.256s/dir_*",
				 exec_path, exec_path );
	}
	system( buf );
#endif
}

float
compute_rank( ClassAd* mach_classad, ClassAd* req_classad )
{
	float rank;

	if( mach_classad->EvalFloat( ATTR_RANK, req_classad, rank ) == 0 ) {
		dprintf( D_ALWAYS, "Error evaluating rank.\n" );
		rank = 0;
	}
	return rank;
}

int
create_port( ReliSock* rsock )
{
	rsock->bind();
	rsock->listen();
	return rsock->get_file_desc();
}

char*
command_to_string( int cmd )
{
	switch( cmd ) {
	case CONTINUE_CLAIM:
		return "continue_claim";
	case SUSPEND_CLAIM:
		return "suspend_claim";
	case DEACTIVATE_CLAIM:
		return "deactivate_claim";
	case DEACTIVATE_CLAIM_FORCIBLY:
		return "deactivate_claim_forcibly";
	case MATCH_INFO:
		return "match_info";
	case ALIVE:
		return "alive";
	case REQUEST_CLAIM:
		return "request_claim";
	case RELEASE_CLAIM:
		return "release_claim";
	case ACTIVATE_CLAIM:
		return "activate_claim";
	case GIVE_STATE:
		return "give_state";
	case PCKPT_JOB:
		return "pckpt_job";
	case PCKPT_ALL_JOBS:
		return "pckpt_all_jobs";
	case VACATE_CLAIM:
		return "vacate_claim";
	case VACATE_ALL_CLAIMS:
		return "vacate_all_claims";

	default:
		return "unknown";
	}
	return "error";
}

int
reply( Stream* s, int cmd )
{
	s->encode();
	if( !s->code( cmd ) || !s->end_of_message() ) {
		return FALSE;
	} else {
		return TRUE;
	}
}

int
caInsert( ClassAd* target, ClassAd* source, const char* attr, int verbose )
{
	char buf[4096];
	buf[0] = '\0';
	ExprTree* tree;
	if( !attr ) {
		EXCEPT( "caInsert called with NULL attribute" );
	}
	if( !target || !source ) {
		EXCEPT( "caInsert called with NULL classad" );
	}

	tree = source->Lookup( attr );
	if( !tree ) {
		if( verbose ) {
			dprintf( D_ALWAYS,
					 "caInsert: Can't find %s in source classad.\n",
					 attr );
		}
		return FALSE;
	}
	tree->PrintToStr( buf );

	if( ! target->Insert( buf ) ) {
		dprintf( D_ALWAYS, "caInsert: Can't insert %s into target classad.\n",
				 attr );
		return FALSE;
	}
	return TRUE;
}

int
send_classad_to_sock( int cmd, Sock* sock, ClassAd* pubCA, ClassAd*
					  privCA )
{
	sock->encode();
	if( ! sock->put( cmd ) ) {
		dprintf( D_ALWAYS, "Can't send command\n");
		sock->end_of_message();
		return FALSE;
	}
	if( pubCA ) {
		if( ! pubCA->put( *sock ) ) {
			dprintf( D_ALWAYS, "Can't send public classad\n");
			sock->end_of_message();
			return FALSE;
		}
	}
	if( privCA ) {
		if( ! privCA->put( *sock ) ) {
			dprintf( D_ALWAYS, "Can't send private classad\n");
			sock->end_of_message();
			return FALSE;
		}
	}
	if( ! sock->end_of_message() ) {
		dprintf( D_ALWAYS, "Can't send end_of_message\n");
		return FALSE;
	}
	return TRUE;
}

/*
   This function reads of a capability string and an eom from the
   given stream.  It looks up that capability in the resmgr to find
   the corresponding Resource*.  If such a Resource is found, we
   return the pointer to it, otherwise, we return NULL.
*/
Resource*
stream_to_rip( Stream* stream )
{
	char* cap = NULL;
	Resource* rip;

	stream->decode();
	if( ! stream->code(cap) ) {
		dprintf( D_ALWAYS, "Can't read capability\n" );
		free( cap );
		return NULL;
	}
	if( ! stream->end_of_message() ) {
		dprintf( D_ALWAYS, "Can't read end_of_message\n" );
		free( cap );
		return NULL;
	}
	rip = resmgr->get_by_cur_cap( cap );
	if( !rip ) {
		dprintf( D_ALWAYS,
				 "Error: can't find resource with capability (%s)\n",
				 cap );
		free( cap );
		return NULL;
	}
	free( cap );
	return rip;
}
<commit_msg>On Win32, startd now cleans out the execute directory (via the Directory object).<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "startd.h"
#include "directory.h"

void
check_perms()
{
	struct stat st;
	mode_t mode;

	if (stat(exec_path, &st) < 0) {
		EXCEPT("stat exec path");
	}

	if ((st.st_mode & 0777) != 0777) {
		dprintf(D_FULLDEBUG, "Changing permission on %s\n", exec_path);
		mode = st.st_mode | 0777;
		if (chmod(exec_path, mode) < 0) {
			EXCEPT("chmod exec path");
		}
	}
}

void
cleanup_execute_dir(int pid)
{
	char buf[2048];

#if defined(WIN32)
	if( pid ) {
		sprintf( buf, "rmdir /s /q %.256s\\dir_%d",
				 exec_path, pid );
		system( buf );
	} else {
		// get rid of everything in the execute directory
		Directory dir(exec_path);
		dir.Remove_Entire_Directory();
	}
#else
	if( pid ) {
		sprintf( buf, "/bin/rm -rf %.256s/dir_%d",
				exec_path, pid );
	} else {
		sprintf( buf, "/bin/rm -rf %.256s/condor_exec* %.256s/dir_*",
				 exec_path, exec_path );
	}
	system( buf );
#endif
}

float
compute_rank( ClassAd* mach_classad, ClassAd* req_classad )
{
	float rank;

	if( mach_classad->EvalFloat( ATTR_RANK, req_classad, rank ) == 0 ) {
		dprintf( D_ALWAYS, "Error evaluating rank.\n" );
		rank = 0;
	}
	return rank;
}

int
create_port( ReliSock* rsock )
{
	rsock->bind();
	rsock->listen();
	return rsock->get_file_desc();
}

char*
command_to_string( int cmd )
{
	switch( cmd ) {
	case CONTINUE_CLAIM:
		return "continue_claim";
	case SUSPEND_CLAIM:
		return "suspend_claim";
	case DEACTIVATE_CLAIM:
		return "deactivate_claim";
	case DEACTIVATE_CLAIM_FORCIBLY:
		return "deactivate_claim_forcibly";
	case MATCH_INFO:
		return "match_info";
	case ALIVE:
		return "alive";
	case REQUEST_CLAIM:
		return "request_claim";
	case RELEASE_CLAIM:
		return "release_claim";
	case ACTIVATE_CLAIM:
		return "activate_claim";
	case GIVE_STATE:
		return "give_state";
	case PCKPT_JOB:
		return "pckpt_job";
	case PCKPT_ALL_JOBS:
		return "pckpt_all_jobs";
	case VACATE_CLAIM:
		return "vacate_claim";
	case VACATE_ALL_CLAIMS:
		return "vacate_all_claims";

	default:
		return "unknown";
	}
	return "error";
}

int
reply( Stream* s, int cmd )
{
	s->encode();
	if( !s->code( cmd ) || !s->end_of_message() ) {
		return FALSE;
	} else {
		return TRUE;
	}
}

int
caInsert( ClassAd* target, ClassAd* source, const char* attr, int verbose )
{
	char buf[4096];
	buf[0] = '\0';
	ExprTree* tree;
	if( !attr ) {
		EXCEPT( "caInsert called with NULL attribute" );
	}
	if( !target || !source ) {
		EXCEPT( "caInsert called with NULL classad" );
	}

	tree = source->Lookup( attr );
	if( !tree ) {
		if( verbose ) {
			dprintf( D_ALWAYS,
					 "caInsert: Can't find %s in source classad.\n",
					 attr );
		}
		return FALSE;
	}
	tree->PrintToStr( buf );

	if( ! target->Insert( buf ) ) {
		dprintf( D_ALWAYS, "caInsert: Can't insert %s into target classad.\n",
				 attr );
		return FALSE;
	}
	return TRUE;
}

int
send_classad_to_sock( int cmd, Sock* sock, ClassAd* pubCA, ClassAd*
					  privCA )
{
	sock->encode();
	if( ! sock->put( cmd ) ) {
		dprintf( D_ALWAYS, "Can't send command\n");
		sock->end_of_message();
		return FALSE;
	}
	if( pubCA ) {
		if( ! pubCA->put( *sock ) ) {
			dprintf( D_ALWAYS, "Can't send public classad\n");
			sock->end_of_message();
			return FALSE;
		}
	}
	if( privCA ) {
		if( ! privCA->put( *sock ) ) {
			dprintf( D_ALWAYS, "Can't send private classad\n");
			sock->end_of_message();
			return FALSE;
		}
	}
	if( ! sock->end_of_message() ) {
		dprintf( D_ALWAYS, "Can't send end_of_message\n");
		return FALSE;
	}
	return TRUE;
}

/*
   This function reads of a capability string and an eom from the
   given stream.  It looks up that capability in the resmgr to find
   the corresponding Resource*.  If such a Resource is found, we
   return the pointer to it, otherwise, we return NULL.
*/
Resource*
stream_to_rip( Stream* stream )
{
	char* cap = NULL;
	Resource* rip;

	stream->decode();
	if( ! stream->code(cap) ) {
		dprintf( D_ALWAYS, "Can't read capability\n" );
		free( cap );
		return NULL;
	}
	if( ! stream->end_of_message() ) {
		dprintf( D_ALWAYS, "Can't read end_of_message\n" );
		free( cap );
		return NULL;
	}
	rip = resmgr->get_by_cur_cap( cap );
	if( !rip ) {
		dprintf( D_ALWAYS,
				 "Error: can't find resource with capability (%s)\n",
				 cap );
		free( cap );
		return NULL;
	}
	free( cap );
	return rip;
}
<|endoftext|>


<commit_before>#include "S_Temporal_Boss_Room.h"
#include "j1Input.h"
#include "SDL\include\SDL.h"
#include "j1Scene.h"
#include "p2Log.h"
#include "j1App.h"
#include "j1Map.h"
#include "j1Render.h"
#include "j1Textures.h"
#include "j1Pathfinding.h"
#include "j1App.h"
#include "j1Player.h"
#include "j1Camera.h"
#include "j1HUD.h"
#include "j1Enemy.h"
#include"j1Audio.h"
#include"j1GameStartMenuBack.h"
#include "S_InGameMenu.h"
#include "O_ElectricBall.h"
#include"Video.h"

bool S_TempBossRoom::Start()
{
	scene_str = "HYRULE CASTLE";

	App->camera->Enable();
	App->hud->Enable();
	App->collision->Enable();
	App->map->Enable();
	App->player->Enable();
	App->object->Enable();
	App->enemy->Enable();

	App->enemy->Final_Boss = new Boss();
	App->enemy->Final_Boss->im_active = true;
	App->enemy->Final_Boss->is_testing = true;
	//PAUSE FALSE
	App->player->paused = true;
	App->enemy->paused = false;
	App->collision->paused = false;
	App->pathfinding->paused = false;
	SDL_Rect r = { 0,0,1280,720 };
	App->videoplayer->PlayVideo("Boss video.ogv", r);
	App->videoplayer->video_finished = false;

	done_second_video = false;
	done_video_boss = false;
	if (App->map->Load("final_boss_map_advanced.tmx") == true)

	{
		int w, h = 0;
		uchar* data = nullptr;
		if (App->map->CreateWalkabilityMap(w, h, &data))
			App->pathfinding->SetMap(w, h);

		for (uint i = 0; i < App->object->V_Objects.size(); i++) {
			if (App->object->V_Objects[i]->collider_tiles.size() > 0) {
				App->object->CreateColliders(*App->object->V_Objects[i]);
			}
		}

		int w_two, h_two = 0;
		uchar* data_two = nullptr;
		if (App->map->CreateEnemyMap(w_two, h_two, &data_two)) {
			int w_three = 0;
			int h_three = 0;
			uchar* data_three = nullptr;
			if (App->map->CreateEnemyPathMap(w_three, h_three, &data_three)) {
				App->enemy->Enable();
			}
		}
		RELEASE_ARRAY(data);
		//App->map->CreateLogicMap();
	}

	App->render->camera.x = 0;
	App->render->camera.y = 0;

	//App->player->Link->pos = { 660,1400 };
	//App->player->Zelda->pos = { 620,1400 };
	App->player->Link->logic_height = 0;
	App->player->Zelda->logic_height = 0;

	LOG("World Open");
	App->cutscenemanager->StartCutscene(3);
	return false;
}

bool S_TempBossRoom::Update()
{
	for (int i = 0; i < App->object->V_Objects.size(); i++) {
		if (App->object->V_Objects[i]->type == objectType::electric_ball) {
			App->object->V_Objects[i]->texture_rect = App->object->V_Objects[i]->actual_animation.GetCurrentFrame().rect;
		}
	}
	if (App->videoplayer->video_finished && done_video_boss == false)
	{
		App->audio->CleanUp();
		App->audio->Awake(App->config);
		App->audio->Start();
		App->player->paused = false;
		done_video_boss = true;
		App->audio->PlayMusic("audio/music/Final-boss-theme.ogg", 0);
		App->audio->VolumeMusic(100);
	}

	if (!App->player->paused)
		App->enemy->Final_Boss->UpdateLegs();

	return false;
}

bool S_TempBossRoom::PostUpdate()
{
	if (App->videoplayer->video_finished && done_video_boss == false)
	{
		/*if (App->player->loop_game_menu == true || App->player->half_hearts_test_purpose <= 0) {

			App->scene->ChangeScene(Scene_ID::Send);
			App->startmenuback->Freeze(false);
			App->player->loop_game_menu = false;
			App->player->half_hearts_test_purpose = App->player->hearts_containers_test_purpose * 2;
		}*/

		for (int i = 0; i < App->object->V_Objects.size(); i++) {
			if (App->object->V_Objects[i]->type == objectType::electric_ball) {
				ElectricBall* temp = (ElectricBall*)App->object->V_Objects[i];
				if (temp->active_phase == 1 && (App->enemy->Final_Boss->actual_phase == boss_phase_2 || App->enemy->Final_Boss->actual_phase == boss_phase_3))
					temp->active = true;
				if (temp->active_phase == 2 && (App->enemy->Final_Boss->actual_phase == boss_phase_3))
					temp->active = true;
			}
		}
		if (App->enemy->Final_Boss != nullptr) {
			if (App->enemy->Final_Boss->boss_defeated) {
				//Play final video
				//if finished App->scene->ChangeScene(Scene_ID::credits);
				SDL_Rect r = { 0,0,1280,720 };
				App->videoplayer->PlayVideo("Credits Sequence.ogv", r);
				App->videoplayer->video_finished = false;
				App->enemy->Final_Boss->boss_defeated = false;
				done_second_video = true;
			}
		}

	}

	if (App->enemy->Final_Boss != nullptr) {

			if (App->videoplayer->video_finished && done_second_video)  {
				App->audio->CleanUp();
				App->audio->Awake(App->config);
				App->audio->Start();
				App->player->paused = false;
				done_video_boss = true;
				App->scene->ChangeScene(Scene_ID::credits);
				App->scene->win_game_variableforshowcredits = true;
			}
		}

	return true;

}

bool S_TempBossRoom::Clean()
{
	if (App->enemy->Final_Boss != NULL) {
		App->enemy->Final_Boss->im_active = false;
		delete App->enemy->Final_Boss;
		App->enemy->Final_Boss = NULL;
	}
	LOG("World Test Deleted");

	App->player->Disable();
	App->enemy->Disable();
	App->map->Disable();
	App->collision->Disable();
	App->hud->Disable();
	App->object->Disable();

	//std::list <TileSet*>::iterator temp = App->map->data.tilesets.begin();

	/*p2List_item<TileSet*>* temp = App->map->data.tilesets.start;
	while (temp != NULL) {
	App->tex->UnLoad(temp->data->texture);
	temp = temp->next;
	}*/

	//This must be revised
	((S_InGameMenu*)App->scene->InGameMenuScene())->active = false;

	return false;
}

bool S_TempBossRoom::Save(pugi::xml_node& node) const
{
	return true;
}

bool S_TempBossRoom::Load(pugi::xml_node& node)
{
	return true;
}<commit_msg>Boss video fixed<commit_after>#include "S_Temporal_Boss_Room.h"
#include "j1Input.h"
#include "SDL\include\SDL.h"
#include "j1Scene.h"
#include "p2Log.h"
#include "j1App.h"
#include "j1Map.h"
#include "j1Render.h"
#include "j1Textures.h"
#include "j1Pathfinding.h"
#include "j1App.h"
#include "j1Player.h"
#include "j1Camera.h"
#include "j1HUD.h"
#include "j1Enemy.h"
#include"j1Audio.h"
#include"j1GameStartMenuBack.h"
#include "S_InGameMenu.h"
#include "O_ElectricBall.h"
#include"Video.h"

bool S_TempBossRoom::Start()
{
	scene_str = "HYRULE CASTLE";

	App->camera->Enable();
	App->hud->Enable();
	App->collision->Enable();
	App->map->Enable();
	App->player->Enable();
	App->object->Enable();
	App->enemy->Enable();

	App->enemy->Final_Boss = new Boss();
	App->enemy->Final_Boss->im_active = true;
	App->enemy->Final_Boss->is_testing = true;
	//PAUSE FALSE
	App->player->paused = true;
	App->enemy->paused = false;
	App->collision->paused = false;
	App->pathfinding->paused = false;
	SDL_Rect r = { 0,0,1280,720 };
	App->videoplayer->PlayVideo("Boss video.ogv", r);
	App->videoplayer->video_finished = false;

	done_second_video = false;
	done_video_boss = false;
	if (App->map->Load("final_boss_map_advanced.tmx") == true)

	{
		int w, h = 0;
		uchar* data = nullptr;
		if (App->map->CreateWalkabilityMap(w, h, &data))
			App->pathfinding->SetMap(w, h);

		for (uint i = 0; i < App->object->V_Objects.size(); i++) {
			if (App->object->V_Objects[i]->collider_tiles.size() > 0) {
				App->object->CreateColliders(*App->object->V_Objects[i]);
			}
		}

		int w_two, h_two = 0;
		uchar* data_two = nullptr;
		if (App->map->CreateEnemyMap(w_two, h_two, &data_two)) {
			int w_three = 0;
			int h_three = 0;
			uchar* data_three = nullptr;
			if (App->map->CreateEnemyPathMap(w_three, h_three, &data_three)) {
				App->enemy->Enable();
			}
		}
		RELEASE_ARRAY(data);
		//App->map->CreateLogicMap();
	}

	App->render->camera.x = 0;
	App->render->camera.y = 0;

	//App->player->Link->pos = { 660,1400 };
	//App->player->Zelda->pos = { 620,1400 };
	App->player->Link->logic_height = 0;
	App->player->Zelda->logic_height = 0;

	LOG("World Open");
	App->cutscenemanager->StartCutscene(3);
	return false;
}

bool S_TempBossRoom::Update()
{
	for (int i = 0; i < App->object->V_Objects.size(); i++) {
		if (App->object->V_Objects[i]->type == objectType::electric_ball) {
			App->object->V_Objects[i]->texture_rect = App->object->V_Objects[i]->actual_animation.GetCurrentFrame().rect;
		}
	}
	if (App->videoplayer->video_finished && done_video_boss == false)
	{
		App->audio->CleanUp();
		App->audio->Awake(App->config);
		App->audio->Start();
		App->player->paused = false;
		done_video_boss = true;
		App->audio->PlayMusic("audio/music/Final-boss-theme.ogg", 0);
		App->audio->VolumeMusic(100);
	}

	if (!App->player->paused)
		App->enemy->Final_Boss->UpdateLegs();

	return false;
}

bool S_TempBossRoom::PostUpdate()
{
	if (App->videoplayer->video_finished && done_video_boss == true)
	{
		/*if (App->player->loop_game_menu == true || App->player->half_hearts_test_purpose <= 0) {

			App->scene->ChangeScene(Scene_ID::Send);
			App->startmenuback->Freeze(false);
			App->player->loop_game_menu = false;
			App->player->half_hearts_test_purpose = App->player->hearts_containers_test_purpose * 2;
		}*/

		for (int i = 0; i < App->object->V_Objects.size(); i++) {
			if (App->object->V_Objects[i]->type == objectType::electric_ball) {
				ElectricBall* temp = (ElectricBall*)App->object->V_Objects[i];
				if (temp->active_phase == 1 && (App->enemy->Final_Boss->actual_phase == boss_phase_2 || App->enemy->Final_Boss->actual_phase == boss_phase_3))
					temp->active = true;
				if (temp->active_phase == 2 && (App->enemy->Final_Boss->actual_phase == boss_phase_3))
					temp->active = true;
			}
		}
		if (App->enemy->Final_Boss != nullptr) {
			if (App->enemy->Final_Boss->boss_defeated) {
				//Play final video
				//if finished App->scene->ChangeScene(Scene_ID::credits);
				SDL_Rect r = { 0,0,1280,720 };
				App->videoplayer->PlayVideo("Credits-sequence.ogv", r);
				App->videoplayer->video_finished = false;
				App->enemy->Final_Boss->boss_defeated = false;
				done_second_video = true;
			}
		}

	}

	if (App->enemy->Final_Boss != nullptr) {

			if (App->videoplayer->video_finished && done_second_video)  {
				App->audio->CleanUp();
				App->audio->Awake(App->config);
				App->audio->Start();
				App->player->paused = false;
				done_video_boss = true;
				App->scene->ChangeScene(Scene_ID::credits);
				App->scene->win_game_variableforshowcredits = true;
			}
		}

	return true;

}

bool S_TempBossRoom::Clean()
{
	if (App->enemy->Final_Boss != NULL) {
		App->enemy->Final_Boss->im_active = false;
		delete App->enemy->Final_Boss;
		App->enemy->Final_Boss = NULL;
	}
	LOG("World Test Deleted");

	App->player->Disable();
	App->enemy->Disable();
	App->map->Disable();
	App->collision->Disable();
	App->hud->Disable();
	App->object->Disable();

	//std::list <TileSet*>::iterator temp = App->map->data.tilesets.begin();

	/*p2List_item<TileSet*>* temp = App->map->data.tilesets.start;
	while (temp != NULL) {
	App->tex->UnLoad(temp->data->texture);
	temp = temp->next;
	}*/

	//This must be revised
	((S_InGameMenu*)App->scene->InGameMenuScene())->active = false;

	return false;
}

bool S_TempBossRoom::Save(pugi::xml_node& node) const
{
	return true;
}

bool S_TempBossRoom::Load(pugi::xml_node& node)
{
	return true;
}<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium team:
http://bohrium.bitbucket.org

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BOHRIUM_BRIDGE_CPP_RUNTIME
#define __BOHRIUM_BRIDGE_CPP_RUNTIME
#include <iostream>
#include <sstream>

namespace bxx {

// Runtime : Definition
inline Runtime& Runtime::instance()
{
    static Runtime instance;
    return instance;
}

inline Runtime::Runtime() : global_random_seed_(0), global_random_state_(0), extension_count(BH_MAX_OPCODE_ID+1), queue_size(0)
{
    bh_error err;
    char err_msg[1000];

    if((err = bh_component_init(&bridge, NULL)) != BH_SUCCESS)
        exit(-1);
    if(bridge.nchildren != 1)
    {
        sprintf(err_msg, "Error in the runtime configuration: the bridge must "
                         "have exactly one child of type VEM or FILTER.\n");
        throw std::runtime_error(err_msg);
    }
    runtime = &bridge.children[0];
    if((err = runtime->init(runtime->name)) != BH_SUCCESS)
    {
        sprintf(err_msg, "Error in the initialization of the VEM.\n");
        throw std::runtime_error(err_msg);
    }
}

inline Runtime::~Runtime()
{
    if (ref_count.size()) {
        std::cout << "There are " << ref_count.size() << " dangling refs." << std::endl;
        for (std::map<bh_base*, size_t>::iterator it=ref_count.begin();
            it!=ref_count.end();
            ++it) {
            std::cout << it->first << " => " << it->second << '\n';
        }
    }

    flush();
    runtime->shutdown();
    bh_component_destroy(&bridge);
}

inline size_t Runtime::get_queue_size()
{
    return queue_size;
}

/**
 * De-allocate all bh_base associated with BH_DISCARD instruction in the queue.
 *
 * @param count The max number of instructions to look at.
 * @return The number of bh_base that got de-allocated.
 */
inline
size_t Runtime::deallocate_meta(size_t count)
{
    size_t deallocated = 0;
    if (count > BH_CPP_QUEUE_MAX) {
        throw std::runtime_error("Trying to de-allocate more than physically possible.");
    }
    while(!garbage.empty()) {
        delete garbage.front();
        ++deallocated;
        garbage.pop_front();
    }
    return deallocated;
}

/**
 * Sends the instruction-list to the bohrium runtime.
 *
 * NOTE: Assumes that the list is non-empty.
 */
inline
size_t Runtime::execute()
{
    size_t cur_size = queue_size;

    bh_ir bhir = bh_ir(queue_size, queue);
    bh_error status = runtime->execute(&bhir);   // Send instructions to Bohrium
    queue_size = 0;                                // Reset size of the queue

    if (status != BH_SUCCESS) {
        std::stringstream err_msg;
        err_msg << "Err: Runtime::execute() child->execute() failed: " << bh_error_text(status) << std::endl;

        throw std::runtime_error(err_msg.str());
    }

    deallocate_meta(cur_size);

    return cur_size;
}

/**
 * Flush the instruction-queue if it is about to get overflowed.
 *
 * This is used as a pre-condition to adding instructions to the queue.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::guard()
{
    if (queue_size >= BH_CPP_QUEUE_MAX) {
        return execute();
    }
    return 0;
}

/**
 * Flush the instruction-queue.
 *
 * This will force the runtime system to execute the queued up instructions,
 * at least if there are any queued instructions.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::flush()
{
    if (queue_size > 0) {
        return execute();
    }
    return 0;
}

/**
 * Create an unitialized intermediate operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp()
{
    multi_array<T>* operand = new multi_array<T>();
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an intermediate operand based on another operands meta-data.
 */
template <typename T, typename OtherT>
inline
multi_array<T>& Runtime::temp(multi_array<OtherT>& input)
{
    multi_array<T>* operand = new multi_array<T>(input);
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);

    operand->meta.base = base.meta.base;
    Runtime::instance().ref_count[operand->meta.base] += 1;

    return *operand;
}

/**
 * Create an intermediate alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp_view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);

    operand->meta.base = base.meta.base;
    operand->setTemp(true);
    Runtime::instance().ref_count[operand->meta.base] += 1;

    return *operand;
}

template <typename TO, typename TL, typename TR>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, multi_array<TL>& op1, multi_array<TR>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;

    if ((!identical(op0, op1)) && op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename TO, typename TL, typename TR>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, multi_array<TL>& op1, const TR op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op2);

    if ((!identical(op0, op1)) && op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
}

template <typename TO, typename TL, typename TR>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, const TL op1, multi_array<TR>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op1 );

    if ((!identical(op0, op2)) && op0.getTemp()) { delete &op0; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename TO, typename TI>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, multi_array<TI>& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;

    if ((!identical(op0, op1)) && op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
}

template <typename TO, typename TI>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, const TI op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op1);

    if (op0.getTemp()) { delete &op0; }
}

template <typename TO>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;

    if (op0.getTemp()) { delete &op0; }
}

//
//  This function should only be used by random to encode the degenerate bh_r123 type.
//
template <typename TO>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, const uint64_t op1, const uint64_t op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;

    instr->constant.type = BH_R123;
    instr->constant.value.r123.start = op1;
    instr->constant.value.r123.key   = op2;
}

template <typename T1, typename T2, typename T3>
inline
void Runtime::enqueue_extension(const std::string& name,
                                multi_array<T1>& op0,
                                multi_array<T2>& op1,
                                multi_array<T3>& op2)
{
    bh_instruction* instr;
    bh_opcode opcode;

    // Look for the extension opcode
    std::map<std::string, bh_opcode>::iterator it = extensions.find(name);
    if (it != extensions.end()) {   // Got it
        opcode = it->second;
    } else {                        // Add it
        opcode = extension_count++;
        extensions.insert(std::pair<std::string, bh_opcode>(name, opcode));
        if(runtime->extmethod(name.c_str(), opcode) != BH_SUCCESS)
            throw std::runtime_error("Unknown extmethod");
    }

    guard();

    // Construct and enqueue the instructions
    instr = &queue[queue_size++];
    instr->opcode = extensions[name];
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;

    if (op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename T>
T scalar(multi_array<T>& op)
{
    bool is_temp = op.getTemp();
    op.setTemp(false);
    Runtime::instance().enqueue((bh_opcode)BH_SYNC, op);
    Runtime::instance().flush();

    bh_base *op_a = op.getBase();
    T* data = (T*)(op_a->data);
    data += op.meta.start;

    T value = *data;

    if (is_temp) {      // If it was a temp you will never see it again
        delete &op;     // so you better clean it up!
        Runtime::instance().flush();
    }

    return value;
}

inline void Runtime::trash(bh_base *base)
{
    garbage.push_back(base);
}

inline uint64_t Runtime::getRandSeed(void) {
    return global_random_seed_;
}

inline void Runtime::setRandSeed(uint64_t seed) {
    global_random_seed_ = seed;
}

inline uint64_t Runtime::getRandState(void) {
    return global_random_state_;
}

inline void Runtime::setRandState(uint64_t state) {
    global_random_state_ = state;
}

}
#endif

<commit_msg>bxx: Moved assignment out of conditional.<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium team:
http://bohrium.bitbucket.org

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BOHRIUM_BRIDGE_CPP_RUNTIME
#define __BOHRIUM_BRIDGE_CPP_RUNTIME
#include <iostream>
#include <sstream>

namespace bxx {

// Runtime : Definition
inline Runtime& Runtime::instance()
{
    static Runtime instance;
    return instance;
}

inline Runtime::Runtime() : global_random_seed_(0), global_random_state_(0), extension_count(BH_MAX_OPCODE_ID+1), queue_size(0)
{
    char err_msg[1000];

    bh_error err = bh_component_init(&bridge, NULL);
    if (BH_SUCCESS != err) {
        exit(-1);
    }
    if (bridge.nchildren != 1) {
        sprintf(err_msg, "Error in the runtime configuration: the bridge must "
                         "have exactly one child of type VEM or FILTER.\n");
        throw std::runtime_error(err_msg);
    }
    runtime = &bridge.children[0];

    err = runtime->init(runtime->name);
    if (BH_SUCCESS != err) {
        sprintf(err_msg, "Error in the initialization of the VEM.\n");
        throw std::runtime_error(err_msg);
    }
}

inline Runtime::~Runtime()
{
    if (ref_count.size()) {
        std::cout << "There are " << ref_count.size() << " dangling refs." << std::endl;
        for (std::map<bh_base*, size_t>::iterator it=ref_count.begin();
            it!=ref_count.end();
            ++it) {
            std::cout << it->first << " => " << it->second << '\n';
        }
    }

    flush();
    runtime->shutdown();
    bh_component_destroy(&bridge);
}

inline size_t Runtime::get_queue_size()
{
    return queue_size;
}

/**
 * De-allocate all bh_base associated with BH_DISCARD instruction in the queue.
 *
 * @param count The max number of instructions to look at.
 * @return The number of bh_base that got de-allocated.
 */
inline
size_t Runtime::deallocate_meta(size_t count)
{
    size_t deallocated = 0;
    if (count > BH_CPP_QUEUE_MAX) {
        throw std::runtime_error("Trying to de-allocate more than physically possible.");
    }
    while(!garbage.empty()) {
        delete garbage.front();
        ++deallocated;
        garbage.pop_front();
    }
    return deallocated;
}

/**
 * Sends the instruction-list to the bohrium runtime.
 *
 * NOTE: Assumes that the list is non-empty.
 */
inline
size_t Runtime::execute()
{
    size_t cur_size = queue_size;

    bh_ir bhir = bh_ir(queue_size, queue);
    bh_error status = runtime->execute(&bhir);   // Send instructions to Bohrium
    queue_size = 0;                                // Reset size of the queue

    if (status != BH_SUCCESS) {
        std::stringstream err_msg;
        err_msg << "Err: Runtime::execute() child->execute() failed: " << bh_error_text(status) << std::endl;

        throw std::runtime_error(err_msg.str());
    }

    deallocate_meta(cur_size);

    return cur_size;
}

/**
 * Flush the instruction-queue if it is about to get overflowed.
 *
 * This is used as a pre-condition to adding instructions to the queue.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::guard()
{
    if (queue_size >= BH_CPP_QUEUE_MAX) {
        return execute();
    }
    return 0;
}

/**
 * Flush the instruction-queue.
 *
 * This will force the runtime system to execute the queued up instructions,
 * at least if there are any queued instructions.
 *
 * @return The number of instructions flushed.
 */
inline
size_t Runtime::flush()
{
    if (queue_size > 0) {
        return execute();
    }
    return 0;
}

/**
 * Create an unitialized intermediate operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp()
{
    multi_array<T>* operand = new multi_array<T>();
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an intermediate operand based on another operands meta-data.
 */
template <typename T, typename OtherT>
inline
multi_array<T>& Runtime::temp(multi_array<OtherT>& input)
{
    multi_array<T>* operand = new multi_array<T>(input);
    operand->setTemp(true);

    return *operand;
}

/**
 * Create an alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);

    operand->meta.base = base.meta.base;
    Runtime::instance().ref_count[operand->meta.base] += 1;

    return *operand;
}

/**
 * Create an intermediate alias/segment/view of the supplied base operand.
 */
template <typename T>
inline
multi_array<T>& Runtime::temp_view(multi_array<T>& base)
{
    multi_array<T>* operand = new multi_array<T>(base);

    operand->meta.base = base.meta.base;
    operand->setTemp(true);
    Runtime::instance().ref_count[operand->meta.base] += 1;

    return *operand;
}

template <typename TO, typename TL, typename TR>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, multi_array<TL>& op1, multi_array<TR>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;

    if ((!identical(op0, op1)) && op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename TO, typename TL, typename TR>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, multi_array<TL>& op1, const TR op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op2);

    if ((!identical(op0, op1)) && op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
}

template <typename TO, typename TL, typename TR>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, const TL op1, multi_array<TR>& op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2] = op2.meta;
    assign_const_type( &instr->constant, op1 );

    if ((!identical(op0, op2)) && op0.getTemp()) { delete &op0; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename TO, typename TI>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, multi_array<TI>& op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2].base = NULL;

    if ((!identical(op0, op1)) && op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
}

template <typename TO, typename TI>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, const TI op1)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;
    assign_const_type(&instr->constant, op1);

    if (op0.getTemp()) { delete &op0; }
}

template <typename TO>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;

    if (op0.getTemp()) { delete &op0; }
}

//
//  This function should only be used by random to encode the degenerate bh_r123 type.
//
template <typename TO>
inline
void Runtime::enqueue(bh_opcode opcode, multi_array<TO>& op0, const uint64_t op1, const uint64_t op2)
{
    bh_instruction* instr;

    guard();

    instr = &queue[queue_size++];
    instr->opcode = opcode;
    instr->operand[0] = op0.meta;
    instr->operand[1].base = NULL;
    instr->operand[2].base = NULL;

    instr->constant.type = BH_R123;
    instr->constant.value.r123.start = op1;
    instr->constant.value.r123.key   = op2;
}

template <typename T1, typename T2, typename T3>
inline
void Runtime::enqueue_extension(const std::string& name,
                                multi_array<T1>& op0,
                                multi_array<T2>& op1,
                                multi_array<T3>& op2)
{
    bh_instruction* instr;
    bh_opcode opcode;

    // Look for the extension opcode
    std::map<std::string, bh_opcode>::iterator it = extensions.find(name);
    if (it != extensions.end()) {   // Got it
        opcode = it->second;
    } else {                        // Add it
        opcode = extension_count++;
        extensions.insert(std::pair<std::string, bh_opcode>(name, opcode));
        if(runtime->extmethod(name.c_str(), opcode) != BH_SUCCESS)
            throw std::runtime_error("Unknown extmethod");
    }

    guard();

    // Construct and enqueue the instructions
    instr = &queue[queue_size++];
    instr->opcode = extensions[name];
    instr->operand[0] = op0.meta;
    instr->operand[1] = op1.meta;
    instr->operand[2] = op2.meta;

    if (op0.getTemp()) { delete &op0; }
    if (op1.getTemp()) { delete &op1; }
    if (op2.getTemp()) { delete &op2; }
}

template <typename T>
T scalar(multi_array<T>& op)
{
    bool is_temp = op.getTemp();
    op.setTemp(false);
    Runtime::instance().enqueue((bh_opcode)BH_SYNC, op);
    Runtime::instance().flush();

    bh_base *op_a = op.getBase();
    T* data = (T*)(op_a->data);
    data += op.meta.start;

    T value = *data;

    if (is_temp) {      // If it was a temp you will never see it again
        delete &op;     // so you better clean it up!
        Runtime::instance().flush();
    }

    return value;
}

inline void Runtime::trash(bh_base *base)
{
    garbage.push_back(base);
}

inline uint64_t Runtime::getRandSeed(void) {
    return global_random_seed_;
}

inline void Runtime::setRandSeed(uint64_t seed) {
    global_random_seed_ = seed;
}

inline uint64_t Runtime::getRandState(void) {
    return global_random_state_;
}

inline void Runtime::setRandState(uint64_t state) {
    global_random_state_ = state;
}

}
#endif

<|endoftext|>


<commit_before>#pragma once

#include "../Includes/Includes.hpp"

namespace NE
{
	class NE_DLL NamedUnitTagger : public NEModule
	{
	public:
		typedef NamedUnitTagger ThisClass;
		typedef NEModule SuperClass;

	public:
		NETArgument<NEBooleanKey>	arg_enable;
		NETArgument<NECodeSetKey>	arg_codes;

	protected:
		virtual type_result _onFetchModule()
		{
			arg_enable.setPurposeLimitation(NEArgumentBase::READ_OR_WRITTEN);
			arg_enable.setEnable(false);
			arg_codes.setPurposeLimitation(NEArgumentBase::READ_OR_WRITTEN);
			arg_codes.setEnable(false);

			return RESULT_SUCCESS;
		}
		virtual type_result _onFetchArguments(NEArgumentList& tray)
		{
			tray.push(arg_enable);
			tray.push(arg_codes);

			return RESULT_SUCCESS;
		}

	protected:
		type_result _onExecute(NENamedUnit& target)
		{
			if(arg_enable.isEnable())
			{
				if(arg_enable.getPurpose() == NEArgumentBase::WRITTEN)
					target.setEnable(arg_enable.getValue());
				else
					arg_enable.setValue(target.isEnable());
			}
			if(arg_codes.isEnable())
			{
				const NECodeSet& codes = arg_codes.getValue();

				if (arg_codes.getPurpose() == NEArgumentBase::WRITTEN)
					target.setCodes(codes);
				else
					arg_codes.setValue(target.getCodes(codes.getCodeType()));
			}

			return RESULT_SUCCESS;
		}

	public:
		virtual const NEExportable::ModuleHeader& getHeader() const
		{
			static NEExportable::ModuleHeader _instance;

			if (_instance.isValid() != RESULT_NOTHING)
			{
				_instance.getName() = "NamedUnitTagger";
				_instance.getDeveloper() = "kniz";
				_instance.setRevision(1);
				_instance.getReleaseDate() = "2015/01/02";
				_instance.getComment() =
					"\tEnable:\tü Ȱȭ .\n"
					"\tCodes:\tü ־ Code";
				NETStringSet& args = _instance.getArgumentsComments();
				args.create(2);
				args.push("Enable Ӽ\n Ȱȭ Դϴ. INPUT, OUTPUT ο   ų Ҵմϴ.");
				args.push("Codes Ӽ\nSCRIPT, NAME, GROUP  ü ڵ Դϴ.");
			}

			return _instance;
		}
	};
}<commit_msg>FIX: NamedUnitTagger가 주어진 Codes의 CodeType이 UNDEFINED일 경우의 예외 처리<commit_after>#pragma once

#include "../Includes/Includes.hpp"

namespace NE
{
	class NE_DLL NamedUnitTagger : public NEModule
	{
	public:
		typedef NamedUnitTagger ThisClass;
		typedef NEModule SuperClass;

	public:
		NETArgument<NEBooleanKey>	arg_enable;
		NETArgument<NECodeSetKey>	arg_codes;

	protected:
		virtual type_result _onFetchModule()
		{
			arg_enable.setPurposeLimitation(NEArgumentBase::READ_OR_WRITTEN);
			arg_enable.setEnable(false);
			arg_codes.setPurposeLimitation(NEArgumentBase::READ_OR_WRITTEN);
			arg_codes.setEnable(false);

			return RESULT_SUCCESS;
		}
		virtual type_result _onFetchArguments(NEArgumentList& tray)
		{
			tray.push(arg_enable);
			tray.push(arg_codes);

			return RESULT_SUCCESS;
		}

	protected:

		type_result _onExecute(NENamedUnit& target)
		{
			if(arg_enable.isEnable())
			{
				if(arg_enable.getPurpose() == NEArgumentBase::WRITTEN)
					target.setEnable(arg_enable.getValue());
				else
					arg_enable.setValue(target.isEnable());
			}
			if(arg_codes.isEnable())
			{
				const NECodeSet& codes = arg_codes.getValue();
				if (codes.getCodeType().getCodeType() == NEArgumentBase::UNDEFINED)
					return ALERT_WARNING(" ߸ CodeSet CodeType(%d)Դϴ.", codes.getCodeType());

				if (arg_codes.getPurpose() == NEArgumentBase::WRITTEN)
					target.setCodes(codes);
				else
					arg_codes.setValue(target.getCodes(codes.getCodeType()));
			}

			return RESULT_SUCCESS;
		}

	public:
		virtual const NEExportable::ModuleHeader& getHeader() const
		{
			static NEExportable::ModuleHeader _instance;

			if (_instance.isValid() != RESULT_NOTHING)
			{
				_instance.getName() = "NamedUnitTagger";
				_instance.getDeveloper() = "kniz";
				_instance.setRevision(1);
				_instance.getReleaseDate() = "2015/01/02";
				_instance.getComment() =
					"\tEnable:\tü Ȱȭ .\n"
					"\tCodes:\tü ־ Code";
				NETStringSet& args = _instance.getArgumentsComments();
				args.create(2);
				args.push("Enable Ӽ\n Ȱȭ Դϴ. INPUT, OUTPUT ο   ų Ҵմϴ.");
				args.push("Codes Ӽ\nSCRIPT, NAME, GROUP  ü ڵ Դϴ.");
			}

			return _instance;
		}
	};
}<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreRoot.h"

#include "OgreGLESPrerequisites.h"
#include "OgreGLESRenderSystem.h"

#include "OgreSymbianEGLSupport.h"
#include "OgreSymbianEGLWindow.h"
#include "OgreSymbianEGLRenderTexture.h"
#include "OgreSymbianEGLContext.h"

#ifdef __GCCE__
#include <staticlibinit_gcce.h>
#endif

#include <e32base.h> // for Symbian classes.
#include <coemain.h> // for CCoeEnv.

namespace Ogre {

	SymbianEGLSupport::SymbianEGLSupport()
	{

		TSizeMode sizeMode = CCoeEnv::Static()->ScreenDevice()->GetCurrentScreenModeAttributes();

		//RECT windowRect;
		//GetClientRect(mNativeDisplay, &windowRect);
		mCurrentMode.first.first = sizeMode.iScreenSize.iWidth;
		mCurrentMode.first.second = sizeMode.iScreenSize.iHeight;
		mCurrentMode.second = 0;
		mOriginalMode = mCurrentMode;
		mVideoModes.push_back(mCurrentMode);
/*
		EGLConfig *glConfigs;
		int config, nConfigs = 0;

		glConfigs = chooseGLConfig(NULL, &nConfigs);

		for (config = 0; config < nConfigs; config++)
		{
			int caveat, samples;

			getGLConfigAttrib(glConfigs[config], EGL_CONFIG_CAVEAT, &caveat);

			if (caveat != EGL_SLOW_CONFIG)
			{
				getGLConfigAttrib(glConfigs[config], EGL_SAMPLES, &samples);
				mSampleLevels.push_back(StringConverter::toString(samples));
			}
		}

		free(glConfigs);

		removeDuplicates(mSampleLevels);
*/

		mNativeDisplay = EGL_DEFAULT_DISPLAY;
		mGLDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
		//eglInitialize( mGLDisplay, NULL, NULL ) ; - not possible here

	}

	SymbianEGLSupport::~SymbianEGLSupport()
	{

	}

	EGLWindow* SymbianEGLSupport::createEGLWindow(  EGLSupport * support )
	{
		return new SymbianEGLWindow(support);
	}

	GLESPBuffer* SymbianEGLSupport::createPBuffer( PixelComponentType format, size_t width, size_t height )
	{
		return new SymbianEGLPBuffer(this, format, width, height);
	}

	void SymbianEGLSupport::switchMode( uint& width, uint& height, short& frequency )
	{
		if (!mRandr)
			return;

		int size = 0;
		int newSize = -1;

		VideoModes::iterator mode;
		VideoModes::iterator end = mVideoModes.end();
		VideoMode *newMode = 0;

		for(mode = mVideoModes.begin(); mode != end; size++)
		{
			if (mode->first.first >= static_cast<int>(width) &&
				mode->first.second >= static_cast<int>(height))
			{
				if (!newMode ||
					mode->first.first < newMode->first.first ||
					mode->first.second < newMode->first.second)
				{
					newSize = size;
					newMode = &(*mode);
				}
			}

			VideoMode* lastMode = &(*mode);

			while (++mode != end && mode->first == lastMode->first)
			{
				if (lastMode == newMode && mode->second == frequency)
				{
					newMode = &(*mode);
				}
			}
		}

		//todo
	}

	RenderWindow* SymbianEGLSupport::newWindow( const String &name, unsigned int width, unsigned int height, bool fullScreen, const NameValuePairList *miscParams /*= 0*/ )
	{
		SymbianEGLWindow* window = new SymbianEGLWindow(this);
		window->create(name, width, height, fullScreen, miscParams);

		return window;
	}
}
<commit_msg>Symbian port: Removed some unneeded __GCCE__ include code and added some validity checks to egl initialization.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreRoot.h"

#include "OgreGLESPrerequisites.h"
#include "OgreGLESRenderSystem.h"

#include "OgreSymbianEGLSupport.h"
#include "OgreSymbianEGLWindow.h"
#include "OgreSymbianEGLRenderTexture.h"
#include "OgreSymbianEGLContext.h"

#include <e32base.h> // for Symbian classes.
#include <coemain.h> // for CCoeEnv.

namespace Ogre {

	SymbianEGLSupport::SymbianEGLSupport()
	{

		TSizeMode sizeMode = CCoeEnv::Static()->ScreenDevice()->GetCurrentScreenModeAttributes();

		//RECT windowRect;
		//GetClientRect(mNativeDisplay, &windowRect);
		mCurrentMode.first.first = sizeMode.iScreenSize.iWidth;
		mCurrentMode.first.second = sizeMode.iScreenSize.iHeight;
		mCurrentMode.second = 0;
		mOriginalMode = mCurrentMode;
		mVideoModes.push_back(mCurrentMode);
/*
		EGLConfig *glConfigs;
		int config, nConfigs = 0;

		glConfigs = chooseGLConfig(NULL, &nConfigs);

		for (config = 0; config < nConfigs; config++)
		{
			int caveat, samples;

			getGLConfigAttrib(glConfigs[config], EGL_CONFIG_CAVEAT, &caveat);

			if (caveat != EGL_SLOW_CONFIG)
			{
				getGLConfigAttrib(glConfigs[config], EGL_SAMPLES, &samples);
				mSampleLevels.push_back(StringConverter::toString(samples));
			}
		}

		free(glConfigs);

		removeDuplicates(mSampleLevels);
*/

		mNativeDisplay = EGL_DEFAULT_DISPLAY;
		mGLDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
		if( mGLDisplay != NULL )
		{
			// Initialize EGL.
			if( eglInitialize( mGLDisplay, NULL, NULL ) == EGL_FALSE )
			{
				OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
					"EGL Initialize failed!",
					"SymbianEGLSupport::SymbianEGLSupport");

			}
		}

	}

	SymbianEGLSupport::~SymbianEGLSupport()
	{

	}

	EGLWindow* SymbianEGLSupport::createEGLWindow(  EGLSupport * support )
	{
		return new SymbianEGLWindow(support);
	}

	GLESPBuffer* SymbianEGLSupport::createPBuffer( PixelComponentType format, size_t width, size_t height )
	{
		return new SymbianEGLPBuffer(this, format, width, height);
	}

	void SymbianEGLSupport::switchMode( uint& width, uint& height, short& frequency )
	{
		if (!mRandr)
			return;

		int size = 0;
		int newSize = -1;

		VideoModes::iterator mode;
		VideoModes::iterator end = mVideoModes.end();
		VideoMode *newMode = 0;

		for(mode = mVideoModes.begin(); mode != end; size++)
		{
			if (mode->first.first >= static_cast<int>(width) &&
				mode->first.second >= static_cast<int>(height))
			{
				if (!newMode ||
					mode->first.first < newMode->first.first ||
					mode->first.second < newMode->first.second)
				{
					newSize = size;
					newMode = &(*mode);
				}
			}

			VideoMode* lastMode = &(*mode);

			while (++mode != end && mode->first == lastMode->first)
			{
				if (lastMode == newMode && mode->second == frequency)
				{
					newMode = &(*mode);
				}
			}
		}

		//todo
	}

	RenderWindow* SymbianEGLSupport::newWindow( const String &name, unsigned int width, unsigned int height, bool fullScreen, const NameValuePairList *miscParams /*= 0*/ )
	{
		SymbianEGLWindow* window = new SymbianEGLWindow(this);
		window->create(name, width, height, fullScreen, miscParams);

		return window;
	}
}
<|endoftext|>


<commit_before>#include<iostream>

using namespace std;

int main()
{
  cout<<"hello world!"<<endl;
  cout<<"hello world!"<<endl;
  cout<<"hello world!"<<endl;
  return 0;
}<commit_msg>add branch<commit_after>#include<iostream>

using namespace std;

int main()
{
  cout<<"hello world!"<<endl;
  cout<<"hello world!"<<endl;
  cout<<"hello world!"<<endl;
  cout<<"hello world!"<<endl;
  return 0;
}<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file opt_algebraic.cpp
 *
 * Takes advantage of association, commutivity, and other algebraic
 * properties to simplify expressions.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h"
#include "glsl_types.h"

/**
 * Visitor class for replacing expressions with ir_constant values.
 */

class ir_algebraic_visitor : public ir_rvalue_visitor {
public:
   ir_algebraic_visitor()
   {
      this->progress = false;
      this->mem_ctx = NULL;
   }

   virtual ~ir_algebraic_visitor()
   {
   }

   ir_rvalue *handle_expression(ir_expression *ir);
   void handle_rvalue(ir_rvalue **rvalue);
   bool reassociate_constant(ir_expression *ir1,
			     int const_index,
			     ir_constant *constant,
			     ir_expression *ir2);
   void reassociate_operands(ir_expression *ir1,
			     int op1,
			     ir_expression *ir2,
			     int op2);
   ir_rvalue *swizzle_if_required(ir_expression *expr,
				  ir_rvalue *operand);

   void *mem_ctx;

   bool progress;
};

static inline bool
is_vec_zero(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_zero();
}

static inline bool
is_vec_one(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_one();
}

static void
update_type(ir_expression *ir)
{
   if (ir->operands[0]->type->is_vector())
      ir->type = ir->operands[0]->type;
   else
      ir->type = ir->operands[1]->type;
}

void
ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
					   int op1,
					   ir_expression *ir2,
					   int op2)
{
   ir_rvalue *temp = ir2->operands[op2];
   ir2->operands[op2] = ir1->operands[op1];
   ir1->operands[op1] = temp;

   /* Update the type of ir2.  The type of ir1 won't have changed --
    * base types matched, and at least one of the operands of the 2
    * binops is still a vector if any of them were.
    */
   update_type(ir2);

   this->progress = true;
}

/**
 * Reassociates a constant down a tree of adds or multiplies.
 *
 * Consider (2 * (a * (b * 0.5))).  We want to send up with a * b.
 */
bool
ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
					   ir_constant *constant,
					   ir_expression *ir2)
{
   if (!ir2 || ir1->operation != ir2->operation)
      return false;

   /* Don't want to even think about matrices. */
   if (ir1->operands[0]->type->is_matrix() ||
       ir1->operands[0]->type->is_matrix() ||
       ir2->operands[1]->type->is_matrix() ||
       ir2->operands[1]->type->is_matrix())
      return false;

   ir_constant *ir2_const[2];
   ir2_const[0] = ir2->operands[0]->constant_expression_value();
   ir2_const[1] = ir2->operands[1]->constant_expression_value();

   if (ir2_const[0] && ir2_const[1])
      return false;

   if (ir2_const[0]) {
      reassociate_operands(ir1, const_index, ir2, 1);
      return true;
   } else if (ir2_const[1]) {
      reassociate_operands(ir1, const_index, ir2, 0);
      return true;
   }

   if (reassociate_constant(ir1, const_index, constant,
			    ir2->operands[0]->as_expression())) {
      update_type(ir2);
      return true;
   }

   if (reassociate_constant(ir1, const_index, constant,
			    ir2->operands[1]->as_expression())) {
      update_type(ir2);
      return true;
   }

   return false;
}

/* When eliminating an expression and just returning one of its operands,
 * we may need to swizzle that operand out to a vector if the expression was
 * vector type.
 */
ir_rvalue *
ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
					  ir_rvalue *operand)
{
   if (expr->type->is_vector() && operand->type->is_scalar()) {
      return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
				     expr->type->vector_elements);
   } else
      return operand;
}

ir_rvalue *
ir_algebraic_visitor::handle_expression(ir_expression *ir)
{
   ir_constant *op_const[2] = {NULL, NULL};
   ir_expression *op_expr[2] = {NULL, NULL};
   ir_expression *temp;
   unsigned int i;

   assert(ir->get_num_operands() <= 2);
   for (i = 0; i < ir->get_num_operands(); i++) {
      if (ir->operands[i]->type->is_matrix())
	 return ir;

      op_const[i] = ir->operands[i]->constant_expression_value();
      op_expr[i] = ir->operands[i]->as_expression();
   }

   if (this->mem_ctx == NULL)
      this->mem_ctx = talloc_parent(ir);

   switch (ir->operation) {
   case ir_unop_logic_not: {
      enum ir_expression_operation new_op = ir_unop_logic_not;

      if (op_expr[0] == NULL)
	 break;

      switch (op_expr[0]->operation) {
      case ir_binop_less:    new_op = ir_binop_gequal;  break;
      case ir_binop_greater: new_op = ir_binop_lequal;  break;
      case ir_binop_lequal:  new_op = ir_binop_greater; break;
      case ir_binop_gequal:  new_op = ir_binop_less;    break;
      case ir_binop_equal:   new_op = ir_binop_nequal;  break;
      case ir_binop_nequal:  new_op = ir_binop_equal;   break;
      case ir_binop_all_equal:   new_op = ir_binop_any_nequal;  break;
      case ir_binop_any_nequal:  new_op = ir_binop_all_equal;   break;

      default:
	 /* The default case handler is here to silence a warning from GCC.
	  */
	 break;
      }

      if (new_op != ir_unop_logic_not) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(new_op,
					   ir->type,
					   op_expr[0]->operands[0],
					   op_expr[0]->operands[1]);
      }

      break;
   }

   case ir_binop_add:
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[1]);
      }
      if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }

      /* Reassociate addition of constants so that we can do constant
       * folding.
       */
      if (op_const[0] && !op_const[1])
	 reassociate_constant(ir, 0, op_const[0],
			      ir->operands[1]->as_expression());
      if (op_const[1] && !op_const[0])
	 reassociate_constant(ir, 1, op_const[1],
			      ir->operands[0]->as_expression());
      break;

   case ir_binop_sub:
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_neg,
					   ir->operands[1]->type,
					   ir->operands[1],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }
      if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }
      break;

   case ir_binop_mul:
      if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[1]);
      }
      if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }

      if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(ir, ir->type);
      }

      /* Reassociate multiplication of constants so that we can do
       * constant folding.
       */
      if (op_const[0] && !op_const[1])
	 reassociate_constant(ir, 0, op_const[0],
			      ir->operands[1]->as_expression());
      if (op_const[1] && !op_const[0])
	 reassociate_constant(ir, 1, op_const[1],
			      ir->operands[0]->as_expression());

      break;

   case ir_binop_div:
      if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_rcp,
					   ir->operands[1]->type,
					   ir->operands[1],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }
      if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }
      break;

   case ir_binop_logic_and:
      /* FINISHME: Also simplify (a && a) to (a). */
      if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(mem_ctx, ir->type);
      }
      break;

   case ir_binop_logic_xor:
      /* FINISHME: Also simplify (a ^^ a) to (false). */
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
					   ir->operands[1], NULL);
      } else if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
					   ir->operands[0], NULL);
      }
      break;

   case ir_binop_logic_or:
      /* FINISHME: Also simplify (a || a) to (a). */
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
	 ir_constant_data data;

	 for (unsigned i = 0; i < 16; i++)
	    data.b[i] = true;

	 this->progress = true;
	 return new(mem_ctx) ir_constant(ir->type, &data);
      }
      break;

   case ir_unop_rcp:
      if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
	 this->progress = true;
	 return op_expr[0]->operands[0];
      }

      /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
       * backends, except that some backends will have done sqrt ->
       * rcp(rsq(x)) and we don't want to undo it for them.
       */

      /* As far as we know, all backends are OK with rsq. */
      if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_rsq,
					   op_expr[0]->operands[0]->type,
					   op_expr[0]->operands[0],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }

      break;

   default:
      break;
   }

   return ir;
}

void
ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_expression *expr = (*rvalue)->as_expression();
   if (!expr || expr->operation == ir_quadop_vector)
      return;

   *rvalue = handle_expression(expr);
}

bool
do_algebraic(exec_list *instructions)
{
   ir_algebraic_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
<commit_msg>glsl: fix matrix type check in ir_algebraic<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file opt_algebraic.cpp
 *
 * Takes advantage of association, commutivity, and other algebraic
 * properties to simplify expressions.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h"
#include "glsl_types.h"

/**
 * Visitor class for replacing expressions with ir_constant values.
 */

class ir_algebraic_visitor : public ir_rvalue_visitor {
public:
   ir_algebraic_visitor()
   {
      this->progress = false;
      this->mem_ctx = NULL;
   }

   virtual ~ir_algebraic_visitor()
   {
   }

   ir_rvalue *handle_expression(ir_expression *ir);
   void handle_rvalue(ir_rvalue **rvalue);
   bool reassociate_constant(ir_expression *ir1,
			     int const_index,
			     ir_constant *constant,
			     ir_expression *ir2);
   void reassociate_operands(ir_expression *ir1,
			     int op1,
			     ir_expression *ir2,
			     int op2);
   ir_rvalue *swizzle_if_required(ir_expression *expr,
				  ir_rvalue *operand);

   void *mem_ctx;

   bool progress;
};

static inline bool
is_vec_zero(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_zero();
}

static inline bool
is_vec_one(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_one();
}

static void
update_type(ir_expression *ir)
{
   if (ir->operands[0]->type->is_vector())
      ir->type = ir->operands[0]->type;
   else
      ir->type = ir->operands[1]->type;
}

void
ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
					   int op1,
					   ir_expression *ir2,
					   int op2)
{
   ir_rvalue *temp = ir2->operands[op2];
   ir2->operands[op2] = ir1->operands[op1];
   ir1->operands[op1] = temp;

   /* Update the type of ir2.  The type of ir1 won't have changed --
    * base types matched, and at least one of the operands of the 2
    * binops is still a vector if any of them were.
    */
   update_type(ir2);

   this->progress = true;
}

/**
 * Reassociates a constant down a tree of adds or multiplies.
 *
 * Consider (2 * (a * (b * 0.5))).  We want to send up with a * b.
 */
bool
ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
					   ir_constant *constant,
					   ir_expression *ir2)
{
   if (!ir2 || ir1->operation != ir2->operation)
      return false;

   /* Don't want to even think about matrices. */
   if (ir1->operands[0]->type->is_matrix() ||
       ir1->operands[1]->type->is_matrix() ||
       ir2->operands[0]->type->is_matrix() ||
       ir2->operands[1]->type->is_matrix())
      return false;

   ir_constant *ir2_const[2];
   ir2_const[0] = ir2->operands[0]->constant_expression_value();
   ir2_const[1] = ir2->operands[1]->constant_expression_value();

   if (ir2_const[0] && ir2_const[1])
      return false;

   if (ir2_const[0]) {
      reassociate_operands(ir1, const_index, ir2, 1);
      return true;
   } else if (ir2_const[1]) {
      reassociate_operands(ir1, const_index, ir2, 0);
      return true;
   }

   if (reassociate_constant(ir1, const_index, constant,
			    ir2->operands[0]->as_expression())) {
      update_type(ir2);
      return true;
   }

   if (reassociate_constant(ir1, const_index, constant,
			    ir2->operands[1]->as_expression())) {
      update_type(ir2);
      return true;
   }

   return false;
}

/* When eliminating an expression and just returning one of its operands,
 * we may need to swizzle that operand out to a vector if the expression was
 * vector type.
 */
ir_rvalue *
ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
					  ir_rvalue *operand)
{
   if (expr->type->is_vector() && operand->type->is_scalar()) {
      return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
				     expr->type->vector_elements);
   } else
      return operand;
}

ir_rvalue *
ir_algebraic_visitor::handle_expression(ir_expression *ir)
{
   ir_constant *op_const[2] = {NULL, NULL};
   ir_expression *op_expr[2] = {NULL, NULL};
   ir_expression *temp;
   unsigned int i;

   assert(ir->get_num_operands() <= 2);
   for (i = 0; i < ir->get_num_operands(); i++) {
      if (ir->operands[i]->type->is_matrix())
	 return ir;

      op_const[i] = ir->operands[i]->constant_expression_value();
      op_expr[i] = ir->operands[i]->as_expression();
   }

   if (this->mem_ctx == NULL)
      this->mem_ctx = talloc_parent(ir);

   switch (ir->operation) {
   case ir_unop_logic_not: {
      enum ir_expression_operation new_op = ir_unop_logic_not;

      if (op_expr[0] == NULL)
	 break;

      switch (op_expr[0]->operation) {
      case ir_binop_less:    new_op = ir_binop_gequal;  break;
      case ir_binop_greater: new_op = ir_binop_lequal;  break;
      case ir_binop_lequal:  new_op = ir_binop_greater; break;
      case ir_binop_gequal:  new_op = ir_binop_less;    break;
      case ir_binop_equal:   new_op = ir_binop_nequal;  break;
      case ir_binop_nequal:  new_op = ir_binop_equal;   break;
      case ir_binop_all_equal:   new_op = ir_binop_any_nequal;  break;
      case ir_binop_any_nequal:  new_op = ir_binop_all_equal;   break;

      default:
	 /* The default case handler is here to silence a warning from GCC.
	  */
	 break;
      }

      if (new_op != ir_unop_logic_not) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(new_op,
					   ir->type,
					   op_expr[0]->operands[0],
					   op_expr[0]->operands[1]);
      }

      break;
   }

   case ir_binop_add:
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[1]);
      }
      if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }

      /* Reassociate addition of constants so that we can do constant
       * folding.
       */
      if (op_const[0] && !op_const[1])
	 reassociate_constant(ir, 0, op_const[0],
			      ir->operands[1]->as_expression());
      if (op_const[1] && !op_const[0])
	 reassociate_constant(ir, 1, op_const[1],
			      ir->operands[0]->as_expression());
      break;

   case ir_binop_sub:
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_neg,
					   ir->operands[1]->type,
					   ir->operands[1],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }
      if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }
      break;

   case ir_binop_mul:
      if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[1]);
      }
      if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }

      if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(ir, ir->type);
      }

      /* Reassociate multiplication of constants so that we can do
       * constant folding.
       */
      if (op_const[0] && !op_const[1])
	 reassociate_constant(ir, 0, op_const[0],
			      ir->operands[1]->as_expression());
      if (op_const[1] && !op_const[0])
	 reassociate_constant(ir, 1, op_const[1],
			      ir->operands[0]->as_expression());

      break;

   case ir_binop_div:
      if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_rcp,
					   ir->operands[1]->type,
					   ir->operands[1],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }
      if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }
      break;

   case ir_binop_logic_and:
      /* FINISHME: Also simplify (a && a) to (a). */
      if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(mem_ctx, ir->type);
      }
      break;

   case ir_binop_logic_xor:
      /* FINISHME: Also simplify (a ^^ a) to (false). */
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
					   ir->operands[1], NULL);
      } else if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
					   ir->operands[0], NULL);
      }
      break;

   case ir_binop_logic_or:
      /* FINISHME: Also simplify (a || a) to (a). */
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
	 ir_constant_data data;

	 for (unsigned i = 0; i < 16; i++)
	    data.b[i] = true;

	 this->progress = true;
	 return new(mem_ctx) ir_constant(ir->type, &data);
      }
      break;

   case ir_unop_rcp:
      if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
	 this->progress = true;
	 return op_expr[0]->operands[0];
      }

      /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
       * backends, except that some backends will have done sqrt ->
       * rcp(rsq(x)) and we don't want to undo it for them.
       */

      /* As far as we know, all backends are OK with rsq. */
      if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_rsq,
					   op_expr[0]->operands[0]->type,
					   op_expr[0]->operands[0],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }

      break;

   default:
      break;
   }

   return ir;
}

void
ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_expression *expr = (*rvalue)->as_expression();
   if (!expr || expr->operation == ir_quadop_vector)
      return;

   *rvalue = handle_expression(expr);
}

bool
do_algebraic(exec_list *instructions)
{
   ir_algebraic_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
<|endoftext|>