<commit_before>#include "pb_conn.h"
#include "pink_define.h"
#include "worker_thread.h"
#include "xdebug.h"

#include <string>

namespace pink {

PbConn::PbConn(const int fd, const std::string &ip_port) :
  PinkConn(fd, ip_port),
  header_len_(-1),
  cur_pos_(0),
  rbuf_len_(0),
  remain_packet_len_(0),
  connStatus_(kHeader),
  wbuf_len_(0),
  wbuf_pos_(0)
{
  rbuf_ = (char *)malloc(sizeof(char) * PB_MAX_MESSAGE);
  wbuf_ = (char *)malloc(sizeof(char) * PB_MAX_MESSAGE);
}

PbConn::~PbConn()
{
  free(rbuf_);
  free(wbuf_);
}

// Msg is [ length(COMMAND_HEADER_LENGTH) | body(length bytes) ]
//   step 1. kHeader, we read COMMAND_HEADER_LENGTH bytes;
//   step 2. kPacket, we read header_len bytes;
ReadStatus PbConn::GetRequest()
{
  // TODO  cur_pos_ can be omitted
  while (true) {
    switch (connStatus_) {
      case kHeader: {
        ssize_t nread = read(fd(), rbuf_ + rbuf_len_, COMMAND_HEADER_LENGTH - rbuf_len_);
        if (nread == -1) {
          if (errno == EAGAIN) {
            return kReadHalf;
          } else {
            return kReadError;
          }
        } else if (nread == 0) {
          return kReadClose;
        } else {
          rbuf_len_ += nread;
          if (rbuf_len_ - cur_pos_ == COMMAND_HEADER_LENGTH) {
            uint32_t integer = 0;
            memcpy((char *)(&integer), rbuf_ + cur_pos_, sizeof(uint32_t));
            header_len_ = ntohl(integer);
            remain_packet_len_ = header_len_;
            cur_pos_ += COMMAND_HEADER_LENGTH;
            connStatus_ = kPacket;
          }
          log_info ("GetRequest kHeader header_len=%u cur_pos=%u rbuf_len=%u remain_packet_len_=%d nread=%d\n", header_len_, cur_pos_, rbuf_len_, remain_packet_len_, nread);
        }
        break;
      }
      case kPacket: {
        if (header_len_ >= PB_MAX_MESSAGE - COMMAND_HEADER_LENGTH) {
          return kFullError;
        } else {
          // read msg body
          ssize_t nread = read(fd(), rbuf_ + rbuf_len_, remain_packet_len_);
          if (nread == -1) {
            if (errno == EAGAIN) {
              return kReadHalf;
            } else {
              return kReadError;
            }
          } else if (nread == 0) {
            return kReadClose;
          }

          rbuf_len_ += nread;
          remain_packet_len_ -= nread;
          if (remain_packet_len_ == 0) {
            cur_pos_ = rbuf_len_;
            connStatus_ = kComplete;
          }
          log_info ("GetRequest kPacket header_len=%u cur_pos=%u rbuf_len=%u remain_packet_len_=%d nread=%d\n", header_len_, cur_pos_, rbuf_len_, remain_packet_len_, nread);
        }
        break;
      }
      case kComplete: {
        DealMessage();
        connStatus_ = kHeader;

        cur_pos_ = 0;
        rbuf_len_ = 0;
        return kReadAll;
      }
      // Add this switch case just for delete compile warning
      case kBuildObuf:
        break;

      case kWriteObuf:
        break;
    }
  }

  return kReadHalf;
}

WriteStatus PbConn::SendReply()
{
  BuildObuf();
  ssize_t nwritten = 0;
  while (wbuf_len_ > 0) {
    nwritten = write(fd(), wbuf_ + wbuf_pos_, wbuf_len_ - wbuf_pos_);
    if (nwritten <= 0) {
      break;
    }
    wbuf_pos_ += nwritten;
    if (wbuf_pos_ == wbuf_len_) {
      wbuf_len_ = 0;
      wbuf_pos_ = 0;
    }
  }
  if (nwritten == -1) {
    if (errno == EAGAIN) {
      return kWriteHalf;
    } else {
      // Here we should close the connection
      return kWriteError;
    }
  }
  if (wbuf_len_ == 0) {
    return kWriteAll;
  } else {
    return kWriteHalf;
  }
}

Status PbConn::BuildObuf()
{
  wbuf_len_ = res_->ByteSize();
  res_->SerializeToArray(wbuf_ + 4, wbuf_len_);
  uint32_t u;
  u = htonl(wbuf_len_);
  memcpy(wbuf_, &u, sizeof(uint32_t));
  wbuf_len_ += COMMAND_HEADER_LENGTH;

  return Status::OK();
}

}
<commit_msg>change code style to follow google c++ coding style<commit_after>#include "./pb_conn.h"

#include <string>

#include "./pink_define.h"
#include "./worker_thread.h"
#include "./xdebug.h"

namespace pink {

PbConn::PbConn(const int fd, const std::string &ip_port) :
  PinkConn(fd, ip_port),
  header_len_(-1),
  cur_pos_(0),
  rbuf_len_(0),
  remain_packet_len_(0),
  connStatus_(kHeader),
  wbuf_len_(0),
  wbuf_pos_(0) {
  rbuf_ = reinterpret_cast<char *>(malloc(sizeof(char) * PB_MAX_MESSAGE));
  wbuf_ = reinterpret_cast<char *>(malloc(sizeof(char) * PB_MAX_MESSAGE));
}

PbConn::~PbConn()
{
  free(rbuf_);
  free(wbuf_);
}

// Msg is [ length(COMMAND_HEADER_LENGTH) | body(length bytes) ]
//   step 1. kHeader, we read COMMAND_HEADER_LENGTH bytes;
//   step 2. kPacket, we read header_len bytes;
ReadStatus PbConn::GetRequest()
{
  // TODO  cur_pos_ can be omitted
  while (true) {
    switch (connStatus_) {
      case kHeader: {
        ssize_t nread = read(fd(), rbuf_ + rbuf_len_, COMMAND_HEADER_LENGTH - rbuf_len_);
        if (nread == -1) {
          if (errno == EAGAIN) {
            return kReadHalf;
          } else {
            return kReadError;
          }
        } else if (nread == 0) {
          return kReadClose;
        } else {
          rbuf_len_ += nread;
          if (rbuf_len_ - cur_pos_ == COMMAND_HEADER_LENGTH) {
            uint32_t integer = 0;
            memcpy((char *)(&integer), rbuf_ + cur_pos_, sizeof(uint32_t));
            header_len_ = ntohl(integer);
            remain_packet_len_ = header_len_;
            cur_pos_ += COMMAND_HEADER_LENGTH;
            connStatus_ = kPacket;
          }
          log_info("GetRequest kHeader header_len=%u cur_pos=%u rbuf_len=%u remain_packet_len_=%d nread=%d\n", header_len_, cur_pos_, rbuf_len_, remain_packet_len_, nread);
        }
        break;
      }
      case kPacket: {
        if (header_len_ >= PB_MAX_MESSAGE - COMMAND_HEADER_LENGTH) {
          return kFullError;
        } else {
          // read msg body
          ssize_t nread = read(fd(), rbuf_ + rbuf_len_, remain_packet_len_);
          if (nread == -1) {
            if (errno == EAGAIN) {
              return kReadHalf;
            } else {
              return kReadError;
            }
          } else if (nread == 0) {
            return kReadClose;
          }

          rbuf_len_ += nread;
          remain_packet_len_ -= nread;
          if (remain_packet_len_ == 0) {
            cur_pos_ = rbuf_len_;
            connStatus_ = kComplete;
          }
          log_info("GetRequest kPacket header_len=%u cur_pos=%u rbuf_len=%u remain_packet_len_=%d nread=%d\n", header_len_, cur_pos_, rbuf_len_, remain_packet_len_, nread);
        }
        break;
      }
      case kComplete: {
        DealMessage();
        connStatus_ = kHeader;

        cur_pos_ = 0;
        rbuf_len_ = 0;
        return kReadAll;
      }
      // Add this switch case just for delete compile warning
      case kBuildObuf:
        break;

      case kWriteObuf:
        break;
    }
  }

  return kReadHalf;
}

WriteStatus PbConn::SendReply()
{
  BuildObuf();
  ssize_t nwritten = 0;
  while (wbuf_len_ > 0) {
    nwritten = write(fd(), wbuf_ + wbuf_pos_, wbuf_len_ - wbuf_pos_);
    if (nwritten <= 0) {
      break;
    }
    wbuf_pos_ += nwritten;
    if (wbuf_pos_ == wbuf_len_) {
      wbuf_len_ = 0;
      wbuf_pos_ = 0;
    }
  }
  if (nwritten == -1) {
    if (errno == EAGAIN) {
      return kWriteHalf;
    } else {
      // Here we should close the connection
      return kWriteError;
    }
  }
  if (wbuf_len_ == 0) {
    return kWriteAll;
  } else {
    return kWriteHalf;
  }
}

Status PbConn::BuildObuf()
{
  wbuf_len_ = res_->ByteSize();
  res_->SerializeToArray(wbuf_ + 4, wbuf_len_);
  uint32_t u;
  u = htonl(wbuf_len_);
  memcpy(wbuf_, &u, sizeof(uint32_t));
  wbuf_len_ += COMMAND_HEADER_LENGTH;

  return Status::OK();
}

} // namespace pink
<|endoftext|>


<commit_before>//std::copy wird nur durch zeiger aufgerufen, deswegen muss die Warnung deaktiviert werden

#include <cstdlib>
#include <cstring>
#include <string>

class Primitive_Matrix
{
private:
	//hche und breite, beginnen bei 1!
	unsigned int height = 0;
	unsigned int width = 0;
	//Matrix als dynamische Array
	float **matrix;

public:
	//Konstr. Hhe und Breite
	Primitive_Matrix(unsigned int h, unsigned int w);

	//Kontrs. 2D dyn. Array
	Primitive_Matrix(float **arr, unsigned int h, unsigned int w);

	//Destruktor
	~Primitive_Matrix();

	//ndert Hhe
	bool ChangeHeight(unsigned int newHeight);

	//ndert Breite
	bool ChangeWidth(unsigned int newWidth);

	//ndert Gre
	bool ChangeSize(unsigned int newHeight, unsigned int newWidth);

	//Zu string
	std::string ToString();

};

Primitive_Matrix::Primitive_Matrix(unsigned int h, unsigned int w)
{
	//hhe und breite zuweisen
	height = h;
	width = w;
	//dyn. array aufspannen
	//matrix = new float*[height];
	matrix = (float **)calloc(height, sizeof(float *));
	for (unsigned int i = 0; i < height; i++)
	{
		//matrix[i] = new float[width];
		matrix[i] = (float *)calloc(width, sizeof(float));
	}
}

Primitive_Matrix::Primitive_Matrix(float **arr ,unsigned int h, unsigned int w)
{
	//hhe und breite zuweisen
	height = h;
	width = w;
	//dyn. array aufspannen
	//matrix = new float*[height];
	matrix = (float **)calloc(height, sizeof(float *));
	for (unsigned int i = 0; i < height; i++)
	{
		//matrix[i] = new float[width];
		matrix[i] = (float *)calloc(width, sizeof(float));
		//Gleichzeitiges Kopieren der Arrayzeilen - TESTEN!
		//std::copy(matrix[i], matrix[i] + width, arr[i]); algorithm und #define _SCL_SECURE_NO_WARNINGS bentigt
		memcpy(matrix[i], arr[i], width * sizeof(float));
	}
}

Primitive_Matrix::~Primitive_Matrix()
{
	for (unsigned int i = 0; i < height; i++)
	{
		//dyn Array auf jeder Zeile wird gelscht
		//delete[] matrix[i];
		free(matrix[i]);
	}
}

bool Primitive_Matrix::ChangeHeight(unsigned int newHeight)//Testen!
{
	//hhen array realloc mit neuer hhe und berprfung
	//bei realloc wird mtrix automatisch deallocated, wenn nicht NULL
	float **temp = (float **)realloc(matrix, newHeight * sizeof(float *));
	if (temp != NULL)
	{
		matrix = temp;
	}
	else if (temp == NULL)
	{
		return 0;
	}
	//neue hhe kleiner als alte: zeilen lschen, bis newHeight -1
	if (newHeight < height)
	{
		for (unsigned int i = height - 1; i >= newHeight; i--)
		{
			//dyn Array auf betroffenen Zeile wird gelscht
			//delete[] matrix[i];
			free(matrix[i]);
		}
		height = newHeight;
	}
	//neue hhe grer als alte: zeilen hinzufgen
	else if (newHeight > height)
	{
		for (unsigned int i = height - 1; i < newHeight; i++)
		{
			//dyn Array auf betroffenen Zeile wird hinzugefgt
			//matrix[i] = new float[width];
			matrix[i] = (float *)calloc(width, sizeof(float));
		}
		height = newHeight;
	}

	return 1;
}

bool Primitive_Matrix::ChangeWidth(unsigned int newWidth)//Testen!
{
	//spalten realloc zu neuer gre mit berprfung durch temp == NULL
	for (unsigned int i = 0; i < height; i++)
	{
		float *temp = (float *)realloc(matrix[i], newWidth * sizeof(float));

		if (temp != NULL)
		{
			matrix[i] = temp;
		}
		else if (temp == NULL)
		{
			return 0;
		}
	}
	width = newWidth;

	return 1;
}

bool Primitive_Matrix::ChangeSize(unsigned int newHeight, unsigned int newWidth)
{
	//Beide mssen klappen
	if (ChangeHeight(newHeight) == 1 && ChangeWidth(newWidth) == 1)
	{
		return 1;
	}

	return 0;
}

std::string Primitive_Matrix::ToString()
{
	std::string s = "";

	for (int row = 0; row < height; row++)//Schleife Zeilen
	{
		s += "[ ";
		for (int col = 0; col < width; col++)//Schleife Spalten in einer Zeile
		{
			s += (std::to_string( matrix[row][col] ) + " ");
		}
		s += "]\n";
	}

	return s;
}<commit_msg>fix in ChangeHeight: realloc wird mtrix automatisch deallocated, wenn nicht NULL, free wird nicht benötigt<commit_after>//std::copy wird nur durch zeiger aufgerufen, deswegen muss die Warnung deaktiviert werden

#include <cstdlib>
#include <cstring>
#include <string>

class Primitive_Matrix
{
private:
	//hche und breite, beginnen bei 1!
	unsigned int height = 0;
	unsigned int width = 0;
	//Matrix als dynamische Array
	float **matrix;

public:
	//Konstr. Hhe und Breite
	Primitive_Matrix(unsigned int h, unsigned int w);

	//Kontrs. 2D dyn. Array
	Primitive_Matrix(float **arr, unsigned int h, unsigned int w);

	//Destruktor
	~Primitive_Matrix();

	//ndert Hhe
	bool ChangeHeight(unsigned int newHeight);

	//ndert Breite
	bool ChangeWidth(unsigned int newWidth);

	//ndert Gre
	bool ChangeSize(unsigned int newHeight, unsigned int newWidth);

	//Zu string
	std::string ToString();

};

Primitive_Matrix::Primitive_Matrix(unsigned int h, unsigned int w)
{
	//hhe und breite zuweisen
	height = h;
	width = w;
	//dyn. array aufspannen
	//matrix = new float*[height];
	matrix = (float **)calloc(height, sizeof(float *));
	for (unsigned int i = 0; i < height; i++)
	{
		//matrix[i] = new float[width];
		matrix[i] = (float *)calloc(width, sizeof(float));
	}
}

Primitive_Matrix::Primitive_Matrix(float **arr ,unsigned int h, unsigned int w)
{
	//hhe und breite zuweisen
	height = h;
	width = w;
	//dyn. array aufspannen
	//matrix = new float*[height];
	matrix = (float **)calloc(height, sizeof(float *));
	for (unsigned int i = 0; i < height; i++)
	{
		//matrix[i] = new float[width];
		matrix[i] = (float *)calloc(width, sizeof(float));
		//Gleichzeitiges Kopieren der Arrayzeilen - TESTEN!
		//std::copy(matrix[i], matrix[i] + width, arr[i]); algorithm und #define _SCL_SECURE_NO_WARNINGS bentigt
		memcpy(matrix[i], arr[i], width * sizeof(float));
	}
}

Primitive_Matrix::~Primitive_Matrix()
{
	for (unsigned int i = 0; i < height; i++)
	{
		//dyn Array auf jeder Zeile wird gelscht
		//delete[] matrix[i];
		free(matrix[i]);
	}
}

bool Primitive_Matrix::ChangeHeight(unsigned int newHeight)//Testen!
{
	//hhen array realloc mit neuer hhe und berprfung
	//bei realloc wird mtrix automatisch deallocated, wenn nicht NULL
	float **temp = (float **)realloc(matrix, newHeight * sizeof(float *));
	if (temp != NULL)
	{
		matrix = temp;
	}
	else if (temp == NULL)
	{
		return 0;
	}
	height = newHeight;//neu

	return 1;
}

bool Primitive_Matrix::ChangeWidth(unsigned int newWidth)//Testen!
{
	//spalten realloc zu neuer gre mit berprfung durch temp == NULL
	for (unsigned int i = 0; i < height; i++)
	{
		float *temp = (float *)realloc(matrix[i], newWidth * sizeof(float));

		if (temp != NULL)
		{
			matrix[i] = temp;
		}
		else if (temp == NULL)
		{
			return 0;
		}
	}
	width = newWidth;

	return 1;
}

bool Primitive_Matrix::ChangeSize(unsigned int newHeight, unsigned int newWidth)
{
	//Beide mssen klappen
	if (ChangeHeight(newHeight) == 1 && ChangeWidth(newWidth) == 1)
	{
		return 1;
	}

	return 0;
}

std::string Primitive_Matrix::ToString()
{
	std::string s = "";

	for (int row = 0; row < height; row++)//Schleife Zeilen
	{
		s += "[ ";
		for (int col = 0; col < width; col++)//Schleife Spalten in einer Zeile
		{
			s += (std::to_string( matrix[row][col] ) + " ");
		}
		s += "]\n";
	}

	return s;
}

#include <iostream>

int main()
{
	float t0[3] = { 0, 1, 2 };
	float t1[3] = { 3, 4, 5 };
	float t2[3] = { 6, 7, 8 };

	float **test = new float*[3];
	test[0] = t0;
	test[1] = t1;
	test[2] = t2;

	Primitive_Matrix mtrTest = Primitive_Matrix(test, 3, 3);
	std::cout << mtrTest.ToString();

	mtrTest.ChangeSize(2, 2);
	std::cout << mtrTest.ToString();

}<|endoftext|>


<commit_before>#include "../codecvt/codecvt_specializations.h"
#include "../codecvt/codecvt_utf8.h"
#include "../codecvt/utf_conversion_helpers.h"

#include <cstring>

#include "cppunit-header.h"
#include "multistring.h"

// utility wrapper to adapt locale-bound facets for wstring/wbuffer convert
template<class Facet>
struct deletable_facet : Facet
{
	template<class ...Args>
	deletable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}

	~deletable_facet() {}
};

static const DEF_MULTISTRING(nul_char, "\x0");
static const DEF_MULTISTRING(ascii_max, "\x7f");

// Bug in gcc converts u"\uffff" into {0xd7ff, 0xdffff } - workaround for that
static const multistring bmp_max(u8"\uffff", L"\xffff",
                                 u"\xffff", U"\xffff");

class Test_codecvt : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE(Test_codecvt);
	CPPUNIT_TEST(construction<char16_t>);
	CPPUNIT_TEST(encoding<char16_t>);
	CPPUNIT_TEST(always_noconv<char16_t>);
	CPPUNIT_TEST(max_length<char16_t>);
	CPPUNIT_TEST(out<char16_t>);
	CPPUNIT_TEST(in<char16_t>);

	CPPUNIT_TEST(construction<char32_t>);
	CPPUNIT_TEST(encoding<char32_t>);
	CPPUNIT_TEST(always_noconv<char32_t>);
	CPPUNIT_TEST(max_length<char32_t>);
	CPPUNIT_TEST(out<char32_t>);
	CPPUNIT_TEST(in<char32_t>);
	CPPUNIT_TEST_SUITE_END();

	typedef std::codecvt_base::result result;

	// FIXME: we're using deletable_facet here instead of the proper machinery
	// until we get a change into gcc's libstdc++-v3/src/c++98/locale_init.cc
	// to register these facets... without that, the use_facet/has_facet
	// functions will continue to be broken
#if 0
	template<typename T>
	void construction()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		std::locale mylocale;
		const cvt_t & cvt = std::use_facet<cvt_t>(mylocale);

		CPPUNIT_ASSERT(cvt.encoding() == 0);
	}
#else
	template<typename T>
	void construction()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		deletable_facet<cvt_t> cvt2(1);
		deletable_facet<cvt_t> cvt3(2);

		static_assert(std::is_same<T, typename cvt_t::intern_type>::value,
		              "codecvt<> intern_type is invalid");
		static_assert(std::is_same<char, typename cvt_t::extern_type>::value,
		              "codecvt<> extern_type is invalid");
		CPPUNIT_ASSERT(cvt.encoding() == 0);

	}
#endif

	template<typename T>
	void encoding()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		CPPUNIT_ASSERT(cvt.encoding() == 0);
	}

	template<typename T>
	void always_noconv()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		CPPUNIT_ASSERT(cvt.always_noconv() == false);
	}

	template<typename T>
	void max_length()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		if (std::is_same<char16_t, T>::value)
			CPPUNIT_ASSERT(cvt.max_length() == 4);
		else if (std::is_same<char32_t, T>::value)
			CPPUNIT_ASSERT(cvt.max_length() == 6);
	}

	template<typename T>
	void out_type_specific();

	template<typename T>
	void out()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		T input_buffer[20];
		std::mbstate_t state;
		result r = std::codecvt_base::ok;

		const int bufSz = 2 * cvt.max_length();
		std::unique_ptr<char[]> output_buffer(new char[bufSz]);
		char * out_start = output_buffer.get();
		char * out_end = out_start + bufSz;
		const T * const_intern_ptr = nullptr;
		char * extern_ptr = nullptr;

		CPPUNIT_ASSERT(nul_char.get<T>().size() != 0);
		for (size_t i = 0; i < nul_char.get<T>().length(); ++i)
			input_buffer[i] = nul_char.get<T>()[i];
		input_buffer[nul_char.get<T>().length()] = 0;

#if 0
		input_buffer[0] = 0;
#endif
		memset(&state, 0, sizeof(state));
		r = cvt.out(state, input_buffer,
		            input_buffer + 1, const_intern_ptr,
		            out_start, out_end, extern_ptr);

		CPPUNIT_ASSERT(r == std::codecvt_base::ok);
		CPPUNIT_ASSERT((extern_ptr - out_start) == 1);
		CPPUNIT_ASSERT(output_buffer[0] == '\0');

		//////

		CPPUNIT_ASSERT(ascii_max.get<T>().size() != 0);
		for (size_t i = 0; i < ascii_max.get<T>().length(); ++i)
			input_buffer[i] = ascii_max.get<T>()[i];
		input_buffer[ascii_max.get<T>().length()] = 0;

		memset(&state, 0, sizeof(state));
		memset(output_buffer.get(), 0, bufSz);
		r = cvt.out(state, input_buffer,
		            input_buffer + 1, const_intern_ptr,
		            out_start, out_end, extern_ptr);

		CPPUNIT_ASSERT(r == std::codecvt_base::ok);
		CPPUNIT_ASSERT((extern_ptr - out_start) == 1);
		CPPUNIT_ASSERT(output_buffer[0] == 0x7f);

		//////

		CPPUNIT_ASSERT(bmp_max.get<T>().size() != 0);
		for (size_t i = 0; i < bmp_max.get<T>().length(); ++i)
		{
			input_buffer[i] = bmp_max.get<T>()[i];
			printf("---> %08X\n", static_cast<uint32_t>(input_buffer[i]));
		}
		input_buffer[bmp_max.get<T>().length()] = 0;

		memset(&state, 0, sizeof(state));
		memset(output_buffer.get(), 0, bufSz);
		r = cvt.out(state, input_buffer,
		            input_buffer + 1, const_intern_ptr,
		            out_start, out_end, extern_ptr);

		CPPUNIT_ASSERT(r == std::codecvt_base::ok);
		CPPUNIT_ASSERT((extern_ptr - out_start) == 3);
		CPPUNIT_ASSERT(  static_cast<uint8_t>(output_buffer[0]) == 0xefu
		              && static_cast<uint8_t>(output_buffer[1]) == 0xbfu
		              && static_cast<uint8_t>(output_buffer[2]) == 0xbfu);

		out_type_specific<T>();
	}

	template<typename T>
	void in()
	{
#if 0
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		T input_buffer[2] = { 0, 0 };
		std::mbstate_t state;
		result r = std::codecvt_base::ok;
#endif

	}
};

template<>
void Test_codecvt::out_type_specific<char16_t>()
{
	typedef std::codecvt<char16_t, char, std::mbstate_t> cvt_t;
	deletable_facet<cvt_t> cvt;
	char16_t input_buffer[3];
	std::mbstate_t state;
	result r = std::codecvt_base::ok;

	const int bufSz = 2 * cvt.max_length();
	std::unique_ptr<char[]> output_buffer(new char[bufSz]);
	char * out_start = output_buffer.get();
	char * out_end = out_start + bufSz;
	const char16_t * const_intern_ptr = nullptr;
	char * extern_ptr = nullptr;

	input_buffer[0] = 0xdbff;
	input_buffer[1] = 0xdfff;
	input_buffer[2] = 0;
	memset(&state, 0, sizeof(state));
	memset(output_buffer.get(), 0, bufSz);
	r = cvt.out(state, input_buffer,
	            input_buffer + 2, const_intern_ptr,
	            out_start, out_end, extern_ptr);

	CPPUNIT_ASSERT(r == std::codecvt_base::ok);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[0]) == 0xf4);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[1]) == 0x8f);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[2]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[3]) == 0xbf);
}

template<>
void Test_codecvt::out_type_specific<char32_t>()
{
	typedef std::codecvt<char32_t, char, std::mbstate_t> cvt_t;
	deletable_facet<cvt_t> cvt;
	char32_t input_buffer[2];
	std::mbstate_t state;
	result r = std::codecvt_base::ok;

	const int bufSz = 2 * cvt.max_length();
	std::unique_ptr<char[]> output_buffer(new char[bufSz]);
	char * out_start = output_buffer.get();
	char * out_end = out_start + bufSz;
	const char32_t * const_intern_ptr = nullptr;
	char * extern_ptr = nullptr;

	input_buffer[0] = 0x0010ffffu;
	input_buffer[1] = 0;
	memset(&state, 0, sizeof(state));
	memset(output_buffer.get(), 0, bufSz);
	r = cvt.out(state, input_buffer,
	            input_buffer + 2, const_intern_ptr,
	            out_start, out_end, extern_ptr);

	CPPUNIT_ASSERT(r == std::codecvt_base::ok);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[0]) == 0xf4);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[1]) == 0x8f);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[2]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[3]) == 0xbf);

	memcpy(input_buffer, U"\U0010ffff", 4);
	input_buffer[0] = 0x7fffffffu;
	input_buffer[1] = 0;
	memset(&state, 0, sizeof(state));
	memset(output_buffer.get(), 0, bufSz);
	r = cvt.out(state, input_buffer,
	            input_buffer + 2, const_intern_ptr,
	            out_start, out_end, extern_ptr);

	CPPUNIT_ASSERT(r == std::codecvt_base::ok);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[0]) == 0xfd);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[1]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[2]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[3]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[4]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[5]) == 0xbf);
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test_codecvt);
<commit_msg>remove printf<commit_after>#include "../codecvt/codecvt_specializations.h"
#include "../codecvt/codecvt_utf8.h"
#include "../codecvt/utf_conversion_helpers.h"

#include <cstring>

#include "cppunit-header.h"
#include "multistring.h"

// utility wrapper to adapt locale-bound facets for wstring/wbuffer convert
template<class Facet>
struct deletable_facet : Facet
{
	template<class ...Args>
	deletable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}

	~deletable_facet() {}
};

static const DEF_MULTISTRING(nul_char, "\x0");
static const DEF_MULTISTRING(ascii_max, "\x7f");

// Bug in gcc converts u"\uffff" into {0xd7ff, 0xdffff } - workaround for that
static const multistring bmp_max(u8"\uffff", L"\xffff",
                                 u"\xffff", U"\xffff");

class Test_codecvt : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE(Test_codecvt);
	CPPUNIT_TEST(construction<char16_t>);
	CPPUNIT_TEST(encoding<char16_t>);
	CPPUNIT_TEST(always_noconv<char16_t>);
	CPPUNIT_TEST(max_length<char16_t>);
	CPPUNIT_TEST(out<char16_t>);
	CPPUNIT_TEST(in<char16_t>);

	CPPUNIT_TEST(construction<char32_t>);
	CPPUNIT_TEST(encoding<char32_t>);
	CPPUNIT_TEST(always_noconv<char32_t>);
	CPPUNIT_TEST(max_length<char32_t>);
	CPPUNIT_TEST(out<char32_t>);
	CPPUNIT_TEST(in<char32_t>);
	CPPUNIT_TEST_SUITE_END();

	typedef std::codecvt_base::result result;

	// FIXME: we're using deletable_facet here instead of the proper machinery
	// until we get a change into gcc's libstdc++-v3/src/c++98/locale_init.cc
	// to register these facets... without that, the use_facet/has_facet
	// functions will continue to be broken
#if 0
	template<typename T>
	void construction()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		std::locale mylocale;
		const cvt_t & cvt = std::use_facet<cvt_t>(mylocale);

		CPPUNIT_ASSERT(cvt.encoding() == 0);
	}
#else
	template<typename T>
	void construction()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		deletable_facet<cvt_t> cvt2(1);
		deletable_facet<cvt_t> cvt3(2);

		static_assert(std::is_same<T, typename cvt_t::intern_type>::value,
		              "codecvt<> intern_type is invalid");
		static_assert(std::is_same<char, typename cvt_t::extern_type>::value,
		              "codecvt<> extern_type is invalid");
		CPPUNIT_ASSERT(cvt.encoding() == 0);

	}
#endif

	template<typename T>
	void encoding()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		CPPUNIT_ASSERT(cvt.encoding() == 0);
	}

	template<typename T>
	void always_noconv()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		CPPUNIT_ASSERT(cvt.always_noconv() == false);
	}

	template<typename T>
	void max_length()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		if (std::is_same<char16_t, T>::value)
			CPPUNIT_ASSERT(cvt.max_length() == 4);
		else if (std::is_same<char32_t, T>::value)
			CPPUNIT_ASSERT(cvt.max_length() == 6);
	}

	template<typename T>
	void out_type_specific();

	template<typename T>
	void out()
	{
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		T input_buffer[20];
		std::mbstate_t state;
		result r = std::codecvt_base::ok;

		const int bufSz = 2 * cvt.max_length();
		std::unique_ptr<char[]> output_buffer(new char[bufSz]);
		char * out_start = output_buffer.get();
		char * out_end = out_start + bufSz;
		const T * const_intern_ptr = nullptr;
		char * extern_ptr = nullptr;

		CPPUNIT_ASSERT(nul_char.get<T>().size() != 0);
		for (size_t i = 0; i < nul_char.get<T>().length(); ++i)
			input_buffer[i] = nul_char.get<T>()[i];
		input_buffer[nul_char.get<T>().length()] = 0;

#if 0
		input_buffer[0] = 0;
#endif
		memset(&state, 0, sizeof(state));
		r = cvt.out(state, input_buffer,
		            input_buffer + 1, const_intern_ptr,
		            out_start, out_end, extern_ptr);

		CPPUNIT_ASSERT(r == std::codecvt_base::ok);
		CPPUNIT_ASSERT((extern_ptr - out_start) == 1);
		CPPUNIT_ASSERT(output_buffer[0] == '\0');

		//////

		CPPUNIT_ASSERT(ascii_max.get<T>().size() != 0);
		for (size_t i = 0; i < ascii_max.get<T>().length(); ++i)
			input_buffer[i] = ascii_max.get<T>()[i];
		input_buffer[ascii_max.get<T>().length()] = 0;

		memset(&state, 0, sizeof(state));
		memset(output_buffer.get(), 0, bufSz);
		r = cvt.out(state, input_buffer,
		            input_buffer + 1, const_intern_ptr,
		            out_start, out_end, extern_ptr);

		CPPUNIT_ASSERT(r == std::codecvt_base::ok);
		CPPUNIT_ASSERT((extern_ptr - out_start) == 1);
		CPPUNIT_ASSERT(output_buffer[0] == 0x7f);

		//////

		CPPUNIT_ASSERT(bmp_max.get<T>().size() != 0);
		for (size_t i = 0; i < bmp_max.get<T>().length(); ++i)
			input_buffer[i] = bmp_max.get<T>()[i];
		input_buffer[bmp_max.get<T>().length()] = 0;

		memset(&state, 0, sizeof(state));
		memset(output_buffer.get(), 0, bufSz);
		r = cvt.out(state, input_buffer,
		            input_buffer + 1, const_intern_ptr,
		            out_start, out_end, extern_ptr);

		CPPUNIT_ASSERT(r == std::codecvt_base::ok);
		CPPUNIT_ASSERT((extern_ptr - out_start) == 3);
		CPPUNIT_ASSERT(  static_cast<uint8_t>(output_buffer[0]) == 0xefu
		              && static_cast<uint8_t>(output_buffer[1]) == 0xbfu
		              && static_cast<uint8_t>(output_buffer[2]) == 0xbfu);

		out_type_specific<T>();
	}

	template<typename T>
	void in()
	{
#if 0
		typedef std::codecvt<T, char, std::mbstate_t> cvt_t;
		deletable_facet<cvt_t> cvt;
		T input_buffer[2] = { 0, 0 };
		std::mbstate_t state;
		result r = std::codecvt_base::ok;
#endif

	}
};

template<>
void Test_codecvt::out_type_specific<char16_t>()
{
	typedef std::codecvt<char16_t, char, std::mbstate_t> cvt_t;
	deletable_facet<cvt_t> cvt;
	char16_t input_buffer[3];
	std::mbstate_t state;
	result r = std::codecvt_base::ok;

	const int bufSz = 2 * cvt.max_length();
	std::unique_ptr<char[]> output_buffer(new char[bufSz]);
	char * out_start = output_buffer.get();
	char * out_end = out_start + bufSz;
	const char16_t * const_intern_ptr = nullptr;
	char * extern_ptr = nullptr;

	input_buffer[0] = 0xdbff;
	input_buffer[1] = 0xdfff;
	input_buffer[2] = 0;
	memset(&state, 0, sizeof(state));
	memset(output_buffer.get(), 0, bufSz);
	r = cvt.out(state, input_buffer,
	            input_buffer + 2, const_intern_ptr,
	            out_start, out_end, extern_ptr);

	CPPUNIT_ASSERT(r == std::codecvt_base::ok);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[0]) == 0xf4);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[1]) == 0x8f);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[2]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[3]) == 0xbf);
}

template<>
void Test_codecvt::out_type_specific<char32_t>()
{
	typedef std::codecvt<char32_t, char, std::mbstate_t> cvt_t;
	deletable_facet<cvt_t> cvt;
	char32_t input_buffer[2];
	std::mbstate_t state;
	result r = std::codecvt_base::ok;

	const int bufSz = 2 * cvt.max_length();
	std::unique_ptr<char[]> output_buffer(new char[bufSz]);
	char * out_start = output_buffer.get();
	char * out_end = out_start + bufSz;
	const char32_t * const_intern_ptr = nullptr;
	char * extern_ptr = nullptr;

	input_buffer[0] = 0x0010ffffu;
	input_buffer[1] = 0;
	memset(&state, 0, sizeof(state));
	memset(output_buffer.get(), 0, bufSz);
	r = cvt.out(state, input_buffer,
	            input_buffer + 2, const_intern_ptr,
	            out_start, out_end, extern_ptr);

	CPPUNIT_ASSERT(r == std::codecvt_base::ok);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[0]) == 0xf4);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[1]) == 0x8f);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[2]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[3]) == 0xbf);

	memcpy(input_buffer, U"\U0010ffff", 4);
	input_buffer[0] = 0x7fffffffu;
	input_buffer[1] = 0;
	memset(&state, 0, sizeof(state));
	memset(output_buffer.get(), 0, bufSz);
	r = cvt.out(state, input_buffer,
	            input_buffer + 2, const_intern_ptr,
	            out_start, out_end, extern_ptr);

	CPPUNIT_ASSERT(r == std::codecvt_base::ok);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[0]) == 0xfd);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[1]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[2]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[3]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[4]) == 0xbf);
	CPPUNIT_ASSERT(static_cast<uint8_t>(output_buffer[5]) == 0xbf);
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test_codecvt);
<|endoftext|>


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

// +build ignore

#include "eval.h"

#include <errno.h>
#include <glob.h>
#include <string.h>

#include "ast.h"
#include "file.h"
#include "file_cache.h"
#include "parser.h"
#include "rule.h"
#include "strutil.h"
#include "symtab.h"
#include "value.h"
#include "var.h"

EvalResult::~EvalResult() {
  for (auto p : rule_vars)
    delete p.second;
  delete vars;
}

Evaluator::Evaluator(const Vars* vars)
    : in_vars_(vars),
      vars_(new Vars()),
      last_rule_(NULL),
      current_scope_(NULL) {
}

Evaluator::~Evaluator() {
  // delete vars_;
  // for (auto p : rule_vars) {
  //   delete p.second;
  // }
}

Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
                        AssignOp op, bool is_override) {
  VarOrigin origin = (
      (is_bootstrap_ ? VarOrigin::DEFAULT :
       is_override ? VarOrigin::OVERRIDE : VarOrigin::FILE));

  Var* rhs = NULL;
  bool needs_assign = true;
  switch (op) {
    case AssignOp::COLON_EQ:
      rhs = new SimpleVar(rhs_v->Eval(this), origin);
      break;
    case AssignOp::EQ:
      rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
      break;
    case AssignOp::PLUS_EQ: {
      Var* prev = LookupVarInCurrentScope(lhs);
      if (!prev->IsDefined()) {
        rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
      } else {
        prev->AppendVar(this, rhs_v);
        rhs = prev;
        needs_assign = false;
      }
      break;
    }
    case AssignOp::QUESTION_EQ: {
      Var* prev = LookupVarInCurrentScope(lhs);
      if (!prev->IsDefined()) {
        rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
      } else {
        rhs = prev;
        needs_assign = false;
      }
      break;
    }
  }

  LOG("Assign: %s=%s", lhs.c_str(), rhs->DebugString().c_str());
  if (needs_assign) {
    return rhs;
  }
  return NULL;
}

void Evaluator::EvalAssign(const AssignAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;
  Symbol lhs = Intern(*ast->lhs->Eval(this));
  if (lhs.empty())
    Error("*** empty variable name.");
  Var* rhs = EvalRHS(lhs, ast->rhs, ast->orig_rhs, ast->op,
                     ast->directive == AssignDirective::OVERRIDE);
  if (rhs)
    vars_->Assign(lhs, rhs);
}

void Evaluator::EvalRule(const RuleAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;

  shared_ptr<string> expr = ast->expr->Eval(this);
  // See semicolon.mk.
  if (expr->find_first_not_of(" \t\n;") == string::npos)
    return;

  Rule* rule;
  RuleVarAssignment rule_var;
  ParseRule(loc_, *expr, ast->term, &rule, &rule_var);

  if (rule) {
    if (ast->term == ';') {
      rule->cmds.push_back(ast->after_term);
    }

    LOG("Rule: %s", rule->DebugString().c_str());
    rules_.push_back(shared_ptr<Rule>(rule));
    last_rule_ = rule;
    return;
  }

  for (Symbol output : rule_var.outputs) {
    auto p = rule_vars_.emplace(output, nullptr);
    if (p.second) {
      p.first->second = new Vars;
    }

    Value* rhs = ast->after_term;
    if (!rule_var.rhs.empty()) {
      Value* lit = NewLiteral(rule_var.rhs);
      if (rhs) {
        // TODO: We always insert two whitespaces around the
        // terminator. Preserve whitespaces properly.
        if (ast->term == ';') {
          rhs = NewExpr3(lit, NewLiteral(STRING_PIECE(" ; ")), rhs);
        } else {
          rhs = NewExpr3(lit, NewLiteral(STRING_PIECE(" = ")), rhs);
        }
      } else {
        rhs = lit;
      }
    }

    current_scope_ = p.first->second;
    Symbol lhs = Intern(rule_var.lhs);
    Var* rhs_var = EvalRHS(lhs, rhs, STRING_PIECE("*TODO*"), rule_var.op);
    if (rhs_var)
      current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
    current_scope_ = NULL;
  }
}

void Evaluator::EvalCommand(const CommandAST* ast) {
  loc_ = ast->loc();

  if (!last_rule_) {
    // TODO:
    ERROR("TODO");
  }

  last_rule_->cmds.push_back(ast->expr);
  if (last_rule_->cmd_lineno == 0)
    last_rule_->cmd_lineno = ast->loc().lineno;
  LOG("Command: %s", ast->expr->DebugString().c_str());
}

void Evaluator::EvalIf(const IfAST* ast) {
  loc_ = ast->loc();

  bool is_true;
  switch (ast->op) {
    case CondOp::IFDEF:
    case CondOp::IFNDEF: {
      Symbol lhs = Intern(*ast->lhs->Eval(this));
      Var* v = LookupVarInCurrentScope(lhs);
      shared_ptr<string> s = v->Eval(this);
      is_true = (s->empty() == (ast->op == CondOp::IFNDEF));
      break;
    }
    case CondOp::IFEQ:
    case CondOp::IFNEQ: {
      shared_ptr<string> lhs = ast->lhs->Eval(this);
      shared_ptr<string> rhs = ast->rhs->Eval(this);
      is_true = ((*lhs == *rhs) == (ast->op == CondOp::IFEQ));
      break;
    }
    default:
      CHECK(false);
  }

  const vector<AST*>* asts;
  if (is_true) {
    asts = &ast->true_asts;
  } else {
    asts = &ast->false_asts;
  }
  for (AST* a : *asts) {
    LOG("%s", a->DebugString().c_str());
    a->Eval(this);
  }
}

void Evaluator::DoInclude(const char* fname, bool should_exist) {
  if (!should_exist && g_ignore_optional_include_pattern &&
      Pattern(g_ignore_optional_include_pattern).Match(fname)) {
    return;
  }

  Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
  if (!mk->Exists()) {
    if (should_exist) {
      Error(StringPrintf(
          "%s: %s\n"
          "NOTE: kati does not support generating missing makefiles",
          fname, strerror(errno)));
    }
    return;
  }

  Var* var_list = LookupVar(Intern("MAKEFILE_LIST"));
  var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str()));
  for (AST* ast : mk->asts()) {
    LOG("%s", ast->DebugString().c_str());
    ast->Eval(this);
  }
}

void Evaluator::EvalInclude(const IncludeAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;

  shared_ptr<string> pats = ast->expr->Eval(this);
  for (StringPiece pat : WordScanner(*pats)) {
    ScopedTerminator st(pat);
    if (pat.find_first_of("?*[") != string::npos) {
      glob_t gl;
      glob(pat.data(), GLOB_NOSORT, NULL, &gl);
      for (size_t i = 0; i < gl.gl_pathc; i++) {
        DoInclude(gl.gl_pathv[i], ast->should_exist);
      }
      globfree(&gl);
    } else {
      DoInclude(pat.data(), ast->should_exist);
    }
  }
}

void Evaluator::EvalExport(const ExportAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;

  shared_ptr<string> exports = ast->expr->Eval(this);
  for (StringPiece tok : WordScanner(*exports)) {
    size_t equal_index = tok.find('=');
    if (equal_index == string::npos) {
      exports_[Intern(tok)] = ast->is_export;
    } else if (equal_index == 0 ||
               (equal_index == 1 &&
                (tok[0] == ':' || tok[0] == '?' || tok[0] == '+'))) {
      // Do not export tokens after an assignment.
      break;
    } else {
      StringPiece lhs, rhs;
      AssignOp op;
      ParseAssignStatement(tok, equal_index, &lhs, &rhs, &op);
      exports_[Intern(lhs)] = ast->is_export;
    }
  }
}

Var* Evaluator::LookupVar(Symbol name) {
  if (current_scope_) {
    Var* v = current_scope_->Lookup(name);
    if (v->IsDefined())
      return v;
  }
  Var* v = vars_->Lookup(name);
  if (v->IsDefined())
    return v;
  return in_vars_->Lookup(name);
}

Var* Evaluator::LookupVarInCurrentScope(Symbol name) {
  if (current_scope_) {
    return current_scope_->Lookup(name);
  }
  Var* v = vars_->Lookup(name);
  if (v->IsDefined())
    return v;
  return in_vars_->Lookup(name);
}

void Evaluator::Error(const string& msg) {
  ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
}
<commit_msg>[C++] Initialize Evaluator::avoid_io_<commit_after>// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include "eval.h"

#include <errno.h>
#include <glob.h>
#include <string.h>

#include "ast.h"
#include "file.h"
#include "file_cache.h"
#include "parser.h"
#include "rule.h"
#include "strutil.h"
#include "symtab.h"
#include "value.h"
#include "var.h"

EvalResult::~EvalResult() {
  for (auto p : rule_vars)
    delete p.second;
  delete vars;
}

Evaluator::Evaluator(const Vars* vars)
    : in_vars_(vars),
      vars_(new Vars()),
      last_rule_(NULL),
      current_scope_(NULL),
      avoid_io_(false) {
}

Evaluator::~Evaluator() {
  // delete vars_;
  // for (auto p : rule_vars) {
  //   delete p.second;
  // }
}

Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
                        AssignOp op, bool is_override) {
  VarOrigin origin = (
      (is_bootstrap_ ? VarOrigin::DEFAULT :
       is_override ? VarOrigin::OVERRIDE : VarOrigin::FILE));

  Var* rhs = NULL;
  bool needs_assign = true;
  switch (op) {
    case AssignOp::COLON_EQ:
      rhs = new SimpleVar(rhs_v->Eval(this), origin);
      break;
    case AssignOp::EQ:
      rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
      break;
    case AssignOp::PLUS_EQ: {
      Var* prev = LookupVarInCurrentScope(lhs);
      if (!prev->IsDefined()) {
        rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
      } else {
        prev->AppendVar(this, rhs_v);
        rhs = prev;
        needs_assign = false;
      }
      break;
    }
    case AssignOp::QUESTION_EQ: {
      Var* prev = LookupVarInCurrentScope(lhs);
      if (!prev->IsDefined()) {
        rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
      } else {
        rhs = prev;
        needs_assign = false;
      }
      break;
    }
  }

  LOG("Assign: %s=%s", lhs.c_str(), rhs->DebugString().c_str());
  if (needs_assign) {
    return rhs;
  }
  return NULL;
}

void Evaluator::EvalAssign(const AssignAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;
  Symbol lhs = Intern(*ast->lhs->Eval(this));
  if (lhs.empty())
    Error("*** empty variable name.");
  Var* rhs = EvalRHS(lhs, ast->rhs, ast->orig_rhs, ast->op,
                     ast->directive == AssignDirective::OVERRIDE);
  if (rhs)
    vars_->Assign(lhs, rhs);
}

void Evaluator::EvalRule(const RuleAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;

  shared_ptr<string> expr = ast->expr->Eval(this);
  // See semicolon.mk.
  if (expr->find_first_not_of(" \t\n;") == string::npos)
    return;

  Rule* rule;
  RuleVarAssignment rule_var;
  ParseRule(loc_, *expr, ast->term, &rule, &rule_var);

  if (rule) {
    if (ast->term == ';') {
      rule->cmds.push_back(ast->after_term);
    }

    LOG("Rule: %s", rule->DebugString().c_str());
    rules_.push_back(shared_ptr<Rule>(rule));
    last_rule_ = rule;
    return;
  }

  for (Symbol output : rule_var.outputs) {
    auto p = rule_vars_.emplace(output, nullptr);
    if (p.second) {
      p.first->second = new Vars;
    }

    Value* rhs = ast->after_term;
    if (!rule_var.rhs.empty()) {
      Value* lit = NewLiteral(rule_var.rhs);
      if (rhs) {
        // TODO: We always insert two whitespaces around the
        // terminator. Preserve whitespaces properly.
        if (ast->term == ';') {
          rhs = NewExpr3(lit, NewLiteral(STRING_PIECE(" ; ")), rhs);
        } else {
          rhs = NewExpr3(lit, NewLiteral(STRING_PIECE(" = ")), rhs);
        }
      } else {
        rhs = lit;
      }
    }

    current_scope_ = p.first->second;
    Symbol lhs = Intern(rule_var.lhs);
    Var* rhs_var = EvalRHS(lhs, rhs, STRING_PIECE("*TODO*"), rule_var.op);
    if (rhs_var)
      current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
    current_scope_ = NULL;
  }
}

void Evaluator::EvalCommand(const CommandAST* ast) {
  loc_ = ast->loc();

  if (!last_rule_) {
    // TODO:
    ERROR("TODO");
  }

  last_rule_->cmds.push_back(ast->expr);
  if (last_rule_->cmd_lineno == 0)
    last_rule_->cmd_lineno = ast->loc().lineno;
  LOG("Command: %s", ast->expr->DebugString().c_str());
}

void Evaluator::EvalIf(const IfAST* ast) {
  loc_ = ast->loc();

  bool is_true;
  switch (ast->op) {
    case CondOp::IFDEF:
    case CondOp::IFNDEF: {
      Symbol lhs = Intern(*ast->lhs->Eval(this));
      Var* v = LookupVarInCurrentScope(lhs);
      shared_ptr<string> s = v->Eval(this);
      is_true = (s->empty() == (ast->op == CondOp::IFNDEF));
      break;
    }
    case CondOp::IFEQ:
    case CondOp::IFNEQ: {
      shared_ptr<string> lhs = ast->lhs->Eval(this);
      shared_ptr<string> rhs = ast->rhs->Eval(this);
      is_true = ((*lhs == *rhs) == (ast->op == CondOp::IFEQ));
      break;
    }
    default:
      CHECK(false);
  }

  const vector<AST*>* asts;
  if (is_true) {
    asts = &ast->true_asts;
  } else {
    asts = &ast->false_asts;
  }
  for (AST* a : *asts) {
    LOG("%s", a->DebugString().c_str());
    a->Eval(this);
  }
}

void Evaluator::DoInclude(const char* fname, bool should_exist) {
  if (!should_exist && g_ignore_optional_include_pattern &&
      Pattern(g_ignore_optional_include_pattern).Match(fname)) {
    return;
  }

  Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
  if (!mk->Exists()) {
    if (should_exist) {
      Error(StringPrintf(
          "%s: %s\n"
          "NOTE: kati does not support generating missing makefiles",
          fname, strerror(errno)));
    }
    return;
  }

  Var* var_list = LookupVar(Intern("MAKEFILE_LIST"));
  var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str()));
  for (AST* ast : mk->asts()) {
    LOG("%s", ast->DebugString().c_str());
    ast->Eval(this);
  }
}

void Evaluator::EvalInclude(const IncludeAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;

  shared_ptr<string> pats = ast->expr->Eval(this);
  for (StringPiece pat : WordScanner(*pats)) {
    ScopedTerminator st(pat);
    if (pat.find_first_of("?*[") != string::npos) {
      glob_t gl;
      glob(pat.data(), GLOB_NOSORT, NULL, &gl);
      for (size_t i = 0; i < gl.gl_pathc; i++) {
        DoInclude(gl.gl_pathv[i], ast->should_exist);
      }
      globfree(&gl);
    } else {
      DoInclude(pat.data(), ast->should_exist);
    }
  }
}

void Evaluator::EvalExport(const ExportAST* ast) {
  loc_ = ast->loc();
  last_rule_ = NULL;

  shared_ptr<string> exports = ast->expr->Eval(this);
  for (StringPiece tok : WordScanner(*exports)) {
    size_t equal_index = tok.find('=');
    if (equal_index == string::npos) {
      exports_[Intern(tok)] = ast->is_export;
    } else if (equal_index == 0 ||
               (equal_index == 1 &&
                (tok[0] == ':' || tok[0] == '?' || tok[0] == '+'))) {
      // Do not export tokens after an assignment.
      break;
    } else {
      StringPiece lhs, rhs;
      AssignOp op;
      ParseAssignStatement(tok, equal_index, &lhs, &rhs, &op);
      exports_[Intern(lhs)] = ast->is_export;
    }
  }
}

Var* Evaluator::LookupVar(Symbol name) {
  if (current_scope_) {
    Var* v = current_scope_->Lookup(name);
    if (v->IsDefined())
      return v;
  }
  Var* v = vars_->Lookup(name);
  if (v->IsDefined())
    return v;
  return in_vars_->Lookup(name);
}

Var* Evaluator::LookupVarInCurrentScope(Symbol name) {
  if (current_scope_) {
    return current_scope_->Lookup(name);
  }
  Var* v = vars_->Lookup(name);
  if (v->IsDefined())
    return v;
  return in_vars_->Lookup(name);
}

void Evaluator::Error(const string& msg) {
  ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
}
<|endoftext|>


<commit_before>//===--- GlobalObjects.cpp - Statically-initialized objects ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  Objects that are allocated at global scope instead of on the heap,
//  and statically initialized to avoid synchronization costs, are
//  defined here.
//
//===----------------------------------------------------------------------===//

#include "../SwiftShims/GlobalObjects.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Debug.h"
#include <stdlib.h>
#include <random>

namespace swift {
// FIXME(ABI)#76 : does this declaration need SWIFT_RUNTIME_STDLIB_INTERFACE?
// _direct type metadata for Swift._EmptyArrayStorage
SWIFT_RUNTIME_STDLIB_INTERFACE
ClassMetadata CLASS_METADATA_SYM(s18_EmptyArrayStorage);

// _direct type metadata for Swift._RawNativeDictionaryStorage
SWIFT_RUNTIME_STDLIB_INTERFACE
ClassMetadata CLASS_METADATA_SYM(s27_RawNativeDictionaryStorage);

// _direct type metadata for Swift._RawNativeSetStorage
SWIFT_RUNTIME_STDLIB_INTERFACE
ClassMetadata CLASS_METADATA_SYM(s20_RawNativeSetStorage);
} // namespace swift

swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
  // HeapObject header;
  {
    &swift::CLASS_METADATA_SYM(s18_EmptyArrayStorage), // isa pointer
  },

  // _SwiftArrayBodyStorage body;
  {
    0, // int count;
    1  // unsigned int _capacityAndFlags; 1 means elementTypeIsBridgedVerbatim
  }
};

swift::_SwiftEmptyDictionaryStorage swift::_swiftEmptyDictionaryStorage = {
  // HeapObject header;
  {
    &swift::CLASS_METADATA_SYM(s27_RawNativeDictionaryStorage), // isa pointer
  },

  // _SwiftDictionaryBodyStorage body;
  {
    // We set the capacity to 1 so that there's an empty hole to search.
    // Any insertion will lead to a real storage being allocated, because
    // Dictionary guarantees there's always another empty hole after insertion.
    1, // int capacity;
    0, // int count;

    // _SwiftUnsafeBitMap initializedEntries
    {
      &swift::_swiftEmptyDictionaryStorage.entries, // unsigned int* values;
      1 // int bitCount; (1 so there's something for iterators to read)
    },

    (void*)1, // void* keys; (non-null garbage)
    (void*)1  // void* values; (non-null garbage)
  },

  0 // int entries; (zero'd bits)
};

swift::_SwiftEmptySetStorage swift::_swiftEmptySetStorage = {
  // HeapObject header;
  {
    &swift::CLASS_METADATA_SYM(s20_RawNativeSetStorage), // isa pointer
  },

  // _SwiftDictionaryBodyStorage body;
  {
    // We set the capacity to 1 so that there's an empty hole to search.
    // Any insertion will lead to a real storage being allocated, because
    // Dictionary guarantees there's always another empty hole after insertion.
    1, // int capacity;
    0, // int count;

    // _SwiftUnsafeBitMap initializedEntries
    {
      &swift::_swiftEmptySetStorage.entries, // unsigned int* values;
      1 // int bitCount; (1 so there's something for iterators to read)
    },

    (void*)1 // void* keys; (non-null garbage)
  },

  0 // int entries; (zero'd bits)
};

static __swift_uint64_t randomUInt64() {
  std::random_device randomDevice;
  std::mt19937_64 twisterEngine(randomDevice());
  std::uniform_int_distribution<__swift_uint64_t> distribution;
  return distribution(twisterEngine);
}

SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_BEGIN
swift::_SwiftHashingSecretKey swift::_swift_stdlib_Hashing_secretKey = {
  randomUInt64(), randomUInt64()
};
SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END

__swift_uint64_t swift::_swift_stdlib_HashingDetail_fixedSeedOverride = 0;

SWIFT_RUNTIME_STDLIB_INTERFACE
void swift::_swift_instantiateInertHeapObject(void *address,
                                              const HeapMetadata *metadata) {
  ::new (address) HeapObject{metadata};
}

namespace llvm { namespace hashing { namespace detail {
  // An extern variable expected by LLVM's hashing templates. We don't link any
  // LLVM libs into the runtime, so define this here.
  size_t fixed_seed_override = 0;
} // namespace detail
} // namespace hashing
} // namespace llvm
<commit_msg>Mark the runtime's reimplementation of llvm::hashing::detail::fixed_seed_override as weak in case it is staticly linked into an app that includes a real definition from LLVM.<commit_after>//===--- GlobalObjects.cpp - Statically-initialized objects ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  Objects that are allocated at global scope instead of on the heap,
//  and statically initialized to avoid synchronization costs, are
//  defined here.
//
//===----------------------------------------------------------------------===//

#include "../SwiftShims/GlobalObjects.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Debug.h"
#include <stdlib.h>
#include <random>

namespace swift {
// FIXME(ABI)#76 : does this declaration need SWIFT_RUNTIME_STDLIB_INTERFACE?
// _direct type metadata for Swift._EmptyArrayStorage
SWIFT_RUNTIME_STDLIB_INTERFACE
ClassMetadata CLASS_METADATA_SYM(s18_EmptyArrayStorage);

// _direct type metadata for Swift._RawNativeDictionaryStorage
SWIFT_RUNTIME_STDLIB_INTERFACE
ClassMetadata CLASS_METADATA_SYM(s27_RawNativeDictionaryStorage);

// _direct type metadata for Swift._RawNativeSetStorage
SWIFT_RUNTIME_STDLIB_INTERFACE
ClassMetadata CLASS_METADATA_SYM(s20_RawNativeSetStorage);
} // namespace swift

swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
  // HeapObject header;
  {
    &swift::CLASS_METADATA_SYM(s18_EmptyArrayStorage), // isa pointer
  },

  // _SwiftArrayBodyStorage body;
  {
    0, // int count;
    1  // unsigned int _capacityAndFlags; 1 means elementTypeIsBridgedVerbatim
  }
};

swift::_SwiftEmptyDictionaryStorage swift::_swiftEmptyDictionaryStorage = {
  // HeapObject header;
  {
    &swift::CLASS_METADATA_SYM(s27_RawNativeDictionaryStorage), // isa pointer
  },

  // _SwiftDictionaryBodyStorage body;
  {
    // We set the capacity to 1 so that there's an empty hole to search.
    // Any insertion will lead to a real storage being allocated, because
    // Dictionary guarantees there's always another empty hole after insertion.
    1, // int capacity;
    0, // int count;

    // _SwiftUnsafeBitMap initializedEntries
    {
      &swift::_swiftEmptyDictionaryStorage.entries, // unsigned int* values;
      1 // int bitCount; (1 so there's something for iterators to read)
    },

    (void*)1, // void* keys; (non-null garbage)
    (void*)1  // void* values; (non-null garbage)
  },

  0 // int entries; (zero'd bits)
};

swift::_SwiftEmptySetStorage swift::_swiftEmptySetStorage = {
  // HeapObject header;
  {
    &swift::CLASS_METADATA_SYM(s20_RawNativeSetStorage), // isa pointer
  },

  // _SwiftDictionaryBodyStorage body;
  {
    // We set the capacity to 1 so that there's an empty hole to search.
    // Any insertion will lead to a real storage being allocated, because
    // Dictionary guarantees there's always another empty hole after insertion.
    1, // int capacity;
    0, // int count;

    // _SwiftUnsafeBitMap initializedEntries
    {
      &swift::_swiftEmptySetStorage.entries, // unsigned int* values;
      1 // int bitCount; (1 so there's something for iterators to read)
    },

    (void*)1 // void* keys; (non-null garbage)
  },

  0 // int entries; (zero'd bits)
};

static __swift_uint64_t randomUInt64() {
  std::random_device randomDevice;
  std::mt19937_64 twisterEngine(randomDevice());
  std::uniform_int_distribution<__swift_uint64_t> distribution;
  return distribution(twisterEngine);
}

SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_BEGIN
swift::_SwiftHashingSecretKey swift::_swift_stdlib_Hashing_secretKey = {
  randomUInt64(), randomUInt64()
};
SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END

__swift_uint64_t swift::_swift_stdlib_HashingDetail_fixedSeedOverride = 0;

SWIFT_RUNTIME_STDLIB_INTERFACE
void swift::_swift_instantiateInertHeapObject(void *address,
                                              const HeapMetadata *metadata) {
  ::new (address) HeapObject{metadata};
}

namespace llvm { namespace hashing { namespace detail {
  // An extern variable expected by LLVM's hashing templates. We don't link any
  // LLVM libs into the runtime, so define it as a weak symbol.
  //
  // Systems that compile this code into a dynamic library will do so with
  // hidden visibility, making this all internal to the dynamic library.
  // Systems that statically link the Swift runtime into applications (e.g. on
  // Linux) need this to handle the case when the app already uses LLVM.
  size_t LLVM_ATTRIBUTE_WEAK fixed_seed_override = 0;
} // namespace detail
} // namespace hashing
} // namespace llvm
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AccessibleEmptyEditSource.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:36:55 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

//------------------------------------------------------------------------
//
// Global header
//
//------------------------------------------------------------------------

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

#ifndef _MyEDITDATA_HXX
#include <svx/editdata.hxx>
#endif

#ifndef _OUTLINER_HXX
#include <svx/outliner.hxx>
#endif

#ifndef _SVDMODEL_HXX
#include <svx/svdmodel.hxx>
#endif

#ifndef _SVDOBJ_HXX
#include <svx/svdobj.hxx>
#endif

//------------------------------------------------------------------------
//
// Project-local header
//
//------------------------------------------------------------------------

#include "AccessibleEmptyEditSource.hxx"
#include <svx/unoshtxt.hxx>

namespace accessibility
{

    /** This class simply wraps a SvxTextEditSource, forwarding all
        methods except the GetBroadcaster() call
     */
    class AccessibleProxyEditSource_Impl : public SvxEditSource
    {
    public:
        /** Construct AccessibleEmptyEditSource_Impl

            @param rBrdCast

            Proxy broadcaster to allow seamless flipping of edit source implementations. ProxyEditSource and EmptyEditSource
         */
        AccessibleProxyEditSource_Impl( SdrObject&      rObj,
                                        SdrView&        rView,
                                        const Window&   rViewWindow );
        ~AccessibleProxyEditSource_Impl();

        // from the SvxEditSource interface
        SvxTextForwarder*       GetTextForwarder();
        SvxViewForwarder*       GetViewForwarder();
        SvxEditViewForwarder*   GetEditViewForwarder( sal_Bool bCreate = sal_False );

        SvxEditSource*          Clone() const;

        void                    UpdateData();

        SfxBroadcaster&         GetBroadcaster() const;

    private:
        SvxTextEditSource       maEditSource;

    };

    /** Dummy class, faking exactly one empty paragraph for EditEngine accessibility
     */
    class AccessibleEmptyEditSource_Impl : public SvxEditSource, public SvxViewForwarder, public SvxTextForwarder, public SfxBroadcaster
    {
    public:

        AccessibleEmptyEditSource_Impl() {}
        ~AccessibleEmptyEditSource_Impl() {}

        // from the SfxListener interface
        void                    Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

        // SvxEditSource
        SvxTextForwarder*       GetTextForwarder() { return this; }
        SvxViewForwarder*       GetViewForwarder() { return this; }
        SvxEditSource*          Clone() const { return NULL; }
        void                    UpdateData() {}
        SfxBroadcaster&         GetBroadcaster() const { return *(const_cast<AccessibleEmptyEditSource_Impl*>(this)); }

        // SvxTextForwarder
        USHORT          GetParagraphCount() const { return 1; }
        USHORT          GetTextLen( USHORT /*nParagraph*/ ) const { return 0; }
        String          GetText( const ESelection& /*rSel*/ ) const { return String(); }
        SfxItemSet      GetAttribs( const ESelection& /*rSel*/, BOOL /*bOnlyHardAttrib*/ = 0 ) const
        {
            String aDummyStr(RTL_CONSTASCII_USTRINGPARAM("Dummy"));
            SfxItemPool aPool(aDummyStr,0,0,NULL);
            return SfxItemSet(aPool);
        }
        SfxItemSet      GetParaAttribs( USHORT /*nPara*/ ) const { return GetAttribs(ESelection()); }
        void            SetParaAttribs( USHORT /*nPara*/, const SfxItemSet& /*rSet*/ ) {}
        void            GetPortions( USHORT /*nPara*/, SvUShorts& /*rList*/ ) const {}

        USHORT          GetItemState( const ESelection& /*rSel*/, USHORT /*nWhich*/ ) const { return 0; }
        USHORT          GetItemState( USHORT /*nPara*/, USHORT /*nWhich*/ ) const { return 0; }

        SfxItemPool*    GetPool() const { return NULL; }

        void            QuickInsertText( const String& /*rText*/, const ESelection& /*rSel*/ ) {}
        void            QuickInsertField( const SvxFieldItem& /*rFld*/, const ESelection& /*rSel*/ ) {}
        void            QuickSetAttribs( const SfxItemSet& /*rSet*/, const ESelection& /*rSel*/ ) {}
        void            QuickInsertLineBreak( const ESelection& /*rSel*/ ) {}

        XubString       CalcFieldValue( const SvxFieldItem& /*rField*/, USHORT /*nPara*/, USHORT /*nPos*/, Color*& /*rpTxtColor*/, Color*& /*rpFldColor*/ )
        {
            return  XubString();
        }
        BOOL            IsValid() const { return sal_True; }

        void            SetNotifyHdl( const Link& ) {}
        LanguageType    GetLanguage( USHORT, USHORT ) const { return LANGUAGE_DONTKNOW; }
        USHORT          GetFieldCount( USHORT ) const { return 0; }
        EFieldInfo      GetFieldInfo( USHORT, USHORT ) const { return EFieldInfo(); }
        EBulletInfo     GetBulletInfo( USHORT ) const { return EBulletInfo(); }
        Rectangle       GetCharBounds( USHORT, USHORT ) const { return Rectangle(); }
        Rectangle       GetParaBounds( USHORT ) const { return Rectangle(); }
        MapMode         GetMapMode() const { return MapMode(); }
        OutputDevice*   GetRefDevice() const { return NULL; }
        sal_Bool        GetIndexAtPoint( const Point&, USHORT&, USHORT& ) const { return sal_False; }
        sal_Bool        GetWordIndices( USHORT, USHORT, USHORT&, USHORT& ) const { return sal_False; }
        sal_Bool        GetAttributeRun( USHORT&, USHORT&, USHORT, USHORT ) const { return sal_False; }
        USHORT          GetLineCount( USHORT nPara ) const { return nPara == 0 ? 1 : 0; }
        USHORT          GetLineLen( USHORT, USHORT ) const { return 0; }

        // the following two methods would, strictly speaking, require
        // a switch to a real EditSource, too. Fortunately, the
        // AccessibleEditableTextPara implementation currently always
        // calls GetEditViewForwarder(true) before doing
        // changes. Thus, we rely on this behabviour here (problem
        // when that changes: via accessibility API, it would no
        // longer be possible to enter text in previously empty
        // shapes).
        sal_Bool        Delete( const ESelection& ) { return sal_False; }
        sal_Bool        InsertText( const String&, const ESelection& ) { return sal_False; }
        sal_Bool        QuickFormatDoc( BOOL ) { return sal_True; }
        USHORT          GetDepth( USHORT ) const { return 0; }
        sal_Bool        SetDepth( USHORT, USHORT ) { return 0; }

        Rectangle       GetVisArea() const { return Rectangle(); }
        Point           LogicToPixel( const Point& rPoint, const MapMode& /*rMapMode*/ ) const { return rPoint; }
        Point           PixelToLogic( const Point& rPoint, const MapMode& /*rMapMode*/ ) const { return rPoint; }

    };

    // -------------------------------------------------------------------------
    // Implementing AccessibleProxyEditSource_Impl
    // -------------------------------------------------------------------------

    AccessibleProxyEditSource_Impl::AccessibleProxyEditSource_Impl( SdrObject&      rObj,
                                                                    SdrView&        rView,
                                                                    const Window&   rViewWindow ) :
        maEditSource( rObj, rView, rViewWindow )
    {
    }

    AccessibleProxyEditSource_Impl::~AccessibleProxyEditSource_Impl()
    {
    }

    SvxTextForwarder* AccessibleProxyEditSource_Impl::GetTextForwarder()
    {
        return maEditSource.GetTextForwarder();
    }

    SvxViewForwarder* AccessibleProxyEditSource_Impl::GetViewForwarder()
    {
        return maEditSource.GetViewForwarder();
    }

    SvxEditViewForwarder* AccessibleProxyEditSource_Impl::GetEditViewForwarder( sal_Bool bCreate )
    {
        return maEditSource.GetEditViewForwarder( bCreate );
    }

    SvxEditSource* AccessibleProxyEditSource_Impl::Clone() const
    {
        return maEditSource.Clone();
    }

    void AccessibleProxyEditSource_Impl::UpdateData()
    {
        maEditSource.UpdateData();
    }

    SfxBroadcaster& AccessibleProxyEditSource_Impl::GetBroadcaster() const
    {
        return maEditSource.GetBroadcaster();
    }

    // -------------------------------------------------------------------------
    // Implementing AccessibleEmptyEditSource
    // -------------------------------------------------------------------------

    AccessibleEmptyEditSource::AccessibleEmptyEditSource( SdrObject&    rObj,
                                                          SdrView&      rView,
                                                          const Window& rViewWindow ) :
        mpEditSource( new AccessibleEmptyEditSource_Impl() ),
        mrObj(rObj),
        mrView(rView),
        mrViewWindow(rViewWindow),
        mbEditSourceEmpty( true )
    {
        if( mrObj.GetModel() )
            StartListening( *mrObj.GetModel() );
    }

    AccessibleEmptyEditSource::~AccessibleEmptyEditSource()
    {
        if( !mbEditSourceEmpty )
        {
            // deregister as listener
            if( mpEditSource.get() )
                EndListening( mpEditSource->GetBroadcaster() );
        }
        else
        {
            if( mrObj.GetModel() )
                EndListening( *mrObj.GetModel() );
        }
    }

    SvxTextForwarder* AccessibleEmptyEditSource::GetTextForwarder()
    {
        if( !mpEditSource.get() )
            return NULL;

        return mpEditSource->GetTextForwarder();
    }

    SvxViewForwarder* AccessibleEmptyEditSource::GetViewForwarder()
    {
        if( !mpEditSource.get() )
            return NULL;

        return mpEditSource->GetViewForwarder();
    }

    void AccessibleEmptyEditSource::Switch2ProxyEditSource()
    {
        // deregister EmptyEditSource model listener
        if( mrObj.GetModel() )
            EndListening( *mrObj.GetModel() );

        ::std::auto_ptr< SvxEditSource > pProxySource( new AccessibleProxyEditSource_Impl(mrObj, mrView, mrViewWindow) );
        ::std::auto_ptr< SvxEditSource > tmp = mpEditSource;
        mpEditSource = pProxySource;
        pProxySource = tmp;

        // register as listener
        StartListening( mpEditSource->GetBroadcaster() );

        // we've irrevocably a full EditSource now.
        mbEditSourceEmpty = false;
    }

    SvxEditViewForwarder* AccessibleEmptyEditSource::GetEditViewForwarder( sal_Bool bCreate )
    {
        if( !mpEditSource.get() )
            return NULL;

        // switch edit source, if not yet done
        if( mbEditSourceEmpty && bCreate )
            Switch2ProxyEditSource();

        return mpEditSource->GetEditViewForwarder( bCreate );
    }

    SvxEditSource* AccessibleEmptyEditSource::Clone() const
    {
        if( !mpEditSource.get() )
            return NULL;

        return mpEditSource->Clone();
    }

    void AccessibleEmptyEditSource::UpdateData()
    {
        if( mpEditSource.get() )
            mpEditSource->UpdateData();
    }

    SfxBroadcaster& AccessibleEmptyEditSource::GetBroadcaster() const
    {
        return *(const_cast<AccessibleEmptyEditSource*>(this));
    }

    void AccessibleEmptyEditSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
    {
        const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );

        if( pSdrHint && pSdrHint->GetKind() == HINT_BEGEDIT &&
            &mrObj == pSdrHint->GetObject() && mpEditSource.get() )
        {
            // switch edit source, if not yet done. This is necessary
            // to become a full-fledged EditSource the first time a
            // user start entering text in a previously empty object.
            if( mbEditSourceEmpty )
                Switch2ProxyEditSource();
        }

        // forward messages
        Broadcast( rHint );
    }

} // end of namespace accessibility

//------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS os100 (1.7.18); FILE MERGED 2007/07/10 14:07:56 os 1.7.18.1: #i65257# text append interfaces<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AccessibleEmptyEditSource.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2007-07-18 13:06:39 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

//------------------------------------------------------------------------
//
// Global header
//
//------------------------------------------------------------------------

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

#ifndef _MyEDITDATA_HXX
#include <svx/editdata.hxx>
#endif

#ifndef _OUTLINER_HXX
#include <svx/outliner.hxx>
#endif

#ifndef _SVDMODEL_HXX
#include <svx/svdmodel.hxx>
#endif

#ifndef _SVDOBJ_HXX
#include <svx/svdobj.hxx>
#endif

//------------------------------------------------------------------------
//
// Project-local header
//
//------------------------------------------------------------------------

#include "AccessibleEmptyEditSource.hxx"
#include <svx/unoshtxt.hxx>

namespace accessibility
{

    /** This class simply wraps a SvxTextEditSource, forwarding all
        methods except the GetBroadcaster() call
     */
    class AccessibleProxyEditSource_Impl : public SvxEditSource
    {
    public:
        /** Construct AccessibleEmptyEditSource_Impl

            @param rBrdCast

            Proxy broadcaster to allow seamless flipping of edit source implementations. ProxyEditSource and EmptyEditSource
         */
        AccessibleProxyEditSource_Impl( SdrObject&      rObj,
                                        SdrView&        rView,
                                        const Window&   rViewWindow );
        ~AccessibleProxyEditSource_Impl();

        // from the SvxEditSource interface
        SvxTextForwarder*       GetTextForwarder();
        SvxViewForwarder*       GetViewForwarder();
        SvxEditViewForwarder*   GetEditViewForwarder( sal_Bool bCreate = sal_False );

        SvxEditSource*          Clone() const;

        void                    UpdateData();

        SfxBroadcaster&         GetBroadcaster() const;

    private:
        SvxTextEditSource       maEditSource;

    };

    /** Dummy class, faking exactly one empty paragraph for EditEngine accessibility
     */
    class AccessibleEmptyEditSource_Impl : public SvxEditSource, public SvxViewForwarder, public SvxTextForwarder, public SfxBroadcaster
    {
    public:

        AccessibleEmptyEditSource_Impl() {}
        ~AccessibleEmptyEditSource_Impl() {}

        // from the SfxListener interface
        void                    Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

        // SvxEditSource
        SvxTextForwarder*       GetTextForwarder() { return this; }
        SvxViewForwarder*       GetViewForwarder() { return this; }
        SvxEditSource*          Clone() const { return NULL; }
        void                    UpdateData() {}
        SfxBroadcaster&         GetBroadcaster() const { return *(const_cast<AccessibleEmptyEditSource_Impl*>(this)); }

        // SvxTextForwarder
        USHORT          GetParagraphCount() const { return 1; }
        USHORT          GetTextLen( USHORT /*nParagraph*/ ) const { return 0; }
        String          GetText( const ESelection& /*rSel*/ ) const { return String(); }
        SfxItemSet      GetAttribs( const ESelection& /*rSel*/, BOOL /*bOnlyHardAttrib*/ = 0 ) const
        {
            String aDummyStr(RTL_CONSTASCII_USTRINGPARAM("Dummy"));
            SfxItemPool aPool(aDummyStr,0,0,NULL);
            return SfxItemSet(aPool);
        }
        SfxItemSet      GetParaAttribs( USHORT /*nPara*/ ) const { return GetAttribs(ESelection()); }
        void            SetParaAttribs( USHORT /*nPara*/, const SfxItemSet& /*rSet*/ ) {}
        void            GetPortions( USHORT /*nPara*/, SvUShorts& /*rList*/ ) const {}

        USHORT          GetItemState( const ESelection& /*rSel*/, USHORT /*nWhich*/ ) const { return 0; }
        USHORT          GetItemState( USHORT /*nPara*/, USHORT /*nWhich*/ ) const { return 0; }

        SfxItemPool*    GetPool() const { return NULL; }

        void            QuickInsertText( const String& /*rText*/, const ESelection& /*rSel*/ ) {}
        void            QuickInsertField( const SvxFieldItem& /*rFld*/, const ESelection& /*rSel*/ ) {}
        void            QuickSetAttribs( const SfxItemSet& /*rSet*/, const ESelection& /*rSel*/ ) {}
        void            QuickInsertLineBreak( const ESelection& /*rSel*/ ) {}

        const SfxItemSet * GetEmptyItemSetPtr() { return 0; }

        void        AppendParagraph() {}
        xub_StrLen  AppendTextPortion( USHORT /*nPara*/, const String & /*rText*/, const SfxItemSet & /*rSet*/ ) { return 0; }

        XubString       CalcFieldValue( const SvxFieldItem& /*rField*/, USHORT /*nPara*/, USHORT /*nPos*/, Color*& /*rpTxtColor*/, Color*& /*rpFldColor*/ )
        {
            return  XubString();
        }
        BOOL            IsValid() const { return sal_True; }

        void            SetNotifyHdl( const Link& ) {}
        LanguageType    GetLanguage( USHORT, USHORT ) const { return LANGUAGE_DONTKNOW; }
        USHORT          GetFieldCount( USHORT ) const { return 0; }
        EFieldInfo      GetFieldInfo( USHORT, USHORT ) const { return EFieldInfo(); }
        EBulletInfo     GetBulletInfo( USHORT ) const { return EBulletInfo(); }
        Rectangle       GetCharBounds( USHORT, USHORT ) const { return Rectangle(); }
        Rectangle       GetParaBounds( USHORT ) const { return Rectangle(); }
        MapMode         GetMapMode() const { return MapMode(); }
        OutputDevice*   GetRefDevice() const { return NULL; }
        sal_Bool        GetIndexAtPoint( const Point&, USHORT&, USHORT& ) const { return sal_False; }
        sal_Bool        GetWordIndices( USHORT, USHORT, USHORT&, USHORT& ) const { return sal_False; }
        sal_Bool        GetAttributeRun( USHORT&, USHORT&, USHORT, USHORT ) const { return sal_False; }
        USHORT          GetLineCount( USHORT nPara ) const { return nPara == 0 ? 1 : 0; }
        USHORT          GetLineLen( USHORT, USHORT ) const { return 0; }

        // the following two methods would, strictly speaking, require
        // a switch to a real EditSource, too. Fortunately, the
        // AccessibleEditableTextPara implementation currently always
        // calls GetEditViewForwarder(true) before doing
        // changes. Thus, we rely on this behabviour here (problem
        // when that changes: via accessibility API, it would no
        // longer be possible to enter text in previously empty
        // shapes).
        sal_Bool        Delete( const ESelection& ) { return sal_False; }
        sal_Bool        InsertText( const String&, const ESelection& ) { return sal_False; }
        sal_Bool        QuickFormatDoc( BOOL ) { return sal_True; }
        USHORT          GetDepth( USHORT ) const { return 0; }
        sal_Bool        SetDepth( USHORT, USHORT ) { return 0; }

        Rectangle       GetVisArea() const { return Rectangle(); }
        Point           LogicToPixel( const Point& rPoint, const MapMode& /*rMapMode*/ ) const { return rPoint; }
        Point           PixelToLogic( const Point& rPoint, const MapMode& /*rMapMode*/ ) const { return rPoint; }

    };

    // -------------------------------------------------------------------------
    // Implementing AccessibleProxyEditSource_Impl
    // -------------------------------------------------------------------------

    AccessibleProxyEditSource_Impl::AccessibleProxyEditSource_Impl( SdrObject&      rObj,
                                                                    SdrView&        rView,
                                                                    const Window&   rViewWindow ) :
        maEditSource( rObj, rView, rViewWindow )
    {
    }

    AccessibleProxyEditSource_Impl::~AccessibleProxyEditSource_Impl()
    {
    }

    SvxTextForwarder* AccessibleProxyEditSource_Impl::GetTextForwarder()
    {
        return maEditSource.GetTextForwarder();
    }

    SvxViewForwarder* AccessibleProxyEditSource_Impl::GetViewForwarder()
    {
        return maEditSource.GetViewForwarder();
    }

    SvxEditViewForwarder* AccessibleProxyEditSource_Impl::GetEditViewForwarder( sal_Bool bCreate )
    {
        return maEditSource.GetEditViewForwarder( bCreate );
    }

    SvxEditSource* AccessibleProxyEditSource_Impl::Clone() const
    {
        return maEditSource.Clone();
    }

    void AccessibleProxyEditSource_Impl::UpdateData()
    {
        maEditSource.UpdateData();
    }

    SfxBroadcaster& AccessibleProxyEditSource_Impl::GetBroadcaster() const
    {
        return maEditSource.GetBroadcaster();
    }

    // -------------------------------------------------------------------------
    // Implementing AccessibleEmptyEditSource
    // -------------------------------------------------------------------------

    AccessibleEmptyEditSource::AccessibleEmptyEditSource( SdrObject&    rObj,
                                                          SdrView&      rView,
                                                          const Window& rViewWindow ) :
        mpEditSource( new AccessibleEmptyEditSource_Impl() ),
        mrObj(rObj),
        mrView(rView),
        mrViewWindow(rViewWindow),
        mbEditSourceEmpty( true )
    {
        if( mrObj.GetModel() )
            StartListening( *mrObj.GetModel() );
    }

    AccessibleEmptyEditSource::~AccessibleEmptyEditSource()
    {
        if( !mbEditSourceEmpty )
        {
            // deregister as listener
            if( mpEditSource.get() )
                EndListening( mpEditSource->GetBroadcaster() );
        }
        else
        {
            if( mrObj.GetModel() )
                EndListening( *mrObj.GetModel() );
        }
    }

    SvxTextForwarder* AccessibleEmptyEditSource::GetTextForwarder()
    {
        if( !mpEditSource.get() )
            return NULL;

        return mpEditSource->GetTextForwarder();
    }

    SvxViewForwarder* AccessibleEmptyEditSource::GetViewForwarder()
    {
        if( !mpEditSource.get() )
            return NULL;

        return mpEditSource->GetViewForwarder();
    }

    void AccessibleEmptyEditSource::Switch2ProxyEditSource()
    {
        // deregister EmptyEditSource model listener
        if( mrObj.GetModel() )
            EndListening( *mrObj.GetModel() );

        ::std::auto_ptr< SvxEditSource > pProxySource( new AccessibleProxyEditSource_Impl(mrObj, mrView, mrViewWindow) );
        ::std::auto_ptr< SvxEditSource > tmp = mpEditSource;
        mpEditSource = pProxySource;
        pProxySource = tmp;

        // register as listener
        StartListening( mpEditSource->GetBroadcaster() );

        // we've irrevocably a full EditSource now.
        mbEditSourceEmpty = false;
    }

    SvxEditViewForwarder* AccessibleEmptyEditSource::GetEditViewForwarder( sal_Bool bCreate )
    {
        if( !mpEditSource.get() )
            return NULL;

        // switch edit source, if not yet done
        if( mbEditSourceEmpty && bCreate )
            Switch2ProxyEditSource();

        return mpEditSource->GetEditViewForwarder( bCreate );
    }

    SvxEditSource* AccessibleEmptyEditSource::Clone() const
    {
        if( !mpEditSource.get() )
            return NULL;

        return mpEditSource->Clone();
    }

    void AccessibleEmptyEditSource::UpdateData()
    {
        if( mpEditSource.get() )
            mpEditSource->UpdateData();
    }

    SfxBroadcaster& AccessibleEmptyEditSource::GetBroadcaster() const
    {
        return *(const_cast<AccessibleEmptyEditSource*>(this));
    }

    void AccessibleEmptyEditSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
    {
        const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );

        if( pSdrHint && pSdrHint->GetKind() == HINT_BEGEDIT &&
            &mrObj == pSdrHint->GetObject() && mpEditSource.get() )
        {
            // switch edit source, if not yet done. This is necessary
            // to become a full-fledged EditSource the first time a
            // user start entering text in a previously empty object.
            if( mbEditSourceEmpty )
                Switch2ProxyEditSource();
        }

        // forward messages
        Broadcast( rHint );
    }

} // end of namespace accessibility

//------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*
 * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: eval.cc,v 1.25 2001/12/29 00:43:55 steve Exp $"
#endif

# include "config.h"

# include  <iostream>

# include  "PExpr.h"
# include  "netlist.h"
# include  "compiler.h"

verinum* PExpr::eval_const(const Design*, const NetScope*) const
{
      return 0;
}

verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
{
      verinum*l = left_->eval_const(des, scope);
      if (l == 0) return 0;
      verinum*r = right_->eval_const(des, scope);
      if (r == 0) {
	    delete l;
	    return 0;
      }
      verinum*res;

      switch (op_) {
	  case '+': {
		assert(l->is_defined());
		assert(r->is_defined());
		long lv = l->as_long();
		long rv = r->as_long();
		res = new verinum(lv+rv, l->len());
		break;
	  }
	  case '-': {
		assert(l->is_defined());
		assert(r->is_defined());
		long lv = l->as_long();
		long rv = r->as_long();
		res = new verinum(lv-rv, l->len());
		break;
	  }
	  case '*': {
		assert(l->is_defined());
		assert(r->is_defined());
		long lv = l->as_long();
		long rv = r->as_long();
		res = new verinum(lv * rv, l->len());
		break;
	  }
	  case '/': {
		assert(l->is_defined());
		assert(r->is_defined());
		long lv = l->as_long();
		long rv = r->as_long();
		res = new verinum(lv / rv, l->len());
		break;
	  }
	  case '%': {
		assert(l->is_defined());
		assert(r->is_defined());
		long lv = l->as_long();
		long rv = r->as_long();
		res = new verinum(lv % rv, l->len());
		break;
	  }
	  case 'l': { // left shift (<<)
		assert(r->is_defined());
		unsigned long rv = r->as_ulong();
		res = new verinum(verinum::V0, l->len());
		if (rv < res->len()) {
		      unsigned cnt = res->len() - rv;
		      for (unsigned idx = 0 ;  idx < cnt ;  idx += 1)
			    res->set(idx+rv, l->get(idx));
		}
		break;
	  }
	  case 'r': { // right shift (>>)
		assert(r->is_defined());
		unsigned long rv = r->as_ulong();
		res = new verinum(verinum::V0, l->len());
		if (rv < res->len()) {
		      unsigned cnt = res->len() - rv;
		      for (unsigned idx = 0 ;  idx < cnt ;  idx += 1)
			    res->set(idx, l->get(idx+rv));
		}
		break;
	  }

	  default:
	    delete l;
	    delete r;
	    return 0;
      }

      delete l;
      delete r;
      return res;
}

/*
 * Evaluate an identifier as a constant expression. This is only
 * possible if the identifier is that of a parameter.
 */
verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
{
      assert(scope);
      const NetExpr*expr = des->find_parameter(scope, path_);

      if (expr == 0)
	    return 0;

      assert(msb_ == 0);

      if (dynamic_cast<const NetEParam*>(expr)) {
	    cerr << get_line() << ": sorry: I cannot evaluate ``" <<
		  path_ << "'' in this scope: " << scope->name() << endl;
	    return 0;
      }

      const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
      assert(eval);
      return new verinum(eval->value());
}

verinum* PEFNumber::eval_const(const Design*, const NetScope*) const
{
      long val = value_->as_long();
      return new verinum(val);
}

verinum* PENumber::eval_const(const Design*, const NetScope*) const
{
      return new verinum(value());
}

verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
{
      verinum*test = expr_->eval_const(des, scope);
      if (test == 0)
	    return 0;

      verinum::V bit = test->get(0);
      delete test;
      switch (bit) {
	  case verinum::V0:
	    return fal_->eval_const(des, scope);
	  case verinum::V1:
	    return tru_->eval_const(des, scope);
	  default:
	    return 0;
	      // XXXX It is possible to handle this case if both fal_
	      // and tru_ are constant. Someday...
      }
}

verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
{
      verinum*val = expr_->eval_const(des, scope);
      if (val == 0)
	    return 0;

      switch (op_) {
	  case '+':
	    return val;

	  case '-': {
		  /* We need to expand the value a bit if we are
		     taking the 2's complement so that we are
		     guaranteed to not overflow. */
		verinum tmp (0UL, val->len()+1);
		for (unsigned idx = 0 ;  idx < val->len() ;  idx += 1)
		      tmp.set(idx, val->get(idx));

		*val = v_not(tmp) + verinum(verinum::V1, 1);
		val->has_sign(true);
		return val;
	  }

      }
	    delete val;
      return 0;
}

/*
 * $Log: eval.cc,v $
 * Revision 1.25  2001/12/29 00:43:55  steve
 *  Evaluate constant right shifts.
 *
 * Revision 1.24  2001/12/03 04:47:15  steve
 *  Parser and pform use hierarchical names as hname_t
 *  objects instead of encoded strings.
 *
 * Revision 1.23  2001/11/07 04:01:59  steve
 *  eval_const uses scope instead of a string path.
 *
 * Revision 1.22  2001/11/06 06:11:55  steve
 *  Support more real arithmetic in delay constants.
 *
 * Revision 1.21  2001/07/25 03:10:49  steve
 *  Create a config.h.in file to hold all the config
 *  junk, and support gcc 3.0. (Stephan Boettcher)
 *
 * Revision 1.20  2001/02/09 02:49:59  steve
 *  Be more clear about scope of failure.
 *
 * Revision 1.19  2001/01/27 05:41:48  steve
 *  Fix sign extension of evaluated constants. (PR#91)
 *
 * Revision 1.18  2001/01/14 23:04:56  steve
 *  Generalize the evaluation of floating point delays, and
 *  get it working with delay assignment statements.
 *
 *  Allow parameters to be referenced by hierarchical name.
 *
 * Revision 1.17  2001/01/04 04:47:51  steve
 *  Add support for << is signal indices.
 *
 * Revision 1.16  2000/12/10 22:01:36  steve
 *  Support decimal constants in behavioral delays.
 *
 * Revision 1.15  2000/09/07 22:38:13  steve
 *  Support unary + and - in constants.
 */

<commit_msg> constant eval of arithmetic with x and z.<commit_after>/*
 * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: eval.cc,v 1.26 2001/12/29 22:10:10 steve Exp $"
#endif

# include "config.h"

# include  <iostream>

# include  "PExpr.h"
# include  "netlist.h"
# include  "compiler.h"

verinum* PExpr::eval_const(const Design*, const NetScope*) const
{
      return 0;
}

verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
{
      verinum*l = left_->eval_const(des, scope);
      if (l == 0) return 0;
      verinum*r = right_->eval_const(des, scope);
      if (r == 0) {
	    delete l;
	    return 0;
      }
      verinum*res;

      switch (op_) {
	  case '+': {
		if (l->is_defined() && r->is_defined()) {
		      long lv = l->as_long();
		      long rv = r->as_long();
		      res = new verinum(lv+rv, l->len());
		} else {
		      res = new verinum(verinum::Vx, l->len());
		}
		break;
	  }
	  case '-': {
		if (l->is_defined() && r->is_defined()) {
		      long lv = l->as_long();
		      long rv = r->as_long();
		      res = new verinum(lv-rv, l->len());
		} else {
		      res = new verinum(verinum::Vx, l->len());
		}
		break;
	  }
	  case '*': {
		if (l->is_defined() && r->is_defined()) {
		      long lv = l->as_long();
		      long rv = r->as_long();
		      res = new verinum(lv * rv, l->len());
		} else {
		      res = new verinum(verinum::Vx, l->len());
		}
		break;
	  }
	  case '/': {
		if (l->is_defined() && r->is_defined()) {
		      long lv = l->as_long();
		      long rv = r->as_long();
		      res = new verinum(lv / rv, l->len());
		} else {
		      res = new verinum(verinum::Vx, l->len());
		}
		break;
	  }
	  case '%': {
		if (l->is_defined() && r->is_defined()) {
		      long lv = l->as_long();
		      long rv = r->as_long();
		      res = new verinum(lv % rv, l->len());
		} else {
		      res = new verinum(verinum::Vx, l->len());
		}
		break;
	  }
	  case 'l': { // left shift (<<)
		assert(r->is_defined());
		unsigned long rv = r->as_ulong();
		res = new verinum(verinum::V0, l->len());
		if (rv < res->len()) {
		      unsigned cnt = res->len() - rv;
		      for (unsigned idx = 0 ;  idx < cnt ;  idx += 1)
			    res->set(idx+rv, l->get(idx));
		}
		break;
	  }
	  case 'r': { // right shift (>>)
		assert(r->is_defined());
		unsigned long rv = r->as_ulong();
		res = new verinum(verinum::V0, l->len());
		if (rv < res->len()) {
		      unsigned cnt = res->len() - rv;
		      for (unsigned idx = 0 ;  idx < cnt ;  idx += 1)
			    res->set(idx, l->get(idx+rv));
		}
		break;
	  }

	  default:
	    delete l;
	    delete r;
	    return 0;
      }

      delete l;
      delete r;
      return res;
}

/*
 * Evaluate an identifier as a constant expression. This is only
 * possible if the identifier is that of a parameter.
 */
verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
{
      assert(scope);
      const NetExpr*expr = des->find_parameter(scope, path_);

      if (expr == 0)
	    return 0;

      assert(msb_ == 0);

      if (dynamic_cast<const NetEParam*>(expr)) {
	    cerr << get_line() << ": sorry: I cannot evaluate ``" <<
		  path_ << "'' in this scope: " << scope->name() << endl;
	    return 0;
      }

      const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
      assert(eval);
      return new verinum(eval->value());
}

verinum* PEFNumber::eval_const(const Design*, const NetScope*) const
{
      long val = value_->as_long();
      return new verinum(val);
}

verinum* PENumber::eval_const(const Design*, const NetScope*) const
{
      return new verinum(value());
}

verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
{
      verinum*test = expr_->eval_const(des, scope);
      if (test == 0)
	    return 0;

      verinum::V bit = test->get(0);
      delete test;
      switch (bit) {
	  case verinum::V0:
	    return fal_->eval_const(des, scope);
	  case verinum::V1:
	    return tru_->eval_const(des, scope);
	  default:
	    return 0;
	      // XXXX It is possible to handle this case if both fal_
	      // and tru_ are constant. Someday...
      }
}

verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
{
      verinum*val = expr_->eval_const(des, scope);
      if (val == 0)
	    return 0;

      switch (op_) {
	  case '+':
	    return val;

	  case '-': {
		  /* We need to expand the value a bit if we are
		     taking the 2's complement so that we are
		     guaranteed to not overflow. */
		verinum tmp (0UL, val->len()+1);
		for (unsigned idx = 0 ;  idx < val->len() ;  idx += 1)
		      tmp.set(idx, val->get(idx));

		*val = v_not(tmp) + verinum(verinum::V1, 1);
		val->has_sign(true);
		return val;
	  }

      }
	    delete val;
      return 0;
}

/*
 * $Log: eval.cc,v $
 * Revision 1.26  2001/12/29 22:10:10  steve
 *  constant eval of arithmetic with x and z.
 *
 * Revision 1.25  2001/12/29 00:43:55  steve
 *  Evaluate constant right shifts.
 *
 * Revision 1.24  2001/12/03 04:47:15  steve
 *  Parser and pform use hierarchical names as hname_t
 *  objects instead of encoded strings.
 *
 * Revision 1.23  2001/11/07 04:01:59  steve
 *  eval_const uses scope instead of a string path.
 *
 * Revision 1.22  2001/11/06 06:11:55  steve
 *  Support more real arithmetic in delay constants.
 *
 * Revision 1.21  2001/07/25 03:10:49  steve
 *  Create a config.h.in file to hold all the config
 *  junk, and support gcc 3.0. (Stephan Boettcher)
 *
 * Revision 1.20  2001/02/09 02:49:59  steve
 *  Be more clear about scope of failure.
 *
 * Revision 1.19  2001/01/27 05:41:48  steve
 *  Fix sign extension of evaluated constants. (PR#91)
 *
 * Revision 1.18  2001/01/14 23:04:56  steve
 *  Generalize the evaluation of floating point delays, and
 *  get it working with delay assignment statements.
 *
 *  Allow parameters to be referenced by hierarchical name.
 *
 * Revision 1.17  2001/01/04 04:47:51  steve
 *  Add support for << is signal indices.
 *
 * Revision 1.16  2000/12/10 22:01:36  steve
 *  Support decimal constants in behavioral delays.
 *
 * Revision 1.15  2000/09/07 22:38:13  steve
 *  Support unary + and - in constants.
 */

<|endoftext|>


<commit_before><commit_msg>Take SolarMutex when pushing app events that need a VclPtr.<commit_after><|endoftext|>