<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"

#include <stdint.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/poll.h>

#include "base/eintr_wrapper.h"
#include "base/process_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/pickle.h"
#include "base/string_util.h"
#include "base/unix_domain_socket_posix.h"
#include "chrome/common/sandbox_methods_linux.h"
#include "webkit/api/public/gtk/WebFontInfo.h"
#include "webkit/api/public/WebData.h"
#include "webkit/api/public/WebKit.h"
#include "webkit/api/public/WebKitClient.h"

#include "SkFontHost_fontconfig_direct.h"
#include "SkFontHost_fontconfig_ipc.h"

using WebKit::WebClipboard;
using WebKit::WebData;
using WebKit::WebFontInfo;
using WebKit::WebKitClient;
using WebKit::WebMimeRegistry;
using WebKit::WebPluginInfo;
using WebKit::WebPluginListBuilder;
using WebKit::WebSandboxSupport;
using WebKit::WebString;
using WebKit::WebThemeEngine;
using WebKit::WebUChar;
using WebKit::WebURL;
using WebKit::WebURLLoader;

// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC

// BEWARE: code in this file run across *processes* (not just threads).

// This code runs in a child process
class SandboxIPCProcess : public WebKitClient {
 public:
  // lifeline_fd: this is the read end of a pipe which the browser process
  //   holds the other end of. If the browser process dies, it's descriptors are
  //   closed and we will noticed an EOF on the pipe. That's our signal to exit.
  // browser_socket: the 'browser's end of the sandbox IPC socketpair. From the
  //   point of view of the renderer's, it's talking to the browser but this
  //   object actually services the requests.
  SandboxIPCProcess(int lifeline_fd, int browser_socket)
      : lifeline_fd_(lifeline_fd),
        browser_socket_(browser_socket),
        font_config_(new FontConfigDirect()) {
    WebKit::initialize(this);

    base::InjectiveMultimap multimap;
    multimap.push_back(base::InjectionArc(0, lifeline_fd, false));
    multimap.push_back(base::InjectionArc(0, browser_socket, false));

    base::CloseSuperfluousFds(multimap);
  }

  void Run() {
    struct pollfd pfds[2];
    pfds[0].fd = lifeline_fd_;
    pfds[0].events = POLLIN;
    pfds[1].fd = browser_socket_;
    pfds[1].events = POLLIN;

    bool failed_polls = 0;
    for (;;) {
      const int r = HANDLE_EINTR(poll(pfds, 2, -1));
      if (r < 1) {
        LOG(WARNING) << "poll errno:" << errno;
        if (failed_polls++ == 3) {
          LOG(FATAL) << "poll failing. Sandbox host aborting.";
          return;
        }
        continue;
      }

      failed_polls = 0;

      if (pfds[0].revents) {
        // our parent died so we should too.
        _exit(0);
      }

      if (pfds[1].revents) {
        HandleRequestFromRenderer(browser_socket_);
      }
    }
  }

  // ---------------------------------------------------------------------------
  // WebKitClient impl...

  virtual WebClipboard* clipboard() { return NULL; }
  virtual WebMimeRegistry* mimeRegistry() { return NULL; }
  virtual WebSandboxSupport* sandboxSupport() { return NULL; }
  virtual WebThemeEngine* themeEngine() { return NULL; }

  virtual unsigned long long visitedLinkHash(const char*, size_t) { return 0; }
  virtual bool isLinkVisited(unsigned long long) { return false; }

  virtual void setCookies(const WebURL&, const WebURL&, const WebString&) { }
  virtual WebString cookies(const WebURL&, const WebURL&) { return WebString(); }

  virtual void prefetchHostName(const WebString&) { }

  virtual bool getFileSize(const WebString& path, long long& result) {
    return false;
  }

  virtual WebURLLoader* createURLLoader() { return NULL; }

  virtual void getPluginList(bool refresh, WebPluginListBuilder*) { }

  virtual void decrementStatsCounter(const char*) { }
  virtual void incrementStatsCounter(const char*) { }

  virtual void traceEventBegin(const char* name, void*, const char*) { }
  virtual void traceEventEnd(const char* name, void*, const char*) { }

  virtual WebData loadResource(const char*) { return WebData(); }

  virtual void suddenTerminationChanged(bool) { }

  virtual WebString defaultLocale() { return WebString(); }

  virtual double currentTime() { return 0; }

  virtual void setSharedTimerFiredFunction(void (*)()) { }
  virtual void setSharedTimerFireTime(double) { }
  virtual void stopSharedTimer() { }

  virtual void callOnMainThread(void (*)()) { }

 private:
  // ---------------------------------------------------------------------------
  // Requests from the renderer...

  void HandleRequestFromRenderer(int fd) {
    std::vector<int> fds;
    static const unsigned kMaxMessageLength = 2048;
    char buf[kMaxMessageLength];
    const ssize_t len = base::RecvMsg(fd, buf, sizeof(buf), &fds);
    if (len == -1)
      return;
    if (fds.size() == 0)
      return;

    Pickle pickle(buf, len);
    void* iter = NULL;

    int kind;
    if (!pickle.ReadInt(&iter, &kind))
      goto error;

    if (kind == FontConfigIPC::METHOD_MATCH) {
      HandleFontMatchRequest(fd, pickle, iter, fds);
    } else if (kind == FontConfigIPC::METHOD_OPEN) {
      HandleFontOpenRequest(fd, pickle, iter, fds);
    } else if (kind == LinuxSandbox::METHOD_GET_FONT_FAMILY_FOR_CHARS) {
      HandleGetFontFamilyForChars(fd, pickle, iter, fds);
    }

  error:
    for (std::vector<int>::const_iterator
         i = fds.begin(); i != fds.end(); ++i) {
      close(*i);
    }
  }

  void HandleFontMatchRequest(int fd, Pickle& pickle, void* iter,
                              std::vector<int>& fds) {
    bool fileid_valid;
    uint32_t fileid;
    bool is_bold, is_italic;
    std::string family;

    if (!pickle.ReadBool(&iter, &fileid_valid))
      return;
    if (fileid_valid) {
      if (!pickle.ReadUInt32(&iter, &fileid))
        return;
    }
    if (!pickle.ReadBool(&iter, &is_bold) ||
        !pickle.ReadBool(&iter, &is_italic) ||
        !pickle.ReadString(&iter, &family)) {
      return;
    }

    std::string result_family;
    unsigned result_fileid;

    const bool r = font_config_->Match(
        &result_family, &result_fileid, fileid_valid, fileid, family, &is_bold,
        &is_italic);

    Pickle reply;
    if (!r) {
      reply.WriteBool(false);
    } else {
      reply.WriteBool(true);
      reply.WriteUInt32(result_fileid);
      reply.WriteString(result_family);
      reply.WriteBool(is_bold);
      reply.WriteBool(is_italic);
    }
    SendRendererReply(fds, reply, -1);
  }

  void HandleFontOpenRequest(int fd, Pickle& pickle, void* iter,
                             std::vector<int>& fds) {
    uint32_t fileid;
    if (!pickle.ReadUInt32(&iter, &fileid))
      return;
    const int result_fd = font_config_->Open(fileid);

    Pickle reply;
    if (result_fd == -1) {
      reply.WriteBool(false);
    } else {
      reply.WriteBool(true);
    }

    SendRendererReply(fds, reply, result_fd);
  }

  void HandleGetFontFamilyForChars(int fd, Pickle& pickle, void* iter,
                                   std::vector<int>& fds) {
    // The other side of this call is
    // chrome/renderer/renderer_sandbox_support_linux.cc

    int num_chars;
    if (!pickle.ReadInt(&iter, &num_chars))
      return;

    // We don't want a corrupt renderer asking too much of us, it might
    // overflow later in the code.
    static const int kMaxChars = 4096;
    if (num_chars < 1 || num_chars > kMaxChars) {
      LOG(WARNING) << "HandleGetFontFamilyForChars: too many chars: "
                   << num_chars;
      return;
    }

    scoped_array<WebUChar> chars(new WebUChar[num_chars]);

    for (int i = 0; i < num_chars; ++i) {
      uint32_t c;
      if (!pickle.ReadUInt32(&iter, &c)) {
        return;
      }

      chars[i] = c;
    }

    const WebString family = WebFontInfo::familyForChars(chars.get(), num_chars);
    const std::string family_utf8 = UTF16ToUTF8(family);

    Pickle reply;
    reply.WriteString(family_utf8);
    SendRendererReply(fds, reply, -1);
  }

  void SendRendererReply(const std::vector<int>& fds, const Pickle& reply,
                         int reply_fd) {
    struct msghdr msg;
    memset(&msg, 0, sizeof(msg));
    struct iovec iov = {const_cast<void*>(reply.data()), reply.size()};
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    char control_buffer[CMSG_SPACE(sizeof(int))];

    if (reply_fd != -1) {
      struct cmsghdr *cmsg;

      msg.msg_control = control_buffer;
      msg.msg_controllen = sizeof(control_buffer);
      cmsg = CMSG_FIRSTHDR(&msg);
      cmsg->cmsg_level = SOL_SOCKET;
      cmsg->cmsg_type = SCM_RIGHTS;
      cmsg->cmsg_len = CMSG_LEN(sizeof(int));
      memcpy(CMSG_DATA(cmsg), &reply_fd, sizeof(int));
      msg.msg_controllen = cmsg->cmsg_len;
    }

    HANDLE_EINTR(sendmsg(fds[0], &msg, MSG_DONTWAIT));
  }

  // ---------------------------------------------------------------------------

  const int lifeline_fd_;
  const int browser_socket_;
  FontConfigDirect* const font_config_;
};

// -----------------------------------------------------------------------------

// Runs on the main thread at startup.
RenderSandboxHostLinux::RenderSandboxHostLinux() {
  int fds[2];
  CHECK(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0);

  renderer_socket_ = fds[0];
  const int browser_socket = fds[1];

  int pipefds[2];
  CHECK(0 == pipe(pipefds));
  const int child_lifeline_fd = pipefds[0];
  childs_lifeline_fd_ = pipefds[1];

  const pid_t child = fork();
  if (child == 0) {
    SandboxIPCProcess handler(child_lifeline_fd, browser_socket);
    handler.Run();
    _exit(0);
  }
}

RenderSandboxHostLinux::~RenderSandboxHostLinux() {
  HANDLE_EINTR(close(renderer_socket_));
  HANDLE_EINTR(close(childs_lifeline_fd_));
}
<commit_msg>Linux: don't leak file descriptors in the sandbox host.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"

#include <stdint.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/poll.h>

#include "base/eintr_wrapper.h"
#include "base/process_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/pickle.h"
#include "base/string_util.h"
#include "base/unix_domain_socket_posix.h"
#include "chrome/common/sandbox_methods_linux.h"
#include "webkit/api/public/gtk/WebFontInfo.h"
#include "webkit/api/public/WebData.h"
#include "webkit/api/public/WebKit.h"
#include "webkit/api/public/WebKitClient.h"

#include "SkFontHost_fontconfig_direct.h"
#include "SkFontHost_fontconfig_ipc.h"

using WebKit::WebClipboard;
using WebKit::WebData;
using WebKit::WebFontInfo;
using WebKit::WebKitClient;
using WebKit::WebMimeRegistry;
using WebKit::WebPluginInfo;
using WebKit::WebPluginListBuilder;
using WebKit::WebSandboxSupport;
using WebKit::WebString;
using WebKit::WebThemeEngine;
using WebKit::WebUChar;
using WebKit::WebURL;
using WebKit::WebURLLoader;

// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC

// BEWARE: code in this file run across *processes* (not just threads).

// This code runs in a child process
class SandboxIPCProcess : public WebKitClient {
 public:
  // lifeline_fd: this is the read end of a pipe which the browser process
  //   holds the other end of. If the browser process dies, it's descriptors are
  //   closed and we will noticed an EOF on the pipe. That's our signal to exit.
  // browser_socket: the 'browser's end of the sandbox IPC socketpair. From the
  //   point of view of the renderer's, it's talking to the browser but this
  //   object actually services the requests.
  SandboxIPCProcess(int lifeline_fd, int browser_socket)
      : lifeline_fd_(lifeline_fd),
        browser_socket_(browser_socket),
        font_config_(new FontConfigDirect()) {
    WebKit::initialize(this);

    base::InjectiveMultimap multimap;
    multimap.push_back(base::InjectionArc(0, lifeline_fd, false));
    multimap.push_back(base::InjectionArc(0, browser_socket, false));

    base::CloseSuperfluousFds(multimap);
  }

  void Run() {
    struct pollfd pfds[2];
    pfds[0].fd = lifeline_fd_;
    pfds[0].events = POLLIN;
    pfds[1].fd = browser_socket_;
    pfds[1].events = POLLIN;

    bool failed_polls = 0;
    for (;;) {
      const int r = HANDLE_EINTR(poll(pfds, 2, -1));
      if (r < 1) {
        LOG(WARNING) << "poll errno:" << errno;
        if (failed_polls++ == 3) {
          LOG(FATAL) << "poll failing. Sandbox host aborting.";
          return;
        }
        continue;
      }

      failed_polls = 0;

      if (pfds[0].revents) {
        // our parent died so we should too.
        _exit(0);
      }

      if (pfds[1].revents) {
        HandleRequestFromRenderer(browser_socket_);
      }
    }
  }

  // ---------------------------------------------------------------------------
  // WebKitClient impl...

  virtual WebClipboard* clipboard() { return NULL; }
  virtual WebMimeRegistry* mimeRegistry() { return NULL; }
  virtual WebSandboxSupport* sandboxSupport() { return NULL; }
  virtual WebThemeEngine* themeEngine() { return NULL; }

  virtual unsigned long long visitedLinkHash(const char*, size_t) { return 0; }
  virtual bool isLinkVisited(unsigned long long) { return false; }

  virtual void setCookies(const WebURL&, const WebURL&, const WebString&) { }
  virtual WebString cookies(const WebURL&, const WebURL&) { return WebString(); }

  virtual void prefetchHostName(const WebString&) { }

  virtual bool getFileSize(const WebString& path, long long& result) {
    return false;
  }

  virtual WebURLLoader* createURLLoader() { return NULL; }

  virtual void getPluginList(bool refresh, WebPluginListBuilder*) { }

  virtual void decrementStatsCounter(const char*) { }
  virtual void incrementStatsCounter(const char*) { }

  virtual void traceEventBegin(const char* name, void*, const char*) { }
  virtual void traceEventEnd(const char* name, void*, const char*) { }

  virtual WebData loadResource(const char*) { return WebData(); }

  virtual void suddenTerminationChanged(bool) { }

  virtual WebString defaultLocale() { return WebString(); }

  virtual double currentTime() { return 0; }

  virtual void setSharedTimerFiredFunction(void (*)()) { }
  virtual void setSharedTimerFireTime(double) { }
  virtual void stopSharedTimer() { }

  virtual void callOnMainThread(void (*)()) { }

 private:
  // ---------------------------------------------------------------------------
  // Requests from the renderer...

  void HandleRequestFromRenderer(int fd) {
    std::vector<int> fds;
    static const unsigned kMaxMessageLength = 2048;
    char buf[kMaxMessageLength];
    const ssize_t len = base::RecvMsg(fd, buf, sizeof(buf), &fds);
    if (len == -1)
      return;
    if (fds.size() == 0)
      return;

    Pickle pickle(buf, len);
    void* iter = NULL;

    int kind;
    if (!pickle.ReadInt(&iter, &kind))
      goto error;

    if (kind == FontConfigIPC::METHOD_MATCH) {
      HandleFontMatchRequest(fd, pickle, iter, fds);
    } else if (kind == FontConfigIPC::METHOD_OPEN) {
      HandleFontOpenRequest(fd, pickle, iter, fds);
    } else if (kind == LinuxSandbox::METHOD_GET_FONT_FAMILY_FOR_CHARS) {
      HandleGetFontFamilyForChars(fd, pickle, iter, fds);
    }

  error:
    for (std::vector<int>::const_iterator
         i = fds.begin(); i != fds.end(); ++i) {
      close(*i);
    }
  }

  void HandleFontMatchRequest(int fd, Pickle& pickle, void* iter,
                              std::vector<int>& fds) {
    bool fileid_valid;
    uint32_t fileid;
    bool is_bold, is_italic;
    std::string family;

    if (!pickle.ReadBool(&iter, &fileid_valid))
      return;
    if (fileid_valid) {
      if (!pickle.ReadUInt32(&iter, &fileid))
        return;
    }
    if (!pickle.ReadBool(&iter, &is_bold) ||
        !pickle.ReadBool(&iter, &is_italic) ||
        !pickle.ReadString(&iter, &family)) {
      return;
    }

    std::string result_family;
    unsigned result_fileid;

    const bool r = font_config_->Match(
        &result_family, &result_fileid, fileid_valid, fileid, family, &is_bold,
        &is_italic);

    Pickle reply;
    if (!r) {
      reply.WriteBool(false);
    } else {
      reply.WriteBool(true);
      reply.WriteUInt32(result_fileid);
      reply.WriteString(result_family);
      reply.WriteBool(is_bold);
      reply.WriteBool(is_italic);
    }
    SendRendererReply(fds, reply, -1);
  }

  void HandleFontOpenRequest(int fd, Pickle& pickle, void* iter,
                             std::vector<int>& fds) {
    uint32_t fileid;
    if (!pickle.ReadUInt32(&iter, &fileid))
      return;
    const int result_fd = font_config_->Open(fileid);

    Pickle reply;
    if (result_fd == -1) {
      reply.WriteBool(false);
    } else {
      reply.WriteBool(true);
    }

    SendRendererReply(fds, reply, result_fd);

    if (result_fd >= 0)
      close(result_fd);
  }

  void HandleGetFontFamilyForChars(int fd, Pickle& pickle, void* iter,
                                   std::vector<int>& fds) {
    // The other side of this call is
    // chrome/renderer/renderer_sandbox_support_linux.cc

    int num_chars;
    if (!pickle.ReadInt(&iter, &num_chars))
      return;

    // We don't want a corrupt renderer asking too much of us, it might
    // overflow later in the code.
    static const int kMaxChars = 4096;
    if (num_chars < 1 || num_chars > kMaxChars) {
      LOG(WARNING) << "HandleGetFontFamilyForChars: too many chars: "
                   << num_chars;
      return;
    }

    scoped_array<WebUChar> chars(new WebUChar[num_chars]);

    for (int i = 0; i < num_chars; ++i) {
      uint32_t c;
      if (!pickle.ReadUInt32(&iter, &c)) {
        return;
      }

      chars[i] = c;
    }

    const WebString family = WebFontInfo::familyForChars(chars.get(), num_chars);
    const std::string family_utf8 = UTF16ToUTF8(family);

    Pickle reply;
    reply.WriteString(family_utf8);
    SendRendererReply(fds, reply, -1);
  }

  void SendRendererReply(const std::vector<int>& fds, const Pickle& reply,
                         int reply_fd) {
    struct msghdr msg;
    memset(&msg, 0, sizeof(msg));
    struct iovec iov = {const_cast<void*>(reply.data()), reply.size()};
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    char control_buffer[CMSG_SPACE(sizeof(int))];

    if (reply_fd != -1) {
      struct cmsghdr *cmsg;

      msg.msg_control = control_buffer;
      msg.msg_controllen = sizeof(control_buffer);
      cmsg = CMSG_FIRSTHDR(&msg);
      cmsg->cmsg_level = SOL_SOCKET;
      cmsg->cmsg_type = SCM_RIGHTS;
      cmsg->cmsg_len = CMSG_LEN(sizeof(int));
      memcpy(CMSG_DATA(cmsg), &reply_fd, sizeof(int));
      msg.msg_controllen = cmsg->cmsg_len;
    }

    HANDLE_EINTR(sendmsg(fds[0], &msg, MSG_DONTWAIT));
  }

  // ---------------------------------------------------------------------------

  const int lifeline_fd_;
  const int browser_socket_;
  FontConfigDirect* const font_config_;
};

// -----------------------------------------------------------------------------

// Runs on the main thread at startup.
RenderSandboxHostLinux::RenderSandboxHostLinux() {
  int fds[2];
  CHECK(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0);

  renderer_socket_ = fds[0];
  const int browser_socket = fds[1];

  int pipefds[2];
  CHECK(0 == pipe(pipefds));
  const int child_lifeline_fd = pipefds[0];
  childs_lifeline_fd_ = pipefds[1];

  const pid_t child = fork();
  if (child == 0) {
    SandboxIPCProcess handler(child_lifeline_fd, browser_socket);
    handler.Run();
    _exit(0);
  }
}

RenderSandboxHostLinux::~RenderSandboxHostLinux() {
  HANDLE_EINTR(close(renderer_socket_));
  HANDLE_EINTR(close(childs_lifeline_fd_));
}
<|endoftext|>


<commit_before>#include "disassembler.h"
#include "util.h"
#include "symtab.h"

#include <vector>
#include <cctype>

using namespace std;

enum ByteTypeGuess {
	UNINITIALIZED,
	UNKNOWN,
	CHAR_DATA,
	UNINITIALIZED_CHAR_DATA,
	WORD_DATA,
	UNINITIALIZED_WORD_DATA,
	CODE,
};

struct program {
	ByteTypeGuess byte_type_guess[65536];
	char memory[65536];
	bool is_labelled[65536];

	string name;
	string starting_address;
	int length_of_program;
	string first_executable_instruction;
	program() {
		for ( int i = 0 ; i < 65536 ; i++ ) {
			byte_type_guess[i] = UNINITIALIZED;
			memory[i] = 0;
			is_labelled[i] = false;
		}
		name = "";
		starting_address = "";
		length_of_program = 0;
		first_executable_instruction = "";
	}
};

bool read_record(ifstream &ifile, string &record);
void record_to_memory(const string record, program &p);
void analyze_code_data(program &p);
void write_assembly(const program &p, ofstream &ofile);

bool disassemble(ifstream &ifile, ofstream &ofile) {
	string record;
	program p;
	while ( read_record(ifile, record) ) {
		record_to_memory(record, p);
	}
	status("Done reading records");
	analyze_code_data(p);
	status("Done analyzing program for code and data");
	write_assembly(p, ofile);
	status("Done writing output file");
	return true;
}

string read_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	char t;
	for ( int col = col_begin ; col <= col_end ; col++ ) {
		t = ifile.get();
		if ( t == EOF || t == '\n' ) {
			string errstr;
			errstr += "Unexpected end of ";
			errstr += record_type;
			errstr += " record";
			fatal(errstr);
		}
		ret += t;
	}
	return ret;
}

string read_hex_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	ret = read_columns(ifile,col_begin,col_end,record_type);
	make_upper_case(ret);
	if ( !is_hex_string(ret) ) {
		string errstr;
		errstr += "Unexpected non-hexadecimal character found in ";
		errstr += record_type;
		errstr += " record";
		fatal(errstr);
	}
	return ret;
}

bool read_record(ifstream &ifile, string &record) {
	int temp_int;
	string temp_str;
	char t;

	do {
		t = ifile.get();
		if ( t == EOF ) {
			return false;
		}
	} while ( t == '\n' || t == ' ' );
	record = "";
	record += t;

	switch (t) {
		case 'H': // Header
			record += read_columns(ifile,2,7,'H');
			record += read_hex_columns(ifile,8,19,'H');
			break;
		case 'T': // Text
			record += read_hex_columns(ifile,2,7,'T');
			temp_str = read_hex_columns(ifile,8,9,'T');
			temp_int = hex2int(temp_str);
			record += temp_str;
			record +=  read_hex_columns(ifile,10,9+2*temp_int,'T');
			break;
		case 'E': // End
			record += read_hex_columns(ifile,2,7,'E');
			break;
		default:
			{
				string errstr = "Unknown record type ";
				errstr += t;
				fatal(errstr);
			}
	}
	return true;
}

void record_to_memory(const string record, program &p) {
	const char * c_record = record.c_str();
	switch (*c_record) {
		case 'H': // Header
			if ( p.name.length() != 0 ) {
				fatal("Multiple H records");
			}
			p.name = record.substr(1,6);
			p.starting_address = record.substr(7,6);
			p.length_of_program = hex2int(record.substr(13,6));
			break;
		case 'T': // Text
			{
				int text_start = hex2int(record.substr(1,6));
				int bit_length = hex2int(record.substr(7,2));
				for ( int i = 0 ; i < bit_length ; i++ ) {
					p.memory[i+text_start] = hex2int(record.substr(9+2*i,2));
					p.byte_type_guess[i+text_start] = UNKNOWN;
				}
			}
			break;
		case 'E': // End
			if ( p.first_executable_instruction.length() != 0 ) {
				fatal("Multiple E records");
			}
			p.first_executable_instruction = record.substr(1,6);
			break;
		default:
			{
				string errstr;
				errstr += "Unknown record type ";
				errstr += *c_record;
				fatal(errstr);
			}
	}
}

void mark_code_data(program &p, int location, ByteTypeGuess btg) {
	if ( location >= hex2int(p.starting_address) + p.length_of_program ) {
		return;
	}
	switch (btg) {
		case UNINITIALIZED:
		case UNKNOWN:
			break;
		case CHAR_DATA:
		case UNINITIALIZED_CHAR_DATA:
			{
				if ( p.byte_type_guess[location] != UNKNOWN &&
					 p.byte_type_guess[location] != UNINITIALIZED ) {
					break;
				}
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_CHAR_DATA;
				p.byte_type_guess[location] = btg;
				break;
			}
		case WORD_DATA:
		case UNINITIALIZED_WORD_DATA:
			{
				if ( p.byte_type_guess[location] != UNKNOWN &&
					 p.byte_type_guess[location] != UNINITIALIZED ) {
					break;
				}
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_WORD_DATA;
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;
				break;
			}
		case CODE:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED ) {
					fatal("Attempting to use uninitialized section as code");
				}
				if ( p.byte_type_guess[location] == CODE ) {
					break;
				}
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;

				string opcode_val = byte2hex(p.memory[location]);
				string opcode;
				string operand = byte2hex(p.memory[location+1])+byte2hex(p.memory[location+2]);
				operand = int2hex(hex2int(operand)&0x7FFF); // remove index flag
				if ( ! find_from_symtab(opcode,opcode_val) ) {
					string errstr;
					errstr += "Unknown opcode ";
					errstr += opcode_val;
					errstr += " at location ";
					errstr += int2hex(location);
					fatal(errstr);
				}

				if ( opcode == "ADD"  ||
					 opcode == "AND"  ||
					 opcode == "COMP" ||
					 opcode == "DIV"  ||
					 opcode == "LDA"  ||
					 opcode == "LDL"  ||
					 opcode == "LDX"  ||
					 opcode == "MUL"  ||
					 opcode == "OR"   ||
					 opcode == "STA"  ||
					 opcode == "STL"  ||
					 opcode == "STX"  ||
					 opcode == "SUB"  ||
					 opcode == "TIX" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),WORD_DATA);
				}

				if ( opcode == "LDCH" ||
					 opcode == "STCH" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CHAR_DATA);
				}

				if ( opcode == "J"    ||
					 opcode == "JEQ"  ||
					 opcode == "JGT"  ||
					 opcode == "JLT"  ||
					 opcode == "JSUB" ||
					 opcode == "RSUB" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CODE);
				}

				if ( opcode != "J" &&
					 opcode != "RSUB" ) {
					mark_code_data(p,location+3,btg);
				}

				break;
			}
	}
}

void analyze_code_data(program &p) {
	if ( p.name.length() == 0 ) {
		fatal("No Header record");
	}
	if ( p.first_executable_instruction.length() == 0 ) {
		fatal("No End record");
	}
	initialize_symtab();
	add_to_symtab("FIRST",p.first_executable_instruction);
	p.is_labelled[hex2int(p.first_executable_instruction)] = true;
	mark_code_data(p,hex2int(p.first_executable_instruction),CODE);
}

string asm_to_line(string label, string opcode, string operand, bool is_indexed) {
	const int labellength = 8;
	const int opcodelength = 6;
	string ret = "";
	ret += label + string(labellength-label.length(),' ');
	ret += opcode + string(opcodelength-opcode.length(),' ');
	ret += operand;
	if ( is_indexed ) {
		ret += ",X";
	}
	ret += '\n';
	return ret;
}

void write_assembly(const program &p, ofstream &ofile) {
	ofile << asm_to_line(p.name,"START",p.starting_address,false);
	int start_of_program = hex2int(p.starting_address);
	int end_of_program = start_of_program + p.length_of_program;
	for ( int locctr = start_of_program ; locctr < end_of_program ; ) {
		if ( p.byte_type_guess[locctr] == CODE ) {
			string opcode;
			if ( ! find_from_symtab(opcode,byte2hex(p.memory[locctr])) ) {
				string errstr;
				errstr += "Unknown opcode ";
				errstr += opcode;
				errstr += " at location ";
				errstr += int2hex(locctr);
				fatal(errstr);
			}
			string operand = byte2hex(p.memory[locctr+1])+byte2hex(p.memory[locctr+2]);
			bool is_indexed = (hex2int(operand)&0x8000);
			operand = int2hex(hex2int(operand)&0x7FFF); // remove index flag

			if ( opcode != "RD" &&
				 opcode != "TD" &&
				 opcode != "WD" &&
				 opcode != "RSUB" ) {
				if ( !find_from_symtab(operand,operand) ) {
					string errstr;
					errstr += "Label not created for operand ";
					errstr += operand;
					error(errstr);
				}
			}

			if ( opcode == "RSUB" ) {
				operand = "";
			}

			string label = "";
			if ( p.is_labelled[locctr] ) {
				if ( !find_from_symtab(label,int2hex(locctr)) ) {
					string errstr;
					errstr += "Label not created for location ";
					errstr += int2hex(locctr);
					error(errstr);
				}
			} // TODO: Refactor to prevent rewrite of code

			ofile << asm_to_line(label,opcode,operand,is_indexed);

			locctr += 3;
		} else if ( p.byte_type_guess[locctr] == CHAR_DATA ) {
			string label;
			if ( p.is_labelled[locctr] ) {
				if ( !find_from_symtab(label,int2hex(locctr)) ) {
					string errstr;
					errstr += "Label not created for location ";
					errstr += int2hex(locctr);
					error(errstr);
				}
			} // TODO: Refactor to prevent rewrite of code

			vector<char> byte_list;
			bool type_c = true;
			do {
				byte_list.push_back(p.memory[locctr]);
				if ( !isprint(p.memory[locctr]) ) {
					type_c = false;
				}
				locctr++;
			} while ( p.byte_type_guess[locctr] == CHAR_DATA && !p.is_labelled[locctr] );

			string opcode = "CHAR";
			bool is_indexed = false;
			string operand = "";

			operand += (type_c?"C":"X");
			operand += "'";
			for ( int i = 0 ; i < (int)byte_list.size() ; i++ ) {
				if ( type_c ) {
					operand += byte_list[i];
				} else {
					operand += byte2hex(byte_list[i]);
				}
			}
			operand += "'";

			ofile << asm_to_line(label,opcode,operand,is_indexed); // TODO: Refactor
		} else {
			// TODO
			locctr++; // temporarily
		}
	}
	ofile << asm_to_line("","END","FIRST",false);
}<commit_msg>Refactor<commit_after>#include "disassembler.h"
#include "util.h"
#include "symtab.h"

#include <vector>
#include <cctype>

using namespace std;

enum ByteTypeGuess {
	UNINITIALIZED,
	UNKNOWN,
	CHAR_DATA,
	UNINITIALIZED_CHAR_DATA,
	WORD_DATA,
	UNINITIALIZED_WORD_DATA,
	CODE,
};

struct program {
	ByteTypeGuess byte_type_guess[65536];
	char memory[65536];
	bool is_labelled[65536];

	string name;
	string starting_address;
	int length_of_program;
	string first_executable_instruction;
	program() {
		for ( int i = 0 ; i < 65536 ; i++ ) {
			byte_type_guess[i] = UNINITIALIZED;
			memory[i] = 0;
			is_labelled[i] = false;
		}
		name = "";
		starting_address = "";
		length_of_program = 0;
		first_executable_instruction = "";
	}
};

bool read_record(ifstream &ifile, string &record);
void record_to_memory(const string record, program &p);
void analyze_code_data(program &p);
void write_assembly(const program &p, ofstream &ofile);

bool disassemble(ifstream &ifile, ofstream &ofile) {
	string record;
	program p;
	while ( read_record(ifile, record) ) {
		record_to_memory(record, p);
	}
	status("Done reading records");
	analyze_code_data(p);
	status("Done analyzing program for code and data");
	write_assembly(p, ofile);
	status("Done writing output file");
	return true;
}

string read_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	char t;
	for ( int col = col_begin ; col <= col_end ; col++ ) {
		t = ifile.get();
		if ( t == EOF || t == '\n' ) {
			string errstr;
			errstr += "Unexpected end of ";
			errstr += record_type;
			errstr += " record";
			fatal(errstr);
		}
		ret += t;
	}
	return ret;
}

string read_hex_columns(ifstream &ifile, int col_begin, int col_end, char record_type = 'a') { // inclusive of both
	string ret;
	ret = read_columns(ifile,col_begin,col_end,record_type);
	make_upper_case(ret);
	if ( !is_hex_string(ret) ) {
		string errstr;
		errstr += "Unexpected non-hexadecimal character found in ";
		errstr += record_type;
		errstr += " record";
		fatal(errstr);
	}
	return ret;
}

bool read_record(ifstream &ifile, string &record) {
	int temp_int;
	string temp_str;
	char t;

	do {
		t = ifile.get();
		if ( t == EOF ) {
			return false;
		}
	} while ( t == '\n' || t == ' ' );
	record = "";
	record += t;

	switch (t) {
		case 'H': // Header
			record += read_columns(ifile,2,7,'H');
			record += read_hex_columns(ifile,8,19,'H');
			break;
		case 'T': // Text
			record += read_hex_columns(ifile,2,7,'T');
			temp_str = read_hex_columns(ifile,8,9,'T');
			temp_int = hex2int(temp_str);
			record += temp_str;
			record +=  read_hex_columns(ifile,10,9+2*temp_int,'T');
			break;
		case 'E': // End
			record += read_hex_columns(ifile,2,7,'E');
			break;
		default:
			{
				string errstr = "Unknown record type ";
				errstr += t;
				fatal(errstr);
			}
	}
	return true;
}

void record_to_memory(const string record, program &p) {
	const char * c_record = record.c_str();
	switch (*c_record) {
		case 'H': // Header
			if ( p.name.length() != 0 ) {
				fatal("Multiple H records");
			}
			p.name = record.substr(1,6);
			p.starting_address = record.substr(7,6);
			p.length_of_program = hex2int(record.substr(13,6));
			break;
		case 'T': // Text
			{
				int text_start = hex2int(record.substr(1,6));
				int bit_length = hex2int(record.substr(7,2));
				for ( int i = 0 ; i < bit_length ; i++ ) {
					p.memory[i+text_start] = hex2int(record.substr(9+2*i,2));
					p.byte_type_guess[i+text_start] = UNKNOWN;
				}
			}
			break;
		case 'E': // End
			if ( p.first_executable_instruction.length() != 0 ) {
				fatal("Multiple E records");
			}
			p.first_executable_instruction = record.substr(1,6);
			break;
		default:
			{
				string errstr;
				errstr += "Unknown record type ";
				errstr += *c_record;
				fatal(errstr);
			}
	}
}

void mark_code_data(program &p, int location, ByteTypeGuess btg) {
	if ( location >= hex2int(p.starting_address) + p.length_of_program ) {
		return;
	}
	switch (btg) {
		case UNINITIALIZED:
		case UNKNOWN:
			break;
		case CHAR_DATA:
		case UNINITIALIZED_CHAR_DATA:
			{
				if ( p.byte_type_guess[location] != UNKNOWN &&
					 p.byte_type_guess[location] != UNINITIALIZED ) {
					break;
				}
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_CHAR_DATA;
				p.byte_type_guess[location] = btg;
				break;
			}
		case WORD_DATA:
		case UNINITIALIZED_WORD_DATA:
			{
				if ( p.byte_type_guess[location] != UNKNOWN &&
					 p.byte_type_guess[location] != UNINITIALIZED ) {
					break;
				}
				if ( p.byte_type_guess[location] == UNINITIALIZED )
					btg = UNINITIALIZED_WORD_DATA;
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;
				break;
			}
		case CODE:
			{
				if ( p.byte_type_guess[location] == UNINITIALIZED ) {
					fatal("Attempting to use uninitialized section as code");
				}
				if ( p.byte_type_guess[location] == CODE ) {
					break;
				}
				p.byte_type_guess[location+0] = btg;
				p.byte_type_guess[location+1] = btg;
				p.byte_type_guess[location+2] = btg;

				string opcode_val = byte2hex(p.memory[location]);
				string opcode;
				string operand = byte2hex(p.memory[location+1])+byte2hex(p.memory[location+2]);
				operand = int2hex(hex2int(operand)&0x7FFF); // remove index flag
				if ( ! find_from_symtab(opcode,opcode_val) ) {
					string errstr;
					errstr += "Unknown opcode ";
					errstr += opcode_val;
					errstr += " at location ";
					errstr += int2hex(location);
					fatal(errstr);
				}

				if ( opcode == "ADD"  ||
					 opcode == "AND"  ||
					 opcode == "COMP" ||
					 opcode == "DIV"  ||
					 opcode == "LDA"  ||
					 opcode == "LDL"  ||
					 opcode == "LDX"  ||
					 opcode == "MUL"  ||
					 opcode == "OR"   ||
					 opcode == "STA"  ||
					 opcode == "STL"  ||
					 opcode == "STX"  ||
					 opcode == "SUB"  ||
					 opcode == "TIX" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),WORD_DATA);
				}

				if ( opcode == "LDCH" ||
					 opcode == "STCH" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CHAR_DATA);
				}

				if ( opcode == "J"    ||
					 opcode == "JEQ"  ||
					 opcode == "JGT"  ||
					 opcode == "JLT"  ||
					 opcode == "JSUB" ||
					 opcode == "RSUB" ) {
					give_label(operand);
					p.is_labelled[hex2int(operand)] = true;
					mark_code_data(p,hex2int(operand),CODE);
				}

				if ( opcode != "J" &&
					 opcode != "RSUB" ) {
					mark_code_data(p,location+3,btg);
				}

				break;
			}
	}
}

void analyze_code_data(program &p) {
	if ( p.name.length() == 0 ) {
		fatal("No Header record");
	}
	if ( p.first_executable_instruction.length() == 0 ) {
		fatal("No End record");
	}
	initialize_symtab();
	add_to_symtab("FIRST",p.first_executable_instruction);
	p.is_labelled[hex2int(p.first_executable_instruction)] = true;
	mark_code_data(p,hex2int(p.first_executable_instruction),CODE);
}

string asm_to_line(string label, string opcode, string operand, bool is_indexed) {
	const int labellength = 8;
	const int opcodelength = 6;
	string ret = "";
	ret += label + string(labellength-label.length(),' ');
	ret += opcode + string(opcodelength-opcode.length(),' ');
	ret += operand;
	if ( is_indexed ) {
		ret += ",X";
	}
	ret += '\n';
	return ret;
}

void write_assembly(const program &p, ofstream &ofile) {
	ofile << asm_to_line(p.name,"START",p.starting_address,false);
	int start_of_program = hex2int(p.starting_address);
	int end_of_program = start_of_program + p.length_of_program;

	for ( int locctr = start_of_program ; locctr < end_of_program ; ) {
		string label = "";
		string opcode = "";
		string operand = "";
		bool is_indexed = false;

		if ( p.byte_type_guess[locctr] == CODE ) {
			if ( ! find_from_symtab(opcode,byte2hex(p.memory[locctr])) ) {
				string errstr;
				errstr += "Unknown opcode ";
				errstr += opcode;
				errstr += " at location ";
				errstr += int2hex(locctr);
				fatal(errstr);
			}
			operand = byte2hex(p.memory[locctr+1])+byte2hex(p.memory[locctr+2]);
			is_indexed = (hex2int(operand)&0x8000);
			operand = int2hex(hex2int(operand)&0x7FFF); // remove index flag

			if ( opcode != "RD" &&
				 opcode != "TD" &&
				 opcode != "WD" &&
				 opcode != "RSUB" ) {
				if ( !find_from_symtab(operand,operand) ) {
					string errstr;
					errstr += "Label not created for operand ";
					errstr += operand;
					error(errstr);
				}
			}

			if ( opcode == "RSUB" ) {
				operand = "";
			}

			label = "";
			if ( p.is_labelled[locctr] ) {
				if ( !find_from_symtab(label,int2hex(locctr)) ) {
					string errstr;
					errstr += "Label not created for location ";
					errstr += int2hex(locctr);
					error(errstr);
				}
			} // TODO: Refactor to prevent rewrite of code

			locctr += 3;
		} else if ( p.byte_type_guess[locctr] == CHAR_DATA ) {
			if ( p.is_labelled[locctr] ) {
				if ( !find_from_symtab(label,int2hex(locctr)) ) {
					string errstr;
					errstr += "Label not created for location ";
					errstr += int2hex(locctr);
					error(errstr);
				}
			} // TODO: Refactor to prevent rewrite of code

			vector<char> byte_list;
			bool type_c = true;
			do {
				byte_list.push_back(p.memory[locctr]);
				if ( !isprint(p.memory[locctr]) ) {
					type_c = false;
				}
				locctr++;
			} while ( p.byte_type_guess[locctr] == CHAR_DATA && !p.is_labelled[locctr] );

			opcode = "CHAR";

			operand += (type_c?"C":"X");
			operand += "'";
			for ( int i = 0 ; i < (int)byte_list.size() ; i++ ) {
				if ( type_c ) {
					operand += byte_list[i];
				} else {
					operand += byte2hex(byte_list[i]);
				}
			}
			operand += "'";
		} else {
			// TODO
			locctr++; // temporarily
		}
		ofile << asm_to_line(label,opcode,operand,is_indexed);
	}
	ofile << asm_to_line("","END","FIRST",false);
}<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2015-2019 Ingo Wald                                            //
//                                                                          //
// 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.                                           //
// ======================================================================== //

// pbrt_parser
#include "pbrtParser/Scene.h"
// stl
#include <iostream>
#include <vector>
#include <sstream>
#include <assert.h>
// std
#include <set>
#include <stack>

namespace pbrt {
  namespace semantic {

    using std::cout;
    using std::endl;

    void usage(const std::string &msg)
    {
      if (msg != "") std::cerr << "Error: " << msg << std::endl << std::endl;
      std::cout << "./pbrt2pbf inFile.pbrt|inFile.pbf <args>" << std::endl;
      std::cout << std::endl;
      std::cout << "  -o <out.pbf>   : where to write the output to" << std::endl;
      std::cout << "                   (tris to quads, removing reundant fields, etc)" << std::endl;
    }

    inline bool endsWith(const std::string &s, const std::string &suffix)
    {
      return s.substr(s.size()-suffix.size(),suffix.size()) == suffix;
    }

    void pbrt2pbf(int ac, char **av)
    {
      std::string inFileName;
      std::string outFileName;
      for (int i=1;i<ac;i++) {
        const std::string arg = av[i];
        if (arg == "-o") {
          assert(i+1 < ac);
          outFileName = av[++i];
        } else if (arg[0] != '-') {
          inFileName = arg;
        } else {
          usage("invalid argument '"+arg+"'");
        }
      }

      if (outFileName == "")
        usage("no output file specified (-o <file.pbff>)");
      if (inFileName == "")
        usage("no input pbrt file specified");

      if (!endsWith(outFileName,".pbf")) {
        std::cout << "output file name missing '.pbsf' extension - adding it ..." << std::endl;
        outFileName = outFileName+".pbf";
      }

      std::cout << "-------------------------------------------------------" << std::endl;
      std::cout << "parsing pbrt file " << inFileName << std::endl;
      // try {
        Scene::SP scene = importPBRT(inFileName);
        std::cout << "\033[1;32m done importing scene.\033[0m" << std::endl;
        std::cout << "writing to binary file " << outFileName << std::endl;
        scene->saveTo(outFileName);
        std::cout << "\033[1;32m => yay! writing successful...\033[0m" << std::endl;
      // } catch (std::runtime_error &e) {
      //   cout << "\033[1;31mError in parsing: " << e.what() << "\033[0m\n";
      //   throw e;
      // }
    }

    extern "C" int main(int ac, char **av)
    {
      pbrt2pbf(ac,av);
      return 0;
    }

  } // ::pbrt::semantic
} // ::pbrt
<commit_msg>usage() exit in pbrt2pbf now properly exits after error message<commit_after>// ======================================================================== //
// Copyright 2015-2019 Ingo Wald                                            //
//                                                                          //
// 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.                                           //
// ======================================================================== //

// pbrt_parser
#include "pbrtParser/Scene.h"
// stl
#include <iostream>
#include <vector>
#include <sstream>
#include <assert.h>
// std
#include <set>
#include <stack>

namespace pbrt {
  namespace semantic {

    using std::cout;
    using std::endl;

    void usage(const std::string &msg)
    {
      if (msg != "") std::cerr << "Error: " << msg << std::endl << std::endl;
      std::cout << "./pbrt2pbf inFile.pbrt|inFile.pbf <args>" << std::endl;
      std::cout << std::endl;
      std::cout << "  -o <out.pbf>   : where to write the output to" << std::endl;
      std::cout << "                   (tris to quads, removing reundant fields, etc)" << std::endl;
      exit(msg == "" ? 0 : 1);
    }

    inline bool endsWith(const std::string &s, const std::string &suffix)
    {
      return s.substr(s.size()-suffix.size(),suffix.size()) == suffix;
    }

    void pbrt2pbf(int ac, char **av)
    {
      std::string inFileName;
      std::string outFileName;
      for (int i=1;i<ac;i++) {
        const std::string arg = av[i];
        if (arg == "-o") {
          assert(i+1 < ac);
          outFileName = av[++i];
        } else if (arg[0] != '-') {
          inFileName = arg;
        } else {
          usage("invalid argument '"+arg+"'");
        }
      }

      if (outFileName == "")
        usage("no output file specified (-o <file.pbff>)");
      if (inFileName == "")
        usage("no input pbrt file specified");

      if (!endsWith(outFileName,".pbf")) {
        std::cout << "output file name missing '.pbsf' extension - adding it ..." << std::endl;
        outFileName = outFileName+".pbf";
      }

      std::cout << "-------------------------------------------------------" << std::endl;
      std::cout << "parsing pbrt file " << inFileName << std::endl;
      // try {
        Scene::SP scene = importPBRT(inFileName);
        std::cout << "\033[1;32m done importing scene.\033[0m" << std::endl;
        std::cout << "writing to binary file " << outFileName << std::endl;
        scene->saveTo(outFileName);
        std::cout << "\033[1;32m => yay! writing successful...\033[0m" << std::endl;
      // } catch (std::runtime_error &e) {
      //   cout << "\033[1;31mError in parsing: " << e.what() << "\033[0m\n";
      //   throw e;
      // }
    }

    extern "C" int main(int ac, char **av)
    {
      pbrt2pbf(ac,av);
      return 0;
    }

  } // ::pbrt::semantic
} // ::pbrt
<|endoftext|>


<commit_before>
// (c) COPYRIGHT URI/MIT 1997-1999
// Please read the full copyright statement in the file COPYRIGHT.
//
// Authors:
//      jhrg,jimg       James Gallagher (jgallagher@gso.uri.edu)

// Implementation of the DODSFilter class. This class is used to build dods
// filter programs which, along with a CGI program, comprise DODS servers.
// jhrg 8/26/97

// $Log: DODSFilter.cc,v $
// Revision 1.14  1999/05/25 21:57:52  dan
// Added an optional second argument to read_ancillary_dds to support
// JGOFS usage.
//
// Revision 1.13  1999/05/25 21:54:19  dan
// Added an optional argument to read_ancillary_das to support JGOFS
// data object usage, where the location of the ancillary DAS file isn't
// readily available through the 'dataset' argument of the command line.
//
// Revision 1.12  1999/05/21 17:15:46  jimg
// Added instrumentation to the ctor. This simplifies debugging the interaction
// between the filter programs and the perl script.
//
// Revision 1.11  1999/05/19 23:56:57  jimg
// Changed the support address from @dods to @unidata
//
// Revision 1.10  1999/05/05 00:36:36  jimg
// Added the -V option. -v now is used to pass the version information from the
// CGI to the C++ software; -V triggers output of the version message. This
// allows the DODSFilter class to pass information about the server's version to
// the core software.
// All set_mime_*() functions are now passes the CGI version information so that
// all MIME headers contain information about the server's version.
// Added the get_cgi_version() member function so that clients of DODSFilter can
// find out the version number.
//
// Revision 1.9  1999/05/04 19:47:21  jimg
// Fixed copyright statements. Removed more of the GNU classes.
//
// Revision 1.8  1999/04/29 02:29:28  jimg
// Merge of no-gnu branch
//
// Revision 1.7  1999/02/22 22:59:07  jimg
// Added the get_accept_types() accessor.
// Changed the ctor so that the -t option is recognized.
//
// Revision 1.6  1998/12/16 19:10:53  jimg
// Added support for XDODS-Server MIME header. This fixes a problem where our
// use of Server clashed with Java.
//
// Revision 1.5  1998/11/10 01:04:42  jimg
// Added `ends' to strings made with ostrstream (fixes a bug found with
// purify).
// Added catch for throws from within the CE evaluation functions.
//
// Revision 1.4.2.2  1999/02/05 09:32:34  jimg
// Fixed __unused__ so that it not longer clashes with Red Hat 5.2 inlined
// math code.
//
// Revision 1.4.2.1  1999/02/02 21:56:57  jimg
// String to string version
//
// Revision 1.4  1998/08/06 16:12:30  jimg
// Added cache dir methods and stuff to ctor (from jeh)
//
// Revision 1.3  1998/03/19 23:34:21  jimg
// Fixed calls to set_mime_*().
// Removed the compression code (it is now in DDS::send().
// Removed old code (that was surrounded by #if 0 ... #endif).
//
// Revision 1.2  1998/02/11 22:00:46  jimg
// Added call to util.cc:deflate_exists() to send_data(). This means that
// send_data() will only try to start the compressor if an executable copy of
// deflate can be found. If, for any reason a copy of deflate cannot be found
// data is sent without trying to compress it.
//
// Revision 1.1  1997/08/28 20:39:02  jimg
// Created
//

#ifdef __GNUG__
#pragma "implemenation"
#endif

#include "config_dap.h"

static char rcsid[] not_used = {"$Id: DODSFilter.cc,v 1.14 1999/05/25 21:57:52 dan Exp $"};

#include <iostream>
#ifdef __GNUG__
#include <strstream>
#else
#include <sstream>
#endif
#include <string>
#include <GetOpt.h>

#include "DAS.h"
#include "DDS.h"
#include "debug.h"
#include "cgi_util.h"
#include "DODSFilter.h"

DODSFilter::DODSFilter(int argc, char *argv[]) : comp(false), ver(false),
    bad_options(false), dataset(""), ce(""), cgi_ver(""),
    anc_dir(""), anc_file(""), cache_dir(""), accept_types("All")
{
    program_name = argv[0];

    int option_char;
    GetOpt getopt (argc, argv, "ce:v:Vd:f:r:t:");

    while ((option_char = getopt()) != EOF)
	switch (option_char) {
	  case 'c': comp = true; break;
	  case 'e': ce = getopt.optarg; break;
	  case 'v': cgi_ver = getopt.optarg; break;
	  case 'V': ver = true; break;
	  case 'd': anc_dir = getopt.optarg; break;
	  case 'f': anc_file = getopt.optarg; break;
	  case 'r': cache_dir = getopt.optarg; break;
	  case 't': accept_types = getopt.optarg; break;
	  default: bad_options = true; break;
	}

    int next_arg = getopt.optind;
    if(next_arg < argc)
	dataset = argv[next_arg];
    else
	bad_options = true;

    DBG(cerr << "comp: " << comp << endl);
    DBG(cerr << "ce: " << ce << endl);
    DBG(cerr << "cgi_ver: " << cgi_ver << endl);
    DBG(cerr << "ver: " << ver << endl);
    DBG(cerr << "anc_dir: " << anc_dir << endl);
    DBG(cerr << "anc_file: " << anc_file << endl);
    DBG(cerr << "cache_dir: " << cache_dir << endl);
    DBG(cerr << "accept_types: " << accept_types << endl);
}

DODSFilter::~DODSFilter()
{
}

bool
DODSFilter::OK()
{

    return !bad_options;
}

bool
DODSFilter::version()
{
    return ver;
}

string
DODSFilter::get_cgi_version()
{
    return cgi_ver;
}

string
DODSFilter::get_ce()
{
    return ce;
}

string
DODSFilter::get_dataset_name()
{
    return dataset;
}

string
DODSFilter::get_dataset_version()
{
    return "";
}

string
DODSFilter::get_cache_dir()
{
  return cache_dir;
}

string
DODSFilter::get_accept_types()
{
    return accept_types;
}

bool
DODSFilter::read_ancillary_das(DAS &das, string anc_location)
{
    if ( anc_location == "" ) anc_location = anc_dir;

    string name = find_ancillary_file(dataset, "das", anc_location, anc_file);
    FILE *in = fopen(name.c_str(), "r");

    if (in) {
	int status = das.parse(in);
	fclose(in);

	if(!status) {
	    string msg = "Parse error in external file " + dataset + ".das";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error, cgi_ver);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

bool
DODSFilter::read_ancillary_dds(DDS &dds, string anc_location)
{
    if ( anc_location == "" ) anc_location = anc_dir;

    string name = find_ancillary_file(dataset, "dds", anc_location, anc_file);
    FILE *in = fopen(name.c_str(), "r");

    if (in) {
	int status = dds.parse(in);
	fclose(in);

	if(!status) {
	    string msg = "Parse error in external file " + dataset + ".dds";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error, cgi_ver);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

static const char *emessage = \
"DODS internal server error. Please report this to the dataset maintainer, \
or to support@unidata.ucar.edu.";

void
DODSFilter::print_usage()
{
    // Write a message to the WWW server error log file.
    ostrstream oss;
    oss << "Usage: " << program_name
	<< " [-c] [-v <cgi version>] [-e <ce>]"
	<< " [-d <ancillary file directory>] [-f <ancillary file name>]"
	<< " <dataset>" << ends;
    ErrMsgT(oss.str());
    oss.rdbuf()->freeze(0);

    // Build an error object to return to the user.
    Error e(unknown_error, emessage);
    set_mime_text(cout, dods_error, cgi_ver);
    e.print(cout);
}

void
DODSFilter::send_version_info()
{
    cout << "HTTP/1.0 200 OK" << endl
	 << "XDODS-Server: " << cgi_ver << endl
	 << "Content-Type: text/plain" << endl
	 << endl;

    cout << "Core version: " << DVR << endl;

    if (cgi_ver != "")
	cout << "Server vision: " << cgi_ver << endl;

    string v = get_dataset_version();
    if (v != "")
	cout << "Dataset version: " << v << endl;
}

bool
DODSFilter::send_das(DAS &das)
{
    set_mime_text(cout, dods_das, cgi_ver);
    das.print(cout);

    return true;
}

bool
DODSFilter::send_dds(DDS &dds, bool constrained)
{
    if (constrained) {
	if (!dds.parse_constraint(ce, cout, true)) {
	    string m = program_name + ": parse error in constraint: "
		+  ce;
	    ErrMsgT(m);

	    set_mime_text(cout, dods_error, cgi_ver);
	    Error e(unknown_error, m);
	    e.print(cout);

	    return false;
	}
	set_mime_text(cout, dods_dds, cgi_ver);
	dds.print_constrained(cout);  // send constrained DDS
    }
    else {
	set_mime_text(cout, dods_dds, cgi_ver);
	dds.print(cout);
    }

    return true;
}

bool
DODSFilter::send_data(DDS &dds, FILE *data_stream)
{
    bool compress = comp && deflate_exists();

    // This catch is a quick & dirty hack for exceptions thrown by the new
    // (11/6/98) projection functions in CEs. I might add exceptions to other
    // parts of the CE parser and evaluator. Eventually, the C++ classes
    // should switch to exceptions. 11/6/98 jhrg
    try {
	if (!dds.send(dataset, ce, data_stream, compress, cgi_ver)) {
	    ErrMsgT((compress) ? "Could not send compressed data" :
		    "Could not send data");
	    return false;
	}
    }
    catch (Error &e) {
	set_mime_text(cout, dods_error, cgi_ver);
	e.print(cout);

	return false;
    }

    return true;
}

<commit_msg>Added a bit where, before sending caught Error objects to the client, we write the message to t eh httpd's error_log.<commit_after>
// (c) COPYRIGHT URI/MIT 1997-1999
// Please read the full copyright statement in the file COPYRIGHT.
//
// Authors:
//      jhrg,jimg       James Gallagher (jgallagher@gso.uri.edu)

// Implementation of the DODSFilter class. This class is used to build dods
// filter programs which, along with a CGI program, comprise DODS servers.
// jhrg 8/26/97

// $Log: DODSFilter.cc,v $
// Revision 1.15  1999/05/26 17:37:02  jimg
// Added a bit where, before sending caught Error objects to the client, we
// write the message to t eh httpd's error_log.
//
// Revision 1.14  1999/05/25 21:57:52  dan
// Added an optional second argument to read_ancillary_dds to support
// JGOFS usage.
//
// Revision 1.13  1999/05/25 21:54:19  dan
// Added an optional argument to read_ancillary_das to support JGOFS
// data object usage, where the location of the ancillary DAS file isn't
// readily available through the 'dataset' argument of the command line.
//
// Revision 1.12  1999/05/21 17:15:46  jimg
// Added instrumentation to the ctor. This simplifies debugging the interaction
// between the filter programs and the perl script.
//
// Revision 1.11  1999/05/19 23:56:57  jimg
// Changed the support address from @dods to @unidata
//
// Revision 1.10  1999/05/05 00:36:36  jimg
// Added the -V option. -v now is used to pass the version information from the
// CGI to the C++ software; -V triggers output of the version message. This
// allows the DODSFilter class to pass information about the server's version to
// the core software.
// All set_mime_*() functions are now passes the CGI version information so that
// all MIME headers contain information about the server's version.
// Added the get_cgi_version() member function so that clients of DODSFilter can
// find out the version number.
//
// Revision 1.9  1999/05/04 19:47:21  jimg
// Fixed copyright statements. Removed more of the GNU classes.
//
// Revision 1.8  1999/04/29 02:29:28  jimg
// Merge of no-gnu branch
//
// Revision 1.7  1999/02/22 22:59:07  jimg
// Added the get_accept_types() accessor.
// Changed the ctor so that the -t option is recognized.
//
// Revision 1.6  1998/12/16 19:10:53  jimg
// Added support for XDODS-Server MIME header. This fixes a problem where our
// use of Server clashed with Java.
//
// Revision 1.5  1998/11/10 01:04:42  jimg
// Added `ends' to strings made with ostrstream (fixes a bug found with
// purify).
// Added catch for throws from within the CE evaluation functions.
//
// Revision 1.4.2.2  1999/02/05 09:32:34  jimg
// Fixed __unused__ so that it not longer clashes with Red Hat 5.2 inlined
// math code.
//
// Revision 1.4.2.1  1999/02/02 21:56:57  jimg
// String to string version
//
// Revision 1.4  1998/08/06 16:12:30  jimg
// Added cache dir methods and stuff to ctor (from jeh)
//
// Revision 1.3  1998/03/19 23:34:21  jimg
// Fixed calls to set_mime_*().
// Removed the compression code (it is now in DDS::send().
// Removed old code (that was surrounded by #if 0 ... #endif).
//
// Revision 1.2  1998/02/11 22:00:46  jimg
// Added call to util.cc:deflate_exists() to send_data(). This means that
// send_data() will only try to start the compressor if an executable copy of
// deflate can be found. If, for any reason a copy of deflate cannot be found
// data is sent without trying to compress it.
//
// Revision 1.1  1997/08/28 20:39:02  jimg
// Created
//

#ifdef __GNUG__
#pragma "implemenation"
#endif

#include "config_dap.h"

static char rcsid[] not_used = {"$Id: DODSFilter.cc,v 1.15 1999/05/26 17:37:02 jimg Exp $"};

#include <iostream>
#ifdef __GNUG__
#include <strstream>
#else
#include <sstream>
#endif
#include <string>
#include <GetOpt.h>

#include "DAS.h"
#include "DDS.h"
#include "debug.h"
#include "cgi_util.h"
#include "DODSFilter.h"

DODSFilter::DODSFilter(int argc, char *argv[]) : comp(false), ver(false),
    bad_options(false), dataset(""), ce(""), cgi_ver(""),
    anc_dir(""), anc_file(""), cache_dir(""), accept_types("All")
{
    program_name = argv[0];

    int option_char;
    GetOpt getopt (argc, argv, "ce:v:Vd:f:r:t:");

    while ((option_char = getopt()) != EOF)
	switch (option_char) {
	  case 'c': comp = true; break;
	  case 'e': ce = getopt.optarg; break;
	  case 'v': cgi_ver = getopt.optarg; break;
	  case 'V': ver = true; break;
	  case 'd': anc_dir = getopt.optarg; break;
	  case 'f': anc_file = getopt.optarg; break;
	  case 'r': cache_dir = getopt.optarg; break;
	  case 't': accept_types = getopt.optarg; break;
	  default: bad_options = true; break;
	}

    int next_arg = getopt.optind;
    if(next_arg < argc)
	dataset = argv[next_arg];
    else
	bad_options = true;

    DBG(cerr << "comp: " << comp << endl);
    DBG(cerr << "ce: " << ce << endl);
    DBG(cerr << "cgi_ver: " << cgi_ver << endl);
    DBG(cerr << "ver: " << ver << endl);
    DBG(cerr << "anc_dir: " << anc_dir << endl);
    DBG(cerr << "anc_file: " << anc_file << endl);
    DBG(cerr << "cache_dir: " << cache_dir << endl);
    DBG(cerr << "accept_types: " << accept_types << endl);
}

DODSFilter::~DODSFilter()
{
}

bool
DODSFilter::OK()
{

    return !bad_options;
}

bool
DODSFilter::version()
{
    return ver;
}

string
DODSFilter::get_cgi_version()
{
    return cgi_ver;
}

string
DODSFilter::get_ce()
{
    return ce;
}

string
DODSFilter::get_dataset_name()
{
    return dataset;
}

string
DODSFilter::get_dataset_version()
{
    return "";
}

string
DODSFilter::get_cache_dir()
{
  return cache_dir;
}

string
DODSFilter::get_accept_types()
{
    return accept_types;
}

bool
DODSFilter::read_ancillary_das(DAS &das, string anc_location)
{
    if ( anc_location == "" ) anc_location = anc_dir;

    string name = find_ancillary_file(dataset, "das", anc_location, anc_file);
    FILE *in = fopen(name.c_str(), "r");

    if (in) {
	int status = das.parse(in);
	fclose(in);

	if(!status) {
	    string msg = "Parse error in external file " + dataset + ".das";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error, cgi_ver);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

bool
DODSFilter::read_ancillary_dds(DDS &dds, string anc_location)
{
    if ( anc_location == "" ) anc_location = anc_dir;

    string name = find_ancillary_file(dataset, "dds", anc_location, anc_file);
    FILE *in = fopen(name.c_str(), "r");

    if (in) {
	int status = dds.parse(in);
	fclose(in);

	if(!status) {
	    string msg = "Parse error in external file " + dataset + ".dds";

	    // server error message
	    ErrMsgT(msg);

	    // client error message
	    set_mime_text(cout, dods_error, cgi_ver);
	    Error e(malformed_expr, msg);
	    e.print(cout);

	    return false;
	}
    }

    return true;
}

static const char *emessage = \
"DODS internal server error. Please report this to the dataset maintainer, \
or to support@unidata.ucar.edu.";

void
DODSFilter::print_usage()
{
    // Write a message to the WWW server error log file.
    ostrstream oss;
    oss << "Usage: " << program_name
	<< " [-c] [-v <cgi version>] [-e <ce>]"
	<< " [-d <ancillary file directory>] [-f <ancillary file name>]"
	<< " <dataset>" << ends;
    ErrMsgT(oss.str());
    oss.rdbuf()->freeze(0);

    // Build an error object to return to the user.
    Error e(unknown_error, emessage);
    set_mime_text(cout, dods_error, cgi_ver);
    e.print(cout);
}

void
DODSFilter::send_version_info()
{
    cout << "HTTP/1.0 200 OK" << endl
	 << "XDODS-Server: " << cgi_ver << endl
	 << "Content-Type: text/plain" << endl
	 << endl;

    cout << "Core version: " << DVR << endl;

    if (cgi_ver != "")
	cout << "Server vision: " << cgi_ver << endl;

    string v = get_dataset_version();
    if (v != "")
	cout << "Dataset version: " << v << endl;
}

bool
DODSFilter::send_das(DAS &das)
{
    set_mime_text(cout, dods_das, cgi_ver);
    das.print(cout);

    return true;
}

bool
DODSFilter::send_dds(DDS &dds, bool constrained)
{
    if (constrained) {
	if (!dds.parse_constraint(ce, cout, true)) {
	    string m = program_name + ": parse error in constraint: "
		+  ce;
	    ErrMsgT(m);

	    set_mime_text(cout, dods_error, cgi_ver);
	    Error e(unknown_error, m);
	    e.print(cout);

	    return false;
	}
	set_mime_text(cout, dods_dds, cgi_ver);
	dds.print_constrained(cout);  // send constrained DDS
    }
    else {
	set_mime_text(cout, dods_dds, cgi_ver);
	dds.print(cout);
    }

    return true;
}

bool
DODSFilter::send_data(DDS &dds, FILE *data_stream)
{
    bool compress = comp && deflate_exists();

    // This catch is a quick & dirty hack for exceptions thrown by the new
    // (11/6/98) projection functions in CEs. I might add exceptions to other
    // parts of the CE parser and evaluator. Eventually, the C++ classes
    // should switch to exceptions. 11/6/98 jhrg
    //
    // I'm not sure we should catch errors from dds.send and its callees
    // here. I think they should be caught in the outer layer (e.g.,
    // ff_dods). 5/26/99 jhrg
    try {
	if (!dds.send(dataset, ce, data_stream, compress, cgi_ver)) {
	    ErrMsgT((compress) ? "Could not send compressed data" :
		    "Could not send data");
	    return false;
	}
    }
    catch (Error &e) {
	ErrMsgT((compress) ? "Could not send compressed data" :
		"Could not send data");
	set_mime_text(cout, dods_error, cgi_ver);
	e.print(cout);

	return false;
    }

    return true;
}

<|endoftext|>


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

#ifndef BYOM_DYNAMIC_VIEW_HPP
#define BYOM_DYNAMIC_VIEW_HPP

#include <string>
#include <memory>
#include <functional>
#include <type_traits>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>

namespace byom {

class dynamic_view;

using visit_function =
  std::function<void(dynamic_view const&, dynamic_view const&)>;

template <typename T, typename Enable = void>
struct ext;

class dynamic_view
{
  template <typename T>
  using no_copy_ctor = typename std::enable_if<!std::is_same<
    typename std::remove_reference<T>::type, dynamic_view>::value>::type;

public:
  template <typename T, typename Enable = no_copy_ctor<T>>
  dynamic_view(T&& t)
    : dynamic_view(std::forward<T>(t), std::is_lvalue_reference<T>())
  {
  }

  dynamic_view(dynamic_view const& x)
  {
    x.object().clone(storage());
  }

  dynamic_view(dynamic_view&& x)
  {
    x.object().move_clone(storage());
  }

  ~dynamic_view()
  {
    object().~concept_t();
  }

  dynamic_view& operator=(dynamic_view&& x) = delete;
  dynamic_view& operator=(dynamic_view const& x) = delete;

public:
  bool empty() const
  {
    return object().empty();
  }

  dynamic_view at(std::string const& n) const &
  {
    return object().at(n);
  }

  dynamic_view at(std::string const& n) const &&
  {
    auto member = object().at(n);
    if (object().owned() && !member.object().owned()) {
      throw std::invalid_argument{ "dangling reference" };
    }
    return member;
  }

  void for_each(visit_function const& v) const
  {
    object().for_each(v);
  }

  friend std::ostream& operator<<(std::ostream& os, dynamic_view const& self)
  {
    self.object().print(os);
    return os;
  }

private:
  struct concept_t
  {
    virtual ~concept_t() = default;
    virtual void clone(void* storage) const = 0;
    virtual void move_clone(void* storage) = 0;
    virtual bool owned() const = 0;
    virtual bool empty() const = 0;
    virtual dynamic_view at(std::string const& n) const = 0;
    virtual void for_each(visit_function const& v) const = 0;
    virtual void print(std::ostream& os) const = 0;
  };

  template <template <typename> class Derived, typename T>
  struct model_base_t : concept_t
  {
    bool empty() const override
    {
      return ext<T>::empty_impl(get());
    }

    dynamic_view at(std::string const& n) const override
    {
      return ext<T>::at_impl(get(), n);
    }

    void for_each(visit_function const& v) const override
    {
      ext<T>::for_each_impl(get(), v);
    }

    void print(std::ostream& os) const override
    {
      ext<T>::print_impl(os, get());
    }

    T const& get() const
    {
      return static_cast<Derived<T> const*>(this)->get();
    }
  };

  template <typename T>
  struct cref_model_t : model_base_t<cref_model_t, T>
  {
    cref_model_t(T const& x)
      : object(x)
    {
    }

    void clone(void* storage) const override
    {
      new (storage) cref_model_t(object);
    }

    void move_clone(void* storage) override
    {
      clone(storage);
    }

    bool owned() const override
    {
      return false;
    }

    T const& get() const
    {
      return object;
    }

    T const& object;
  };

  template <typename T>
  struct local_model_t : model_base_t<local_model_t, T>
  {
    local_model_t(T x)
      : object(std::move(x))
    {
    }

    void clone(void* storage) const override
    {
      new (storage) local_model_t(object);
    }

    bool owned() const override
    {
      return true;
    }

    void move_clone(void* storage) override
    {
      new (storage) local_model_t(std::move(object));
    }

    T const& get() const
    {
      return object;
    }

    T object;
  };

  template <typename T>
  struct remote_model_t : model_base_t<remote_model_t, T>
  {
    remote_model_t(T x)
      : object(std::make_unique<T const>(std::move(x)))
    {
    }

    void clone(void* storage) const override
    {
      new (storage) remote_model_t(get());
    }

    void move_clone(void* storage) override
    {
      new (storage) remote_model_t(std::move(*this));
    }

    bool owned() const override
    {
      return true;
    }

    T const& get() const
    {
      return *object;
    }

    std::unique_ptr<T const> object;
  };

private:
  template <typename T>
  dynamic_view(T&& t, std::true_type)
  {
    using model = cref_model_t<typename std::decay<T>::type>;
    static_assert(sizeof(model) <= sizeof(data), "size mismatch");
    new (storage()) model(t);
  }

  template <typename T>
  dynamic_view(T&& t, std::false_type)
  {
    using local_type = local_model_t<typename std::decay<T>::type>;
    using remote_type = remote_model_t<typename std::decay<T>::type>;
    using use_local_type =
      boost::mpl::bool_<(sizeof(local_type) <= sizeof(data)) &&
                        (std::is_nothrow_copy_constructible<T>::value ||
                         std::is_nothrow_move_constructible<T>::value)>;
    using model =
      typename boost::mpl::if_<use_local_type, local_type, remote_type>::type;
    static_assert(sizeof(model) <= sizeof(data), "size mismatch");
    new (storage()) model(std::move(t));
  }

private:
  concept_t& object()
  {
    return *static_cast<concept_t*>(storage());
  }

  concept_t const& object() const
  {
    return *static_cast<concept_t const*>(storage());
  }

  void* storage()
  {
    return &data;
  }

  void const* storage() const
  {
    return &data;
  }

  double data[2];
};

} // namespace byom

#endif /* BYOM_DYNAMIC_VIEW_HPP */
<commit_msg>make sure pointers are stored by value<commit_after>// Copyright (c) 2015, Daniel Pfeifer <daniel@pfeifer-mail.de>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#ifndef BYOM_DYNAMIC_VIEW_HPP
#define BYOM_DYNAMIC_VIEW_HPP

#include <string>
#include <memory>
#include <functional>
#include <type_traits>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>

namespace byom {

class dynamic_view;

using visit_function =
  std::function<void(dynamic_view const&, dynamic_view const&)>;

template <typename T, typename Enable = void>
struct ext;

class dynamic_view
{
  template <typename T>
  using no_copy_ctor = typename std::enable_if<!std::is_same<
    typename std::remove_reference<T>::type, dynamic_view>::value>::type;

public:
  template <typename T, typename Enable = no_copy_ctor<T>>
  dynamic_view(T&& t)
    : dynamic_view(std::forward<T>(t), std::is_lvalue_reference<T>())
  {
  }

  template <typename T>
  dynamic_view(T* t)
  {
    new (storage()) local_model_t<T*>(t);
  }

  template <typename T>
  dynamic_view(T const* t)
  {
    new (storage()) local_model_t<T const*>(t);
  }

  dynamic_view(dynamic_view const& x)
  {
    x.object().clone(storage());
  }

  dynamic_view(dynamic_view&& x)
  {
    x.object().move_clone(storage());
  }

  ~dynamic_view()
  {
    object().~concept_t();
  }

  dynamic_view& operator=(dynamic_view&& x) = delete;
  dynamic_view& operator=(dynamic_view const& x) = delete;

public:
  bool empty() const
  {
    return object().empty();
  }

  dynamic_view at(std::string const& n) const &
  {
    return object().at(n);
  }

  dynamic_view at(std::string const& n) const &&
  {
    auto member = object().at(n);
    if (object().owned() && !member.object().owned()) {
      throw std::invalid_argument{ "dangling reference" };
    }
    return member;
  }

  void for_each(visit_function const& v) const
  {
    object().for_each(v);
  }

  friend std::ostream& operator<<(std::ostream& os, dynamic_view const& self)
  {
    self.object().print(os);
    return os;
  }

private:
  struct concept_t
  {
    virtual ~concept_t() = default;
    virtual void clone(void* storage) const = 0;
    virtual void move_clone(void* storage) = 0;
    virtual bool owned() const = 0;
    virtual bool empty() const = 0;
    virtual dynamic_view at(std::string const& n) const = 0;
    virtual void for_each(visit_function const& v) const = 0;
    virtual void print(std::ostream& os) const = 0;
  };

  template <template <typename> class Derived, typename T>
  struct model_base_t : concept_t
  {
    bool empty() const override
    {
      return ext<T>::empty_impl(get());
    }

    dynamic_view at(std::string const& n) const override
    {
      return ext<T>::at_impl(get(), n);
    }

    void for_each(visit_function const& v) const override
    {
      ext<T>::for_each_impl(get(), v);
    }

    void print(std::ostream& os) const override
    {
      ext<T>::print_impl(os, get());
    }

    T const& get() const
    {
      return static_cast<Derived<T> const*>(this)->get();
    }
  };

  template <typename T>
  struct cref_model_t : model_base_t<cref_model_t, T>
  {
    cref_model_t(T const& x)
      : object(x)
    {
    }

    void clone(void* storage) const override
    {
      new (storage) cref_model_t(object);
    }

    void move_clone(void* storage) override
    {
      clone(storage);
    }

    bool owned() const override
    {
      return false;
    }

    T const& get() const
    {
      return object;
    }

    T const& object;
  };

  template <typename T>
  struct local_model_t : model_base_t<local_model_t, T>
  {
    local_model_t(T x)
      : object(std::move(x))
    {
    }

    void clone(void* storage) const override
    {
      new (storage) local_model_t(object);
    }

    bool owned() const override
    {
      return true;
    }

    void move_clone(void* storage) override
    {
      new (storage) local_model_t(std::move(object));
    }

    T const& get() const
    {
      return object;
    }

    T object;
  };

  template <typename T>
  struct remote_model_t : model_base_t<remote_model_t, T>
  {
    remote_model_t(T x)
      : object(std::make_unique<T const>(std::move(x)))
    {
    }

    void clone(void* storage) const override
    {
      new (storage) remote_model_t(get());
    }

    void move_clone(void* storage) override
    {
      new (storage) remote_model_t(std::move(*this));
    }

    bool owned() const override
    {
      return true;
    }

    T const& get() const
    {
      return *object;
    }

    std::unique_ptr<T const> object;
  };

private:
  template <typename T>
  dynamic_view(T&& t, std::true_type)
  {
    using model = cref_model_t<typename std::decay<T>::type>;
    static_assert(sizeof(model) <= sizeof(data), "size mismatch");
    new (storage()) model(t);
  }

  template <typename T>
  dynamic_view(T&& t, std::false_type)
  {
    using local_type = local_model_t<typename std::decay<T>::type>;
    using remote_type = remote_model_t<typename std::decay<T>::type>;
    using use_local_type =
      boost::mpl::bool_<(sizeof(local_type) <= sizeof(data)) &&
                        (std::is_nothrow_copy_constructible<T>::value ||
                         std::is_nothrow_move_constructible<T>::value)>;
    using model =
      typename boost::mpl::if_<use_local_type, local_type, remote_type>::type;
    static_assert(sizeof(model) <= sizeof(data), "size mismatch");
    new (storage()) model(std::move(t));
  }

private:
  concept_t& object()
  {
    return *static_cast<concept_t*>(storage());
  }

  concept_t const& object() const
  {
    return *static_cast<concept_t const*>(storage());
  }

  void* storage()
  {
    return &data;
  }

  void const* storage() const
  {
    return &data;
  }

  double data[2];
};

} // namespace byom

#endif /* BYOM_DYNAMIC_VIEW_HPP */
<|endoftext|>


<commit_before>#include <configure/bind.hpp>

#include <configure/Build.hpp>
#include <configure/Rule.hpp>
#include <configure/lua/State.hpp>
#include <configure/lua/Type.hpp>
#include <configure/Filesystem.hpp>
#include <configure/Platform.hpp>

#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;

namespace configure {

	template<typename T>
	static int Build_option(lua_State* state)
	{
		Build& self = lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		auto name = lua::Converter<std::string>::extract(state, 2);
		auto descr = lua::Converter<std::string>::extract(state, 3);
		if (lua_gettop(state) == 3)
		{
			auto res = self.option<T>(std::move(name), std::move(descr));
			if (res)
				lua::Converter<T>::push(state, *res);
			else
				lua_pushnil(state);
		}
		else
		{
			lua::Converter<T>::push(
			    state,
				self.option<T>(
					std::move(name),
					std::move(descr),
					lua::Converter<T>::extract(state, 4)
				)
			);
		}
		return 1;
	}

	template<typename T>
	static int Build_lazy_option(lua_State* state)
	{
		Build& self = lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		auto key = lua::Converter<std::string>::extract(state, 2);
		auto descr = lua::Converter<std::string>::extract(state, 3);
		if (!lua_isfunction(state, -1))
			throw std::runtime_error("Expected a function as a second argument");
		auto res = self.lazy_option<T>(
			key,
			descr,
			[&]() -> T {
				lua::State::check_status(state, lua_pcall(state, 0, 1, 0));
				try { return lua::Converter<T>::extract(state, -1); }
				catch (...) {
				    CONFIGURE_THROW(
				      error::BuildError("The lua callback for option '" + key +
				                        "' didn't return a valid value")
				      << error::nested(std::current_exception()));
			    }
			});
		lua::Converter<T>::push(state, std::move(res));
		return 1;
	}

	template<log::Level level>
	static int Build_log(lua_State* state)
	{
		lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		std::string msg;
		for (int i = 2, len = lua_gettop(state); i <= len; ++i)
		{
			if (!msg.empty()) msg.push_back(' ');
			msg += luaL_tolstring(state, i, nullptr);
		}
		if (level == log::Level::error)
			CONFIGURE_THROW(error::BuildError(msg));
		log::log<level>(msg);
		return 0;
	}

	void bind_build(lua::State& state)
	{
		/// Represent a build.
		// @classmod Build
		lua::Type<Build, std::reference_wrapper<Build>>(state)
		  /// Current project directory @{Path}.
		  // @function Build:project_directory
		  .def("project_directory", &Build::project_directory)

		  /// Current build directory @{Path}.
		  // @function Build:directory
		  .def("directory", &Build::directory)

		  /// Build root node
		  // @function Build:root_node
		  .def("root_node", &Build::root_node)

		  /// Source @{Node} associated to a @{Path}.
		  // @tparam Path path relative path to a source file
		  // @function Build:source_node
		  .def("source_node", &Build::source_node)

		  /// Target @{Node} associated to a @{Path}.
		  // @tparam Path path relative path to a built file
		  // @function Build:target_node
		  .def("target_node", &Build::target_node)

		  /// Directory @{Node} associated to a @{Path}.
		  // @tparam Path path Absolute path to a directory
		  // @function Build:directory_node
		  .def("directory_node", &Build::directory_node)

		  /// File @{Node} associated to a @{Path}.
		  // @tparam Path path Absolute path to a file
		  // @function Build:file_node
		  .def("file_node", &Build::file_node)

		  /// Virtual @{Node}.
		  // @tparam string name A non-empty string
		  // @function Build:virtual_node
		  .def("virtual_node", &Build::virtual_node)

		  /// Add a rule to the build.
		  // @tparam Rule rule Rule to add
		  // @function Build:add_rule
		  .def("add_rule", &Build::add_rule)

		  /// Associated @{Filesystem} instance.
		  // @function Build:fs
		  .def<lua::return_policy::ref>("fs", &Build::fs)

		  /// Associated @{Environ} instance.
		  // @function Build:env
		  .def<lua::return_policy::ref>("env", &Build::env)

		  /// Path to the configure executable
		  // @function Build:configure_program
		  .def<lua::return_policy::copy>(
		     "configure_program", &Build::configure_program)

		  /// Declare an option of type @{string} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] string default_value
		  // @treturn string|nil Associated value
		  // @function Build:string_option
		  .def( "string_option", &Build_option<std::string> )

		  /// Declare an option of type int and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] int default_value
		  // @treturn int|nil Associated value
		  // @function Build:int_option
		  .def( "int_option", &Build_option<int64_t> )

		  /// Declare an option of type bool and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] bool default_value
		  // @treturn bool|nil Associated value
		  // @function Build:bool_option
		  .def( "bool_option", &Build_option<bool> )

		  /// Declare an option of type @{Path} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] Path default_value
		  // @treturn Path|nil Associated value
		  // @function Build:path_option
		  .def( "path_option", &Build_option<fs::path> )

		  /// Declare a lazy option of type @{string} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] string default_value
		  // @treturn string|nil Associated value
		  // @function Build:string_option
		  .def( "lazy_string_option", &Build_lazy_option<std::string> )

		  /// Declare a lazy option of type int and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] int default_value
		  // @treturn int|nil Associated value
		  // @function Build:int_option
		  .def( "lazy_int_option", &Build_lazy_option<int64_t> )

		  /// Declare a lazy option of type bool and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] bool default_value
		  // @treturn bool|nil Associated value
		  // @function Build:bool_option
		  .def( "lazy_bool_option", &Build_lazy_option<bool> )

		  /// Declare a lazy option of type @{Path} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] Path default_value
		  // @treturn Path|nil Associated value
		  // @function Build:path_option
		  .def( "lazy_path_option", &Build_lazy_option<fs::path> )

		  /// The host platform.
		  // @treturn Platform
		  // @function Build:host_platform
		  .def<lua::return_policy::ref>("host", &Build::host)

		  /// The target platform.
		  // @treturn Platform
		  // @function Build:target_platform
		  .def<lua::return_policy::ref>("target", &Build::target)

		  /// Log a debug message.
		  // @param args...
		  // @function Build:debug
		  .def( "debug", &Build_log<log::Level::verbose> )

		  /// Log an informational message.
		  // @param args...
		  // @function Build:status
		  .def( "status", &Build_log<log::Level::status> )

		  /// Log a warning message.
		  // @param args...
		  // @function Build:warning
		  .def( "warning", &Build_log<log::Level::warning> )

		  /// Stop the configuration with an error message.
		  // @param args...
		  // @function Build:error
		  .def("error", &Build_log<log::Level::error>);
	}

}
<commit_msg>Bind the configure method in lua.<commit_after>#include <configure/bind.hpp>

#include <configure/Build.hpp>
#include <configure/Rule.hpp>
#include <configure/lua/State.hpp>
#include <configure/lua/Type.hpp>
#include <configure/Filesystem.hpp>
#include <configure/Platform.hpp>

#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;

namespace configure {

	template<typename T>
	static int Build_option(lua_State* state)
	{
		Build& self = lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		auto name = lua::Converter<std::string>::extract(state, 2);
		auto descr = lua::Converter<std::string>::extract(state, 3);
		if (lua_gettop(state) == 3)
		{
			auto res = self.option<T>(std::move(name), std::move(descr));
			if (res)
				lua::Converter<T>::push(state, *res);
			else
				lua_pushnil(state);
		}
		else
		{
			lua::Converter<T>::push(
			    state,
				self.option<T>(
					std::move(name),
					std::move(descr),
					lua::Converter<T>::extract(state, 4)
				)
			);
		}
		return 1;
	}

	template<typename T>
	static int Build_lazy_option(lua_State* state)
	{
		Build& self = lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		auto key = lua::Converter<std::string>::extract(state, 2);
		auto descr = lua::Converter<std::string>::extract(state, 3);
		if (!lua_isfunction(state, -1))
			throw std::runtime_error("Expected a function as a second argument");
		auto res = self.lazy_option<T>(
			key,
			descr,
			[&]() -> T {
				lua::State::check_status(state, lua_pcall(state, 0, 1, 0));
				try { return lua::Converter<T>::extract(state, -1); }
				catch (...) {
				    CONFIGURE_THROW(
				      error::BuildError("The lua callback for option '" + key +
				                        "' didn't return a valid value")
				      << error::nested(std::current_exception()));
			    }
			});
		lua::Converter<T>::push(state, std::move(res));
		return 1;
	}

	template<log::Level level>
	static int Build_log(lua_State* state)
	{
		lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		std::string msg;
		for (int i = 2, len = lua_gettop(state); i <= len; ++i)
		{
			if (!msg.empty()) msg.push_back(' ');
			msg += luaL_tolstring(state, i, nullptr);
		}
		if (level == log::Level::error)
			CONFIGURE_THROW(error::BuildError(msg));
		log::log<level>(msg);
		return 0;
	}

	static int Build_configure(lua_State* state)
	{
		auto& self = lua::Converter<std::reference_wrapper<Build>>::extract(state, 1);
		fs::path dir = lua::Converter<fs::path>::extract(state, 2);
		self.get().configure(self.get().project_directory(), dir);
		return 0;
	}

	void bind_build(lua::State& state)
	{
		/// Represent a build.
		// @classmod Build
		lua::Type<Build, std::reference_wrapper<Build>>(state)
		  /// Current project directory @{Path}.
		  // @function Build:project_directory
		  .def("project_directory", &Build::project_directory)

		  /// Configure a sub-project
		  // @function Build:configure
		  // @param Path relative path to the sub-project directory
		  .def("configure", &Build_configure)

		  /// Current build directory @{Path}.
		  // @function Build:directory
		  .def("directory", &Build::directory)

		  /// Build root node
		  // @function Build:root_node
		  .def("root_node", &Build::root_node)

		  /// Source @{Node} associated to a @{Path}.
		  // @tparam Path path relative path to a source file
		  // @function Build:source_node
		  .def("source_node", &Build::source_node)

		  /// Target @{Node} associated to a @{Path}.
		  // @tparam Path path relative path to a built file
		  // @function Build:target_node
		  .def("target_node", &Build::target_node)

		  /// Directory @{Node} associated to a @{Path}.
		  // @tparam Path path Absolute path to a directory
		  // @function Build:directory_node
		  .def("directory_node", &Build::directory_node)

		  /// File @{Node} associated to a @{Path}.
		  // @tparam Path path Absolute path to a file
		  // @function Build:file_node
		  .def("file_node", &Build::file_node)

		  /// Virtual @{Node}.
		  // @tparam string name A non-empty string
		  // @function Build:virtual_node
		  .def("virtual_node", &Build::virtual_node)

		  /// Add a rule to the build.
		  // @tparam Rule rule Rule to add
		  // @function Build:add_rule
		  .def("add_rule", &Build::add_rule)

		  /// Associated @{Filesystem} instance.
		  // @function Build:fs
		  .def<lua::return_policy::ref>("fs", &Build::fs)

		  /// Associated @{Environ} instance.
		  // @function Build:env
		  .def<lua::return_policy::ref>("env", &Build::env)

		  /// Path to the configure executable
		  // @function Build:configure_program
		  .def<lua::return_policy::copy>(
		     "configure_program", &Build::configure_program)

		  /// Declare an option of type @{string} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] string default_value
		  // @treturn string|nil Associated value
		  // @function Build:string_option
		  .def( "string_option", &Build_option<std::string> )

		  /// Declare an option of type int and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] int default_value
		  // @treturn int|nil Associated value
		  // @function Build:int_option
		  .def( "int_option", &Build_option<int64_t> )

		  /// Declare an option of type bool and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] bool default_value
		  // @treturn bool|nil Associated value
		  // @function Build:bool_option
		  .def( "bool_option", &Build_option<bool> )

		  /// Declare an option of type @{Path} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] Path default_value
		  // @treturn Path|nil Associated value
		  // @function Build:path_option
		  .def( "path_option", &Build_option<fs::path> )

		  /// Declare a lazy option of type @{string} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] string default_value
		  // @treturn string|nil Associated value
		  // @function Build:string_option
		  .def( "lazy_string_option", &Build_lazy_option<std::string> )

		  /// Declare a lazy option of type int and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] int default_value
		  // @treturn int|nil Associated value
		  // @function Build:int_option
		  .def( "lazy_int_option", &Build_lazy_option<int64_t> )

		  /// Declare a lazy option of type bool and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] bool default_value
		  // @treturn bool|nil Associated value
		  // @function Build:bool_option
		  .def( "lazy_bool_option", &Build_lazy_option<bool> )

		  /// Declare a lazy option of type @{Path} and return it's value.
		  // @string name
		  // @string description
		  // @tparam[opt] Path default_value
		  // @treturn Path|nil Associated value
		  // @function Build:path_option
		  .def( "lazy_path_option", &Build_lazy_option<fs::path> )

		  /// The host platform.
		  // @treturn Platform
		  // @function Build:host_platform
		  .def<lua::return_policy::ref>("host", &Build::host)

		  /// The target platform.
		  // @treturn Platform
		  // @function Build:target_platform
		  .def<lua::return_policy::ref>("target", &Build::target)

		  /// Log a debug message.
		  // @param args...
		  // @function Build:debug
		  .def( "debug", &Build_log<log::Level::verbose> )

		  /// Log an informational message.
		  // @param args...
		  // @function Build:status
		  .def( "status", &Build_log<log::Level::status> )

		  /// Log a warning message.
		  // @param args...
		  // @function Build:warning
		  .def( "warning", &Build_log<log::Level::warning> )

		  /// Stop the configuration with an error message.
		  // @param args...
		  // @function Build:error
		  .def("error", &Build_log<log::Level::error>);
	}

}
<|endoftext|>


<commit_before>#include "helpers/huffmanish.hh"

int main(int argc, char* argv[]){
	Huffman huffmanclass(argv[1]); //initialize
	huffmanclass.assign_values();
	huffmanclass.produce_lookups();

	util::FilePiece filein(argv[1]);

	line_text firstline = splitLine(filein.ReadLine());

	std::vector<unsigned int> encoding = huffmanclass.encode_line(firstline);

	for (std::vector<unsigned int>::iterator it = encoding.begin(); it != encoding.end(); it++){
		std::cout << *it << " ";
	}
	std::cout << std::endl;

	std::map<unsigned int, std::string> lookup_target_phrase = huffmanclass.get_target_lookup_map();
	std::map<unsigned int, std::string> lookup_probabilities = huffmanclass.get_probabilities_lookup_map();
	std::map<unsigned int, std::string> lookup_word_all1 = huffmanclass.get_word_all1_lookup_map();
	std::map<unsigned int, std::string> lookup_word_all2 = huffmanclass.get_word_all2_lookup_map();

	HuffmanDecoder decoder(&lookup_target_phrase, &lookup_probabilities,
	 &lookup_word_all1, &lookup_word_all2);

	decoder.decode_line(encoding);
}<commit_msg>More testing code<commit_after>#include "helpers/huffmanish.hh"

int main(int argc, char* argv[]){
	Huffman huffmanclass(argv[1]); //initialize
	huffmanclass.assign_values();
	huffmanclass.produce_lookups();
	huffmanclass.serialize_maps("/tmp/maps/");

	util::FilePiece filein(argv[1]);

	line_text firstline = splitLine(filein.ReadLine());

	std::vector<unsigned int> encoding = huffmanclass.encode_line(firstline);

	for (std::vector<unsigned int>::iterator it = encoding.begin(); it != encoding.end(); it++){
		std::cout << *it << " ";
	}
	std::cout << std::endl;

	std::map<unsigned int, std::string> lookup_target_phrase = huffmanclass.get_target_lookup_map();
	std::map<unsigned int, std::string> lookup_probabilities = huffmanclass.get_probabilities_lookup_map();
	std::map<unsigned int, std::string> lookup_word_all1 = huffmanclass.get_word_all1_lookup_map();
	std::map<unsigned int, std::string> lookup_word_all2 = huffmanclass.get_word_all2_lookup_map();

	HuffmanDecoder decoder(&lookup_target_phrase, &lookup_probabilities,
	 &lookup_word_all1, &lookup_word_all2);

	target_text tmp = decoder.decode_line(encoding);
	std::cout << decoder.getTargetWordsFromIDs(tmp.target_phrase) << " ";

	for (std::vector<float>::iterator it = tmp.prob.begin(); it != tmp.prob.end(); it++){
		std::cout << *it << " ";
	}

	std::cout << tmp.word_all1[0] << " " << tmp.word_all2[0] << std::endl;
}<|endoftext|>