<commit_before>#include <cybozu/benchmark.hpp>
#include <cybozu/option.hpp>
#include <mcl/fp.hpp>
#include <mcl/conversion.hpp>
#include <mcl/ecparam.hpp>

typedef mcl::FpT<> Fp;
struct tagZn;
typedef mcl::FpT<tagZn> Zn;
typedef mcl::EcT<Fp> Ec;

const char *getModeStr(mcl::fp::Mode mode)
{
	switch (mode) {
	case mcl::fp::FP_GMP: return "gmp";
	case mcl::fp::FP_LLVM: return "llvm";
	case mcl::fp::FP_LLVM_MONT: return "llvm+mont";
	case mcl::fp::FP_XBYAK: return "xbyak";
	default: throw cybozu::Exception("benchFpSub:bad mode") << mode;
	}
}
void benchFpSub(const char *pStr, const char *xStr, const char *yStr, mcl::fp::Mode mode)
{
	const char *s = getModeStr(mode);
	Fp::setModulo(pStr, 0, mode);
	Fp x(xStr);
	Fp y(yStr);

	double addT, subT, mulT, invT;
	CYBOZU_BENCH_T(addT, Fp::add, x, x, x);
	CYBOZU_BENCH_T(subT, Fp::sub, x, x, y);
	CYBOZU_BENCH_T(mulT, Fp::mul, x, x, x);
	CYBOZU_BENCH_T(invT, x += y;Fp::inv, x, x); // avoid same jmp
	printf("%10s bit % 3d add %8.2f sub %8.2f mul %8.2f inv %8.2f\n", s, (int)Fp::getBitSize(), addT, subT, mulT, invT);
}

void benchFp(size_t bitSize, int mode)
{
	const struct {
		size_t bitSize;
		const char *p;
		const char *x;
		const char *y;
	} tbl[] = {
		{
			192,
			"0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
			"0x148094810948190412345678901234567900342423332197",
			"0x7fffffffffffffffffffffe26f2fc170f69466a74defd8d",
		},
		{
			256,
			"0x2523648240000001ba344d80000000086121000000000013a700000000000013",
			"0x1480948109481904123456789234234242423424201234567900342423332197",
			"0x151342342342341517fffffffffffffffffffffe26f2fc170f69466a74defd8d",
		},
		{
			384,
			"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
			"0x19481084109481094820948209482094820984290482212345678901234567900342308472047204720422423332197",
			"0x209348209481094820984209842094820948204204243123456789012345679003423084720472047204224233321972",

		},
		{
			521,
			"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
			"0x2908209582095820941098410948109482094820984209840294829049240294242498540975555312345678901234567900342308472047204720422423332197",
			"0x3948384209834029834092384204920349820948205872380573205782385729385729385723985837ffffffffffffffffffffffe26f2fc170f69466a74defd8d",

		},
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		if (bitSize != 0 && tbl[i].bitSize != bitSize) continue;
		if (mode & (1 << 0)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_GMP);
#ifdef MCL_USE_LLVM
		if (mode & (1 << 1)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM);
		if (mode & (1 << 2)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM_MONT);
#endif
#ifdef MCL_USE_XBYAK
		if (mode & (1 << 3)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_XBYAK);
#endif
	}
}

void benchEcSub(const mcl::EcParam& para, mcl::fp::Mode mode, mcl::ec::Mode ecMode)
{
	Fp::setModulo(para.p, 0, mode);
	Zn::setModulo(para.n);
	Ec::setParam(para.a, para.b, ecMode);
	Fp x(para.gx);
	Fp y(para.gy);
	Ec P(x, y);
	Ec Q = P + P + P;
	double addT, subT, dblT, mulT;
	CYBOZU_BENCH_T(addT, Ec::add, Q, P, Q);
	CYBOZU_BENCH_T(subT, Ec::sub, Q, P, Q);
	CYBOZU_BENCH_T(dblT, Ec::dbl, P, P);
	Zn z("-3");
	CYBOZU_BENCH_T(mulT, Ec::mul, P, P, z);
	printf("%10s %10s add %8.2f sub %8.2f dbl %8.2f mul %8.2f\n", para.name, getModeStr(mode), addT, subT, dblT, mulT);

}
void benchEc(size_t bitSize, int mode, mcl::ec::Mode ecMode)
{
	const struct mcl::EcParam tbl[] = {
		mcl::ecparam::p160_1,
		mcl::ecparam::secp160k1,
		mcl::ecparam::secp192k1,
		mcl::ecparam::NIST_P192,
		mcl::ecparam::secp224k1,
		mcl::ecparam::secp256k1,
		mcl::ecparam::NIST_P224,
		mcl::ecparam::NIST_P256,
//		mcl::ecparam::secp384r1,
		mcl::ecparam::NIST_P384,
//		mcl::ecparam::secp521r1,
		mcl::ecparam::NIST_P521,
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		if (bitSize != 0 && tbl[i].bitSize != bitSize) continue;
		if (mode & (1 << 0)) benchEcSub(tbl[i], mcl::fp::FP_GMP, ecMode);
#ifdef MCL_USE_LLVM
		if (mode & (1 << 1)) benchEcSub(tbl[i], mcl::fp::FP_LLVM, ecMode);
		if (mode & (1 << 2)) benchEcSub(tbl[i], mcl::fp::FP_LLVM_MONT, ecMode);
#endif
#ifdef MCL_USE_XBYAK
		if (mode & (1 << 3)) benchEcSub(tbl[i], mcl::fp::FP_XBYAK, ecMode);
#endif
	}
}

void benchToStr16()
{
	puts("benchToStr16");
	const char *tbl[] = {
		"0x0",
		"0x5",
		"0x123",
		"0x123456789012345679adbc",
		"0xffffffff26f2fc170f69466a74defd8d",
		"0x100000000000000000000000000000033",
		"0x11ee12312312940000000000000000000000000002342343"
	};
	Fp::setModulo("0xffffffffffffffffffffffffffffffffffffffffffffff13");
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		std::string str;
		Fp x(tbl[i]);
		CYBOZU_BENCH("fp::toStr16", mcl::fp::toStr16, str, x.getUnit(), x.getUnitSize(), 16);
		mpz_class y(tbl[i]);
		CYBOZU_BENCH("Gmp:getStr ", mcl::Gmp::getStr, str, y, 16);
	}
}

void benchFromStr16()
{
	puts("benchFromStr16");
	const char *tbl[] = {
		"0",
		"5",
		"123",
		"123456789012345679adbc",
		"ffffffff26f2fc170f69466a74defd8d",
		"100000000000000000000000000000033",
		"11ee12312312940000000000000000000000000002342343"
	};
	Fp::setModulo("0xffffffffffffffffffffffffffffffffffffffffffffff13");
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		std::string str = tbl[i];
		Fp x;
		const size_t N = 64;
		mcl::fp::Unit buf[N];
		CYBOZU_BENCH("fp:fromStr16", mcl::fp::fromStr16, buf, N, str.c_str(), str.size());

		mpz_class y;
		CYBOZU_BENCH("Gmp:setStr  ", mcl::Gmp::setStr, y, str, 16);
	}
}

int main(int argc, char *argv[])
	try
{
	size_t bitSize;
	int mode;
	bool ecOnly;
	bool fpOnly;
	bool misc;
	mcl::ec::Mode ecMode;
	std::string ecModeStr;
	cybozu::Option opt;
	opt.appendOpt(&bitSize, 0, "b", ": bitSize");
	opt.appendOpt(&mode, 0, "m", ": mode(0:all, sum of 1:gmp, 2:llvm, 8:llvm+mont, 8:xbyak");
	opt.appendBoolOpt(&ecOnly, "ec", ": ec only");
	opt.appendBoolOpt(&fpOnly, "fp", ": fp only");
	opt.appendBoolOpt(&misc, "misc", ": other benchmark");
	opt.appendOpt(&ecModeStr, "jacobi", "ecmode", ": jacobi or proj");
	opt.appendHelp("h", ": show this message");
	if (!opt.parse(argc, argv)) {
		opt.usage();
		return 1;
	}
	if (ecModeStr == "jacobi") {
		ecMode = mcl::ec::Jacobi;
	} else if (ecModeStr == "proj") {
		ecMode = mcl::ec::Proj;
	} else {
		printf("bad ecstr %s\n", ecModeStr.c_str());
		opt.usage();
		return 1;
	}
	if (mode < 0 || mode > 15) {
		printf("bad mode %d\n", mode);
		opt.usage();
		return 1;
	}
	if (mode == 0) mode = 15;
	if (misc) {
		benchToStr16();
		benchFromStr16();
	} else {
		if (!ecOnly) benchFp(bitSize, mode);
		if (!fpOnly) {
			printf("ecMode=%s\n", ecModeStr.c_str());
			benchEc(bitSize, mode, ecMode);
		}
	}
} catch (std::exception& e) {
	printf("ERR %s\n", e.what());
}

<commit_msg>add rand test<commit_after>#include <cybozu/benchmark.hpp>
#include <cybozu/option.hpp>
#include <cybozu/xorshift.hpp>
#include <mcl/fp.hpp>
#include <mcl/conversion.hpp>
#include <mcl/ecparam.hpp>

typedef mcl::FpT<> Fp;
struct tagZn;
typedef mcl::FpT<tagZn> Zn;
typedef mcl::EcT<Fp> Ec;

const char *getModeStr(mcl::fp::Mode mode)
{
	switch (mode) {
	case mcl::fp::FP_GMP: return "gmp";
	case mcl::fp::FP_LLVM: return "llvm";
	case mcl::fp::FP_LLVM_MONT: return "llvm+mont";
	case mcl::fp::FP_XBYAK: return "xbyak";
	default: throw cybozu::Exception("benchFpSub:bad mode") << mode;
	}
}
void benchFpSub(const char *pStr, const char *xStr, const char *yStr, mcl::fp::Mode mode)
{
	const char *s = getModeStr(mode);
	Fp::setModulo(pStr, 0, mode);
	Fp x(xStr);
	Fp y(yStr);

	double addT, subT, mulT, invT;
	CYBOZU_BENCH_T(addT, Fp::add, x, x, x);
	CYBOZU_BENCH_T(subT, Fp::sub, x, x, y);
	CYBOZU_BENCH_T(mulT, Fp::mul, x, x, x);
	CYBOZU_BENCH_T(invT, x += y;Fp::inv, x, x); // avoid same jmp
	printf("%10s bit % 3d add %8.2f sub %8.2f mul %8.2f inv %8.2f\n", s, (int)Fp::getBitSize(), addT, subT, mulT, invT);
}

void benchFp(size_t bitSize, int mode)
{
	const struct {
		size_t bitSize;
		const char *p;
		const char *x;
		const char *y;
	} tbl[] = {
		{
			192,
			"0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
			"0x148094810948190412345678901234567900342423332197",
			"0x7fffffffffffffffffffffe26f2fc170f69466a74defd8d",
		},
		{
			256,
			"0x2523648240000001ba344d80000000086121000000000013a700000000000013",
			"0x1480948109481904123456789234234242423424201234567900342423332197",
			"0x151342342342341517fffffffffffffffffffffe26f2fc170f69466a74defd8d",
		},
		{
			384,
			"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
			"0x19481084109481094820948209482094820984290482212345678901234567900342308472047204720422423332197",
			"0x209348209481094820984209842094820948204204243123456789012345679003423084720472047204224233321972",

		},
		{
			521,
			"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
			"0x2908209582095820941098410948109482094820984209840294829049240294242498540975555312345678901234567900342308472047204720422423332197",
			"0x3948384209834029834092384204920349820948205872380573205782385729385729385723985837ffffffffffffffffffffffe26f2fc170f69466a74defd8d",

		},
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		if (bitSize != 0 && tbl[i].bitSize != bitSize) continue;
		if (mode & (1 << 0)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_GMP);
#ifdef MCL_USE_LLVM
		if (mode & (1 << 1)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM);
		if (mode & (1 << 2)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM_MONT);
#endif
#ifdef MCL_USE_XBYAK
		if (mode & (1 << 3)) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_XBYAK);
#endif
	}
}

void benchEcSub(const mcl::EcParam& para, mcl::fp::Mode mode, mcl::ec::Mode ecMode)
{
	Fp::setModulo(para.p, 0, mode);
	Zn::setModulo(para.n);
	Ec::setParam(para.a, para.b, ecMode);
	Fp x(para.gx);
	Fp y(para.gy);
	Ec P(x, y);
	Ec Q = P + P + P;
	double addT, subT, dblT, mulT, mulRandT;
	CYBOZU_BENCH_T(addT, Ec::add, Q, P, Q);
	CYBOZU_BENCH_T(subT, Ec::sub, Q, P, Q);
	CYBOZU_BENCH_T(dblT, Ec::dbl, P, P);
	Zn z("-3");
	CYBOZU_BENCH_T(mulT, Ec::mul, P, P, z);
	cybozu::XorShift rg;
	z.setRand(rg);
	CYBOZU_BENCH_T(mulRandT, Ec::mul, P, P, z);
	printf("%10s %10s add %8.2f sub %8.2f dbl %8.2f mul(-3) %8.2f mul(rand) %8.2f\n", para.name, getModeStr(mode), addT, subT, dblT, mulT, mulRandT);

}
void benchEc(size_t bitSize, int mode, mcl::ec::Mode ecMode)
{
	const struct mcl::EcParam tbl[] = {
		mcl::ecparam::p160_1,
		mcl::ecparam::secp160k1,
		mcl::ecparam::secp192k1,
		mcl::ecparam::NIST_P192,
		mcl::ecparam::secp224k1,
		mcl::ecparam::secp256k1,
		mcl::ecparam::NIST_P224,
		mcl::ecparam::NIST_P256,
//		mcl::ecparam::secp384r1,
		mcl::ecparam::NIST_P384,
//		mcl::ecparam::secp521r1,
		mcl::ecparam::NIST_P521,
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		if (bitSize != 0 && tbl[i].bitSize != bitSize) continue;
		if (mode & (1 << 0)) benchEcSub(tbl[i], mcl::fp::FP_GMP, ecMode);
#ifdef MCL_USE_LLVM
		if (mode & (1 << 1)) benchEcSub(tbl[i], mcl::fp::FP_LLVM, ecMode);
		if (mode & (1 << 2)) benchEcSub(tbl[i], mcl::fp::FP_LLVM_MONT, ecMode);
#endif
#ifdef MCL_USE_XBYAK
		if (mode & (1 << 3)) benchEcSub(tbl[i], mcl::fp::FP_XBYAK, ecMode);
#endif
	}
}

void benchToStr16()
{
	puts("benchToStr16");
	const char *tbl[] = {
		"0x0",
		"0x5",
		"0x123",
		"0x123456789012345679adbc",
		"0xffffffff26f2fc170f69466a74defd8d",
		"0x100000000000000000000000000000033",
		"0x11ee12312312940000000000000000000000000002342343"
	};
	Fp::setModulo("0xffffffffffffffffffffffffffffffffffffffffffffff13");
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		std::string str;
		Fp x(tbl[i]);
		CYBOZU_BENCH("fp::toStr16", mcl::fp::toStr16, str, x.getUnit(), x.getUnitSize(), 16);
		mpz_class y(tbl[i]);
		CYBOZU_BENCH("Gmp:getStr ", mcl::Gmp::getStr, str, y, 16);
	}
}

void benchFromStr16()
{
	puts("benchFromStr16");
	const char *tbl[] = {
		"0",
		"5",
		"123",
		"123456789012345679adbc",
		"ffffffff26f2fc170f69466a74defd8d",
		"100000000000000000000000000000033",
		"11ee12312312940000000000000000000000000002342343"
	};
	Fp::setModulo("0xffffffffffffffffffffffffffffffffffffffffffffff13");
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
		std::string str = tbl[i];
		Fp x;
		const size_t N = 64;
		mcl::fp::Unit buf[N];
		CYBOZU_BENCH("fp:fromStr16", mcl::fp::fromStr16, buf, N, str.c_str(), str.size());

		mpz_class y;
		CYBOZU_BENCH("Gmp:setStr  ", mcl::Gmp::setStr, y, str, 16);
	}
}

int main(int argc, char *argv[])
	try
{
	size_t bitSize;
	int mode;
	bool ecOnly;
	bool fpOnly;
	bool misc;
	mcl::ec::Mode ecMode;
	std::string ecModeStr;
	cybozu::Option opt;
	opt.appendOpt(&bitSize, 0, "b", ": bitSize");
	opt.appendOpt(&mode, 0, "m", ": mode(0:all, sum of 1:gmp, 2:llvm, 8:llvm+mont, 8:xbyak");
	opt.appendBoolOpt(&ecOnly, "ec", ": ec only");
	opt.appendBoolOpt(&fpOnly, "fp", ": fp only");
	opt.appendBoolOpt(&misc, "misc", ": other benchmark");
	opt.appendOpt(&ecModeStr, "jacobi", "ecmode", ": jacobi or proj");
	opt.appendHelp("h", ": show this message");
	if (!opt.parse(argc, argv)) {
		opt.usage();
		return 1;
	}
	if (ecModeStr == "jacobi") {
		ecMode = mcl::ec::Jacobi;
	} else if (ecModeStr == "proj") {
		ecMode = mcl::ec::Proj;
	} else {
		printf("bad ecstr %s\n", ecModeStr.c_str());
		opt.usage();
		return 1;
	}
	if (mode < 0 || mode > 15) {
		printf("bad mode %d\n", mode);
		opt.usage();
		return 1;
	}
	if (mode == 0) mode = 15;
	if (misc) {
		benchToStr16();
		benchFromStr16();
	} else {
		if (!ecOnly) benchFp(bitSize, mode);
		if (!fpOnly) {
			printf("ecMode=%s\n", ecModeStr.c_str());
			benchEc(bitSize, mode, ecMode);
		}
	}
} catch (std::exception& e) {
	printf("ERR %s\n", e.what());
}

<|endoftext|>


<commit_before>///
/// @file   api-c.cpp
/// @brief  primesieve C API.
///         Contains the implementations of the functions declared
///         in the primesieve.h header file.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.h>
#include <primesieve.hpp>
#include <primesieve/PrimeSieve.hpp>
#include <primesieve/ParallelPrimeSieve.hpp>
#include <primesieve/malloc_vector.hpp>

#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <cerrno>
#include <exception>

//////////////////////////////////////////////////////////////////////
//                    Internal helper functions
//////////////////////////////////////////////////////////////////////

namespace {

using namespace primesieve;

template <typename T>
void* primes_helper(uint64_t start, uint64_t stop, size_t* size)
{
  try
  {
    malloc_vector<T> primes;
    StorePrimes<malloc_vector<T>> sp(primes);
    sp.storePrimes(start, stop);

    if (size)
      *size = primes.size();

    primes.disable_free();
    return (void*) primes.data();
  }
  catch (std::exception&)
  {
    errno = EDOM;
    if (size)
      *size = 0;
  }

  return NULL;
}

template <typename T>
void* n_primes_helper(uint64_t n, uint64_t start)
{
  try
  {
    malloc_vector<T> primes;
    Store_N_Primes<malloc_vector<T>> sp(primes);
    sp.storePrimes(n, start);

    primes.disable_free();
    return (void*) primes.data();
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }

  return NULL;
}

} // namespace

//////////////////////////////////////////////////////////////////////
//                    Return an array of primes
//////////////////////////////////////////////////////////////////////

void* primesieve_generate_primes(uint64_t start, uint64_t stop, size_t* size, int type)
{
  switch (type)
  {
    case SHORT_PRIMES:     return primes_helper<short>(start, stop, size);
    case USHORT_PRIMES:    return primes_helper<unsigned short>(start, stop, size);
    case INT_PRIMES:       return primes_helper<int>(start, stop, size);
    case UINT_PRIMES:      return primes_helper<unsigned int>(start, stop, size);
    case LONG_PRIMES:      return primes_helper<long>(start, stop, size);
    case ULONG_PRIMES:     return primes_helper<unsigned long>(start, stop, size);
    case LONGLONG_PRIMES:  return primes_helper<long long>(start, stop, size);
    case ULONGLONG_PRIMES: return primes_helper<unsigned long long>(start, stop, size);
    case INT16_PRIMES:     return primes_helper<int16_t>(start, stop, size);
    case UINT16_PRIMES:    return primes_helper<uint16_t>(start, stop, size);
    case INT32_PRIMES:     return primes_helper<int32_t>(start, stop, size);
    case UINT32_PRIMES:    return primes_helper<uint32_t>(start, stop, size);
    case INT64_PRIMES:     return primes_helper<int64_t>(start, stop, size);
    case UINT64_PRIMES:    return primes_helper<uint64_t>(start, stop, size);
  }
  errno = EDOM;
  if (size)
    *size = 0;
  return NULL;
}

void* primesieve_generate_n_primes(uint64_t n, uint64_t start, int type)
{
  switch (type)
  {
    case SHORT_PRIMES:     return n_primes_helper<short>(n, start);
    case USHORT_PRIMES:    return n_primes_helper<unsigned short>(n, start);
    case INT_PRIMES:       return n_primes_helper<int>(n, start);
    case UINT_PRIMES:      return n_primes_helper<unsigned int>(n, start);
    case LONG_PRIMES:      return n_primes_helper<long>(n, start);
    case ULONG_PRIMES:     return n_primes_helper<unsigned long>(n, start);
    case LONGLONG_PRIMES:  return n_primes_helper<long long>(n, start);
    case ULONGLONG_PRIMES: return n_primes_helper<unsigned long long>(n, start);
    case INT16_PRIMES:     return n_primes_helper<int16_t>(n, start);
    case UINT16_PRIMES:    return n_primes_helper<uint16_t>(n, start);
    case INT32_PRIMES:     return n_primes_helper<int32_t>(n, start);
    case UINT32_PRIMES:    return n_primes_helper<uint32_t>(n, start);
    case INT64_PRIMES:     return n_primes_helper<int64_t>(n, start);
    case UINT64_PRIMES:    return n_primes_helper<uint64_t>(n, start);
  }
  errno = EDOM;
  return NULL;
}

void primesieve_free(void* primes)
{
  free(primes);
}

//////////////////////////////////////////////////////////////////////
//                     Nth prime function
//////////////////////////////////////////////////////////////////////

uint64_t primesieve_nth_prime(int64_t n, uint64_t start)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.nthPrime(n, start);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

//////////////////////////////////////////////////////////////////////
//                      Count functions
//////////////////////////////////////////////////////////////////////

uint64_t primesieve_count_primes(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.countPrimes(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_twins(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.countTwins(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_triplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.countTriplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_quadruplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.countQuadruplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_quintuplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.countQuintuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_sextuplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::ParallelPrimeSieve pps;
    pps.setSieveSize(primesieve::get_sieve_size());
    pps.setNumThreads(primesieve::get_num_threads());
    return pps.countSextuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

//////////////////////////////////////////////////////////////////////
//                      Print functions
//////////////////////////////////////////////////////////////////////

void primesieve_print_primes(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::PrimeSieve ps;
    ps.setSieveSize(primesieve::get_sieve_size());
    ps.printPrimes(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_twins(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::PrimeSieve ps;
    ps.setSieveSize(primesieve::get_sieve_size());
    ps.printTwins(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_triplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::PrimeSieve ps;
    ps.setSieveSize(primesieve::get_sieve_size());
    ps.printTriplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_quadruplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::PrimeSieve ps;
    ps.setSieveSize(primesieve::get_sieve_size());
    ps.printQuadruplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_quintuplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::PrimeSieve ps;
    ps.setSieveSize(primesieve::get_sieve_size());
    ps.printQuintuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_sextuplets(uint64_t start, uint64_t stop)
{
  try
  {
    primesieve::PrimeSieve ps;
    ps.setSieveSize(primesieve::get_sieve_size());
    ps.printSextuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

//////////////////////////////////////////////////////////////////////
//                        Getters and Setters
//////////////////////////////////////////////////////////////////////

int primesieve_get_sieve_size()
{
  return primesieve::get_sieve_size();
}

int primesieve_get_num_threads()
{
  return primesieve::get_num_threads();
}

void primesieve_set_sieve_size(int sieve_size)
{
  primesieve::set_sieve_size(sieve_size);
}

void primesieve_set_num_threads(int num_threads)
{
  primesieve::set_num_threads(num_threads);
}

uint64_t primesieve_get_max_stop()
{
  return primesieve::get_max_stop();
}

//////////////////////////////////////////////////////////////////////
//                           Miscellaneous
//////////////////////////////////////////////////////////////////////

const char* primesieve_version()
{
  return PRIMESIEVE_VERSION;
}
<commit_msg>Refactor<commit_after>///
/// @file   api-c.cpp
/// @brief  primesieve C API.
///         Contains the implementations of the functions declared
///         in the primesieve.h header file.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.h>
#include <primesieve.hpp>
#include <primesieve/PrimeSieve.hpp>
#include <primesieve/ParallelPrimeSieve.hpp>
#include <primesieve/malloc_vector.hpp>

#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <cerrno>
#include <exception>

using namespace primesieve;

namespace {

template <typename T>
void* primes_helper(uint64_t start, uint64_t stop, size_t* size)
{
  try
  {
    malloc_vector<T> primes;
    StorePrimes<malloc_vector<T>> sp(primes);
    sp.storePrimes(start, stop);

    if (size)
      *size = primes.size();

    primes.disable_free();
    return (void*) primes.data();
  }
  catch (std::exception&)
  {
    errno = EDOM;
    if (size)
      *size = 0;
  }

  return NULL;
}

template <typename T>
void* n_primes_helper(uint64_t n, uint64_t start)
{
  try
  {
    malloc_vector<T> primes;
    Store_N_Primes<malloc_vector<T>> sp(primes);
    sp.storePrimes(n, start);

    primes.disable_free();
    return (void*) primes.data();
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }

  return NULL;
}

} // namespace

void* primesieve_generate_primes(uint64_t start, uint64_t stop, size_t* size, int type)
{
  switch (type)
  {
    case SHORT_PRIMES:     return primes_helper<short>(start, stop, size);
    case USHORT_PRIMES:    return primes_helper<unsigned short>(start, stop, size);
    case INT_PRIMES:       return primes_helper<int>(start, stop, size);
    case UINT_PRIMES:      return primes_helper<unsigned int>(start, stop, size);
    case LONG_PRIMES:      return primes_helper<long>(start, stop, size);
    case ULONG_PRIMES:     return primes_helper<unsigned long>(start, stop, size);
    case LONGLONG_PRIMES:  return primes_helper<long long>(start, stop, size);
    case ULONGLONG_PRIMES: return primes_helper<unsigned long long>(start, stop, size);
    case INT16_PRIMES:     return primes_helper<int16_t>(start, stop, size);
    case UINT16_PRIMES:    return primes_helper<uint16_t>(start, stop, size);
    case INT32_PRIMES:     return primes_helper<int32_t>(start, stop, size);
    case UINT32_PRIMES:    return primes_helper<uint32_t>(start, stop, size);
    case INT64_PRIMES:     return primes_helper<int64_t>(start, stop, size);
    case UINT64_PRIMES:    return primes_helper<uint64_t>(start, stop, size);
  }
  errno = EDOM;
  if (size)
    *size = 0;
  return NULL;
}

void* primesieve_generate_n_primes(uint64_t n, uint64_t start, int type)
{
  switch (type)
  {
    case SHORT_PRIMES:     return n_primes_helper<short>(n, start);
    case USHORT_PRIMES:    return n_primes_helper<unsigned short>(n, start);
    case INT_PRIMES:       return n_primes_helper<int>(n, start);
    case UINT_PRIMES:      return n_primes_helper<unsigned int>(n, start);
    case LONG_PRIMES:      return n_primes_helper<long>(n, start);
    case ULONG_PRIMES:     return n_primes_helper<unsigned long>(n, start);
    case LONGLONG_PRIMES:  return n_primes_helper<long long>(n, start);
    case ULONGLONG_PRIMES: return n_primes_helper<unsigned long long>(n, start);
    case INT16_PRIMES:     return n_primes_helper<int16_t>(n, start);
    case UINT16_PRIMES:    return n_primes_helper<uint16_t>(n, start);
    case INT32_PRIMES:     return n_primes_helper<int32_t>(n, start);
    case UINT32_PRIMES:    return n_primes_helper<uint32_t>(n, start);
    case INT64_PRIMES:     return n_primes_helper<int64_t>(n, start);
    case UINT64_PRIMES:    return n_primes_helper<uint64_t>(n, start);
  }
  errno = EDOM;
  return NULL;
}

void primesieve_free(void* primes)
{
  free(primes);
}

uint64_t primesieve_nth_prime(int64_t n, uint64_t start)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.nthPrime(n, start);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_primes(uint64_t start, uint64_t stop)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.countPrimes(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_twins(uint64_t start, uint64_t stop)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.countTwins(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_triplets(uint64_t start, uint64_t stop)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.countTriplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_quadruplets(uint64_t start, uint64_t stop)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.countQuadruplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_quintuplets(uint64_t start, uint64_t stop)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.countQuintuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

uint64_t primesieve_count_sextuplets(uint64_t start, uint64_t stop)
{
  try
  {
    ParallelPrimeSieve pps;
    pps.setSieveSize(get_sieve_size());
    pps.setNumThreads(get_num_threads());
    return pps.countSextuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
  return PRIMESIEVE_ERROR;
}

void primesieve_print_primes(uint64_t start, uint64_t stop)
{
  try
  {
    PrimeSieve ps;
    ps.setSieveSize(get_sieve_size());
    ps.printPrimes(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_twins(uint64_t start, uint64_t stop)
{
  try
  {
    PrimeSieve ps;
    ps.setSieveSize(get_sieve_size());
    ps.printTwins(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_triplets(uint64_t start, uint64_t stop)
{
  try
  {
    PrimeSieve ps;
    ps.setSieveSize(get_sieve_size());
    ps.printTriplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_quadruplets(uint64_t start, uint64_t stop)
{
  try
  {
    PrimeSieve ps;
    ps.setSieveSize(get_sieve_size());
    ps.printQuadruplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_quintuplets(uint64_t start, uint64_t stop)
{
  try
  {
    PrimeSieve ps;
    ps.setSieveSize(get_sieve_size());
    ps.printQuintuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

void primesieve_print_sextuplets(uint64_t start, uint64_t stop)
{
  try
  {
    PrimeSieve ps;
    ps.setSieveSize(get_sieve_size());
    ps.printSextuplets(start, stop);
  }
  catch (std::exception&)
  {
    errno = EDOM;
  }
}

int primesieve_get_sieve_size()
{
  return get_sieve_size();
}

int primesieve_get_num_threads()
{
  return get_num_threads();
}

void primesieve_set_sieve_size(int sieve_size)
{
  set_sieve_size(sieve_size);
}

void primesieve_set_num_threads(int num_threads)
{
  set_num_threads(num_threads);
}

uint64_t primesieve_get_max_stop()
{
  return get_max_stop();
}

const char* primesieve_version()
{
  return PRIMESIEVE_VERSION;
}
<|endoftext|>


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

#include <v8.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef COMPRESS_STARTUP_DATA_BZ2
#error Using compressed startup data is not supported for this sample
#endif

/**
 * This sample program shows how to implement a simple javascript shell
 * based on V8.  This includes initializing V8 with command line options,
 * creating global functions, compiling and executing strings.
 *
 * For a more sophisticated shell, consider using the debug shell D8.
 */

v8::Persistent<v8::Context> CreateShellContext();
void RunShell(v8::Handle<v8::Context> context);
int RunMain(int argc, char* argv[]);
bool ExecuteString(v8::Handle<v8::String> source,
                   v8::Handle<v8::Value> name,
                   bool print_result,
                   bool report_exceptions);
v8::Handle<v8::Value> Print(const v8::Arguments& args);
v8::Handle<v8::Value> Read(const v8::Arguments& args);
v8::Handle<v8::Value> Load(const v8::Arguments& args);
v8::Handle<v8::Value> Quit(const v8::Arguments& args);
v8::Handle<v8::Value> Version(const v8::Arguments& args);
v8::Handle<v8::String> ReadFile(const char* name);
void ReportException(v8::TryCatch* handler);

static bool run_shell;

int main(int argc, char* argv[]) {
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  run_shell = (argc == 1);
  v8::HandleScope handle_scope;
  v8::Persistent<v8::Context> context = CreateShellContext();
  if (context.IsEmpty()) {
    printf("Error creating context\n");
    return 1;
  }
  context->Enter();
  int result = RunMain(argc, argv);
  if (run_shell) RunShell(context);
  context->Exit();
  context.Dispose();
  v8::V8::Dispose();
  return result;
}

// Extracts a C string from a V8 Utf8Value.
const char* ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<string conversion failed>";
}

// Creates a new execution environment containing the built-in
// functions.
v8::Persistent<v8::Context> CreateShellContext() {
  // Create a template for the global object.
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
  // Bind the global 'print' function to the C++ Print callback.
  global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
  // Bind the global 'read' function to the C++ Read callback.
  global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
  // Bind the global 'load' function to the C++ Load callback.
  global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
  // Bind the 'quit' function
  global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
  // Bind the 'version' function
  global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));

  return v8::Context::New(NULL, global);
}

// The callback that is invoked by v8 whenever the JavaScript 'print'
// function is called.  Prints its arguments on stdout separated by
// spaces and ending with a newline.
v8::Handle<v8::Value> Print(const v8::Arguments& args) {
  bool first = true;
  for (int i = 0; i < args.Length(); i++) {
    v8::HandleScope handle_scope;
    if (first) {
      first = false;
    } else {
      printf(" ");
    }
    v8::String::Utf8Value str(args[i]);
    const char* cstr = ToCString(str);
    printf("%s", cstr);
  }
  printf("\n");
  fflush(stdout);
  return v8::Undefined();
}

// The callback that is invoked by v8 whenever the JavaScript 'read'
// function is called.  This function loads the content of the file named in
// the argument into a JavaScript string.
v8::Handle<v8::Value> Read(const v8::Arguments& args) {
  if (args.Length() != 1) {
    return v8::ThrowException(v8::String::New("Bad parameters"));
  }
  v8::String::Utf8Value file(args[0]);
  if (*file == NULL) {
    return v8::ThrowException(v8::String::New("Error loading file"));
  }
  v8::Handle<v8::String> source = ReadFile(*file);
  if (source.IsEmpty()) {
    return v8::ThrowException(v8::String::New("Error loading file"));
  }
  return source;
}

// The callback that is invoked by v8 whenever the JavaScript 'load'
// function is called.  Loads, compiles and executes its argument
// JavaScript file.
v8::Handle<v8::Value> Load(const v8::Arguments& args) {
  for (int i = 0; i < args.Length(); i++) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value file(args[i]);
    if (*file == NULL) {
      return v8::ThrowException(v8::String::New("Error loading file"));
    }
    v8::Handle<v8::String> source = ReadFile(*file);
    if (source.IsEmpty()) {
      return v8::ThrowException(v8::String::New("Error loading file"));
    }
    if (!ExecuteString(source, v8::String::New(*file), false, false)) {
      return v8::ThrowException(v8::String::New("Error executing file"));
    }
  }
  return v8::Undefined();
}

// The callback that is invoked by v8 whenever the JavaScript 'quit'
// function is called.  Quits.
v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
  // If not arguments are given args[0] will yield undefined which
  // converts to the integer value 0.
  int exit_code = args[0]->Int32Value();
  fflush(stdout);
  fflush(stderr);
  exit(exit_code);
  return v8::Undefined();
}

v8::Handle<v8::Value> Version(const v8::Arguments& args) {
  return v8::String::New(v8::V8::GetVersion());
}

// Reads a file into a v8 string.
v8::Handle<v8::String> ReadFile(const char* name) {
  FILE* file = fopen(name, "rb");
  if (file == NULL) return v8::Handle<v8::String>();

  fseek(file, 0, SEEK_END);
  int size = ftell(file);
  rewind(file);

  char* chars = new char[size + 1];
  chars[size] = '\0';
  for (int i = 0; i < size;) {
    int read = fread(&chars[i], 1, size - i, file);
    i += read;
  }
  fclose(file);
  v8::Handle<v8::String> result = v8::String::New(chars, size);
  delete[] chars;
  return result;
}

// Process remaining command line arguments and execute files
int RunMain(int argc, char* argv[]) {
  for (int i = 1; i < argc; i++) {
    const char* str = argv[i];
    if (strcmp(str, "--shell") == 0) {
      run_shell = true;
    } else if (strcmp(str, "-f") == 0) {
      // Ignore any -f flags for compatibility with the other stand-
      // alone JavaScript engines.
      continue;
    } else if (strncmp(str, "--", 2) == 0) {
      printf("Warning: unknown flag %s.\nTry --help for options\n", str);
    } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
      // Execute argument given to -e option directly.
      v8::Handle<v8::String> file_name = v8::String::New("unnamed");
      v8::Handle<v8::String> source = v8::String::New(argv[++i]);
      if (!ExecuteString(source, file_name, false, true)) return 1;
    } else {
      // Use all other arguments as names of files to load and run.
      v8::Handle<v8::String> file_name = v8::String::New(str);
      v8::Handle<v8::String> source = ReadFile(str);
      if (source.IsEmpty()) {
        printf("Error reading '%s'\n", str);
        continue;
      }
      if (!ExecuteString(source, file_name, false, true)) return 1;
    }
  }
  return 0;
}

// The read-eval-execute loop of the shell.
void RunShell(v8::Handle<v8::Context> context) {
  printf("V8 version %s [sample shell]\n", v8::V8::GetVersion());
  static const int kBufferSize = 256;
  // Enter the execution environment before evaluating any code.
  v8::Context::Scope context_scope(context);
  v8::Local<v8::String> name(v8::String::New("(shell)"));
  while (true) {
    char buffer[kBufferSize];
    printf("> ");
    char* str = fgets(buffer, kBufferSize, stdin);
    if (str == NULL) break;
    v8::HandleScope handle_scope;
    ExecuteString(v8::String::New(str), name, true, true);
  }
  printf("\n");
}

// Executes a string within the current v8 context.
bool ExecuteString(v8::Handle<v8::String> source,
                   v8::Handle<v8::Value> name,
                   bool print_result,
                   bool report_exceptions) {
  v8::HandleScope handle_scope;
  v8::TryCatch try_catch;
  v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
  if (script.IsEmpty()) {
    // Print errors that happened during compilation.
    if (report_exceptions)
      ReportException(&try_catch);
    return false;
  } else {
    v8::Handle<v8::Value> result = script->Run();
    if (result.IsEmpty()) {
      assert(try_catch.HasCaught());
      // Print errors that happened during execution.
      if (report_exceptions)
        ReportException(&try_catch);
      return false;
    } else {
      assert(!try_catch.HasCaught());
      if (print_result && !result->IsUndefined()) {
        // If all went well and the result wasn't undefined then print
        // the returned value.
        v8::String::Utf8Value str(result);
        const char* cstr = ToCString(str);
        printf("%s\n", cstr);
      }
      return true;
    }
  }
}

void ReportException(v8::TryCatch* try_catch) {
  v8::HandleScope handle_scope;
  v8::String::Utf8Value exception(try_catch->Exception());
  const char* exception_string = ToCString(exception);
  v8::Handle<v8::Message> message = try_catch->Message();
  if (message.IsEmpty()) {
    // V8 didn't provide any extra information about this error; just
    // print the exception.
    printf("%s\n", exception_string);
  } else {
    // Print (filename):(line number): (message).
    v8::String::Utf8Value filename(message->GetScriptResourceName());
    const char* filename_string = ToCString(filename);
    int linenum = message->GetLineNumber();
    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
    // Print line of source code.
    v8::String::Utf8Value sourceline(message->GetSourceLine());
    const char* sourceline_string = ToCString(sourceline);
    printf("%s\n", sourceline_string);
    // Print wavy underline (GetUnderline is deprecated).
    int start = message->GetStartColumn();
    for (int i = 0; i < start; i++) {
      printf(" ");
    }
    int end = message->GetEndColumn();
    for (int i = start; i < end; i++) {
      printf("^");
    }
    printf("\n");
    v8::String::Utf8Value stack_trace(try_catch->StackTrace());
    if (stack_trace.length() > 0) {
      const char* stack_trace_string = ToCString(stack_trace);
      printf("%s\n", stack_trace_string);
    }
  }
}
<commit_msg>Fix scoping of v8::HandleScope to prevent use-after-dispose<commit_after>// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <v8.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef COMPRESS_STARTUP_DATA_BZ2
#error Using compressed startup data is not supported for this sample
#endif

/**
 * This sample program shows how to implement a simple javascript shell
 * based on V8.  This includes initializing V8 with command line options,
 * creating global functions, compiling and executing strings.
 *
 * For a more sophisticated shell, consider using the debug shell D8.
 */

v8::Persistent<v8::Context> CreateShellContext();
void RunShell(v8::Handle<v8::Context> context);
int RunMain(int argc, char* argv[]);
bool ExecuteString(v8::Handle<v8::String> source,
                   v8::Handle<v8::Value> name,
                   bool print_result,
                   bool report_exceptions);
v8::Handle<v8::Value> Print(const v8::Arguments& args);
v8::Handle<v8::Value> Read(const v8::Arguments& args);
v8::Handle<v8::Value> Load(const v8::Arguments& args);
v8::Handle<v8::Value> Quit(const v8::Arguments& args);
v8::Handle<v8::Value> Version(const v8::Arguments& args);
v8::Handle<v8::String> ReadFile(const char* name);
void ReportException(v8::TryCatch* handler);

static bool run_shell;

int main(int argc, char* argv[]) {
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  run_shell = (argc == 1);
  int result;
  {
    v8::HandleScope handle_scope;
    v8::Persistent<v8::Context> context = CreateShellContext();
    if (context.IsEmpty()) {
      printf("Error creating context\n");
      return 1;
    }
    context->Enter();
    result = RunMain(argc, argv);
    if (run_shell) RunShell(context);
    context->Exit();
    context.Dispose();
  }
  v8::V8::Dispose();
  return result;
}

// Extracts a C string from a V8 Utf8Value.
const char* ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<string conversion failed>";
}

// Creates a new execution environment containing the built-in
// functions.
v8::Persistent<v8::Context> CreateShellContext() {
  // Create a template for the global object.
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
  // Bind the global 'print' function to the C++ Print callback.
  global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
  // Bind the global 'read' function to the C++ Read callback.
  global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
  // Bind the global 'load' function to the C++ Load callback.
  global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
  // Bind the 'quit' function
  global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
  // Bind the 'version' function
  global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));

  return v8::Context::New(NULL, global);
}

// The callback that is invoked by v8 whenever the JavaScript 'print'
// function is called.  Prints its arguments on stdout separated by
// spaces and ending with a newline.
v8::Handle<v8::Value> Print(const v8::Arguments& args) {
  bool first = true;
  for (int i = 0; i < args.Length(); i++) {
    v8::HandleScope handle_scope;
    if (first) {
      first = false;
    } else {
      printf(" ");
    }
    v8::String::Utf8Value str(args[i]);
    const char* cstr = ToCString(str);
    printf("%s", cstr);
  }
  printf("\n");
  fflush(stdout);
  return v8::Undefined();
}

// The callback that is invoked by v8 whenever the JavaScript 'read'
// function is called.  This function loads the content of the file named in
// the argument into a JavaScript string.
v8::Handle<v8::Value> Read(const v8::Arguments& args) {
  if (args.Length() != 1) {
    return v8::ThrowException(v8::String::New("Bad parameters"));
  }
  v8::String::Utf8Value file(args[0]);
  if (*file == NULL) {
    return v8::ThrowException(v8::String::New("Error loading file"));
  }
  v8::Handle<v8::String> source = ReadFile(*file);
  if (source.IsEmpty()) {
    return v8::ThrowException(v8::String::New("Error loading file"));
  }
  return source;
}

// The callback that is invoked by v8 whenever the JavaScript 'load'
// function is called.  Loads, compiles and executes its argument
// JavaScript file.
v8::Handle<v8::Value> Load(const v8::Arguments& args) {
  for (int i = 0; i < args.Length(); i++) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value file(args[i]);
    if (*file == NULL) {
      return v8::ThrowException(v8::String::New("Error loading file"));
    }
    v8::Handle<v8::String> source = ReadFile(*file);
    if (source.IsEmpty()) {
      return v8::ThrowException(v8::String::New("Error loading file"));
    }
    if (!ExecuteString(source, v8::String::New(*file), false, false)) {
      return v8::ThrowException(v8::String::New("Error executing file"));
    }
  }
  return v8::Undefined();
}

// The callback that is invoked by v8 whenever the JavaScript 'quit'
// function is called.  Quits.
v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
  // If not arguments are given args[0] will yield undefined which
  // converts to the integer value 0.
  int exit_code = args[0]->Int32Value();
  fflush(stdout);
  fflush(stderr);
  exit(exit_code);
  return v8::Undefined();
}

v8::Handle<v8::Value> Version(const v8::Arguments& args) {
  return v8::String::New(v8::V8::GetVersion());
}

// Reads a file into a v8 string.
v8::Handle<v8::String> ReadFile(const char* name) {
  FILE* file = fopen(name, "rb");
  if (file == NULL) return v8::Handle<v8::String>();

  fseek(file, 0, SEEK_END);
  int size = ftell(file);
  rewind(file);

  char* chars = new char[size + 1];
  chars[size] = '\0';
  for (int i = 0; i < size;) {
    int read = fread(&chars[i], 1, size - i, file);
    i += read;
  }
  fclose(file);
  v8::Handle<v8::String> result = v8::String::New(chars, size);
  delete[] chars;
  return result;
}

// Process remaining command line arguments and execute files
int RunMain(int argc, char* argv[]) {
  for (int i = 1; i < argc; i++) {
    const char* str = argv[i];
    if (strcmp(str, "--shell") == 0) {
      run_shell = true;
    } else if (strcmp(str, "-f") == 0) {
      // Ignore any -f flags for compatibility with the other stand-
      // alone JavaScript engines.
      continue;
    } else if (strncmp(str, "--", 2) == 0) {
      printf("Warning: unknown flag %s.\nTry --help for options\n", str);
    } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
      // Execute argument given to -e option directly.
      v8::Handle<v8::String> file_name = v8::String::New("unnamed");
      v8::Handle<v8::String> source = v8::String::New(argv[++i]);
      if (!ExecuteString(source, file_name, false, true)) return 1;
    } else {
      // Use all other arguments as names of files to load and run.
      v8::Handle<v8::String> file_name = v8::String::New(str);
      v8::Handle<v8::String> source = ReadFile(str);
      if (source.IsEmpty()) {
        printf("Error reading '%s'\n", str);
        continue;
      }
      if (!ExecuteString(source, file_name, false, true)) return 1;
    }
  }
  return 0;
}

// The read-eval-execute loop of the shell.
void RunShell(v8::Handle<v8::Context> context) {
  printf("V8 version %s [sample shell]\n", v8::V8::GetVersion());
  static const int kBufferSize = 256;
  // Enter the execution environment before evaluating any code.
  v8::Context::Scope context_scope(context);
  v8::Local<v8::String> name(v8::String::New("(shell)"));
  while (true) {
    char buffer[kBufferSize];
    printf("> ");
    char* str = fgets(buffer, kBufferSize, stdin);
    if (str == NULL) break;
    v8::HandleScope handle_scope;
    ExecuteString(v8::String::New(str), name, true, true);
  }
  printf("\n");
}

// Executes a string within the current v8 context.
bool ExecuteString(v8::Handle<v8::String> source,
                   v8::Handle<v8::Value> name,
                   bool print_result,
                   bool report_exceptions) {
  v8::HandleScope handle_scope;
  v8::TryCatch try_catch;
  v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
  if (script.IsEmpty()) {
    // Print errors that happened during compilation.
    if (report_exceptions)
      ReportException(&try_catch);
    return false;
  } else {
    v8::Handle<v8::Value> result = script->Run();
    if (result.IsEmpty()) {
      assert(try_catch.HasCaught());
      // Print errors that happened during execution.
      if (report_exceptions)
        ReportException(&try_catch);
      return false;
    } else {
      assert(!try_catch.HasCaught());
      if (print_result && !result->IsUndefined()) {
        // If all went well and the result wasn't undefined then print
        // the returned value.
        v8::String::Utf8Value str(result);
        const char* cstr = ToCString(str);
        printf("%s\n", cstr);
      }
      return true;
    }
  }
}

void ReportException(v8::TryCatch* try_catch) {
  v8::HandleScope handle_scope;
  v8::String::Utf8Value exception(try_catch->Exception());
  const char* exception_string = ToCString(exception);
  v8::Handle<v8::Message> message = try_catch->Message();
  if (message.IsEmpty()) {
    // V8 didn't provide any extra information about this error; just
    // print the exception.
    printf("%s\n", exception_string);
  } else {
    // Print (filename):(line number): (message).
    v8::String::Utf8Value filename(message->GetScriptResourceName());
    const char* filename_string = ToCString(filename);
    int linenum = message->GetLineNumber();
    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
    // Print line of source code.
    v8::String::Utf8Value sourceline(message->GetSourceLine());
    const char* sourceline_string = ToCString(sourceline);
    printf("%s\n", sourceline_string);
    // Print wavy underline (GetUnderline is deprecated).
    int start = message->GetStartColumn();
    for (int i = 0; i < start; i++) {
      printf(" ");
    }
    int end = message->GetEndColumn();
    for (int i = start; i < end; i++) {
      printf("^");
    }
    printf("\n");
    v8::String::Utf8Value stack_trace(try_catch->StackTrace());
    if (stack_trace.length() > 0) {
      const char* stack_trace_string = ToCString(stack_trace);
      printf("%s\n", stack_trace_string);
    }
  }
}
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/ffinit.h"
#include "kernel/ff.h"
#include "kernel/mem.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct Clk2fflogicPass : public Pass {
	Clk2fflogicPass() : Pass("clk2fflogic", "convert clocked FFs to generic $ff cells") { }
	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    clk2fflogic [options] [selection]\n");
		log("\n");
		log("This command replaces clocked flip-flops with generic $ff cells that use the\n");
		log("implicit global clock. This is useful for formal verification of designs with\n");
		log("multiple clocks.\n");
		log("\n");
	}
	SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity) {
		return wrap_async_control(module, sig, polarity, NEW_ID);
	}
	SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity, IdString past_sig_id) {
		Wire *past_sig = module->addWire(past_sig_id, GetSize(sig));
		past_sig->attributes[ID::init] = RTLIL::Const(polarity ? State::S0 : State::S1, GetSize(sig));
		module->addFf(NEW_ID, sig, past_sig);
		if (polarity)
			sig = module->Or(NEW_ID, sig, past_sig);
		else
			sig = module->And(NEW_ID, sig, past_sig);
		if (polarity)
			return sig;
		else
			return module->Not(NEW_ID, sig);
	}
	SigSpec wrap_async_control_gate(Module *module, SigSpec sig, bool polarity) {
		Wire *past_sig = module->addWire(NEW_ID);
		past_sig->attributes[ID::init] = RTLIL::Const(polarity ? State::S0 : State::S1, GetSize(sig));
		module->addFfGate(NEW_ID, sig, past_sig);
		if (polarity)
			sig = module->OrGate(NEW_ID, sig, past_sig);
		else
			sig = module->AndGate(NEW_ID, sig, past_sig);
		if (polarity)
			return sig;
		else
			return module->NotGate(NEW_ID, sig);
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) override
	{
		// bool flag_noinit = false;

		log_header(design, "Executing CLK2FFLOGIC pass (convert clocked FFs to generic $ff cells).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-noinit") {
			// 	flag_noinit = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		{
			SigMap sigmap(module);
			FfInitVals initvals(&sigmap, module);

			for (auto &mem : Mem::get_selected_memories(module))
			{
				for (int i = 0; i < GetSize(mem.rd_ports); i++) {
					auto &port = mem.rd_ports[i];
					if (port.clk_enable)
						log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! "
								"Call \"memory\" with -nordff to avoid this error.\n", i, log_id(mem.memid), log_id(module));
				}

				for (int i = 0; i < GetSize(mem.wr_ports); i++)
				{
					auto &port = mem.wr_ports[i];

					if (!port.clk_enable)
						continue;

					log("Modifying write port %d on memory %s.%s: CLK=%s, A=%s, D=%s\n",
							i, log_id(module), log_id(mem.memid), log_signal(port.clk),
							log_signal(port.addr), log_signal(port.data));

					Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", log_id(mem.memid), i, log_signal(port.clk))));
					past_clk->attributes[ID::init] = port.clk_polarity ? State::S1 : State::S0;
					module->addFf(NEW_ID, port.clk, past_clk);

					SigSpec clock_edge_pattern;

					if (port.clk_polarity) {
						clock_edge_pattern.append(State::S0);
						clock_edge_pattern.append(State::S1);
					} else {
						clock_edge_pattern.append(State::S1);
						clock_edge_pattern.append(State::S0);
					}

					SigSpec clock_edge = module->Eqx(NEW_ID, {port.clk, SigSpec(past_clk)}, clock_edge_pattern);

					SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", log_id(mem.memid), i)), GetSize(port.en));
					module->addFf(NEW_ID, port.en, en_q);

					SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", log_id(mem.memid), i)), GetSize(port.addr));
					module->addFf(NEW_ID, port.addr, addr_q);

					SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", log_id(mem.memid), i)), GetSize(port.data));
					module->addFf(NEW_ID, port.data, data_q);

					port.clk = State::S0;
					port.en = module->Mux(NEW_ID, Const(0, GetSize(en_q)), en_q, clock_edge);
					port.addr = addr_q;
					port.data = data_q;

					port.clk_enable = false;
					port.clk_polarity = false;
				}

				mem.emit();
			}

			for (auto cell : vector<Cell*>(module->selected_cells()))
			{
				SigSpec qval;
				if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
					FfData ff(&initvals, cell);

					if (ff.has_gclk) {
						// Already a $ff or $_FF_ cell.
						continue;
					}

					if (ff.has_clk) {
						log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
								log_id(module), log_id(cell), log_id(cell->type),
								log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q));
					} else if (ff.has_aload) {
						log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
								log_id(module), log_id(cell), log_id(cell->type),
								log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q));
					} else {
						// $sr.
						log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n",
								log_id(module), log_id(cell), log_id(cell->type),
								log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q));
					}

					ff.remove();

					// Strip spaces from signal name, since Yosys IDs can't contain spaces
					// Spaces only occur when we have a signal that's a slice of a larger bus,
					// e.g. "\myreg [5:0]", so removing spaces shouldn't result in loss of uniqueness
					std::string sig_q_str = log_signal(ff.sig_q);
					sig_q_str.erase(std::remove(sig_q_str.begin(), sig_q_str.end(), ' '), sig_q_str.end());

					Wire *past_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_q_wire", sig_q_str.c_str())), ff.width);

					if (!ff.is_fine) {
						module->addFf(NEW_ID, ff.sig_q, past_q);
					} else {
						module->addFfGate(NEW_ID, ff.sig_q, past_q);
					}
					if (!ff.val_init.is_fully_undef())
						initvals.set_init(past_q, ff.val_init);

					if (ff.has_clk) {
						ff.unmap_ce_srst();

						Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_clk#%s", sig_q_str.c_str(), log_signal(ff.sig_clk))));
						initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0);

						if (!ff.is_fine)
							module->addFf(NEW_ID, ff.sig_clk, past_clk);
						else
							module->addFfGate(NEW_ID, ff.sig_clk, past_clk);

						SigSpec clock_edge_pattern;

						if (ff.pol_clk) {
							clock_edge_pattern.append(State::S0);
							clock_edge_pattern.append(State::S1);
						} else {
							clock_edge_pattern.append(State::S1);
							clock_edge_pattern.append(State::S0);
						}

						SigSpec clock_edge = module->Eqx(NEW_ID, {ff.sig_clk, SigSpec(past_clk)}, clock_edge_pattern);

						Wire *past_d = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_d_wire", sig_q_str.c_str())), ff.width);
						if (!ff.is_fine)
							module->addFf(NEW_ID, ff.sig_d, past_d);
						else
							module->addFfGate(NEW_ID, ff.sig_d, past_d);

						if (!ff.val_init.is_fully_undef())
							initvals.set_init(past_d, ff.val_init);

						if (!ff.is_fine)
							qval = module->Mux(NEW_ID, past_q, past_d, clock_edge);
						else
							qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
					} else {
						qval = past_q;
					}

					if (ff.has_aload) {
						SigSpec sig_aload = wrap_async_control(module, ff.sig_aload, ff.pol_aload);

						if (!ff.is_fine)
							qval = module->Mux(NEW_ID, qval, ff.sig_ad, sig_aload);
						else
							qval = module->MuxGate(NEW_ID, qval, ff.sig_ad, sig_aload);
					}

					if (ff.has_sr) {
						SigSpec setval = wrap_async_control(module, ff.sig_set, ff.pol_set);
						SigSpec clrval = wrap_async_control(module, ff.sig_clr, ff.pol_clr);
						if (!ff.is_fine) {
							clrval = module->Not(NEW_ID, clrval);
							qval = module->Or(NEW_ID, qval, setval);
							module->addAnd(NEW_ID, qval, clrval, ff.sig_q);
						} else {
							clrval = module->NotGate(NEW_ID, clrval);
							qval = module->OrGate(NEW_ID, qval, setval);
							module->addAndGate(NEW_ID, qval, clrval, ff.sig_q);
						}
					} else if (ff.has_arst) {
						IdString id = NEW_ID_SUFFIX(stringf("%s#past_arst#%s", sig_q_str.c_str(), log_signal(ff.sig_arst)));
						SigSpec arst = wrap_async_control(module, ff.sig_arst, ff.pol_arst, id);
						if (!ff.is_fine)
							module->addMux(NEW_ID, qval, ff.val_arst, arst, ff.sig_q);
						else
							module->addMuxGate(NEW_ID, qval, ff.val_arst[0], arst, ff.sig_q);
					} else {
						module->connect(ff.sig_q, qval);
					}
				}
			}
		}

	}
} Clk2fflogicPass;

PRIVATE_NAMESPACE_END
<commit_msg>Use wrap_async_control_gate if ff is fine<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/ffinit.h"
#include "kernel/ff.h"
#include "kernel/mem.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct Clk2fflogicPass : public Pass {
	Clk2fflogicPass() : Pass("clk2fflogic", "convert clocked FFs to generic $ff cells") { }
	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    clk2fflogic [options] [selection]\n");
		log("\n");
		log("This command replaces clocked flip-flops with generic $ff cells that use the\n");
		log("implicit global clock. This is useful for formal verification of designs with\n");
		log("multiple clocks.\n");
		log("\n");
	}
	SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity, bool is_fine, IdString past_sig_id) {
		if (!is_fine)
			return wrap_async_control(module, sig, polarity, past_sig_id);
		return wrap_async_control_gate(module, sig, polarity, past_sig_id);
	}
	SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity, IdString past_sig_id) {
		Wire *past_sig = module->addWire(past_sig_id, GetSize(sig));
		past_sig->attributes[ID::init] = RTLIL::Const(polarity ? State::S0 : State::S1, GetSize(sig));
		module->addFf(NEW_ID, sig, past_sig);
		if (polarity)
			sig = module->Or(NEW_ID, sig, past_sig);
		else
			sig = module->And(NEW_ID, sig, past_sig);
		if (polarity)
			return sig;
		else
			return module->Not(NEW_ID, sig);
	}
	SigSpec wrap_async_control_gate(Module *module, SigSpec sig, bool polarity, IdString past_sig_id) {
		Wire *past_sig = module->addWire(past_sig_id);
		past_sig->attributes[ID::init] = polarity ? State::S0 : State::S1;
		module->addFfGate(NEW_ID, sig, past_sig);
		if (polarity)
			sig = module->OrGate(NEW_ID, sig, past_sig);
		else
			sig = module->AndGate(NEW_ID, sig, past_sig);
		if (polarity)
			return sig;
		else
			return module->NotGate(NEW_ID, sig);
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) override
	{
		// bool flag_noinit = false;

		log_header(design, "Executing CLK2FFLOGIC pass (convert clocked FFs to generic $ff cells).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-noinit") {
			// 	flag_noinit = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		{
			SigMap sigmap(module);
			FfInitVals initvals(&sigmap, module);

			for (auto &mem : Mem::get_selected_memories(module))
			{
				for (int i = 0; i < GetSize(mem.rd_ports); i++) {
					auto &port = mem.rd_ports[i];
					if (port.clk_enable)
						log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! "
								"Call \"memory\" with -nordff to avoid this error.\n", i, log_id(mem.memid), log_id(module));
				}

				for (int i = 0; i < GetSize(mem.wr_ports); i++)
				{
					auto &port = mem.wr_ports[i];

					if (!port.clk_enable)
						continue;

					log("Modifying write port %d on memory %s.%s: CLK=%s, A=%s, D=%s\n",
							i, log_id(module), log_id(mem.memid), log_signal(port.clk),
							log_signal(port.addr), log_signal(port.data));

					Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", log_id(mem.memid), i, log_signal(port.clk))));
					past_clk->attributes[ID::init] = port.clk_polarity ? State::S1 : State::S0;
					module->addFf(NEW_ID, port.clk, past_clk);

					SigSpec clock_edge_pattern;

					if (port.clk_polarity) {
						clock_edge_pattern.append(State::S0);
						clock_edge_pattern.append(State::S1);
					} else {
						clock_edge_pattern.append(State::S1);
						clock_edge_pattern.append(State::S0);
					}

					SigSpec clock_edge = module->Eqx(NEW_ID, {port.clk, SigSpec(past_clk)}, clock_edge_pattern);

					SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", log_id(mem.memid), i)), GetSize(port.en));
					module->addFf(NEW_ID, port.en, en_q);

					SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", log_id(mem.memid), i)), GetSize(port.addr));
					module->addFf(NEW_ID, port.addr, addr_q);

					SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", log_id(mem.memid), i)), GetSize(port.data));
					module->addFf(NEW_ID, port.data, data_q);

					port.clk = State::S0;
					port.en = module->Mux(NEW_ID, Const(0, GetSize(en_q)), en_q, clock_edge);
					port.addr = addr_q;
					port.data = data_q;

					port.clk_enable = false;
					port.clk_polarity = false;
				}

				mem.emit();
			}

			for (auto cell : vector<Cell*>(module->selected_cells()))
			{
				SigSpec qval;
				if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
					FfData ff(&initvals, cell);

					if (ff.has_gclk) {
						// Already a $ff or $_FF_ cell.
						continue;
					}

					if (ff.has_clk) {
						log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
								log_id(module), log_id(cell), log_id(cell->type),
								log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q));
					} else if (ff.has_aload) {
						log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
								log_id(module), log_id(cell), log_id(cell->type),
								log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q));
					} else {
						// $sr.
						log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n",
								log_id(module), log_id(cell), log_id(cell->type),
								log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q));
					}

					ff.remove();

					// Strip spaces from signal name, since Yosys IDs can't contain spaces
					// Spaces only occur when we have a signal that's a slice of a larger bus,
					// e.g. "\myreg [5:0]", so removing spaces shouldn't result in loss of uniqueness
					std::string sig_q_str = log_signal(ff.sig_q);
					sig_q_str.erase(std::remove(sig_q_str.begin(), sig_q_str.end(), ' '), sig_q_str.end());

					Wire *past_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_q_wire", sig_q_str.c_str())), ff.width);

					if (!ff.is_fine) {
						module->addFf(NEW_ID, ff.sig_q, past_q);
					} else {
						module->addFfGate(NEW_ID, ff.sig_q, past_q);
					}
					if (!ff.val_init.is_fully_undef())
						initvals.set_init(past_q, ff.val_init);

					if (ff.has_clk) {
						ff.unmap_ce_srst();

						Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_clk#%s", sig_q_str.c_str(), log_signal(ff.sig_clk))));
						initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0);

						if (!ff.is_fine)
							module->addFf(NEW_ID, ff.sig_clk, past_clk);
						else
							module->addFfGate(NEW_ID, ff.sig_clk, past_clk);

						SigSpec clock_edge_pattern;

						if (ff.pol_clk) {
							clock_edge_pattern.append(State::S0);
							clock_edge_pattern.append(State::S1);
						} else {
							clock_edge_pattern.append(State::S1);
							clock_edge_pattern.append(State::S0);
						}

						SigSpec clock_edge = module->Eqx(NEW_ID, {ff.sig_clk, SigSpec(past_clk)}, clock_edge_pattern);

						Wire *past_d = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_d_wire", sig_q_str.c_str())), ff.width);
						if (!ff.is_fine)
							module->addFf(NEW_ID, ff.sig_d, past_d);
						else
							module->addFfGate(NEW_ID, ff.sig_d, past_d);

						if (!ff.val_init.is_fully_undef())
							initvals.set_init(past_d, ff.val_init);

						if (!ff.is_fine)
							qval = module->Mux(NEW_ID, past_q, past_d, clock_edge);
						else
							qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
					} else {
						qval = past_q;
					}

					if (ff.has_aload) {
						SigSpec sig_aload = wrap_async_control(module, ff.sig_aload, ff.pol_aload, ff.is_fine, NEW_ID);

						if (!ff.is_fine)
							qval = module->Mux(NEW_ID, qval, ff.sig_ad, sig_aload);
						else
							qval = module->MuxGate(NEW_ID, qval, ff.sig_ad, sig_aload);
					}

					if (ff.has_sr) {
						SigSpec setval = wrap_async_control(module, ff.sig_set, ff.pol_set, ff.is_fine, NEW_ID);
						SigSpec clrval = wrap_async_control(module, ff.sig_clr, ff.pol_clr, ff.is_fine, NEW_ID);
						if (!ff.is_fine) {
							clrval = module->Not(NEW_ID, clrval);
							qval = module->Or(NEW_ID, qval, setval);
							module->addAnd(NEW_ID, qval, clrval, ff.sig_q);
						} else {
							clrval = module->NotGate(NEW_ID, clrval);
							qval = module->OrGate(NEW_ID, qval, setval);
							module->addAndGate(NEW_ID, qval, clrval, ff.sig_q);
						}
					} else if (ff.has_arst) {
						IdString id = NEW_ID_SUFFIX(stringf("%s#past_arst#%s", sig_q_str.c_str(), log_signal(ff.sig_arst)));
						SigSpec arst = wrap_async_control(module, ff.sig_arst, ff.pol_arst, ff.is_fine, id);
						if (!ff.is_fine)
							module->addMux(NEW_ID, qval, ff.val_arst, arst, ff.sig_q);
						else
							module->addMuxGate(NEW_ID, qval, ff.val_arst[0], arst, ff.sig_q);
					} else {
						module->connect(ff.sig_q, qval);
					}
				}
			}
		}

	}
} Clk2fflogicPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: entrylisthelper.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 12:54:08 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef FORMS_ENTRYLISTHELPER_HXX
#define FORMS_ENTRYLISTHELPER_HXX

#ifndef _COM_SUN_STAR_FORM_BINDING_XLISTENTRYSINK_HDL_
#include <com/sun/star/form/binding/XListEntrySink.hpp>
#endif
#ifndef _COM_SUN_STAR_FORM_BINDING_XLISTENTRYLISTENER_HDL_
#include <com/sun/star/form/binding/XListEntryListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

//.........................................................................
namespace frm
{
//.........................................................................

    //=====================================================================
    //= OEntryListHelper
    //=====================================================================
    typedef ::cppu::ImplHelper2 <   ::com::sun::star::form::binding::XListEntrySink
                                ,   ::com::sun::star::form::binding::XListEntryListener
                                >   OEntryListHelper_BASE;

    class OEntryListHelper : public OEntryListHelper_BASE
    {
    private:
        ::osl::Mutex&   m_rMutex;

        ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >
                        m_xListSource;      /// our external list source
        ::com::sun::star::uno::Sequence< ::rtl::OUString >
                        m_aStringItems;     /// "overridden" StringItemList property value

    protected:
        OEntryListHelper( ::osl::Mutex& _rMutex );
        OEntryListHelper( const OEntryListHelper& _rSource, ::osl::Mutex& _rMutex );
        ~OEntryListHelper( );

        /// returns the current string item list
        inline const ::com::sun::star::uno::Sequence< ::rtl::OUString >&
                    getStringItemList() const { return m_aStringItems; }
        inline const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >&
                    getExternalListEntrySource() const { return m_xListSource; }

        /// determines whether we actually have an external list source
        inline bool hasExternalListSource( ) const { return m_xListSource.is(); }

        /** handling the XEventListener::disposing call for the case where
            our list source is being disposed
            @return
                <TRUE/> if and only if the disposed object was our list source, and so the
                event was handled
        */
        bool        handleDisposing( const ::com::sun::star::lang::EventObject& _rEvent );

        /** to be called by derived classes' instances when they're being disposed
        */
        void        disposing( );

        // prevent method hiding
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) = 0;

        /** helper for implementing convertFastPropertyValue( StringItemList )

The signature of this method and the return type have the same semantics
            as convertFastPropertyValue.

        */
        sal_Bool    convertNewListSourceProperty(
                        ::com::sun::star::uno::Any& _rConvertedValue,
                        ::com::sun::star::uno::Any& _rOldValue,
                        const ::com::sun::star::uno::Any& _rValue
                    )
                    SAL_THROW( ( ::com::sun::star::lang::IllegalArgumentException ) );

        /** helper for implementing setFastPropertyValueNoBroadcast

Will internally call stringItemListChanged after the new item list
            has been set.

            @precond
                not to be called when we have an external list source
            @see hasExternalListSource
        */
        void        setNewStringItemList( const ::com::sun::star::uno::Any& _rValue );

        /** announces that the list of entries has changed.

Derived classes have to override this. Most probably, they'll set the new
            as model property.

            @pure
            @see getStringItemList
        */
        virtual void    stringItemListChanged( ) = 0;

        /** called whenever a connection to a new external list source has been established
        */
        virtual void    connectedExternalListSource( );

        /** called whenever a connection to a new external list source has been revoked
        */
        virtual void    disconnectedExternalListSource( );

    private:
        // XListEntrySink
        virtual void SAL_CALL setListEntrySource( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > SAL_CALL getListEntrySource(  ) throw (::com::sun::star::uno::RuntimeException);

        // XListEntryListener
        virtual void SAL_CALL entryChanged( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL entryRangeInserted( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL entryRangeRemoved( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL allEntriesChanged( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException);

    private:
        /** disconnects from the active external list source, if present
            @see connectExternalListSource
        */
        void        disconnectExternalListSource( );

        /** connects to a new external list source
            @param _rxSource
                the new list source. Must not be <NULL/>
            @see disconnectExternalListSource
        */
        void        connectExternalListSource(
                        const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource
                    );

    private:
        OEntryListHelper();                                     // never implemented
        OEntryListHelper( const OEntryListHelper& );            // never implemented
        OEntryListHelper& operator=( const OEntryListHelper& ); // never implemented
    };

//.........................................................................
}   // namespace frm
//.........................................................................

#endif // FORMS_ENTRYLISTHELPER_HXX
<commit_msg>INTEGRATION: CWS sb59 (1.6.28); FILE MERGED 2006/08/29 16:10:59 sb 1.6.28.1: #i67487# Made code warning-free (wntmsci10).<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: entrylisthelper.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 11:12:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef FORMS_ENTRYLISTHELPER_HXX
#define FORMS_ENTRYLISTHELPER_HXX

#ifndef _COM_SUN_STAR_FORM_BINDING_XLISTENTRYSINK_HDL_
#include <com/sun/star/form/binding/XListEntrySink.hpp>
#endif
#ifndef _COM_SUN_STAR_FORM_BINDING_XLISTENTRYLISTENER_HDL_
#include <com/sun/star/form/binding/XListEntryListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

//.........................................................................
namespace frm
{
//.........................................................................

    //=====================================================================
    //= OEntryListHelper
    //=====================================================================
    typedef ::cppu::ImplHelper2 <   ::com::sun::star::form::binding::XListEntrySink
                                ,   ::com::sun::star::form::binding::XListEntryListener
                                >   OEntryListHelper_BASE;

    class OEntryListHelper : public OEntryListHelper_BASE
    {
    private:
        ::osl::Mutex&   m_rMutex;

        ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >
                        m_xListSource;      /// our external list source
        ::com::sun::star::uno::Sequence< ::rtl::OUString >
                        m_aStringItems;     /// "overridden" StringItemList property value

    protected:
        OEntryListHelper( ::osl::Mutex& _rMutex );
        OEntryListHelper( const OEntryListHelper& _rSource, ::osl::Mutex& _rMutex );
        virtual ~OEntryListHelper( );

        /// returns the current string item list
        inline const ::com::sun::star::uno::Sequence< ::rtl::OUString >&
                    getStringItemList() const { return m_aStringItems; }
        inline const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >&
                    getExternalListEntrySource() const { return m_xListSource; }

        /// determines whether we actually have an external list source
        inline bool hasExternalListSource( ) const { return m_xListSource.is(); }

        /** handling the XEventListener::disposing call for the case where
            our list source is being disposed
            @return
                <TRUE/> if and only if the disposed object was our list source, and so the
                event was handled
        */
        bool        handleDisposing( const ::com::sun::star::lang::EventObject& _rEvent );

        /** to be called by derived classes' instances when they're being disposed
        */
        void        disposing( );

        // prevent method hiding
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) = 0;

        /** helper for implementing convertFastPropertyValue( StringItemList )

The signature of this method and the return type have the same semantics
            as convertFastPropertyValue.

        */
        sal_Bool    convertNewListSourceProperty(
                        ::com::sun::star::uno::Any& _rConvertedValue,
                        ::com::sun::star::uno::Any& _rOldValue,
                        const ::com::sun::star::uno::Any& _rValue
                    )
                    SAL_THROW( ( ::com::sun::star::lang::IllegalArgumentException ) );

        /** helper for implementing setFastPropertyValueNoBroadcast

Will internally call stringItemListChanged after the new item list
            has been set.

            @precond
                not to be called when we have an external list source
            @see hasExternalListSource
        */
        void        setNewStringItemList( const ::com::sun::star::uno::Any& _rValue );

        /** announces that the list of entries has changed.

Derived classes have to override this. Most probably, they'll set the new
            as model property.

            @pure
            @see getStringItemList
        */
        virtual void    stringItemListChanged( ) = 0;

        /** called whenever a connection to a new external list source has been established
        */
        virtual void    connectedExternalListSource( );

        /** called whenever a connection to a new external list source has been revoked
        */
        virtual void    disconnectedExternalListSource( );

    private:
        // XListEntrySink
        virtual void SAL_CALL setListEntrySource( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > SAL_CALL getListEntrySource(  ) throw (::com::sun::star::uno::RuntimeException);

        // XListEntryListener
        virtual void SAL_CALL entryChanged( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL entryRangeInserted( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL entryRangeRemoved( const ::com::sun::star::form::binding::ListEntryEvent& _rSource ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL allEntriesChanged( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException);

    private:
        /** disconnects from the active external list source, if present
            @see connectExternalListSource
        */
        void        disconnectExternalListSource( );

        /** connects to a new external list source
            @param _rxSource
                the new list source. Must not be <NULL/>
            @see disconnectExternalListSource
        */
        void        connectExternalListSource(
                        const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource
                    );

    private:
        OEntryListHelper();                                     // never implemented
        OEntryListHelper( const OEntryListHelper& );            // never implemented
        OEntryListHelper& operator=( const OEntryListHelper& ); // never implemented
    };

//.........................................................................
}   // namespace frm
//.........................................................................

#endif // FORMS_ENTRYLISTHELPER_HXX
<|endoftext|>


<commit_before><commit_msg>PDF: Use the z-order when there is a link and widget overlaps.<commit_after><|endoftext|>