<commit_before>#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include "ArduinoOTA.h"
#include "MD5Builder.h"

//#define OTA_DEBUG 1

#define U_AUTH 200

ArduinoOTAClass::ArduinoOTAClass()
{
    _udp_ota = new WiFiUDP();
    _password = 0;
    _hostname = 0;
    _port = 0;
    _nonce = 0;
    _state = OTA_IDLE;

    _size = 0;
    _cmd = 0;
    _ota_port = 0;
    _ota_ip = (uint32_t)0;
    _md5 = new char[33];

    _start_callback    = NULL;
    _end_callback      = NULL;
    _progress_callback = NULL;
    _error_callback    = NULL;
}

void ArduinoOTAClass::onStart(OTA_CALLBACK(fn)){
    _start_callback = fn;
}

void ArduinoOTAClass::onEnd(OTA_CALLBACK(fn)){
    _end_callback = fn;
}

void ArduinoOTAClass::onProgress(OTA_CALLBACK_PROGRESS(fn)){
    _progress_callback = fn;
}

void ArduinoOTAClass::onError(OTA_CALLBACK_ERROR(fn)){
    _error_callback = fn;
}

ArduinoOTAClass::~ArduinoOTAClass(){
    delete _udp_ota;
}

void ArduinoOTAClass::setPort(uint16_t port){
  if(!_initialized && !_port && port){
    _port = port;
  }
}

void ArduinoOTAClass::setHostname(const char * hostname){
  if(!_initialized && !_hostname && hostname){
    _hostname = new char[strlen(hostname)];
    sprintf(_hostname, "%s", hostname);
  }
}

void ArduinoOTAClass::setPassword(const char * password){
  if(!_initialized && !_password && password){
    _password = new char[strlen(password)];
    sprintf(_password, "%s", password);
  }
}

void ArduinoOTAClass::begin() {
  if(_initialized)
    return;
  _initialized = true;
  if(!_hostname){
    _hostname = new char[15];
    sprintf(_hostname, "esp8266-%02x", ESP.getChipId());
  }
  if(!_port)
    _port = 8266;

  _udp_ota->begin(_port);
  MDNS.begin(_hostname);
  if(_password){
    _nonce = new char[33];
    MDNS.enableArduino(_port, true);
  } else
    MDNS.enableArduino(_port);
  _state = OTA_IDLE;
#if OTA_DEBUG
  Serial.printf("OTA server at: %s.local:%u\n", _hostname, _port);
#endif
}

void ArduinoOTAClass::_runUpdate(){
  if(!Update.begin(_size, _cmd)){
#if OTA_DEBUG
    Serial.println("Update Begin Error");
#endif
    if (_error_callback) _error_callback(OTA_BEGIN_ERROR);
    _udp_ota->begin(_port);
    _state = OTA_IDLE;
    return;
  }
  Update.setMD5(_md5);
  WiFiUDP::stopAll();
  WiFiClient::stopAll();

  if (_start_callback) _start_callback();
  if (_progress_callback) _progress_callback(0, _size);

  WiFiClient client;
  if (!client.connect(_ota_ip, _ota_port)) {
#if OTA_DEBUG
    Serial.printf("Connect Failed\n");
#endif
    _udp_ota->begin(_port);
    if (_error_callback) _error_callback(OTA_CONNECT_ERROR);
    _state = OTA_IDLE;
  }

  uint32_t written, total = 0;
  while(!Update.isFinished() && client.connected()){
    int waited = 1000;
    while(!client.available() && waited--)
      delay(1);
    if(!waited){
#if OTA_DEBUG
      Serial.printf("Recieve Failed\n");
#endif
      _udp_ota->begin(_port);
      if (_error_callback) _error_callback(OTA_RECIEVE_ERROR);
      _state = OTA_IDLE;
    }
    written = Update.write(client);
    if(written > 0){
      client.print(written, DEC);
      total += written;
      if(_progress_callback) _progress_callback(total, _size);
    }
  }

  if(Update.end()){
    client.print("OK");
#if OTA_DEBUG
    Serial.printf("Update Success\nRebooting...\n");
#endif
    if(_end_callback) _end_callback();
    ESP.restart();
  } else {
    _udp_ota->begin(_port);
    if (_error_callback) _error_callback(OTA_END_ERROR);
    Update.printError(client);
#if OTA_DEBUG
    Update.printError(Serial);
#endif
    _state = OTA_IDLE;
  }
}

void ArduinoOTAClass::handle() {
  if (!*_udp_ota) {
    _udp_ota->begin(_port);
#if OTA_DEBUG
    Serial.println("OTA restarted");
#endif
  }

  if (!_udp_ota->parsePacket()) return;

  if(_state == OTA_IDLE){
    int cmd = _udp_ota->parseInt();
    if(cmd != U_FLASH && cmd != U_SPIFFS)
      return;
    _ota_ip = _udp_ota->remoteIP();
    _cmd  = cmd;
    _ota_port = _udp_ota->parseInt();
    _size = _udp_ota->parseInt();
    _udp_ota->read();
    sprintf(_md5, "%s", _udp_ota->readStringUntil('\n').c_str());
    if(strlen(_md5) != 32)
      return;

#if OTA_DEBUG
    Serial.print("Update Start: ip:");
    Serial.print(_ota_ip);
    Serial.printf(", port:%d, size:%d, md5:%s\n", _ota_port, _size, _md5);
#endif

    _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
    if(_password){
      MD5Builder nonce_md5;
      nonce_md5.begin();
      nonce_md5.add(String(micros()));
      nonce_md5.calculate();
      nonce_md5.getChars(_nonce);
      _udp_ota->printf("AUTH %s", _nonce);
      _udp_ota->endPacket();
      _state = OTA_WAITAUTH;
      return;
    } else {
      _udp_ota->print("OK");
      _udp_ota->endPacket();
      _state = OTA_RUNUPDATE;
    }
  } else if(_state == OTA_WAITAUTH){
    int cmd = _udp_ota->parseInt();
    if(cmd != U_AUTH){
      _state = OTA_IDLE;
      return;
    }
    _udp_ota->read();
    String cnonce = _udp_ota->readStringUntil(' ');
    String response = _udp_ota->readStringUntil('\n');
    if(cnonce.length() != 32 || response.length() != 32){
      _state = OTA_IDLE;
      return;
    }

    MD5Builder _passmd5;
    _passmd5.begin();
    _passmd5.add(_password);
    _passmd5.calculate();
    String passmd5 = _passmd5.toString();

    String challenge = passmd5 + ":" + String(_nonce) + ":" + cnonce;
    MD5Builder _challengemd5;
    _challengemd5.begin();
    _challengemd5.add(challenge);
    _challengemd5.calculate();
    String result = _challengemd5.toString();

    if(result.equals(response)){
      _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
      _udp_ota->print("OK");
      _udp_ota->endPacket();
      _state = OTA_RUNUPDATE;
    } else {
      _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
      _udp_ota->print("Authentication Failed");
      _udp_ota->endPacket();
      if (_error_callback) _error_callback(OTA_AUTH_ERROR);
      _state = OTA_IDLE;
    }
  }

  if(_state == OTA_RUNUPDATE)
    _runUpdate();
}

ArduinoOTAClass ArduinoOTA;
<commit_msg>Let the socket to properly close<commit_after>#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include "ArduinoOTA.h"
#include "MD5Builder.h"

//#define OTA_DEBUG 1

#define U_AUTH 200

ArduinoOTAClass::ArduinoOTAClass()
{
    _udp_ota = new WiFiUDP();
    _password = 0;
    _hostname = 0;
    _port = 0;
    _nonce = 0;
    _state = OTA_IDLE;

    _size = 0;
    _cmd = 0;
    _ota_port = 0;
    _ota_ip = (uint32_t)0;
    _md5 = new char[33];

    _start_callback    = NULL;
    _end_callback      = NULL;
    _progress_callback = NULL;
    _error_callback    = NULL;
}

void ArduinoOTAClass::onStart(OTA_CALLBACK(fn)){
    _start_callback = fn;
}

void ArduinoOTAClass::onEnd(OTA_CALLBACK(fn)){
    _end_callback = fn;
}

void ArduinoOTAClass::onProgress(OTA_CALLBACK_PROGRESS(fn)){
    _progress_callback = fn;
}

void ArduinoOTAClass::onError(OTA_CALLBACK_ERROR(fn)){
    _error_callback = fn;
}

ArduinoOTAClass::~ArduinoOTAClass(){
    delete _udp_ota;
}

void ArduinoOTAClass::setPort(uint16_t port){
  if(!_initialized && !_port && port){
    _port = port;
  }
}

void ArduinoOTAClass::setHostname(const char * hostname){
  if(!_initialized && !_hostname && hostname){
    _hostname = new char[strlen(hostname)];
    sprintf(_hostname, "%s", hostname);
  }
}

void ArduinoOTAClass::setPassword(const char * password){
  if(!_initialized && !_password && password){
    _password = new char[strlen(password)];
    sprintf(_password, "%s", password);
  }
}

void ArduinoOTAClass::begin() {
  if(_initialized)
    return;
  _initialized = true;
  if(!_hostname){
    _hostname = new char[15];
    sprintf(_hostname, "esp8266-%02x", ESP.getChipId());
  }
  if(!_port)
    _port = 8266;

  _udp_ota->begin(_port);
  MDNS.begin(_hostname);
  if(_password){
    _nonce = new char[33];
    MDNS.enableArduino(_port, true);
  } else
    MDNS.enableArduino(_port);
  _state = OTA_IDLE;
#if OTA_DEBUG
  Serial.printf("OTA server at: %s.local:%u\n", _hostname, _port);
#endif
}

void ArduinoOTAClass::_runUpdate(){
  if(!Update.begin(_size, _cmd)){
#if OTA_DEBUG
    Serial.println("Update Begin Error");
#endif
    if (_error_callback) _error_callback(OTA_BEGIN_ERROR);
    _udp_ota->begin(_port);
    _state = OTA_IDLE;
    return;
  }
  Update.setMD5(_md5);
  WiFiUDP::stopAll();
  WiFiClient::stopAll();

  if (_start_callback) _start_callback();
  if (_progress_callback) _progress_callback(0, _size);

  WiFiClient client;
  if (!client.connect(_ota_ip, _ota_port)) {
#if OTA_DEBUG
    Serial.printf("Connect Failed\n");
#endif
    _udp_ota->begin(_port);
    if (_error_callback) _error_callback(OTA_CONNECT_ERROR);
    _state = OTA_IDLE;
  }

  uint32_t written, total = 0;
  while(!Update.isFinished() && client.connected()){
    int waited = 1000;
    while(!client.available() && waited--)
      delay(1);
    if(!waited){
#if OTA_DEBUG
      Serial.printf("Recieve Failed\n");
#endif
      _udp_ota->begin(_port);
      if (_error_callback) _error_callback(OTA_RECIEVE_ERROR);
      _state = OTA_IDLE;
    }
    written = Update.write(client);
    if(written > 0){
      client.print(written, DEC);
      total += written;
      if(_progress_callback) _progress_callback(total, _size);
    }
  }

  if(Update.end()){
    client.print("OK");
    client.stop();
    delay(10);
#if OTA_DEBUG
    Serial.printf("Update Success\nRebooting...\n");
#endif
    if(_end_callback) _end_callback();
    ESP.restart();
  } else {
    _udp_ota->begin(_port);
    if (_error_callback) _error_callback(OTA_END_ERROR);
    Update.printError(client);
#if OTA_DEBUG
    Update.printError(Serial);
#endif
    _state = OTA_IDLE;
  }
}

void ArduinoOTAClass::handle() {
  if (!*_udp_ota) {
    _udp_ota->begin(_port);
#if OTA_DEBUG
    Serial.println("OTA restarted");
#endif
  }

  if (!_udp_ota->parsePacket()) return;

  if(_state == OTA_IDLE){
    int cmd = _udp_ota->parseInt();
    if(cmd != U_FLASH && cmd != U_SPIFFS)
      return;
    _ota_ip = _udp_ota->remoteIP();
    _cmd  = cmd;
    _ota_port = _udp_ota->parseInt();
    _size = _udp_ota->parseInt();
    _udp_ota->read();
    sprintf(_md5, "%s", _udp_ota->readStringUntil('\n').c_str());
    if(strlen(_md5) != 32)
      return;

#if OTA_DEBUG
    Serial.print("Update Start: ip:");
    Serial.print(_ota_ip);
    Serial.printf(", port:%d, size:%d, md5:%s\n", _ota_port, _size, _md5);
#endif

    _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
    if(_password){
      MD5Builder nonce_md5;
      nonce_md5.begin();
      nonce_md5.add(String(micros()));
      nonce_md5.calculate();
      nonce_md5.getChars(_nonce);
      _udp_ota->printf("AUTH %s", _nonce);
      _udp_ota->endPacket();
      _state = OTA_WAITAUTH;
      return;
    } else {
      _udp_ota->print("OK");
      _udp_ota->endPacket();
      _state = OTA_RUNUPDATE;
    }
  } else if(_state == OTA_WAITAUTH){
    int cmd = _udp_ota->parseInt();
    if(cmd != U_AUTH){
      _state = OTA_IDLE;
      return;
    }
    _udp_ota->read();
    String cnonce = _udp_ota->readStringUntil(' ');
    String response = _udp_ota->readStringUntil('\n');
    if(cnonce.length() != 32 || response.length() != 32){
      _state = OTA_IDLE;
      return;
    }

    MD5Builder _passmd5;
    _passmd5.begin();
    _passmd5.add(_password);
    _passmd5.calculate();
    String passmd5 = _passmd5.toString();

    String challenge = passmd5 + ":" + String(_nonce) + ":" + cnonce;
    MD5Builder _challengemd5;
    _challengemd5.begin();
    _challengemd5.add(challenge);
    _challengemd5.calculate();
    String result = _challengemd5.toString();

    if(result.equals(response)){
      _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
      _udp_ota->print("OK");
      _udp_ota->endPacket();
      _state = OTA_RUNUPDATE;
    } else {
      _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
      _udp_ota->print("Authentication Failed");
      _udp_ota->endPacket();
      if (_error_callback) _error_callback(OTA_AUTH_ERROR);
      _state = OTA_IDLE;
    }
  }

  if(_state == OTA_RUNUPDATE)
    _runUpdate();
}

ArduinoOTAClass ArduinoOTA;
<|endoftext|>


<commit_before>#include "mount.hpp"
#include <silicium/ptr_observable.hpp>
#include <silicium/error_or.hpp>
#include <silicium/connecting_observable.hpp>
#include <silicium/coroutine.hpp>
#include <silicium/virtualized_observable.hpp>
#include <silicium/received_from_socket_source.hpp>
#include <silicium/sending_observable.hpp>
#include <silicium/virtualized_source.hpp>
#include <silicium/observable_source.hpp>
#include <silicium/http/http.hpp>
#include <silicium/thread.hpp>
#include <silicium/std_threading.hpp>
#include <server/path.hpp>
#include <server/directory_listing.hpp>
#include <fuse.h>
#include <future>
#include <boost/ref.hpp>

namespace fileserver
{
	namespace
	{
		using file_offset = std::intmax_t;

		struct linear_file
		{
			file_offset size;
			Si::unique_observable<Si::error_or<Si::incoming_bytes>> content;
		};

		struct file_service
		{
			virtual ~file_service();
			virtual Si::unique_observable<Si::error_or<linear_file>> open(unknown_digest const &name) = 0;
		};

		file_service::~file_service()
		{
		}

		struct http_file_service : file_service
		{
			explicit http_file_service(boost::asio::io_service &io, boost::asio::ip::tcp::endpoint server)
				: io(&io)
				, server(server)
			{
			}

			virtual Si::unique_observable<Si::error_or<linear_file>> open(unknown_digest const &name) SILICIUM_OVERRIDE
			{
				return Si::erase_unique(Si::make_coroutine<Si::error_or<linear_file>>(std::bind(&http_file_service::open_impl, this, std::placeholders::_1, name)));
			}

		private:

			boost::asio::io_service *io = nullptr;
			boost::asio::ip::tcp::endpoint server;

			void open_impl(
				Si::yield_context<Si::error_or<linear_file>> yield,
				unknown_digest const &requested_name)
			{
				auto socket = std::make_shared<boost::asio::ip::tcp::socket>(*io);
				Si::connecting_observable connector(*socket, server);
				{
					boost::optional<boost::system::error_code> const ec = yield.get_one(connector);
					assert(ec);
					if (*ec)
					{
						return yield(*ec);
					}
				}

				std::vector<char> request_buffer;
				{
					Si::http::request_header request;
					request.http_version = "HTTP/1.0";
					request.method = "GET";
					request.path = "/";
					encode_ascii_hex_digits(requested_name.begin(), requested_name.end(), std::back_inserter(request.path));
					request.arguments["Host"] = server.address().to_string();
					auto request_sink = Si::make_container_sink(request_buffer);
					Si::http::write_header(request_sink, request);
				}
				Si::sending_observable sending(*socket, boost::make_iterator_range(request_buffer.data(), request_buffer.data() + request_buffer.size()));
				{
					boost::optional<Si::error_or<std::size_t>> const ec = yield.get_one(sending);
					assert(ec);
					if (ec->error())
					{
						return yield(*ec->error());
					}
					assert(ec->get() == request_buffer.size());
				}

				std::array<char, 8192> buffer;
				Si::socket_observable receiving(*socket, boost::make_iterator_range(buffer.data(), buffer.data() + buffer.size()));
				auto receiving_source = Si::virtualize_source(Si::make_observable_source(std::move(receiving), yield));
				Si::received_from_socket_source response_source(receiving_source);
				boost::optional<Si::http::response_header> const response_header = Si::http::parse_response_header(response_source);
				if (!response_header)
				{
					throw std::logic_error("todo 1");
				}

				auto content_length_header = response_header->arguments.find("Content-Length");
				if (content_length_header == response_header->arguments.end())
				{
					throw std::logic_error("todo 2");
				}

				std::vector<byte> first_part(response_source.buffered().begin, response_source.buffered().end);
				file_offset const file_size = boost::lexical_cast<file_offset>(content_length_header->second);
				linear_file file{file_size, Si::erase_unique(Si::make_coroutine<Si::error_or<Si::incoming_bytes>>(
					[first_part, socket, file_size]
						(Si::yield_context<Si::error_or<Si::incoming_bytes>> yield)
					{
						yield(Si::incoming_bytes(
							reinterpret_cast<char const *>(first_part.data()),
							reinterpret_cast<char const *>(first_part.data() + first_part.size())));
						file_offset receive_counter = first_part.size();
						std::array<char, 8192> buffer;
						Si::socket_observable receiving(*socket, boost::make_iterator_range(buffer.data(), buffer.data() + buffer.size()));
						while (receive_counter < file_size)
						{
							auto piece = yield.get_one(receiving);
							if (!piece)
							{
								break;
							}
							if (!piece->is_error())
							{
								receive_counter += piece->get().size();
							}
							yield(*piece);
						}
					}))};
				yield(std::move(file));
			}
		};

		struct file_system
		{
			boost::asio::io_service io;
			std::unique_ptr<file_service> backend;
			std::future<void> worker;
			boost::optional<boost::asio::io_service::work> keep_running;
			unknown_digest root;
		};

		char const * const hello_path = "/hello";
		char const * const hello_str = "Hello, fuse!\n";

		unknown_digest root;

		void *init(struct fuse_conn_info *conn)
		{
			assert(!root.empty());
			auto fs = Si::make_unique<file_system>();
			fs->backend = Si::make_unique<http_file_service>(fs->io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::loopback(), 8080));
			fs->keep_running = boost::in_place(boost::ref(fs->io));
			auto &io = fs->io;
			fs->worker = std::async(std::launch::async, [&io]()
			{
				io.run();
			});
			fs->root = std::move(root);
			return fs.release();
		}

		void destroy(void *private_data)
		{
			std::unique_ptr<file_system>(static_cast<file_system *>(private_data));
		}

		int hello_getattr(const char *path, struct stat *stbuf)
		{
			int res = 0;

			memset(stbuf, 0, sizeof(struct stat));
			if (strcmp(path, "/") == 0) {
				stbuf->st_mode = S_IFDIR | 0755;
				stbuf->st_nlink = 2;
			} else if (strcmp(path, hello_path) == 0) {
				stbuf->st_mode = S_IFREG | 0444;
				stbuf->st_nlink = 1;
				stbuf->st_size = strlen(hello_str);
			} else
				res = -ENOENT;

			return res;
		}

		struct local_yield_context : Si::detail::yield_context_impl<Si::nothing>
		{
			virtual void push_result(Si::nothing result) SILICIUM_OVERRIDE
			{
				boost::ignore_unused(result);
				SILICIUM_UNREACHABLE();
			}

			virtual void get_one(Si::observable<Si::nothing> &target) SILICIUM_OVERRIDE
			{
				Si::detail::event<Si::std_threading> waiting;
				waiting.block(Si::ref(target));
			}
		};

		int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
					 off_t offset, struct fuse_file_info *fi)
		{
			(void) offset;
			(void) fi;

			Si::error_or<linear_file> file;
			file_system * const fs = static_cast<file_system *>(fuse_get_context()->private_data);
			Si::detail::event<Si::std_threading> waiting;
			waiting.block(Si::transform(fs->backend->open(fs->root), [&file](Si::error_or<linear_file> opened_file)
			{
				file = std::move(opened_file);
				return Si::nothing();
			}));

			if (file.is_error())
			{
				return -ENOENT;
			}

			local_yield_context yield_impl;
			Si::yield_context<Si::nothing> yield(yield_impl);
			auto receiving_source = Si::virtualize_source(Si::make_observable_source(std::move(file).get().content, yield));
			Si::received_from_socket_source content_source(receiving_source);
			auto parsed = deserialize_json(std::move(content_source));
			return Si::visit<int>(
				parsed,
				[buf, filler](std::unique_ptr<directory_listing> &listing)
			{
				filler(buf, ".", NULL, 0);
				filler(buf, "..", NULL, 0);
				for (auto const &entry : listing->entries)
				{
					struct stat s{};
					s.st_size = 100;
					s.st_mode = 0777 | __S_IFREG;
					filler(buf, entry.first.c_str(), &s, 0);
				}
				return 0;
			},
				[](std::size_t)
			{
				return -ENOENT;
			});
		}

		int hello_open(const char *path, struct fuse_file_info *fi)
		{
			if (strcmp(path, hello_path) != 0)
				return -ENOENT;

			if ((fi->flags & 3) != O_RDONLY)
				return -EACCES;

			return 0;
		}

		int hello_read(const char *path, char *buf, size_t size, off_t offset,
					  struct fuse_file_info *fi)
		{
			size_t len;
			(void) fi;
			if(strcmp(path, hello_path) != 0)
				return -ENOENT;

			len = strlen(hello_str);
			if (static_cast<size_t>(offset) < len) {
				if (offset + size > len)
					size = len - offset;
				memcpy(buf, hello_str + offset, size);
			} else
				size = 0;

			return static_cast<int>(size);
		}

		struct user_data_for_fuse
		{

		};

		struct chan_deleter
		{
			fileserver::path mount_point;

			void operator()(fuse_chan *chan) const
			{
				fuse_unmount(mount_point.c_str(), chan);
			}
		};

		struct fuse_deleter
		{
			void operator()(fuse *f) const
			{
				fuse_destroy(f);
			}
		};
	}

	void mount_directory(unknown_digest const &root_digest, boost::filesystem::path const &mount_point)
	{
		chan_deleter deleter;
		deleter.mount_point = fileserver::path(mount_point);
		fuse_args args{};
		std::unique_ptr<fuse_chan, chan_deleter> chan(fuse_mount(mount_point.c_str(), &args), std::move(deleter));
		if (!chan)
		{
			throw std::runtime_error("fuse_mount failure");
		}
		fuse_operations operations{};
		operations.init = init;
		operations.destroy = destroy;
		operations.getattr = hello_getattr;
		operations.readdir = hello_readdir;
		operations.open = hello_open;
		operations.read = hello_read;
		root = root_digest;
		user_data_for_fuse user_data;
		std::unique_ptr<fuse, fuse_deleter> const f(fuse_new(chan.get(), &args, &operations, sizeof(operations), &user_data));
		if (!f)
		{
			throw std::runtime_error("fuse_new failure");
		}

		//fuse_new seems to take ownership of the fuse_chan
		chan.release();

		fuse_loop(f.get());
	}
}
<commit_msg>improve error handling<commit_after>#include "mount.hpp"
#include <silicium/ptr_observable.hpp>
#include <silicium/error_or.hpp>
#include <silicium/connecting_observable.hpp>
#include <silicium/coroutine.hpp>
#include <silicium/virtualized_observable.hpp>
#include <silicium/received_from_socket_source.hpp>
#include <silicium/sending_observable.hpp>
#include <silicium/virtualized_source.hpp>
#include <silicium/observable_source.hpp>
#include <silicium/http/http.hpp>
#include <silicium/thread.hpp>
#include <silicium/std_threading.hpp>
#include <server/path.hpp>
#include <server/directory_listing.hpp>
#include <fuse.h>
#include <future>
#include <boost/ref.hpp>

namespace fileserver
{
	enum class service_error
	{
		file_not_found
	};

	struct service_error_category : boost::system::error_category
	{
		virtual const char *name() const BOOST_SYSTEM_NOEXCEPT SILICIUM_OVERRIDE
		{
			return "service error";
		}

		virtual std::string message(int ev) const SILICIUM_OVERRIDE
		{
			switch (ev)
			{
			case static_cast<int>(service_error::file_not_found): return "file not found";
			}
			SILICIUM_UNREACHABLE();
		}

		virtual bool equivalent(
			boost::system::error_code const &code,
			int condition) const BOOST_SYSTEM_NOEXCEPT SILICIUM_OVERRIDE
		{
			boost::ignore_unused_variable_warning(code);
			boost::ignore_unused_variable_warning(condition);
			return false;
		}
	};

	inline boost::system::error_category const &get_system_error_category()
	{
		static service_error_category const instance;
		return instance;
	}

	inline boost::system::error_code make_error_code(service_error error)
	{
		return boost::system::error_code(static_cast<int>(error), get_system_error_category());
	}
}

namespace boost
{
	namespace system
	{
		template<>
	    struct is_error_code_enum<fileserver::service_error> : std::true_type
		{
		};
	}
}

namespace fileserver
{
	namespace
	{

		using file_offset = std::intmax_t;

		struct linear_file
		{
			file_offset size;
			Si::unique_observable<Si::error_or<Si::incoming_bytes>> content;
		};

		struct file_service
		{
			virtual ~file_service();
			virtual Si::unique_observable<Si::error_or<linear_file>> open(unknown_digest const &name) = 0;
		};

		file_service::~file_service()
		{
		}

		struct http_file_service : file_service
		{
			explicit http_file_service(boost::asio::io_service &io, boost::asio::ip::tcp::endpoint server)
				: io(&io)
				, server(server)
			{
			}

			virtual Si::unique_observable<Si::error_or<linear_file>> open(unknown_digest const &name) SILICIUM_OVERRIDE
			{
				return Si::erase_unique(Si::make_coroutine<Si::error_or<linear_file>>(std::bind(&http_file_service::open_impl, this, std::placeholders::_1, name)));
			}

		private:

			boost::asio::io_service *io = nullptr;
			boost::asio::ip::tcp::endpoint server;

			void open_impl(
				Si::yield_context<Si::error_or<linear_file>> yield,
				unknown_digest const &requested_name)
			{
				auto socket = std::make_shared<boost::asio::ip::tcp::socket>(*io);
				Si::connecting_observable connector(*socket, server);
				{
					boost::optional<boost::system::error_code> const ec = yield.get_one(connector);
					assert(ec);
					if (*ec)
					{
						return yield(*ec);
					}
				}

				std::vector<char> request_buffer;
				{
					Si::http::request_header request;
					request.http_version = "HTTP/1.0";
					request.method = "GET";
					request.path = "/";
					encode_ascii_hex_digits(requested_name.begin(), requested_name.end(), std::back_inserter(request.path));
					request.arguments["Host"] = server.address().to_string();
					auto request_sink = Si::make_container_sink(request_buffer);
					Si::http::write_header(request_sink, request);
				}
				Si::sending_observable sending(*socket, boost::make_iterator_range(request_buffer.data(), request_buffer.data() + request_buffer.size()));
				{
					boost::optional<Si::error_or<std::size_t>> const ec = yield.get_one(sending);
					assert(ec);
					if (ec->error())
					{
						return yield(*ec->error());
					}
					assert(ec->get() == request_buffer.size());
				}

				std::array<char, 8192> buffer;
				Si::socket_observable receiving(*socket, boost::make_iterator_range(buffer.data(), buffer.data() + buffer.size()));
				auto receiving_source = Si::virtualize_source(Si::make_observable_source(std::move(receiving), yield));
				Si::received_from_socket_source response_source(receiving_source);
				boost::optional<Si::http::response_header> const response_header = Si::http::parse_response_header(response_source);
				if (!response_header)
				{
					throw std::logic_error("todo 1");
				}

				if (response_header->status != 200)
				{
					return yield(boost::system::error_code(service_error::file_not_found));
				}

				auto content_length_header = response_header->arguments.find("Content-Length");
				if (content_length_header == response_header->arguments.end())
				{
					throw std::logic_error("todo 2");
				}

				std::vector<byte> first_part(response_source.buffered().begin, response_source.buffered().end);
				file_offset const file_size = boost::lexical_cast<file_offset>(content_length_header->second);
				linear_file file{file_size, Si::erase_unique(Si::make_coroutine<Si::error_or<Si::incoming_bytes>>(
					[first_part, socket, file_size]
						(Si::yield_context<Si::error_or<Si::incoming_bytes>> yield)
					{
						yield(Si::incoming_bytes(
							reinterpret_cast<char const *>(first_part.data()),
							reinterpret_cast<char const *>(first_part.data() + first_part.size())));
						file_offset receive_counter = first_part.size();
						std::array<char, 8192> buffer;
						Si::socket_observable receiving(*socket, boost::make_iterator_range(buffer.data(), buffer.data() + buffer.size()));
						while (receive_counter < file_size)
						{
							auto piece = yield.get_one(receiving);
							if (!piece)
							{
								break;
							}
							if (!piece->is_error())
							{
								receive_counter += piece->get().size();
							}
							yield(*piece);
						}
					}))};
				yield(std::move(file));
			}
		};

		struct file_system
		{
			boost::asio::io_service io;
			std::unique_ptr<file_service> backend;
			std::future<void> worker;
			boost::optional<boost::asio::io_service::work> keep_running;
			unknown_digest root;
		};

		char const * const hello_path = "/hello";
		char const * const hello_str = "Hello, fuse!\n";

		unknown_digest root;

		void *init(struct fuse_conn_info *conn)
		{
			assert(!root.empty());
			auto fs = Si::make_unique<file_system>();
			fs->backend = Si::make_unique<http_file_service>(fs->io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::loopback(), 8080));
			fs->keep_running = boost::in_place(boost::ref(fs->io));
			auto &io = fs->io;
			fs->worker = std::async(std::launch::async, [&io]()
			{
				for (;;)
				{
					try
					{
						io.run();
						break;
					}
					catch (...)
					{
						continue;
					}
				}
			});
			fs->root = std::move(root);
			return fs.release();
		}

		void destroy(void *private_data)
		{
			std::unique_ptr<file_system>(static_cast<file_system *>(private_data));
		}

		int hello_getattr(const char *path, struct stat *stbuf)
		{
			int res = 0;

			memset(stbuf, 0, sizeof(struct stat));
			if (strcmp(path, "/") == 0) {
				stbuf->st_mode = S_IFDIR | 0755;
				stbuf->st_nlink = 2;
			} else if (strcmp(path, hello_path) == 0) {
				stbuf->st_mode = S_IFREG | 0444;
				stbuf->st_nlink = 1;
				stbuf->st_size = strlen(hello_str);
			} else
				res = -ENOENT;

			return res;
		}

		struct local_yield_context : Si::detail::yield_context_impl<Si::nothing>
		{
			virtual void push_result(Si::nothing result) SILICIUM_OVERRIDE
			{
				boost::ignore_unused(result);
				SILICIUM_UNREACHABLE();
			}

			virtual void get_one(Si::observable<Si::nothing> &target) SILICIUM_OVERRIDE
			{
				Si::detail::event<Si::std_threading> waiting;
				waiting.block(Si::ref(target));
			}
		};

		int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
					 off_t offset, struct fuse_file_info *fi)
		{
			(void) offset;
			(void) fi;

			try
			{
				Si::error_or<linear_file> file;
				file_system * const fs = static_cast<file_system *>(fuse_get_context()->private_data);
				Si::detail::event<Si::std_threading> waiting;
				waiting.block(Si::transform(fs->backend->open(fs->root), [&file](Si::error_or<linear_file> opened_file)
				{
					file = std::move(opened_file);
					return Si::nothing();
				}));

				if (file.is_error())
				{
					return -ENOENT;
				}

				local_yield_context yield_impl;
				Si::yield_context<Si::nothing> yield(yield_impl);
				auto receiving_source = Si::virtualize_source(Si::make_observable_source(std::move(file).get().content, yield));
				Si::received_from_socket_source content_source(receiving_source);
				auto parsed = deserialize_json(std::move(content_source));
				return Si::visit<int>(
					parsed,
					[buf, filler](std::unique_ptr<directory_listing> &listing)
				{
					filler(buf, ".", NULL, 0);
					filler(buf, "..", NULL, 0);
					for (auto const &entry : listing->entries)
					{
						struct stat s{};
						s.st_size = 100;
						s.st_mode = 0777 | S_IFREG;
						s.st_nlink = 1;
						filler(buf, entry.first.c_str(), &s, 0);
					}
					return 0;
				},
					[](std::size_t)
				{
					return -ENOENT;
				});
			}
			catch (...)
			{
				return -EIO;
			}
		}

		int hello_open(const char *path, struct fuse_file_info *fi)
		{
			if (strcmp(path, hello_path) != 0)
				return -ENOENT;

			if ((fi->flags & 3) != O_RDONLY)
				return -EACCES;

			return 0;
		}

		int hello_read(const char *path, char *buf, size_t size, off_t offset,
					  struct fuse_file_info *fi)
		{
			size_t len;
			(void) fi;
			if(strcmp(path, hello_path) != 0)
				return -ENOENT;

			len = strlen(hello_str);
			if (static_cast<size_t>(offset) < len) {
				if (offset + size > len)
					size = len - offset;
				memcpy(buf, hello_str + offset, size);
			} else
				size = 0;

			return static_cast<int>(size);
		}

		struct user_data_for_fuse
		{

		};

		struct chan_deleter
		{
			fileserver::path mount_point;

			void operator()(fuse_chan *chan) const
			{
				fuse_unmount(mount_point.c_str(), chan);
			}
		};

		struct fuse_deleter
		{
			void operator()(fuse *f) const
			{
				fuse_destroy(f);
			}
		};
	}

	void mount_directory(unknown_digest const &root_digest, boost::filesystem::path const &mount_point)
	{
		chan_deleter deleter;
		deleter.mount_point = fileserver::path(mount_point);
		fuse_args args{};
		std::unique_ptr<fuse_chan, chan_deleter> chan(fuse_mount(mount_point.c_str(), &args), std::move(deleter));
		if (!chan)
		{
			throw std::runtime_error("fuse_mount failure");
		}
		fuse_operations operations{};
		operations.init = init;
		operations.destroy = destroy;
		operations.getattr = hello_getattr;
		operations.readdir = hello_readdir;
		operations.open = hello_open;
		operations.read = hello_read;
		root = root_digest;
		user_data_for_fuse user_data;
		std::unique_ptr<fuse, fuse_deleter> const f(fuse_new(chan.get(), &args, &operations, sizeof(operations), &user_data));
		if (!f)
		{
			throw std::runtime_error("fuse_new failure");
		}

		//fuse_new seems to take ownership of the fuse_chan
		chan.release();

		fuse_loop(f.get());
	}
}
<|endoftext|>


<commit_before>/*
	This file is part of solidity.

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

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

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2016
 * Solidity inline assembly parser.
 */

#include <libsolidity/inlineasm/AsmParser.h>
#include <ctype.h>
#include <algorithm>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/Exceptions.h>

using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::assembly;

shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scanner)
{
	try
	{
		m_scanner = _scanner;
		return make_shared<Block>(parseBlock());
	}
	catch (FatalError const&)
	{
		if (m_errors.empty())
			throw; // Something is weird here, rather throw again.
	}
	return nullptr;
}

assembly::Block Parser::parseBlock()
{
	assembly::Block block = createWithLocation<Block>();
	expectToken(Token::LBrace);
	while (m_scanner->currentToken() != Token::RBrace)
		block.statements.emplace_back(parseStatement());
	block.location.end = endPosition();
	m_scanner->next();
	return block;
}

assembly::Statement Parser::parseStatement()
{
	switch (m_scanner->currentToken())
	{
	case Token::Let:
		return parseVariableDeclaration();
	case Token::Function:
		return parseFunctionDefinition();
	case Token::LBrace:
		return parseBlock();
	case Token::Assign:
	{
		if (m_julia)
			break;
		assembly::Assignment assignment = createWithLocation<assembly::Assignment>();
		m_scanner->next();
		expectToken(Token::Colon);
		assignment.variableName.location = location();
		assignment.variableName.name = m_scanner->currentLiteral();
		if (!m_julia && instructions().count(assignment.variableName.name))
			fatalParserError("Identifier expected, got instruction name.");
		assignment.location.end = endPosition();
		expectToken(Token::Identifier);
		return assignment;
	}
	case Token::Return: // opcode
	case Token::Byte: // opcode
	default:
		break;
	}
	// Options left:
	// Simple instruction (might turn into functional),
	// literal,
	// identifier (might turn into label or functional assignment)
	Statement statement(parseElementaryOperation());
	switch (m_scanner->currentToken())
	{
	case Token::LParen:
		return parseFunctionalInstruction(std::move(statement));
	case Token::Colon:
	{
		if (statement.type() != typeid(assembly::Identifier))
			fatalParserError("Label name / variable name must precede \":\".");
		assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement);
		m_scanner->next();
		// identifier:=: should be parsed as identifier: =: (i.e. a label),
		// while identifier:= (being followed by a non-colon) as identifier := (assignment).
		if (m_scanner->currentToken() == Token::Assign && m_scanner->peekNextToken() != Token::Colon)
		{
			// functional assignment
			FunctionalAssignment funAss = createWithLocation<FunctionalAssignment>(identifier.location);
			if (!m_julia && instructions().count(identifier.name))
				fatalParserError("Cannot use instruction names for identifier names.");
			m_scanner->next();
			funAss.variableName = identifier;
			funAss.value.reset(new Statement(parseExpression()));
			funAss.location.end = locationOf(*funAss.value).end;
			return funAss;
		}
		else
		{
			// label
			Label label = createWithLocation<Label>(identifier.location);
			label.name = identifier.name;
			return label;
		}
	}
	default:
		break;
	}
	return statement;
}

assembly::Statement Parser::parseExpression()
{
	Statement operation = parseElementaryOperation(true);
	if (m_scanner->currentToken() == Token::LParen)
		return parseFunctionalInstruction(std::move(operation));
	else
		return operation;
}

std::map<string, dev::solidity::Instruction> const& Parser::instructions()
{
	// Allowed instructions, lowercase names.
	static map<string, dev::solidity::Instruction> s_instructions;
	if (s_instructions.empty())
	{
		for (auto const& instruction: solidity::c_instructions)
		{
			if (
				instruction.second == solidity::Instruction::JUMPDEST ||
				(solidity::Instruction::PUSH1 <= instruction.second && instruction.second <= solidity::Instruction::PUSH32)
			)
				continue;
			string name = instruction.first;
			transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
			s_instructions[name] = instruction.second;
		}

		// add alias for suicide
		s_instructions["suicide"] = solidity::Instruction::SELFDESTRUCT;
	}
	return s_instructions;
}

assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
{
	Statement ret;
	switch (m_scanner->currentToken())
	{
	case Token::Identifier:
	case Token::Return:
	case Token::Byte:
	case Token::Address:
	{
		string literal;
		if (m_scanner->currentToken() == Token::Return)
			literal = "return";
		else if (m_scanner->currentToken() == Token::Byte)
			literal = "byte";
		else if (m_scanner->currentToken() == Token::Address)
			literal = "address";
		else
			literal = m_scanner->currentLiteral();
		// first search the set of instructions.
		if (!m_julia && instructions().count(literal))
		{
			dev::solidity::Instruction const& instr = instructions().at(literal);
			if (_onlySinglePusher)
			{
				InstructionInfo info = dev::solidity::instructionInfo(instr);
				if (info.ret != 1)
					fatalParserError("Instruction " + info.name + " not allowed in this context.");
			}
			ret = Instruction{location(), instr};
		}
		else
			ret = Identifier{location(), literal};
		break;
	}
	case Token::StringLiteral:
	case Token::Number:
	{
		ret = Literal{
			location(),
			m_scanner->currentToken() == Token::Number,
			m_scanner->currentLiteral()
		};
		break;
	}
	default:
		fatalParserError("Expected elementary inline assembly operation.");
	}
	m_scanner->next();
	return ret;
}

assembly::VariableDeclaration Parser::parseVariableDeclaration()
{
	VariableDeclaration varDecl = createWithLocation<VariableDeclaration>();
	expectToken(Token::Let);
	varDecl.name = expectAsmIdentifier();
	expectToken(Token::Colon);
	expectToken(Token::Assign);
	varDecl.value.reset(new Statement(parseExpression()));
	varDecl.location.end = locationOf(*varDecl.value).end;
	return varDecl;
}

assembly::FunctionDefinition Parser::parseFunctionDefinition()
{
	FunctionDefinition funDef = createWithLocation<FunctionDefinition>();
	expectToken(Token::Function);
	funDef.name = expectAsmIdentifier();
	expectToken(Token::LParen);
	while (m_scanner->currentToken() != Token::RParen)
	{
		funDef.arguments.push_back(expectAsmIdentifier());
		if (m_scanner->currentToken() == Token::RParen)
			break;
		expectToken(Token::Comma);
	}
	expectToken(Token::RParen);
	if (m_scanner->currentToken() == Token::Sub)
	{
		expectToken(Token::Sub);
		expectToken(Token::GreaterThan);
		while (true)
		{
			funDef.returns.push_back(expectAsmIdentifier());
			if (m_scanner->currentToken() == Token::LBrace)
				break;
			expectToken(Token::Comma);
		}
	}
	funDef.body = parseBlock();
	funDef.location.end = funDef.body.location.end;
	return funDef;
}

assembly::Statement Parser::parseFunctionalInstruction(assembly::Statement&& _instruction)
{
	if (_instruction.type() == typeid(Instruction))
	{
		solAssert(!m_julia, "Instructions are invalid in JULIA");
		FunctionalInstruction ret;
		ret.instruction = std::move(boost::get<Instruction>(_instruction));
		ret.location = ret.instruction.location;
		solidity::Instruction instr = ret.instruction.instruction;
		InstructionInfo instrInfo = instructionInfo(instr);
		if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16)
			fatalParserError("DUPi instructions not allowed for functional notation");
		if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16)
			fatalParserError("SWAPi instructions not allowed for functional notation");
		expectToken(Token::LParen);
		unsigned args = unsigned(instrInfo.args);
		for (unsigned i = 0; i < args; ++i)
		{
			ret.arguments.emplace_back(parseExpression());
			if (i != args - 1)
			{
				if (m_scanner->currentToken() != Token::Comma)
					fatalParserError(string(
						"Expected comma (" +
						instrInfo.name +
						" expects " +
						boost::lexical_cast<string>(args) +
						" arguments)"
					));
				else
					m_scanner->next();
			}
		}
		ret.location.end = endPosition();
		if (m_scanner->currentToken() == Token::Comma)
			fatalParserError(
				string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)")
			);
		expectToken(Token::RParen);
		return ret;
	}
	else if (_instruction.type() == typeid(Identifier))
	{
		FunctionCall ret;
		ret.functionName = std::move(boost::get<Identifier>(_instruction));
		ret.location = ret.functionName.location;
		expectToken(Token::LParen);
		while (m_scanner->currentToken() != Token::RParen)
		{
			ret.arguments.emplace_back(parseExpression());
			if (m_scanner->currentToken() == Token::RParen)
				break;
			expectToken(Token::Comma);
		}
		ret.location.end = endPosition();
		expectToken(Token::RParen);
		return ret;
	}
	else
		fatalParserError("Assembly instruction or function name required in front of \"(\")");

	return {};
}

string Parser::expectAsmIdentifier()
{
	string name = m_scanner->currentLiteral();
	if (!m_julia && instructions().count(name))
		fatalParserError("Cannot use instruction names for identifier names.");
	expectToken(Token::Identifier);
	return name;
}
<commit_msg>Disable labels in Julia<commit_after>/*
	This file is part of solidity.

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

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

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2016
 * Solidity inline assembly parser.
 */

#include <libsolidity/inlineasm/AsmParser.h>
#include <ctype.h>
#include <algorithm>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/Exceptions.h>

using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::assembly;

shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scanner)
{
	try
	{
		m_scanner = _scanner;
		return make_shared<Block>(parseBlock());
	}
	catch (FatalError const&)
	{
		if (m_errors.empty())
			throw; // Something is weird here, rather throw again.
	}
	return nullptr;
}

assembly::Block Parser::parseBlock()
{
	assembly::Block block = createWithLocation<Block>();
	expectToken(Token::LBrace);
	while (m_scanner->currentToken() != Token::RBrace)
		block.statements.emplace_back(parseStatement());
	block.location.end = endPosition();
	m_scanner->next();
	return block;
}

assembly::Statement Parser::parseStatement()
{
	switch (m_scanner->currentToken())
	{
	case Token::Let:
		return parseVariableDeclaration();
	case Token::Function:
		return parseFunctionDefinition();
	case Token::LBrace:
		return parseBlock();
	case Token::Assign:
	{
		if (m_julia)
			break;
		assembly::Assignment assignment = createWithLocation<assembly::Assignment>();
		m_scanner->next();
		expectToken(Token::Colon);
		assignment.variableName.location = location();
		assignment.variableName.name = m_scanner->currentLiteral();
		if (!m_julia && instructions().count(assignment.variableName.name))
			fatalParserError("Identifier expected, got instruction name.");
		assignment.location.end = endPosition();
		expectToken(Token::Identifier);
		return assignment;
	}
	case Token::Return: // opcode
	case Token::Byte: // opcode
	case Token::Address: // opcode
	default:
		break;
	}
	// Options left:
	// Simple instruction (might turn into functional),
	// literal,
	// identifier (might turn into label or functional assignment)
	Statement statement(parseElementaryOperation());
	switch (m_scanner->currentToken())
	{
	case Token::LParen:
		return parseFunctionalInstruction(std::move(statement));
	case Token::Colon:
	{
		if (statement.type() != typeid(assembly::Identifier))
			fatalParserError("Label name / variable name must precede \":\".");
		assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement);
		m_scanner->next();
		// identifier:=: should be parsed as identifier: =: (i.e. a label),
		// while identifier:= (being followed by a non-colon) as identifier := (assignment).
		if (m_scanner->currentToken() == Token::Assign && m_scanner->peekNextToken() != Token::Colon)
		{
			// functional assignment
			FunctionalAssignment funAss = createWithLocation<FunctionalAssignment>(identifier.location);
			if (!m_julia && instructions().count(identifier.name))
				fatalParserError("Cannot use instruction names for identifier names.");
			m_scanner->next();
			funAss.variableName = identifier;
			funAss.value.reset(new Statement(parseExpression()));
			funAss.location.end = locationOf(*funAss.value).end;
			return funAss;
		}
		else
		{
			// label
			if (m_julia)
				fatalParserError("Labels are not supported.");
			Label label = createWithLocation<Label>(identifier.location);
			label.name = identifier.name;
			return label;
		}
	}
	default:
		break;
	}
	return statement;
}

assembly::Statement Parser::parseExpression()
{
	Statement operation = parseElementaryOperation(true);
	if (m_scanner->currentToken() == Token::LParen)
		return parseFunctionalInstruction(std::move(operation));
	else
		return operation;
}

std::map<string, dev::solidity::Instruction> const& Parser::instructions()
{
	// Allowed instructions, lowercase names.
	static map<string, dev::solidity::Instruction> s_instructions;
	if (s_instructions.empty())
	{
		for (auto const& instruction: solidity::c_instructions)
		{
			if (
				instruction.second == solidity::Instruction::JUMPDEST ||
				(solidity::Instruction::PUSH1 <= instruction.second && instruction.second <= solidity::Instruction::PUSH32)
			)
				continue;
			string name = instruction.first;
			transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
			s_instructions[name] = instruction.second;
		}

		// add alias for suicide
		s_instructions["suicide"] = solidity::Instruction::SELFDESTRUCT;
	}
	return s_instructions;
}

assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
{
	Statement ret;
	switch (m_scanner->currentToken())
	{
	case Token::Identifier:
	case Token::Return:
	case Token::Byte:
	case Token::Address:
	{
		string literal;
		if (m_scanner->currentToken() == Token::Return)
			literal = "return";
		else if (m_scanner->currentToken() == Token::Byte)
			literal = "byte";
		else if (m_scanner->currentToken() == Token::Address)
			literal = "address";
		else
			literal = m_scanner->currentLiteral();
		// first search the set of instructions.
		if (!m_julia && instructions().count(literal))
		{
			dev::solidity::Instruction const& instr = instructions().at(literal);
			if (_onlySinglePusher)
			{
				InstructionInfo info = dev::solidity::instructionInfo(instr);
				if (info.ret != 1)
					fatalParserError("Instruction " + info.name + " not allowed in this context.");
			}
			ret = Instruction{location(), instr};
		}
		else
			ret = Identifier{location(), literal};
		break;
	}
	case Token::StringLiteral:
	case Token::Number:
	{
		ret = Literal{
			location(),
			m_scanner->currentToken() == Token::Number,
			m_scanner->currentLiteral()
		};
		break;
	}
	default:
		fatalParserError("Expected elementary inline assembly operation.");
	}
	m_scanner->next();
	return ret;
}

assembly::VariableDeclaration Parser::parseVariableDeclaration()
{
	VariableDeclaration varDecl = createWithLocation<VariableDeclaration>();
	expectToken(Token::Let);
	varDecl.name = expectAsmIdentifier();
	expectToken(Token::Colon);
	expectToken(Token::Assign);
	varDecl.value.reset(new Statement(parseExpression()));
	varDecl.location.end = locationOf(*varDecl.value).end;
	return varDecl;
}

assembly::FunctionDefinition Parser::parseFunctionDefinition()
{
	FunctionDefinition funDef = createWithLocation<FunctionDefinition>();
	expectToken(Token::Function);
	funDef.name = expectAsmIdentifier();
	expectToken(Token::LParen);
	while (m_scanner->currentToken() != Token::RParen)
	{
		funDef.arguments.push_back(expectAsmIdentifier());
		if (m_scanner->currentToken() == Token::RParen)
			break;
		expectToken(Token::Comma);
	}
	expectToken(Token::RParen);
	if (m_scanner->currentToken() == Token::Sub)
	{
		expectToken(Token::Sub);
		expectToken(Token::GreaterThan);
		while (true)
		{
			funDef.returns.push_back(expectAsmIdentifier());
			if (m_scanner->currentToken() == Token::LBrace)
				break;
			expectToken(Token::Comma);
		}
	}
	funDef.body = parseBlock();
	funDef.location.end = funDef.body.location.end;
	return funDef;
}

assembly::Statement Parser::parseFunctionalInstruction(assembly::Statement&& _instruction)
{
	if (_instruction.type() == typeid(Instruction))
	{
		solAssert(!m_julia, "Instructions are invalid in JULIA");
		FunctionalInstruction ret;
		ret.instruction = std::move(boost::get<Instruction>(_instruction));
		ret.location = ret.instruction.location;
		solidity::Instruction instr = ret.instruction.instruction;
		InstructionInfo instrInfo = instructionInfo(instr);
		if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16)
			fatalParserError("DUPi instructions not allowed for functional notation");
		if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16)
			fatalParserError("SWAPi instructions not allowed for functional notation");
		expectToken(Token::LParen);
		unsigned args = unsigned(instrInfo.args);
		for (unsigned i = 0; i < args; ++i)
		{
			ret.arguments.emplace_back(parseExpression());
			if (i != args - 1)
			{
				if (m_scanner->currentToken() != Token::Comma)
					fatalParserError(string(
						"Expected comma (" +
						instrInfo.name +
						" expects " +
						boost::lexical_cast<string>(args) +
						" arguments)"
					));
				else
					m_scanner->next();
			}
		}
		ret.location.end = endPosition();
		if (m_scanner->currentToken() == Token::Comma)
			fatalParserError(
				string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)")
			);
		expectToken(Token::RParen);
		return ret;
	}
	else if (_instruction.type() == typeid(Identifier))
	{
		FunctionCall ret;
		ret.functionName = std::move(boost::get<Identifier>(_instruction));
		ret.location = ret.functionName.location;
		expectToken(Token::LParen);
		while (m_scanner->currentToken() != Token::RParen)
		{
			ret.arguments.emplace_back(parseExpression());
			if (m_scanner->currentToken() == Token::RParen)
				break;
			expectToken(Token::Comma);
		}
		ret.location.end = endPosition();
		expectToken(Token::RParen);
		return ret;
	}
	else
		fatalParserError("Assembly instruction or function name required in front of \"(\")");

	return {};
}

string Parser::expectAsmIdentifier()
{
	string name = m_scanner->currentLiteral();
	if (!m_julia && instructions().count(name))
		fatalParserError("Cannot use instruction names for identifier names.");
	expectToken(Token::Identifier);
	return name;
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#define SUITE table_index
#include "test.hpp"

#include "fixtures/events.hpp"
#include "fixtures/filesystem.hpp"

#include "vast/bitmap.hpp"
#include "vast/concept/parseable/to.hpp"
#include "vast/concept/parseable/vast/expression.hpp"
#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/vast/error.hpp"
#include "vast/concept/printable/vast/event.hpp"
#include "vast/concept/printable/vast/expression.hpp"
#include "vast/system/table_index.hpp"

using namespace vast;
using namespace vast::system;

namespace {

struct fixture : fixtures::events, fixtures::filesystem {
  fixture() {
    directory /= "column-layout";
  }
};

} // namespace <anonymous>

FIXTURE_SCOPE(table_index_tests, fixture)

TEST(bro conn logs) {
  MESSAGE("generate column layout for bro conn logs");
  const auto conn_log_type = bro_conn_log[0].type();
  auto ecols = make_table_index(directory, conn_log_type);
  REQUIRE(ecols);
  auto cols = std::move(*ecols);
  CHECK_EQUAL(cols.num_meta_columns(), 2u);
  MESSAGE("ingesting events");
  for (auto& entry : bro_conn_log) {
    auto err = cols.add(entry);
    if (err) {
      FAIL("error during ingestion: " << caf::to_string(err));
    }
  }
  MESSAGE("querying");
  auto pred = to<predicate>("id.resp_p == 995/?");
  REQUIRE(pred);
  auto eresult = cols.lookup(*pred);
  REQUIRE(eresult);
  auto& result = *eresult;
  CHECK_EQUAL(rank(result), 53u);
  auto check_uid = [](const event& e, const std::string& uid) {
    auto& v = get<vector>(e.data());
    return v[1] == uid;
  };
  for (auto i : select(result))
    if (i == 819)
      CHECK(check_uid(bro_conn_log[819], "KKSlmtmkkxf")); // first
    else if (i == 3594)
      CHECK(check_uid(bro_conn_log[3594], "GDzpFiROJQi")); // intermediate
    else if (i == 6338)
      CHECK(check_uid(bro_conn_log[6338], "zwCckCCgXDb")); // last
}

FIXTURE_SCOPE_END()
<commit_msg>Unbox expected result w/o intermediate variables<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#define SUITE table_index
#include "test.hpp"

#include "fixtures/events.hpp"
#include "fixtures/filesystem.hpp"

#include "vast/bitmap.hpp"
#include "vast/concept/parseable/to.hpp"
#include "vast/concept/parseable/vast/expression.hpp"
#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/vast/error.hpp"
#include "vast/concept/printable/vast/event.hpp"
#include "vast/concept/printable/vast/expression.hpp"
#include "vast/system/table_index.hpp"

using namespace vast;
using namespace vast::system;

namespace {

struct fixture : fixtures::events, fixtures::filesystem {
  fixture() {
    directory /= "column-layout";
  }

  template <class T>
  T unbox(expected<T> x) {
    REQUIRE(x);
    return std::move(*x);
  }
};

} // namespace <anonymous>

FIXTURE_SCOPE(table_index_tests, fixture)

TEST(bro conn logs) {
  MESSAGE("generate column layout for bro conn logs");
  const auto conn_log_type = bro_conn_log[0].type();
  auto cols = unbox(make_table_index(directory, conn_log_type));
  CHECK_EQUAL(cols.num_meta_columns(), 2u);
  MESSAGE("ingesting events");
  for (auto& entry : bro_conn_log) {
    auto err = cols.add(entry);
    if (err) {
      FAIL("error during ingestion: " << caf::to_string(err));
    }
  }
  MESSAGE("querying");
  auto pred = to<predicate>("id.resp_p == 995/?");
  REQUIRE(pred);
  auto result = unbox(cols.lookup(*pred));
  CHECK_EQUAL(rank(result), 53u);
  auto check_uid = [](const event& e, const std::string& uid) {
    auto& v = get<vector>(e.data());
    return v[1] == uid;
  };
  for (auto i : select(result))
    if (i == 819)
      CHECK(check_uid(bro_conn_log[819], "KKSlmtmkkxf")); // first
    else if (i == 3594)
      CHECK(check_uid(bro_conn_log[3594], "GDzpFiROJQi")); // intermediate
    else if (i == 6338)
      CHECK(check_uid(bro_conn_log[6338], "zwCckCCgXDb")); // last
}

FIXTURE_SCOPE_END()
<|endoftext|>


<commit_before>#include "packedfontbase.h"
#include "mutablebitmapbase.h"
#include "woopsistring.h"
#include "stringiterator.h"

using namespace WoopsiGfx;

u16 PackedFontBase::getCharWidth(u32 letter) const {
	if (_fontWidth) return _fontWidth;

	if (letter < _first || letter > _last) return _spWidth;
	return _glyphWidth[letter - _first] + 1;
}

const bool PackedFontBase::isCharBlank(const u32 letter) const {
	if (letter >= _first && letter <= _last) return _glyphWidth[letter - _first] == 0;
	return true;
}

u16 PackedFontBase::getStringWidth(const WoopsiString& text) const {
	return getStringWidth(text, 0, text.getLength());
}

u16 PackedFontBase::getStringWidth(const WoopsiString& text, s32 startIndex, s32 length) const {
	if (_fontWidth) return _fontWidth * length;

	u16 total = 0;

	StringIterator* iterator = text.newStringIterator();
	if (!iterator->moveTo(startIndex)) return 0;

	do {
		total += getCharWidth(iterator->getCodePoint());
	} while (iterator->moveToNext() && (iterator->getIndex() < startIndex + length));

	delete iterator;

	return total;
}

s16 PackedFontBase::drawChar(
	MutableBitmapBase* bitmap,
	u32 letter,
	s16 x, s16 y,
	u16 clipX1, u16 clipY1, u16 clipX2, u16 clipY2)
{
	// if there is no glyphdata for this letter, just advance by a space
	if (letter < _first || letter > _last) {
		return x + _spWidth;
	}

	// check what its pixel width is - zero means no such character so
	// fall back on the width of a space
	u16 pixelWidth = _glyphWidth[letter - _first];
	if (pixelWidth == 0) {
		return x + _spWidth;
	}

	// pass off to a subclass for rendering
	renderChar(
		&_glyphData[_glyphOffset[letter - _first]],
		pixelWidth,
		bitmap,
		x, y,
		clipX1, clipY1, clipX2, clipY2);

	return x + getCharWidth(letter);
}
<commit_msg>Syncing with Woopsi.<commit_after>#include "packedfontbase.h"
#include "mutablebitmapbase.h"
#include "woopsistring.h"
#include "stringiterator.h"

using namespace WoopsiGfx;

u8 PackedFontBase::getCharWidth(u32 letter) const {
	if (_fontWidth) return _fontWidth;

	if (letter < _first || letter > _last) return _spWidth;
	return _glyphWidth[letter - _first] + 1;
}

const bool PackedFontBase::isCharBlank(const u32 letter) const {
	if (letter >= _first && letter <= _last) return _glyphWidth[letter - _first] == 0;
	return true;
}

u16 PackedFontBase::getStringWidth(const WoopsiString& text) const {
	return getStringWidth(text, 0, text.getLength());
}

u16 PackedFontBase::getStringWidth(const WoopsiString& text, s32 startIndex, s32 length) const {
	if (_fontWidth) return _fontWidth * length;

	u16 total = 0;

	StringIterator* iterator = text.newStringIterator();
	if (iterator->moveTo(startIndex)) {

		do {
			total += getCharWidth(iterator->getCodePoint());
		} while (iterator->moveToNext() && (iterator->getIndex() < startIndex + length));
	}

	delete iterator;

	return total;
}

s16 PackedFontBase::drawChar(
	MutableBitmapBase* bitmap,
	u32 letter,
	s16 x, s16 y,
	u16 clipX1, u16 clipY1, u16 clipX2, u16 clipY2)
{
	// if there is no glyphdata for this letter, just advance by a space
	if (letter < _first || letter > _last) {
		return x + _spWidth;
	}

	// check what its pixel width is - zero means no such character so
	// fall back on the width of a space
	u16 pixelWidth = _glyphWidth[letter - _first];
	if (pixelWidth == 0) {
		return x + _spWidth;
	}

	// pass off to a subclass for rendering
	renderChar(
		&_glyphData[_glyphOffset[letter - _first]],
		pixelWidth,
		bitmap,
		x, y,
		clipX1, clipY1, clipX2, clipY2);

	return x + getCharWidth(letter);
}
<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>
#include <sys/stat.h>

using namespace std;

class command{
	protected:
		vector<string> commandlist;
		bool commandPass;
		bool prevCommandPass;
		string commandType;
		bool allCount;
		bool forceExit;
		string nextConnector;
	public:
		command(){}
		command(vector<string> c){
			commandlist = c;
			commandType = ";";
			allCount = true;
			prevCommandPass = true;
			nextConnector = ";";
			forceExit = false;
		}
		command(vector<string> c, string t){
			commandlist = c;
			commandType = t;
			prevCommandPass = true;
			forceExit = false;
			allCount = true;
			nextConnector = ";";
		}
		bool getPass(){
			return commandPass;
		}
		string getType(){
			return commandType;
		}
		void runCommand(vector<string> com){
			char* argv[1024];

			for(unsigned int i = 0; i < com.size(); i++){
				argv[i] = (char*)com.at(i).c_str();
			}
			argv[com.size()] = NULL;

			pid_t pid;
			int status;
			pid = fork();
			if (pid == 0){
				prevCommandPass = true;
				execvp(argv[0], argv);
				perror("execvp failed: ");
				exit(-1);
			}
			else{
				if (waitpid(pid, &status, 0) == -1){
					perror("Wait: ");
				}
				if (WIFEXITED(status) && WEXITSTATUS(status) != 0){
					prevCommandPass = false;
				}
			}
		}
		void runAllCommands(){
			vector<string> commandsublist;
			unsigned int i = 0;
			unsigned int j = 0;
			while (i < commandlist.size()){
				j = 0;
				if (checkCommandRun()){
					while (!checkBreaker(i)){
						//Exit check
						if (commandlist.at(i) == "exit"){
							cout << "Forced Exit." << endl;
							forceExit = true;
							_Exit(0);
						}
						// Comment check
						if (commandlist.at(i) == "#" || checkComment(commandlist.at(i))){
							runCommand(commandsublist);
							return;
						}
						if (commandlist.at(i) == "["){
							i++;
							commandsublist.push_back(commandlist.at(i));
							if (commandlist.at(i) == "-e" || commandlist.at(i) == "-f" || commandlist.at(i) == "-d"){
								i++;
								commandsublist.push_back(commandlist.at(i));
							}
							i++;
							if (commandlist.at(i) == "]"){
								i++;
								if (checkTest(commandsublist)){
									cout << "(True)" << endl;
								}
								else{
									cout << "(False)" << endl;
								}
								commandsublist.clear();
							}
							else{
								cout << "Error: Missing close bracket." << endl;
								_exit(1);
							}
							break;
						}
						else if (commandlist.at(i) == "test"){
							i++;
							commandsublist.push_back(commandlist.at(i));
							if (commandlist.at(i) == "-e" || commandlist.at(i) == "-f" || commandlist.at(i) == "-d"){
								i++;
								commandsublist.push_back(commandlist.at(i));
							}
							if (checkTest(commandsublist)){
								cout << "(True)" << endl;
							}
							else{
								cout << "(False)" << endl;
							}
							commandsublist.clear();
							break;
						}
						//Adds command to the list
						commandsublist.push_back(commandlist.at(i));
						i++;
						j++;
						if (i == commandlist.size()){
							runCommand(commandsublist);
							return;
						}
					}
					if (commandsublist.size() > 0){
						runCommand(commandsublist);
						commandsublist.clear();
					}
					if (i >= commandlist.size()){
						return;
					}
					if (checkBreaker(i)){
						if (nextConnector == "||"){
							if (allCount == true){
								prevCommandPass = true;
							}
							else{
								if (prevCommandPass == false){
									allCount = false;
								}
								else{
									allCount = true;
								}
							}
						}
						else if (nextConnector == "&&"){
							if (allCount == true){
								if (prevCommandPass == false){
									allCount = false;
								}
							}
							else{
								allCount = false;
								prevCommandPass = false;
							}
						}
						else if (nextConnector == ";"){
							if (prevCommandPass == true){
								allCount = true;
							}
							else{
								allCount = false;
							}
						}
						if (commandlist.at(i) == "|"){
							nextConnector = "||";
						}
						else if (commandlist.at(i) == "&"){
							nextConnector = "&&";
						}
						else if (commandlist.at(i) == ";"){
							nextConnector = ";";
						}
						i++;
					}
					i++;
				}
				else{
					i++;
					if (i < commandlist.size()){
						if (checkBreaker(i)){
							if (commandlist.at(i) == "&"){
								i++;
								i++;
								nextConnector = "&&";
							}
							else if (commandlist.at(i) == "|"){
								i++;
								i++;
								nextConnector = "||";
							}
							else if (commandlist.at(i) == ";"){
								nextConnector = ";";
							}
						}
					}
				}
			}
		}

		//	Checks if there is a '#' at the front of the string
		bool checkComment(string str){
			if (str.at(0) == '#'){
				return true;
			}
			return false;
		}

		//	Checks if the string is a breaker
		bool checkBreaker(int i){
			if ( (unsigned)i < commandlist.size() + 1){
				if (commandlist.at(i) == "|" && commandlist.at(i + 1) == "|"){
					return true;
				}
				else if (commandlist.at(i) == "&" && commandlist.at(i + 1) == "&"){
					return true;
				}
				else if (commandlist.at(i) == ";"){
					return true;
				}
				else{
					return false;
				}
			}
			else if( (unsigned)i == commandlist.size() + 1){
				if(commandlist.at(i) == ";"){
					return true;
				}
				return false;
			}
			else{
				return false;
			}
		}

		// Checks if the next command should be run
		bool checkCommandRun(){
			if (nextConnector == "||"){
				if(allCount == true){
					return false;
				}
				else{
					return true;
				}
			}
			else if (nextConnector == "&&"){
				if(allCount == true){
					return true;
				}
				return false;
			}
			else if (nextConnector == ";"){
				return true;
			}
			return false;
		}

		bool checkTest(vector<string> temp){
			if (temp.at(0) == "-e"){
				return fileExists(temp.at(1));
			}
			else if (temp.at(0) == "-f"){
				return regFileExists(temp.at(1));
			}
			else if (temp.at(0) == "-d"){
				return dirExists(temp.at(1));
			}
			else{
				return fileExists(temp.at(0));
			}
		}
		bool fileExists(string& path){
			struct stat buffer;
			return (stat(path.c_str(), &buffer) == 0);
		}

		bool dirExists(string& path){
			struct stat buffer;
			if (stat(path.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode)){
				return true;
			}
			return false;
		}

		bool regFileExists(string& path){
			struct stat buffer;
			if (stat(path.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode)){
				return true;
			}
			return false;
		}
		void execute(bool prevCommand){
			if (prevCommand){
				if (commandType == "&&"){
					runAllCommands();
					if (allCount){
						commandPass = true;
					}
					else{
						commandPass = false;
					}
				}
				else if (commandType == "||"){
					commandPass = true;
				}
				else if (commandType == ";"){
					runAllCommands();
					if (allCount){
						commandPass = true;
					}
					else{
						commandPass = false;
					}
				}
			}
			else{
				if (commandType == "&&"){
					commandPass = false;
				}
				else if (commandType == "||"){
					runAllCommands();
					if (allCount){
						commandPass = true;
					}
					else{
						commandPass = false;
					}
				}
				else if (commandType == ";"){
					runAllCommands();
					commandPass = true;
				}
			}
		}

};
<commit_msg>Added getvector<commit_after>#include <string>
#include <vector>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>
#include <sys/stat.h>

using namespace std;

class command{
	protected:
		vector<string> commandlist;
		bool commandPass;
		bool prevCommandPass;
		string commandType;
		bool allCount;
		bool forceExit;
		string nextConnector;
	public:
		command(){}
		command(vector<string> c){
			commandlist = c;
			commandType = ";";
			allCount = true;
			prevCommandPass = true;
			nextConnector = ";";
			forceExit = false;
		}
		command(vector<string> c, string t){
			commandlist = c;
			commandType = t;
			prevCommandPass = true;
			forceExit = false;
			allCount = true;
			nextConnector = ";";
		}
		vector<string>& getVector(){
			return commandlist;
		}
		bool getPass(){
			return commandPass;
		}
		string getType(){
			return commandType;
		}
		void runCommand(vector<string> com){
			char* argv[1024];

			for(unsigned int i = 0; i < com.size(); i++){
				argv[i] = (char*)com.at(i).c_str();
			}
			argv[com.size()] = NULL;

			pid_t pid;
			int status;
			pid = fork();
			if (pid == 0){
				prevCommandPass = true;
				execvp(argv[0], argv);
				perror("execvp failed: ");
				exit(-1);
			}
			else{
				if (waitpid(pid, &status, 0) == -1){
					perror("Wait: ");
				}
				if (WIFEXITED(status) && WEXITSTATUS(status) != 0){
					prevCommandPass = false;
				}
			}
		}
		void runAllCommands(){
			vector<string> commandsublist;
			unsigned int i = 0;
			unsigned int j = 0;
			while (i < commandlist.size()){
				j = 0;
				if (checkCommandRun()){
					while (!checkBreaker(i)){
						//Exit check
						if (commandlist.at(i) == "exit"){
							cout << "Forced Exit." << endl;
							forceExit = true;
							_Exit(0);
						}
						// Comment check
						if (commandlist.at(i) == "#" || checkComment(commandlist.at(i))){
							runCommand(commandsublist);
							return;
						}
						if (commandlist.at(i) == "["){
							i++;
							commandsublist.push_back(commandlist.at(i));
							if (commandlist.at(i) == "-e" || commandlist.at(i) == "-f" || commandlist.at(i) == "-d"){
								i++;
								commandsublist.push_back(commandlist.at(i));
							}
							i++;
							if (commandlist.at(i) == "]"){
								i++;
								if (checkTest(commandsublist)){
									cout << "(True)" << endl;
								}
								else{
									cout << "(False)" << endl;
								}
								commandsublist.clear();
							}
							else{
								cout << "Error: Missing close bracket." << endl;
								_exit(1);
							}
							break;
						}
						else if (commandlist.at(i) == "test"){
							i++;
							commandsublist.push_back(commandlist.at(i));
							if (commandlist.at(i) == "-e" || commandlist.at(i) == "-f" || commandlist.at(i) == "-d"){
								i++;
								commandsublist.push_back(commandlist.at(i));
							}
							if (checkTest(commandsublist)){
								cout << "(True)" << endl;
							}
							else{
								cout << "(False)" << endl;
							}
							commandsublist.clear();
							break;
						}
						//Adds command to the list
						commandsublist.push_back(commandlist.at(i));
						i++;
						j++;
						if (i == commandlist.size()){
							runCommand(commandsublist);
							return;
						}
					}
					if (commandsublist.size() > 0){
						runCommand(commandsublist);
						commandsublist.clear();
					}
					if (i >= commandlist.size()){
						return;
					}
					if (checkBreaker(i)){
						if (nextConnector == "||"){
							if (allCount == true){
								prevCommandPass = true;
							}
							else{
								if (prevCommandPass == false){
									allCount = false;
								}
								else{
									allCount = true;
								}
							}
						}
						else if (nextConnector == "&&"){
							if (allCount == true){
								if (prevCommandPass == false){
									allCount = false;
								}
							}
							else{
								allCount = false;
								prevCommandPass = false;
							}
						}
						else if (nextConnector == ";"){
							if (prevCommandPass == true){
								allCount = true;
							}
							else{
								allCount = false;
							}
						}
						if (commandlist.at(i) == "|"){
							nextConnector = "||";
						}
						else if (commandlist.at(i) == "&"){
							nextConnector = "&&";
						}
						else if (commandlist.at(i) == ";"){
							nextConnector = ";";
						}
						i++;
					}
					i++;
				}
				else{
					i++;
					if (i < commandlist.size()){
						if (checkBreaker(i)){
							if (commandlist.at(i) == "&"){
								i++;
								i++;
								nextConnector = "&&";
							}
							else if (commandlist.at(i) == "|"){
								i++;
								i++;
								nextConnector = "||";
							}
							else if (commandlist.at(i) == ";"){
								nextConnector = ";";
							}
						}
					}
				}
			}
		}

		//	Checks if there is a '#' at the front of the string
		bool checkComment(string str){
			if (str.at(0) == '#'){
				return true;
			}
			return false;
		}

		//	Checks if the string is a breaker
		bool checkBreaker(int i){
			if ( (unsigned)i < commandlist.size() + 1){
				if (commandlist.at(i) == "|" && commandlist.at(i + 1) == "|"){
					return true;
				}
				else if (commandlist.at(i) == "&" && commandlist.at(i + 1) == "&"){
					return true;
				}
				else if (commandlist.at(i) == ";"){
					return true;
				}
				else{
					return false;
				}
			}
			else if( (unsigned)i == commandlist.size() + 1){
				if(commandlist.at(i) == ";"){
					return true;
				}
				return false;
			}
			else{
				return false;
			}
		}

		// Checks if the next command should be run
		bool checkCommandRun(){
			if (nextConnector == "||"){
				if(allCount == true){
					return false;
				}
				else{
					return true;
				}
			}
			else if (nextConnector == "&&"){
				if(allCount == true){
					return true;
				}
				return false;
			}
			else if (nextConnector == ";"){
				return true;
			}
			return false;
		}

		bool checkTest(vector<string> temp){
			if (temp.at(0) == "-e"){
				return fileExists(temp.at(1));
			}
			else if (temp.at(0) == "-f"){
				return regFileExists(temp.at(1));
			}
			else if (temp.at(0) == "-d"){
				return dirExists(temp.at(1));
			}
			else{
				return fileExists(temp.at(0));
			}
		}
		bool fileExists(string& path){
			struct stat buffer;
			return (stat(path.c_str(), &buffer) == 0);
		}

		bool dirExists(string& path){
			struct stat buffer;
			if (stat(path.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode)){
				return true;
			}
			return false;
		}

		bool regFileExists(string& path){
			struct stat buffer;
			if (stat(path.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode)){
				return true;
			}
			return false;
		}
		void execute(bool prevCommand){
			if (checkBreaker(0)){
				cout << "Yay";
				commandType = commandlist.at(0) + commandlist.at(1);
				commandlist.erase(commandlist.begin(), commandlist.begin() + 2);
			}
			if (prevCommand){
				if (commandType == "&&"){
					runAllCommands();
					if (allCount){
						commandPass = true;
					}
					else{
						commandPass = false;
					}
				}
				else if (commandType == "||"){
					commandPass = true;
				}
				else if (commandType == ";"){
					runAllCommands();
					if (allCount){
						commandPass = true;
					}
					else{
						commandPass = false;
					}
				}
			}
			else{
				if (commandType == "&&"){
					commandPass = false;
				}
				else if (commandType == "||"){
					runAllCommands();
					if (allCount){
						commandPass = true;
					}
					else{
						commandPass = false;
					}
				}
				else if (commandType == ";"){
					runAllCommands();
					commandPass = true;
				}
			}
		}

};
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "anomaly.hpp"

#include <string>
#include <utility>
#include <vector>

#include "../anomaly/anomaly_factory.hpp"
#include "../anomaly/anomaly_base.hpp"
#include "../common/vector_util.hpp"
#include "../fv_converter/datum.hpp"
#include "../fv_converter/datum_to_fv_converter.hpp"
#include "../fv_converter/converter_config.hpp"
#include "../fv_converter/revert.hpp"
#include "../storage/storage_factory.hpp"

using std::string;
using std::vector;
using std::pair;
using jubatus::core::fv_converter::weight_manager;
using jubatus::core::fv_converter::mixable_weight_manager;
using jubatus::util::lang::shared_ptr;

namespace jubatus {
namespace core {
namespace driver {

anomaly::anomaly(
    shared_ptr<jubatus::core::anomaly::anomaly_base> anomaly_method,
    shared_ptr<fv_converter::datum_to_fv_converter> converter)
    : converter_(converter),
      anomaly_(anomaly_method),
      wm_(mixable_weight_manager::model_ptr(new weight_manager)) {
  vector<framework::mixable*> mixables = anomaly_->get_mixables();
  for (size_t i = 0; i < mixables.size(); i++) {
    register_mixable(mixables[i]);
  }
  register_mixable(&wm_);

  converter_->set_weight_manager(wm_.get_model());
}

anomaly::~anomaly() {
}

bool anomaly::is_updatable() const {
  return anomaly_->is_updatable();
}

void anomaly::clear_row(const std::string& id) {
  anomaly_->clear_row(id);
}

pair<string, float> anomaly::add(
    const string& id,
    const fv_converter::datum& d) {
  if (anomaly_->is_updatable()) {
    return make_pair(id, this->update(id, d));
  } else {
    return make_pair(id, this->overwrite(id, d));
  }
}

float anomaly::update(const string& id, const fv_converter::datum& d) {
  common::sfv_t v;
  converter_->convert_and_update_weight(d, v);

  if (anomaly_->update_row(id, v)) {
    return anomaly_->calc_anomaly_score(id);
  } else {
    return anomaly_->calc_anomaly_score(id, v);
  }

}

float anomaly::overwrite(const string& id, const fv_converter::datum& d) {
  common::sfv_t v;
  converter_->convert_and_update_weight(d, v);

  if (anomaly_->set_row(id, v)) {
    return anomaly_->calc_anomaly_score(id);
  } else {
    return anomaly_->calc_anomaly_score(v);
  }
}

void anomaly::clear() {
  anomaly_->clear();
  converter_->clear_weights();
}

float anomaly::calc_score(const fv_converter::datum& d) const {
  common::sfv_t v;
  converter_->convert(d, v);
  return anomaly_->calc_anomaly_score(v);
}

vector<string> anomaly::get_all_rows() const {
  vector<string> ids;
  anomaly_->get_all_row_ids(ids);
  return ids;
}

uint64_t anomaly::find_max_int_id() const {
  return anomaly_->find_max_int_id();
}

void anomaly::pack(framework::packer& pk) const {
  pk.pack_array(2);
  anomaly_->pack(pk);
  wm_.get_model()->pack(pk);
}

void anomaly::unpack(msgpack::object o) {
  if (o.type != msgpack::type::ARRAY || o.via.array.size != 2) {
    throw msgpack::type_error();
  }

  // clear before load
  anomaly_->clear();
  converter_->clear_weights();
  anomaly_->unpack(o.via.array.ptr[0]);
  wm_.get_model()->unpack(o.via.array.ptr[1]);
}

}  // namespace driver
}  // namespace core
}  // namespace jubatus
<commit_msg>fix cpplint (refs #223)<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "anomaly.hpp"

#include <string>
#include <utility>
#include <vector>

#include "../anomaly/anomaly_factory.hpp"
#include "../anomaly/anomaly_base.hpp"
#include "../common/vector_util.hpp"
#include "../fv_converter/datum.hpp"
#include "../fv_converter/datum_to_fv_converter.hpp"
#include "../fv_converter/converter_config.hpp"
#include "../fv_converter/revert.hpp"
#include "../storage/storage_factory.hpp"

using std::string;
using std::vector;
using std::pair;
using jubatus::core::fv_converter::weight_manager;
using jubatus::core::fv_converter::mixable_weight_manager;
using jubatus::util::lang::shared_ptr;

namespace jubatus {
namespace core {
namespace driver {

anomaly::anomaly(
    shared_ptr<jubatus::core::anomaly::anomaly_base> anomaly_method,
    shared_ptr<fv_converter::datum_to_fv_converter> converter)
    : converter_(converter),
      anomaly_(anomaly_method),
      wm_(mixable_weight_manager::model_ptr(new weight_manager)) {
  vector<framework::mixable*> mixables = anomaly_->get_mixables();
  for (size_t i = 0; i < mixables.size(); i++) {
    register_mixable(mixables[i]);
  }
  register_mixable(&wm_);

  converter_->set_weight_manager(wm_.get_model());
}

anomaly::~anomaly() {
}

bool anomaly::is_updatable() const {
  return anomaly_->is_updatable();
}

void anomaly::clear_row(const std::string& id) {
  anomaly_->clear_row(id);
}

pair<string, float> anomaly::add(
    const string& id,
    const fv_converter::datum& d) {
  if (anomaly_->is_updatable()) {
    return make_pair(id, this->update(id, d));
  } else {
    return make_pair(id, this->overwrite(id, d));
  }
}

float anomaly::update(const string& id, const fv_converter::datum& d) {
  common::sfv_t v;
  converter_->convert_and_update_weight(d, v);

  if (anomaly_->update_row(id, v)) {
    return anomaly_->calc_anomaly_score(id);
  } else {
    return anomaly_->calc_anomaly_score(id, v);
  }
}

float anomaly::overwrite(const string& id, const fv_converter::datum& d) {
  common::sfv_t v;
  converter_->convert_and_update_weight(d, v);

  if (anomaly_->set_row(id, v)) {
    return anomaly_->calc_anomaly_score(id);
  } else {
    return anomaly_->calc_anomaly_score(v);
  }
}

void anomaly::clear() {
  anomaly_->clear();
  converter_->clear_weights();
}

float anomaly::calc_score(const fv_converter::datum& d) const {
  common::sfv_t v;
  converter_->convert(d, v);
  return anomaly_->calc_anomaly_score(v);
}

vector<string> anomaly::get_all_rows() const {
  vector<string> ids;
  anomaly_->get_all_row_ids(ids);
  return ids;
}

uint64_t anomaly::find_max_int_id() const {
  return anomaly_->find_max_int_id();
}

void anomaly::pack(framework::packer& pk) const {
  pk.pack_array(2);
  anomaly_->pack(pk);
  wm_.get_model()->pack(pk);
}

void anomaly::unpack(msgpack::object o) {
  if (o.type != msgpack::type::ARRAY || o.via.array.size != 2) {
    throw msgpack::type_error();
  }

  // clear before load
  anomaly_->clear();
  converter_->clear_weights();
  anomaly_->unpack(o.via.array.ptr[0]);
  wm_.get_model()->unpack(o.via.array.ptr[1]);
}

}  // namespace driver
}  // namespace core
}  // namespace jubatus
<|endoftext|>