text:
#include "convert_pascal_xml.h"
#include "dlib/data_io.h"
#include <iostream>
#include <dlib/xml_parser.h>
#include <string>
#include <dlib/dir_nav.h>
#include <dlib/cmd_line_parser.h>

using namespace std;
using namespace dlib;

namespace
{
    using namespace dlib::image_dataset_metadata;

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

    class doc_handler : public document_handler
    {
        image& temp_image;
        std::string& dataset_name;

        std::vector<std::string> ts;
        box temp_box;

    public:

        doc_handler(
            image& temp_image_,
            std::string& dataset_name_
        ):
            temp_image(temp_image_),
            dataset_name(dataset_name_)
        {}

        virtual void start_document (
        )
        {
            ts.clear();
            temp_image = image();
            temp_box = box();
            dataset_name.clear();
        }

        virtual void end_document (
        )
        {
        }

        virtual void start_element (
            const unsigned long ,
            const std::string& name,
            const dlib::attribute_list&
        )
        {
            if (ts.size() == 0 && name != "annotation")
            {
                std::ostringstream sout;
                sout << "Invalid XML document.  Root tag must be <annotation>.  Found <" << name << "> instead.";
                throw dlib::error(sout.str());
            }

            ts.push_back(name);
        }

        virtual void end_element (
            const unsigned long ,
            const std::string& name
        )
        {
            ts.pop_back();
            if (ts.size() == 0)
                return;

            if (name == "object" && ts.back() == "annotation")
            {
                temp_image.boxes.push_back(temp_box);
                temp_box = box();
            }
        }

        virtual void characters (
            const std::string& data
        )
        {
            if (ts.size() == 2 && ts[1] == "filename")
            {
                temp_image.filename = trim(data);
            }
            else if (ts.size() == 3 && ts[2] == "database" && ts[1] == "source")
            {
                dataset_name = trim(data);
            }
            else if (ts.size() >= 3)
            {
                if (ts[ts.size()-2] == "bndbox" && ts[ts.size()-3] == "object")
                {
                    if      (ts.back() == "xmin") temp_box.rect.left()   = string_cast<double>(data);
                    else if (ts.back() == "ymin") temp_box.rect.top()    = string_cast<double>(data);
                    else if (ts.back() == "xmax") temp_box.rect.right()  = string_cast<double>(data);
                    else if (ts.back() == "ymax") temp_box.rect.bottom() = string_cast<double>(data);
                }
                else if (ts.back() == "name" && ts[ts.size()-2] == "object")
                {
                    temp_box.label = trim(data);
                }
                else if (ts.back() == "difficult" && ts[ts.size()-2] == "object")
                {
                    if (trim(data) == "0" || trim(data) == "false")
                    {
                        temp_box.difficult = false;
                    }
                    else
                    {
                        temp_box.difficult = true;
                    }
                }
                else if (ts.back() == "truncated" && ts[ts.size()-2] == "object")
                {
                    if (trim(data) == "0" || trim(data) == "false")
                    {
                        temp_box.truncated = false;
                    }
                    else
                    {
                        temp_box.truncated = true;
                    }
                }
                else if (ts.back() == "occluded" && ts[ts.size()-2] == "object")
                {
                    if (trim(data) == "0" || trim(data) == "false")
                    {
                        temp_box.occluded = false;
                    }
                    else
                    {
                        temp_box.occluded = true;
                    }
                }

            }
        }

        virtual void processing_instruction (
            const unsigned long ,
            const std::string& ,
            const std::string&
        )
        {
        }
    };

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

    class xml_error_handler : public error_handler
    {
    public:
        virtual void error (
            const unsigned long
        ) { }

        virtual void fatal_error (
            const unsigned long line_number
        )
        {
            std::ostringstream sout;
            sout << "There is a fatal error on line " << line_number << " so parsing will now halt.";
            throw dlib::error(sout.str());
        }
    };

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

    void parse_annotation_file(
        const std::string& file,
        dlib::image_dataset_metadata::image& img,
        std::string& dataset_name
    )
    {
        doc_handler dh(img, dataset_name);
        xml_error_handler eh;

        xml_parser::kernel_1a parser;
        parser.add_document_handler(dh);
        parser.add_error_handler(eh);

        ifstream fin(file.c_str());
        if (!fin)
            throw dlib::error("Unable to open file " + file);
        parser.parse(fin);
    }

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

}

void convert_pascal_xml(
    const command_line_parser& parser
)
{
    cout << "Convert from PASCAL XML annotation format..." << endl;

    dlib::image_dataset_metadata::dataset dataset;

    std::string name;
    dlib::image_dataset_metadata::image img;

    const std::string filename = parser.option("c").argument();
    // make sure the file exists so we can use the get_parent_directory() command to
    // figure out it's parent directory.
    make_empty_file(filename);
    const std::string parent_dir = get_parent_directory(file(filename)).full_name();

    for (unsigned long i = 0; i < parser.number_of_arguments(); ++i)
    {
        try
        {
            parse_annotation_file(parser[i], img, name);
            const string root = get_parent_directory(get_parent_directory(file(parser[i]))).full_name();
            const string img_path = root + directory::get_separator() + "JPEGImages" + directory::get_separator();

            dataset.name = name;
            img.filename = strip_path(img_path + img.filename,  parent_dir);
            dataset.images.push_back(img);

        }
        catch (exception& )
        {
            cout << "Error while processing file " << parser[i] << endl << endl;
            throw;
        }
    }

    save_image_dataset_metadata(dataset, filename);
}

ext: cpp

max_stars_repo_name: maxmert/nlp-mitie


text:
//==================================================================================================
/*!

  Copyright 2015 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#include <boost/simd/constant/halfeps.hpp>
#include <boost/simd/constant/eps.hpp>
#include <boost/simd/as.hpp>
#include <simd_test.hpp>

STF_CASE_TPL( "Check halfeps behavior for integral types"
            , (std::uint8_t)(std::uint16_t)(std::uint32_t)(std::uint64_t)
              (std::int8_t)(std::int16_t)(std::int32_t)(std::int64_t)
            )
{
  using boost::simd::as;
  using boost::simd::detail::halfeps;
  using boost::simd::Halfeps;

  STF_TYPE_IS(decltype(Halfeps<T>()), T);
  STF_EQUAL(Halfeps<T>(), T(1));
  STF_EQUAL(halfeps( as(T{}) ),T(1));
}

STF_CASE_TPL( "Check halfeps behavior for floating types"
            , (double)(float)
            )
{
  using boost::simd::as;
  using boost::simd::detail::halfeps;
  using boost::simd::Halfeps;
  using boost::simd::Eps;

  STF_TYPE_IS(decltype(Halfeps<T>()), T);
  STF_IEEE_EQUAL(Halfeps<T>(), Eps<T>()/2);
  STF_IEEE_EQUAL(halfeps( as(T{}) ), Eps<T>()/2);
}


text: #include <boost/mpl/aux_/filter_iter.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include <type_traits>
#include <utility>
#include <boost/hana.hpp>

struct Cat
{
    Cat() = delete;
    void meow();
};

struct Dog
{
    Dog() = delete;
    void bark();
};

int main()
{
    auto has_meow = boost::hana::is_valid([](auto x) -> decltype(x.meow())
        {
        });

    auto has_bark = boost::hana::is_valid([](auto x) -> decltype(x.bark())
        {
        });

    static_assert(has_meow(Cat{}));
    static_assert(has_bark(Dog{}));
}


text:
//============================================================================
// Name        :
// Author      : Avi
// Revision    : $Revision: #6 $
//
// Copyright 2009- ECMWF.
// This software is licensed under the terms of the Apache Licence version 2.0
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
// In applying this licence, ECMWF does not waive the privileges and immunities
// granted to it by virtue of its status as an intergovernmental organisation
// nor does it submit to any jurisdiction.
//
// Description :
//============================================================================
#include <iostream>

#include <boost/test/unit_test.hpp>
#include "boost/filesystem/operations.hpp"
#include <boost/date_time/posix_time/posix_time_types.hpp>

#include "Simulator.hpp"
#include "Defs.hpp"
#include "Suite.hpp"
#include "Family.hpp"
#include "Task.hpp"
#include "TestUtil.hpp"
#include "VerifyAttr.hpp"

using namespace std;
using namespace ecf;
using namespace boost::gregorian;
using namespace boost::posix_time;

namespace fs = boost::filesystem;

/// Simulate definition files that are created on then fly. This allows us to create
/// tests with todays date/time this speeds up the testr, we can also validate
/// Defs file, to check for correctness

BOOST_AUTO_TEST_SUITE( SimulatorTestSuite )

BOOST_AUTO_TEST_CASE( test_today )
{
   cout << "Simulator:: ...test_today\n";

   //suite suite
   //  clock real <fixed date>
   //	family family
   //   	task t1
   //      	today <start>  # +1 minute
   //      	today <start>  # +2 minute
   //   endfamily
   //endsuite
   Defs theDefs;
   {
      // Initialise clock   then create a today attribute + minutes
      // such that the task should only run once, in the next minute
      ptime theLocalTime = boost::posix_time::ptime(date(2010,6,21),time_duration(1,2,0));
      boost::posix_time::ptime time_plus_minute =  theLocalTime +  minutes(1);
      boost::posix_time::ptime time_plus_10_minute =  theLocalTime +  minutes(10);

      suite_ptr suite =  theDefs.add_suite( "test_today" );
      ClockAttr clockAttr(theLocalTime,false/*false means use real clock*/);
      suite->addClock( clockAttr );

      family_ptr fam = suite->add_family( "family" );
      task_ptr task = fam->add_task( "t" );
      task->addToday( ecf::TodayAttr( TimeSlot(time_plus_minute.time_of_day()) ) );
      task->addToday( ecf::TodayAttr( TimeSlot(time_plus_10_minute.time_of_day()) ) );
      task->addVerify( VerifyAttr(NState::COMPLETE,2) );  // expect task to complete 2 time
      //  	cout << theDefs << "\n";
   }

   Simulator simulator;
   std::string errorMsg;
   bool result = simulator.run(theDefs, TestUtil::testDataLocation("test_today.def"), errorMsg);

   BOOST_CHECK_MESSAGE(result,errorMsg);

   // remove generated log file. Comment out to debug
   std::string logFileName = TestUtil::testDataLocation("test_today.def") + ".log";
   fs::remove(logFileName);
}

BOOST_AUTO_TEST_CASE( test_today_time_series )
{
   cout << "Simulator:: ...test_today_time_series\n";

   //suite suite
   //  clock real <monday>
   //	family family
   //   	task t1
   //         today 00:30 18:59 04:00  # should run 5 times 00:30 4:30 8:30 12:30 16:30
   //   endfamily
   //endsuite

   Defs theDefs;
   {
      suite_ptr suite = theDefs.add_suite( "test_today_time_series" );
      ClockAttr clockAttr(true/*false means use hybrid clock*/);
      clockAttr.date(12,10,2009); // 12 October 2009 was a Monday
      suite->addClock( clockAttr );

      family_ptr fam = suite->add_family( "family" );
      task_ptr task =  fam->add_task( "t" );
      TimeSeries timeSeries(TimeSlot(00,30), TimeSlot(18,59), TimeSlot(4,0), false/* relative */);

      task->addToday( TodayAttr( timeSeries ));
      task->addVerify( VerifyAttr(NState::COMPLETE,5) );
      //  	cout << theDefs << "\n";
   }

   Simulator simulator;
   std::string errorMsg;
   BOOST_CHECK_MESSAGE(simulator.run(theDefs, TestUtil::testDataLocation("test_today_time_series.def") , errorMsg),errorMsg);

   // remove generated log file. Comment out to debug
   std::string logFileName = TestUtil::testDataLocation("test_today_time_series.def") + ".log";
   fs::remove(logFileName);
}

BOOST_AUTO_TEST_CASE( test_today_time_and_date )
{
   cout << "Simulator:: ...test_today_time_and_date\n";

   //suite suite
   //  clock real <todays date>
   //	family family
   //   	task t1
   //       date  <today date>
   //       time  <start>
   //       today <start>
   //   endfamily
   //endsuite
   Defs theDefs;
   {
      // To speed up simulation: start calendar with hour increment AND time attributes with hours only
      //
      // Task will only run if all time dependencies are satisfied
      boost::posix_time::ptime   theLocalTime = ptime(date(2010,2,10),hours(15));  ;
      boost::gregorian::date todaysDate = theLocalTime.date();
      boost::posix_time::ptime   time_plus_hour =  theLocalTime +  hours(1);

      suite_ptr suite = theDefs.add_suite( "test_today_time_and_date" );
      ClockAttr clockAttr(theLocalTime,false/*false means use real clock*/);
      suite->addClock( clockAttr );

      family_ptr fam = suite->add_family( "family" );
      task_ptr task = fam->add_task( "t" );
      task->addDate( DateAttr(todaysDate) );
      task->addTime( ecf::TimeAttr( TimeSlot(time_plus_hour.time_of_day()) ) );
      task->addToday( ecf::TodayAttr( TimeSlot(time_plus_hour.time_of_day()) ) );

      task->addVerify( VerifyAttr(NState::COMPLETE,1) );
      //  	cout << theDefs << "\n";
   }

   Simulator simulator;
   std::string errorMsg;
   BOOST_CHECK_MESSAGE(simulator.run(theDefs,TestUtil::testDataLocation("test_today_time_and_date.def"),errorMsg),errorMsg);

//   cout << theDefs;

   // remove generated log file. Comment out to debug
   std::string logFileName = TestUtil::testDataLocation("test_today_time_and_date.def") + ".log";
   fs::remove(logFileName);
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: mpartio/ecflow

max_issues_repo_name: mpartio/ecflow

max_forks_repo_name: mpartio/ecflow


text:
// define before any includes
#define BOOST_SPIRIT_THREADSAFE

#include <dirent.h>
#include <syslog.h>
#include <sys/stat.h>

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cassert>
#include <strings.h>
#include <algorithm>
#include <exception>
#include <fstream>
#include <iostream>
#include <tuple>
#include <boost/program_options.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include "proj.hpp"
#include "path-mapper.h"

#include "git-revision.h"
#define VERSION "0.0.0"

namespace argv {
    // argv parser for --zoom=z1-z2
    namespace zoom {
        struct pair_t {
        public:
            uint32_t z1, z2;
        };

        void validate(boost::any& v,
                      const std::vector<std::string>& values,
                      pair_t*, int)
        {
            namespace po = boost::program_options;

            static boost::regex r("(\\d+)(-|,)(\\d+)");

            // Make sure no previous assignment to 'v' was made.
            po::validators::check_first_occurrence(v);
            // Extract the first string from 'values'. If there is more than
            // one string, it's an error, and exception will be thrown.
            const std::string& s = po::validators::get_single_string(values);

            // Do regex match and convert the interesting part to
            // int.
            boost::smatch match;
            if (regex_match(s, match, r)) {
                v = boost::any(pair_t{ boost::lexical_cast<uint32_t>(match[1]), boost::lexical_cast<uint32_t>(match[3]) });
            } else {
                throw po::validation_error(po::validation_error::invalid_option_value);
            }
        }
    }

    // ... and for --bbox=x1,y1,x2,y2
    namespace bbox {
        struct box_t {
        public:
            double x1, y1, x2, y2;
        };

        void validate(boost::any& v,
                      const std::vector<std::string>& values,
                      box_t*, int)
        {
            namespace po = boost::program_options;

            // Make sure no previous assignment to 'v' was made.
            po::validators::check_first_occurrence(v);
            // Extract the first string from 'values'. If there is more than
            // one string, it's an error, and exception will be thrown.
            const std::string& s = po::validators::get_single_string(values);

            try {
                std::vector<std::string> tokens;
                boost::split(tokens, s, boost::is_any_of(","));
                // boost::char_separator<char> sep(",");
                // boost::tokenizer< boost::char_separator<char> > tok(s, sep);
                // auto it = tok.begin();
                double x1 = boost::lexical_cast<double>(tokens[0]);
                double y1 = boost::lexical_cast<double>(tokens[1]);
                double x2 = boost::lexical_cast<double>(tokens[2]);
                double y2 = boost::lexical_cast<double>(tokens[3]);
                v = boost::any(box_t { x1, y1, x2, y2 });
            } catch (...) {
                throw po::validation_error(po::validation_error::invalid_option_value);
            }
        }
    }
}

/*
yield-tile-urls -p base-url [-z z1-z2] [-b x1,y1,x2,y2]
generates URLs for tiles bounded by the box (x1, y1)-(x2, y2) for zoom levels in [z1, z2], prefixed by base-url.
Options:
    -p,--prefix base-url: a URL (or, can be a local path), to which paths for tiles are appended
    -z,--zoom z1-z2: zoom levels in [0, ..., 20] to generate URLs
        + values less/greater than 0/20 are fit to 0/20 resp.
        + defaults to 0-16
    -b,--bbox x1,y1,x2,y2: (x1, y1) and (x2, y2) are two pairs of lon/lat
        + the pairs define the bounding box of URLs
        + defaults to (-180, 90)-(180, -90), i.e. the entire planet
    -s,--suffix (png|jpg|...)
        + suffix of the URLs
    -v,--version
    -h,--help
*/
int main(int ac, char** av) {
    try {
        std::string config;
        std::string base;
        std::string suffix;
        argv::zoom::pair_t zoom_levels;
        argv::bbox::box_t  bbox;
        bool emit_physical = false; // If true, print in the physical form: /base/z/nnn/nnn/nnn/nnn/nnn.png

        /** Define and parse the program options
        */
        namespace po = boost::program_options;
        po::options_description desc(
            "yield-tile-urls -p base-url [-z z1-z2] [-b x1,y1,x2,y2]\n"
            "generates URLs for tiles bounded by the box (x1, y1)-(x2, y2) for zoom levels in [z1, z2], prefixed by base-url.\n\n"
            "Options"
        );
        desc.add_options()
            ("help,h", "Prints help messages")
            ("version,v", "Prints version info.")
            ("prefix,p", po::value<std::string>(&base)->value_name("base-url")->required(), "Specifies the URL (or, can be a local path) to which tile-paths are appended")
            ("physical,P", "Emits tile-paths in the physical form: base/z/nnn/nnn/nnn/nnn/nnn.png")
            ("suffix,s", po::value<std::string>(&suffix)->value_name("suffix")->default_value("png"), "Specifies the suffix of the URLs")
            ("zoom,z",
                po::value<argv::zoom::pair_t>(&zoom_levels)->value_name("z1-z2")->default_value(argv::zoom::pair_t{0, 16}, "0-16"),
                "Specifies zoom levels to generate URLs, between 0-20\n"
                "  + values less/greater than 0/20 are fit to 0/20 resp.\n"
                "  + defaults to 0-16")
            ("bbox,b",
                po::value<argv::bbox::box_t>(&bbox)->value_name("x1,y1,x2,y2")->default_value(argv::bbox::box_t{-180, 90, 180, -90}, "-180,90,180,-90"),
                "Specifies the bounding box of URLs in lon/lat\n"
                "  + defaults to (-180,90)-(180,-90), i.e. the entire planet.")
        ;   // add_options();
        if (ac <= 1) {
            // No options are given.
            // Just print the usage w.o. error messages.
            std::cerr << desc;
            return 0;
        }
        po::variables_map vm;

        try {
            po::store(po::command_line_parser(ac, av).options(desc).run(), vm); // throws on error

            // --help
            if ( vm.count("help")  ) {
                std::cerr << desc;
                return 0;
            }

            if ( vm.count("version") ) {
                std::cout << (
                    VERSION " (commit: " GIT_REVISION_SHORT ")"
                ) << std::endl;
                return 0;
            }

            if ( vm.count("physical") ) {
                emit_physical = true;
            }
            po::notify(vm); // throws on error, so do after help in case
                            // there are any problems
        } catch(po::required_option& e) {
            std::cerr << desc << std::endl;
            std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
            return -1;
        } catch(po::error& e) {
            std::cerr << desc << std::endl;
            std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
            return -1;
        }

#define CHECK_RANGE(val, v1, v2) if (val < v1 || val > v2) { \
    std::cerr << "Error: " << (#val) << " = " << (val) << " is out of the range, must be in [" << (v1) << ", " << (v2) << "]" << std::endl; \
    return -1; \
}

        // Ensure zoom levels are in the valid range
        uint32_t z1 = zoom_levels.z1, z2 = zoom_levels.z2;
        CHECK_RANGE(z1, 0, 20)
        CHECK_RANGE(z2, 0, 20)

        if (z1 > z2) {
            std::swap(z1, z2);
        }

        // and so are bbox coordinates...

        // Mercator projection limits the lat value to this, cf. http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#X_and_Y
        constexpr double LAT_LIMIT = 85.0511;
        double x1 = bbox.x1,
               y1 = bbox.y1,
               x2 = bbox.x2,
               y2 = bbox.y2;
        CHECK_RANGE(x1, -180.0, 180.0)
        CHECK_RANGE(x2, -180.0, 180.0)
        // The magic number 85.0511 is quite counter-intuitive, let us accept any deg. as inputs and then fit them below
        CHECK_RANGE(y1, -90.0, 90.0)
        CHECK_RANGE(y2, -90.0, 90.0)

        // Ensure values are in ascening order.
        if (x1 > x2) {
            std::swap(x1, x2);
        }
        // The y-axis of the Spherical Mercator spans north-to-south, hence smaller lat values (southern points) are mapped to larger tile IDs.
        // To assure the output to be in ascending order, we force y1 >= y2 (not y1 <= y2.)
        if (y1 < y2) {
            std::swap(y1, y2);
        }
        // Tweak lat/lon values so that they fit in their "actual" range.
        // To be strict, the range of lon. values is [-180, 180), so exact 180.0 should be "shifted just a little"
        x1 = std::min(x1, 180.0 - 0.0000001);
        x2 = std::min(x2, 180.0 - 0.0000001);
        // and lat. values are limited to +-85.0511 rather than 90.0, as explained.
        y1 = std::max(-LAT_LIMIT, std::min(y1, LAT_LIMIT));
        y2 = std::max(-LAT_LIMIT, std::min(y2, LAT_LIMIT));

        // Trim the trailing '/' if any.

        char* prefix = const_cast<char*>(base.c_str());
        if (prefix[base.length()-1] == '/') {
            prefix[base.length()-1] = '\0';
        }
        // Emit!
        uint32_t tx_left, ty_top, tx_right, ty_bottom;
        if (emit_physical) {
            char* tile_path = (char*)alloca(base.length() + 28);
            strcpy(tile_path, prefix);
            char* tp_head = tile_path + strlen(prefix);
            *tp_head = '/';
            tp_head++;
            boost::algorithm::to_lower(suffix);
            TILE_SUFFIX ts = (suffix == "png") ? PNG : JPG;

            for (uint32_t z = (uint32_t)z1; z <= (uint32_t)z2; ++z) {
                lonlat_to_tile(x1, y1, z, tx_left, ty_top);
                lonlat_to_tile(x2, y2, z, tx_right, ty_bottom);
                for (uint32_t y = ty_top; y <= ty_bottom; ++y) {
                    for (uint32_t x = tx_left; x <= tx_right; ++x) {
                        to_physical_path(tp_head, z, x, y, ts);
                        puts(tile_path);
                    }
                }
            }
        } else {
            for (uint32_t z = (uint32_t)z1; z <= (uint32_t)z2; ++z) {
                lonlat_to_tile(x1, y1, z, tx_left, ty_top);
                lonlat_to_tile(x2, y2, z, tx_right, ty_bottom);
                for (uint32_t y = ty_top; y <= ty_bottom; ++y) {
                    for (uint32_t x = tx_left; x <= tx_right; ++x) {
                        printf("%s/%d/%d/%d.%s\n", prefix, z, x, y, suffix.c_str());
                    }
                }
            }
        }
    } catch(std::exception& e) {
        std::cerr << "Unhandled Exception reached the top of main: "
              << e.what() << ", application will now exit" << std::endl;
        return -1;

    }
    return 0;
}


text:
/*
	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/>.
*/

#include <test/tools/ossfuzz/protoToYul.h>
#include <test/tools/ossfuzz/yulOptimizerFuzzDictionary.h>

#include <libyul/Exceptions.h>

#include <libsolutil/StringUtils.h>

#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/range/algorithm_ext/erase.hpp>

using namespace std;
using namespace solidity::yul::test::yul_fuzzer;
using namespace solidity::yul::test;
using namespace solidity::langutil;
using namespace solidity::util;
using namespace solidity;

string ProtoConverter::dictionaryToken(HexPrefix _p)
{
	std::string token;
	// If dictionary constant is requested while converting
	// for loop condition, then return zero so that we don't
	// generate infinite for loops.
	if (m_inForCond)
		token = "0";
	else
	{
		unsigned indexVar = m_inputSize * m_inputSize + counter();
		token = hexDictionary[indexVar % hexDictionary.size()];
		yulAssert(token.size() <= 64, "Proto Fuzzer: Dictionary token too large");
	}

	return _p == HexPrefix::Add ? "0x" + token : token;
}

string ProtoConverter::createHex(string const& _hexBytes)
{
	string tmp{_hexBytes};
	if (!tmp.empty())
	{
		boost::range::remove_erase_if(tmp, [=](char c) -> bool {
			return !std::isxdigit(c);
		});
		tmp = tmp.substr(0, 64);
	}
	// We need this awkward if case because hex literals cannot be empty.
	// Use a dictionary token.
	if (tmp.empty())
		tmp = dictionaryToken(HexPrefix::DontAdd);
	// Hex literals must have even number of digits
	if (tmp.size() % 2)
		tmp.insert(0, "0");

	yulAssert(tmp.size() <= 64, "Proto Fuzzer: Dictionary token too large");
	return tmp;
}

string ProtoConverter::createAlphaNum(string const& _strBytes)
{
	string tmp{_strBytes};
	if (!tmp.empty())
	{
		boost::range::remove_erase_if(tmp, [=](char c) -> bool {
			return !(std::isalpha(c) || std::isdigit(c));
		});
		tmp = tmp.substr(0, 32);
	}
	return tmp;
}

EVMVersion ProtoConverter::evmVersionMapping(Program_Version const& _ver)
{
	switch (_ver)
	{
	case Program::HOMESTEAD:
		return EVMVersion::homestead();
	case Program::TANGERINE:
		return EVMVersion::tangerineWhistle();
	case Program::SPURIOUS:
		return EVMVersion::spuriousDragon();
	case Program::BYZANTIUM:
		return EVMVersion::byzantium();
	case Program::CONSTANTINOPLE:
		return EVMVersion::constantinople();
	case Program::PETERSBURG:
		return EVMVersion::petersburg();
	case Program::ISTANBUL:
		return EVMVersion::istanbul();
	case Program::BERLIN:
		return EVMVersion::berlin();
	}
}

string ProtoConverter::visit(Literal const& _x)
{
	switch (_x.literal_oneof_case())
	{
	case Literal::kIntval:
		return to_string(_x.intval());
	case Literal::kHexval:
		return "0x" + createHex(_x.hexval());
	case Literal::kStrval:
		return "\"" + createAlphaNum(_x.strval()) + "\"";
	case Literal::kBoolval:
		return _x.boolval() ? "true" : "false";
	case Literal::LITERAL_ONEOF_NOT_SET:
		return dictionaryToken();
	}
}

void ProtoConverter::consolidateVarDeclsInFunctionDef()
{
	m_currentFuncVars.clear();
	yulAssert(!m_funcVars.empty(), "Proto fuzzer: Invalid operation");

	auto const& scopes = m_funcVars.back();
	for (auto const& s: scopes)
		for (auto const& var: s)
			m_currentFuncVars.push_back(&var);
	yulAssert(!m_funcForLoopInitVars.empty(), "Proto fuzzer: Invalid operation");
	auto const& forinitscopes = m_funcForLoopInitVars.back();
	for (auto const& s: forinitscopes)
		for (auto const& var: s)
			m_currentFuncVars.push_back(&var);
}

void ProtoConverter::consolidateGlobalVarDecls()
{
	m_currentGlobalVars.clear();
	// Place pointers to all global variables that are in scope
	// into a single vector
	for (auto const& scope: m_globalVars)
		for (auto const& var: scope)
			m_currentGlobalVars.push_back(&var);
	// Place pointers to all variables declared in for-init blocks
	// that are still live into the same vector
	for (auto const& init: m_globalForLoopInitVars)
		for (auto const& var: init)
			m_currentGlobalVars.push_back(&var);
}

bool ProtoConverter::varDeclAvailable()
{
	if (m_inFunctionDef)
	{
		consolidateVarDeclsInFunctionDef();
		return m_currentFuncVars.size() > 0;
	}
	else
	{
		consolidateGlobalVarDecls();
		return m_currentGlobalVars.size() > 0;
	}
}

bool ProtoConverter::functionCallNotPossible(FunctionCall_Returns _type)
{
	return _type == FunctionCall::SINGLE ||
		(_type == FunctionCall::MULTIASSIGN && !varDeclAvailable());
}

void ProtoConverter::visit(VarRef const& _x)
{
	if (m_inFunctionDef)
	{
		// Ensure that there is at least one variable declaration to reference in function scope.
		yulAssert(m_currentFuncVars.size() > 0, "Proto fuzzer: No variables to reference.");
		m_output << *m_currentFuncVars[_x.varnum() % m_currentFuncVars.size()];
	}
	else
	{
		// Ensure that there is at least one variable declaration to reference in nested scopes.
		yulAssert(m_currentGlobalVars.size() > 0, "Proto fuzzer: No global variables to reference.");
		m_output << *m_currentGlobalVars[_x.varnum() % m_currentGlobalVars.size()];
	}
}

void ProtoConverter::visit(Expression const& _x)
{
	switch (_x.expr_oneof_case())
	{
	case Expression::kVarref:
		// If the expression requires a variable reference that we cannot provide
		// (because there are no variables in scope), we silently output a literal
		// expression from the optimizer dictionary.
		if (!varDeclAvailable())
			m_output << dictionaryToken();
		else
			visit(_x.varref());
		break;
	case Expression::kCons:
		// If literal expression describes for-loop condition
		// then force it to zero, so we don't generate infinite
		// for loops
		if (m_inForCond)
			m_output << "0";
		else
			m_output << visit(_x.cons());
		break;
	case Expression::kBinop:
		visit(_x.binop());
		break;
	case Expression::kUnop:
		visit(_x.unop());
		break;
	case Expression::kTop:
		visit(_x.top());
		break;
	case Expression::kNop:
		visit(_x.nop());
		break;
	case Expression::kFuncExpr:
		// FunctionCall must return a single value, otherwise
		// we output a trivial expression "1".
		if (_x.func_expr().ret() == FunctionCall::SINGLE)
			visit(_x.func_expr());
		else
			m_output << dictionaryToken();
		break;
	case Expression::kLowcall:
		visit(_x.lowcall());
		break;
	case Expression::kCreate:
		visit(_x.create());
		break;
	case Expression::kUnopdata:
		if (m_isObject)
			visit(_x.unopdata());
		else
			m_output << dictionaryToken();
		break;
	case Expression::EXPR_ONEOF_NOT_SET:
		m_output << dictionaryToken();
		break;
	}
}

void ProtoConverter::visit(BinaryOp const& _x)
{
	BinaryOp_BOp op = _x.op();

	if ((op == BinaryOp::SHL || op == BinaryOp::SHR || op == BinaryOp::SAR) &&
		!m_evmVersion.hasBitwiseShifting())
	{
		m_output << dictionaryToken();
		return;
	}

	switch (op)
	{
	case BinaryOp::ADD:
		m_output << "add";
		break;
	case BinaryOp::SUB:
		m_output << "sub";
		break;
	case BinaryOp::MUL:
		m_output << "mul";
		break;
	case BinaryOp::DIV:
		m_output << "div";
		break;
	case BinaryOp::MOD:
		m_output << "mod";
		break;
	case BinaryOp::XOR:
		m_output << "xor";
		break;
	case BinaryOp::AND:
		m_output << "and";
		break;
	case BinaryOp::OR:
		m_output << "or";
		break;
	case BinaryOp::EQ:
		m_output << "eq";
		break;
	case BinaryOp::LT:
		m_output << "lt";
		break;
	case BinaryOp::GT:
		m_output << "gt";
		break;
	case BinaryOp::SHR:
		yulAssert(m_evmVersion.hasBitwiseShifting(), "Proto fuzzer: Invalid evm version");
		m_output << "shr";
		break;
	case BinaryOp::SHL:
		yulAssert(m_evmVersion.hasBitwiseShifting(), "Proto fuzzer: Invalid evm version");
		m_output << "shl";
		break;
	case BinaryOp::SAR:
		yulAssert(m_evmVersion.hasBitwiseShifting(), "Proto fuzzer: Invalid evm version");
		m_output << "sar";
		break;
	case BinaryOp::SDIV:
		m_output << "sdiv";
		break;
	case BinaryOp::SMOD:
		m_output << "smod";
		break;
	case BinaryOp::EXP:
		m_output << "exp";
		break;
	case BinaryOp::SLT:
		m_output << "slt";
		break;
	case BinaryOp::SGT:
		m_output << "sgt";
		break;
	case BinaryOp::BYTE:
		m_output << "byte";
		break;
	case BinaryOp::SI:
		m_output << "signextend";
		break;
	case BinaryOp::KECCAK:
		m_output << "keccak256";
		break;
	}
	m_output << "(";
	visit(_x.left());
	m_output << ",";
	visit(_x.right());
	m_output << ")";
}

void ProtoConverter::scopeVariables(vector<string> const& _varNames)
{
	// If we are inside a for-init block, there are two places
	// where the visited vardecl may have been defined:
	// - directly inside the for-init block
	// - inside a block within the for-init block
	// In the latter case, we don't scope extend. The flag
	// m_forInitScopeExtEnabled (= true) indicates whether we are directly
	// inside a for-init block e.g., for { let x } or (= false) inside a
	// nested for-init block e.g., for { { let x } }
	bool forInitScopeExtendVariable = m_inForInitScope && m_forInitScopeExtEnabled;

	// There are four cases that are tackled here
	// Case 1. We are inside a function definition and the variable declaration's
	// scope needs to be extended.
	// Case 2. We are inside a function definition but scope extension is disabled
	// Case 3. We are inside global scope and scope extension is required
	// Case 4. We are inside global scope but scope extension is disabled
	if (m_inFunctionDef)
	{
		// Variables declared directly in for-init block
		// are tracked separately because their scope
		// extends beyond the block they are defined in
		// to the rest of the for-loop statement.
		// Case 1
		if (forInitScopeExtendVariable)
		{
			yulAssert(
				!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
				"Proto fuzzer: Invalid operation"
			);
			for (auto const& varName: _varNames)
				m_funcForLoopInitVars.back().back().push_back(varName);
		}
		// Case 2
		else
		{
			yulAssert(
				!m_funcVars.empty() && !m_funcVars.back().empty(),
				"Proto fuzzer: Invalid operation"
			);
			for (auto const& varName: _varNames)
				m_funcVars.back().back().push_back(varName);
		}
	}
	// If m_inFunctionDef is false, we are in global scope
	else
	{
		// Case 3
		if (forInitScopeExtendVariable)
		{
			yulAssert(!m_globalForLoopInitVars.empty(), "Proto fuzzer: Invalid operation");

			for (auto const& varName: _varNames)
				m_globalForLoopInitVars.back().push_back(varName);
		}
		// Case 4
		else
		{
			yulAssert(!m_globalVars.empty(), "Proto fuzzer: Invalid operation");

			for (auto const& varName: _varNames)
				m_globalVars.back().push_back(varName);
		}
	}
}

void ProtoConverter::visit(VarDecl const& _x)
{
	string varName = newVarName();
	m_output << "let " << varName << " := ";
	visit(_x.expr());
	m_output << "\n";
	scopeVariables({varName});
}

void ProtoConverter::visit(MultiVarDecl const& _x)
{
	m_output << "let ";
	vector<string> varNames;
	// We support up to 4 variables in a single
	// declaration statement.
	unsigned numVars = _x.num_vars() % 3 + 2;
	string delimiter = "";
	for (unsigned i = 0; i < numVars; i++)
	{
		string varName = newVarName();
		varNames.push_back(varName);
		m_output << delimiter << varName;
		if (i == 0)
			delimiter = ", ";
	}
	m_output << "\n";
	scopeVariables(varNames);
}

void ProtoConverter::visit(TypedVarDecl const& _x)
{
	string varName = newVarName();
	m_output << "let " << varName;
	switch (_x.type())
	{
	case TypedVarDecl::BOOL:
		m_output << ": bool := ";
		visit(_x.expr());
		m_output << " : bool\n";
		break;
	case TypedVarDecl::S8:
		m_output << ": s8 := ";
		visit(_x.expr());
		m_output << " : s8\n";
		break;
	case TypedVarDecl::S32:
		m_output << ": s32 := ";
		visit(_x.expr());
		m_output << " : s32\n";
		break;
	case TypedVarDecl::S64:
		m_output << ": s64 := ";
		visit(_x.expr());
		m_output << " : s64\n";
		break;
	case TypedVarDecl::S128:
		m_output << ": s128 := ";
		visit(_x.expr());
		m_output << " : s128\n";
		break;
	case TypedVarDecl::S256:
		m_output << ": s256 := ";
		visit(_x.expr());
		m_output << " : s256\n";
		break;
	case TypedVarDecl::U8:
		m_output << ": u8 := ";
		visit(_x.expr());
		m_output << " : u8\n";
		break;
	case TypedVarDecl::U32:
		m_output << ": u32 := ";
		visit(_x.expr());
		m_output << " : u32\n";
		break;
	case TypedVarDecl::U64:
		m_output << ": u64 := ";
		visit(_x.expr());
		m_output << " : u64\n";
		break;
	case TypedVarDecl::U128:
		m_output << ": u128 := ";
		visit(_x.expr());
		m_output << " : u128\n";
		break;
	case TypedVarDecl::U256:
		m_output << ": u256 := ";
		visit(_x.expr());
		m_output << " : u256\n";
		break;
	}
	// If we are inside a for-init block, there are two places
	// where the visited vardecl may have been defined:
	// - directly inside the for-init block
	// - inside a block within the for-init block
	// In the latter case, we don't scope extend.
	if (m_inFunctionDef)
	{
		// Variables declared directly in for-init block
		// are tracked separately because their scope
		// extends beyond the block they are defined in
		// to the rest of the for-loop statement.
		if (m_inForInitScope && m_forInitScopeExtEnabled)
		{
			yulAssert(
				!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
				"Proto fuzzer: Invalid operation"
			);
			m_funcForLoopInitVars.back().back().push_back(varName);
		}
		else
		{
			yulAssert(
				!m_funcVars.empty() && !m_funcVars.back().empty(),
				"Proto fuzzer: Invalid operation"
			);
			m_funcVars.back().back().push_back(varName);
		}
	}
	else
	{
		if (m_inForInitScope && m_forInitScopeExtEnabled)
		{
			yulAssert(
				!m_globalForLoopInitVars.empty(),
				"Proto fuzzer: Invalid operation"
			);
			m_globalForLoopInitVars.back().push_back(varName);
		}
		else
		{
			yulAssert(
				!m_globalVars.empty(),
				"Proto fuzzer: Invalid operation"
			);
			m_globalVars.back().push_back(varName);
		}
	}
}

void ProtoConverter::visit(UnaryOp const& _x)
{
	UnaryOp_UOp op = _x.op();

	// Replace calls to extcodehash on unsupported EVMs with a dictionary
	// token.
	if (op == UnaryOp::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())
	{
		m_output << dictionaryToken();
		return;
	}

	switch (op)
	{
	case UnaryOp::NOT:
		m_output << "not";
		break;
	case UnaryOp::MLOAD:
		m_output << "mload";
		break;
	case UnaryOp::SLOAD:
		m_output << "sload";
		break;
	case UnaryOp::ISZERO:
		m_output << "iszero";
		break;
	case UnaryOp::CALLDATALOAD:
		m_output << "calldataload";
		break;
	case UnaryOp::EXTCODESIZE:
		m_output << "extcodesize";
		break;
	case UnaryOp::EXTCODEHASH:
		m_output << "extcodehash";
		break;
	case UnaryOp::BALANCE:
		m_output << "balance";
		break;
	case UnaryOp::BLOCKHASH:
		m_output << "blockhash";
		break;
	}
	m_output << "(";
	visit(_x.operand());
	m_output << ")";
}

void ProtoConverter::visit(TernaryOp const& _x)
{
	switch (_x.op())
	{
	case TernaryOp::ADDM:
		m_output << "addmod";
		break;
	case TernaryOp::MULM:
		m_output << "mulmod";
		break;
	}
	m_output << "(";
	visit(_x.arg1());
	m_output << ", ";
	visit(_x.arg2());
	m_output << ", ";
	visit(_x.arg3());
	m_output << ")";
}

void ProtoConverter::visit(NullaryOp const& _x)
{
	switch (_x.op())
	{
	case NullaryOp::PC:
		m_output << "pc()";
		break;
	case NullaryOp::MSIZE:
		m_output << "msize()";
		break;
	case NullaryOp::GAS:
		m_output << "gas()";
		break;
	case NullaryOp::CALLDATASIZE:
		m_output << "calldatasize()";
		break;
	case NullaryOp::CODESIZE:
		m_output << "codesize()";
		break;
	case NullaryOp::RETURNDATASIZE:
		// If evm supports returndatasize, we generate it. Otherwise,
		// we output a dictionary token.
		if (m_evmVersion.supportsReturndata())
			m_output << "returndatasize()";
		else
			m_output << dictionaryToken();
		break;
	case NullaryOp::ADDRESS:
		m_output << "address()";
		break;
	case NullaryOp::ORIGIN:
		m_output << "origin()";
		break;
	case NullaryOp::CALLER:
		m_output << "caller()";
		break;
	case NullaryOp::CALLVALUE:
		m_output << "callvalue()";
		break;
	case NullaryOp::GASPRICE:
		m_output << "gasprice()";
		break;
	case NullaryOp::COINBASE:
		m_output << "coinbase()";
		break;
	case NullaryOp::TIMESTAMP:
		m_output << "timestamp()";
		break;
	case NullaryOp::NUMBER:
		m_output << "number()";
		break;
	case NullaryOp::DIFFICULTY:
		m_output << "difficulty()";
		break;
	case NullaryOp::GASLIMIT:
		m_output << "gaslimit()";
		break;
	case NullaryOp::SELFBALANCE:
		// Replace calls to selfbalance() on unsupported EVMs with a dictionary
		// token.
		if (m_evmVersion.hasSelfBalance())
			m_output << "selfbalance()";
		else
			m_output << dictionaryToken();
		break;
	case NullaryOp::CHAINID:
		// Replace calls to chainid() on unsupported EVMs with a dictionary
		// token.
		if (m_evmVersion.hasChainID())
			m_output << "chainid()";
		else
			m_output << dictionaryToken();
		break;
	}
}

void ProtoConverter::visit(CopyFunc const& _x)
{
	CopyFunc_CopyType type = _x.ct();

	// datacopy() is valid only if we are inside
	// a Yul object.
	if (type == CopyFunc::DATA && !m_isObject)
		return;

	// We don't generate code if the copy function is returndatacopy
	// and the underlying evm does not support it.
	if (type == CopyFunc::RETURNDATA && !m_evmVersion.supportsReturndata())
		return;

	switch (type)
	{
	case CopyFunc::CALLDATA:
		m_output << "calldatacopy";
		break;
	case CopyFunc::CODE:
		m_output << "codecopy";
		break;
	case CopyFunc::RETURNDATA:
		yulAssert(m_evmVersion.supportsReturndata(), "Proto fuzzer: Invalid evm version");
		m_output << "returndatacopy";
		break;
	case CopyFunc::DATA:
		m_output << "datacopy";
		break;
	}
	m_output << "(";
	visit(_x.target());
	m_output << ", ";
	visit(_x.source());
	m_output << ", ";
	visit(_x.size());
	m_output << ")\n";
}

void ProtoConverter::visit(ExtCodeCopy const& _x)
{
	m_output << "extcodecopy";
	m_output << "(";
	visit(_x.addr());
	m_output << ", ";
	visit(_x.target());
	m_output << ", ";
	visit(_x.source());
	m_output << ", ";
	visit(_x.size());
	m_output << ")\n";
}

void ProtoConverter::visit(LogFunc const& _x)
{
	switch (_x.num_topics())
	{
	case LogFunc::ZERO:
		m_output << "log0";
		m_output << "(";
		visit(_x.pos());
		m_output << ", ";
		visit(_x.size());
		m_output << ")\n";
		break;
	case LogFunc::ONE:
		m_output << "log1";
		m_output << "(";
		visit(_x.pos());
		m_output << ", ";
		visit(_x.size());
		m_output << ", ";
		visit(_x.t1());
		m_output << ")\n";
		break;
	case LogFunc::TWO:
		m_output << "log2";
		m_output << "(";
		visit(_x.pos());
		m_output << ", ";
		visit(_x.size());
		m_output << ", ";
		visit(_x.t1());
		m_output << ", ";
		visit(_x.t2());
		m_output << ")\n";
		break;
	case LogFunc::THREE:
		m_output << "log3";
		m_output << "(";
		visit(_x.pos());
		m_output << ", ";
		visit(_x.size());
		m_output << ", ";
		visit(_x.t1());
		m_output << ", ";
		visit(_x.t2());
		m_output << ", ";
		visit(_x.t3());
		m_output << ")\n";
		break;
	case LogFunc::FOUR:
		m_output << "log4";
		m_output << "(";
		visit(_x.pos());
		m_output << ", ";
		visit(_x.size());
		m_output << ", ";
		visit(_x.t1());
		m_output << ", ";
		visit(_x.t2());
		m_output << ", ";
		visit(_x.t3());
		m_output << ", ";
		visit(_x.t4());
		m_output << ")\n";
		break;
	}
}

void ProtoConverter::visit(AssignmentStatement const& _x)
{
	visit(_x.ref_id());
	m_output << " := ";
	visit(_x.expr());
	m_output << "\n";
}

void ProtoConverter::visitFunctionInputParams(FunctionCall const& _x, unsigned _numInputParams)
{
	// We reverse the order of function input visits since it helps keep this switch case concise.
	switch (_numInputParams)
	{
	case 4:
		visit(_x.in_param4());
		m_output << ", ";
		BOOST_FALLTHROUGH;
	case 3:
		visit(_x.in_param3());
		m_output << ", ";
		BOOST_FALLTHROUGH;
	case 2:
		visit(_x.in_param2());
		m_output << ", ";
		BOOST_FALLTHROUGH;
	case 1:
		visit(_x.in_param1());
		BOOST_FALLTHROUGH;
	case 0:
		break;
	default:
		yulAssert(false, "Proto fuzzer: Function call with too many input parameters.");
		break;
	}
}

bool ProtoConverter::functionValid(FunctionCall_Returns _type, unsigned _numOutParams)
{
	switch (_type)
	{
	case FunctionCall::ZERO:
		return _numOutParams == 0;
	case FunctionCall::SINGLE:
		return _numOutParams == 1;
	case FunctionCall::MULTIDECL:
	case FunctionCall::MULTIASSIGN:
		return _numOutParams > 1;
	}
}

void ProtoConverter::convertFunctionCall(
	FunctionCall const& _x,
	std::string _name,
	unsigned _numInParams,
	bool _newLine
)
{
	m_output << _name << "(";
	visitFunctionInputParams(_x, _numInParams);
	m_output << ")";
	if (_newLine)
		m_output << "\n";
}

vector<string> ProtoConverter::createVarDecls(unsigned _start, unsigned _end, bool _isAssignment)
{
	m_output << "let ";
	vector<string> varsVec = createVars(_start, _end);
	if (_isAssignment)
		m_output << " := ";
	else
		m_output << "\n";
	return varsVec;
}

void ProtoConverter::visit(FunctionCall const& _x)
{
	bool functionAvailable = m_functionSigMap.size() > 0;
	unsigned numInParams, numOutParams;
	string funcName;
	FunctionCall_Returns funcType = _x.ret();
	if (functionAvailable)
	{
		yulAssert(m_functions.size() > 0, "Proto fuzzer: No function in scope");
		funcName = m_functions[_x.func_index() % m_functions.size()];
		auto ret = m_functionSigMap.at(funcName);
		numInParams = ret.first;
		numOutParams = ret.second;
	}
	else
	{
		// If there are no functions available, calls to functions that
		// return a single value may be replaced by a dictionary token.
		if (funcType == FunctionCall::SINGLE)
			m_output << dictionaryToken();
		return;
	}

	// If function selected for function call does not meet interface
	// requirements (num output values) for the function type
	// specified, then we return early unless it is a function call
	// that returns a single value (which may be replaced by a
	// dictionary token.
	if (!functionValid(funcType, numOutParams))
	{
		if (funcType == FunctionCall::SINGLE)
			m_output << dictionaryToken();
		return;
	}

	// If we are here, it means that we have at least one valid
	// function for making the function call
	switch (funcType)
	{
	case FunctionCall::ZERO:
		convertFunctionCall(_x, funcName, numInParams);
		break;
	case FunctionCall::SINGLE:
		// Since functions that return a single value are used as expressions
		// we do not print a newline because it is done by the expression
		// visitor.
		convertFunctionCall(_x, funcName, numInParams, /*newLine=*/false);
		break;
	case FunctionCall::MULTIDECL:
	{
		// Ensure that the chosen function returns at most 4 values
		yulAssert(
			numOutParams <= 4,
			"Proto fuzzer: Function call with too many output params encountered."
		);

		// Obtain variable name suffix
		unsigned startIdx = counter();
		vector<string> varsVec = createVarDecls(
			startIdx,
			startIdx + numOutParams,
			/*isAssignment=*/true
		);

		// Create RHS of multi var decl
		convertFunctionCall(_x, funcName, numInParams);
		// Add newly minted vars in the multidecl statement to current scope
		addVarsToScope(varsVec);
		break;
	}
	case FunctionCall::MULTIASSIGN:
		// Ensure that the chosen function returns at most 4 values
		yulAssert(
			numOutParams <= 4,
			"Proto fuzzer: Function call with too many output params encountered."
		);

		// Convert LHS of multi assignment
		// We reverse the order of out param visits since the order does not matter.
		// This helps reduce the size of this switch statement.
		switch (numOutParams)
		{
		case 4:
			visit(_x.out_param4());
			m_output << ", ";
			BOOST_FALLTHROUGH;
		case 3:
			visit(_x.out_param3());
			m_output << ", ";
			BOOST_FALLTHROUGH;
		case 2:
			visit(_x.out_param2());
			m_output << ", ";
			visit(_x.out_param1());
			break;
		default:
			yulAssert(false, "Proto fuzzer: Function call with too many or too few input parameters.");
			break;
		}
		m_output << " := ";

		// Convert RHS of multi assignment
		convertFunctionCall(_x, funcName, numInParams);
		break;
	}
}

void ProtoConverter::visit(LowLevelCall const& _x)
{
	LowLevelCall_Type type = _x.callty();

	// Generate staticcall if it is supported by the underlying evm
	if (type == LowLevelCall::STATICCALL && !m_evmVersion.hasStaticCall())
	{
		// Since staticcall is supposed to return 0 on success and 1 on
		// failure, we can use counter value to emulate it
		m_output << ((counter() % 2) ? "0" : "1");
		return;
	}

	switch (type)
	{
	case LowLevelCall::CALL:
		m_output << "call(";
		break;
	case LowLevelCall::CALLCODE:
		m_output << "callcode(";
		break;
	case LowLevelCall::DELEGATECALL:
		m_output << "delegatecall(";
		break;
	case LowLevelCall::STATICCALL:
		yulAssert(m_evmVersion.hasStaticCall(), "Proto fuzzer: Invalid evm version");
		m_output << "staticcall(";
		break;
	}
	visit(_x.gas());
	m_output << ", ";
	visit(_x.addr());
	m_output << ", ";
	if (type == LowLevelCall::CALL || type == LowLevelCall::CALLCODE)
	{
		visit(_x.wei());
		m_output << ", ";
	}
	visit(_x.in());
	m_output << ", ";
	visit(_x.insize());
	m_output << ", ";
	visit(_x.out());
	m_output << ", ";
	visit(_x.outsize());
	m_output << ")";
}

void ProtoConverter::visit(Create const& _x)
{
	Create_Type type = _x.createty();

	// Replace a call to create2 on unsupported EVMs with a dictionary
	// token.
	if (type == Create::CREATE2 && !m_evmVersion.hasCreate2())
	{
		m_output << dictionaryToken();
		return;
	}

	switch (type)
	{
	case Create::CREATE:
		m_output << "create(";
		break;
	case Create::CREATE2:
		m_output << "create2(";
		break;
	}
	visit(_x.wei());
	m_output << ", ";
	visit(_x.position());
	m_output << ", ";
	visit(_x.size());
	if (type == Create::CREATE2)
	{
		m_output << ", ";
		visit(_x.value());
	}
	m_output << ")";
}

void ProtoConverter::visit(IfStmt const& _x)
{
	m_output << "if ";
	visit(_x.cond());
	m_output << " ";
	visit(_x.if_body());
}

void ProtoConverter::visit(StoreFunc const& _x)
{
	switch (_x.st())
	{
	case StoreFunc::MSTORE:
		m_output << "mstore(";
		break;
	case StoreFunc::SSTORE:
		m_output << "sstore(";
		break;
	case StoreFunc::MSTORE8:
		m_output << "mstore8(";
		break;
	}
	visit(_x.loc());
	m_output << ", ";
	visit(_x.val());
	m_output << ")\n";
}

void ProtoConverter::visit(ForStmt const& _x)
{
	if (++m_numForLoops > s_maxForLoops)
		return;
	bool wasInForBody = m_inForBodyScope;
	bool wasInForInit = m_inForInitScope;
	bool wasForInitScopeExtEnabled = m_forInitScopeExtEnabled;
	m_inForBodyScope = false;
	m_inForInitScope = true;
	m_forInitScopeExtEnabled = true;
	m_inForCond = false;
	m_output << "for ";
	visit(_x.for_init());
	m_inForInitScope = false;
	m_forInitScopeExtEnabled = wasForInitScopeExtEnabled;
	m_inForCond = true;
	visit(_x.for_cond());
	m_inForCond = false;
	visit(_x.for_post());
	m_inForBodyScope = true;
	visit(_x.for_body());
	m_inForBodyScope = wasInForBody;
	m_inForInitScope = wasInForInit;
	if (m_inFunctionDef)
	{
		yulAssert(
			!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
			"Proto fuzzer: Invalid data structure"
		);
		// Remove variables in for-init
		m_funcForLoopInitVars.back().pop_back();
	}
	else
	{
		yulAssert(!m_globalForLoopInitVars.empty(), "Proto fuzzer: Invalid data structure");
		m_globalForLoopInitVars.pop_back();
	}
}

void ProtoConverter::visit(BoundedForStmt const& _x)
{
	if (++m_numForLoops > s_maxForLoops)
		return;

	// Boilerplate for loop that limits the number of iterations to a maximum of 4.
	std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++));
	m_output << "for { let " << loopVarName << " := 0 } "
	       << "lt(" << loopVarName << ", 0x60) "
	       << "{ " << loopVarName << " := add(" << loopVarName << ", 0x20) } ";
	// Store previous for body scope
	bool wasInForBody = m_inForBodyScope;
	bool wasInForInit = m_inForInitScope;
	m_inForBodyScope = true;
	m_inForInitScope = false;
	visit(_x.for_body());
	// Restore previous for body scope and init
	m_inForBodyScope = wasInForBody;
	m_inForInitScope = wasInForInit;
}

void ProtoConverter::visit(CaseStmt const& _x)
{
	string literal = visit(_x.case_lit());
	// u256 value of literal
	u256 literalVal;

	// Convert string to u256 before looking for duplicate case literals
	if (_x.case_lit().has_strval())
	{
		// Since string literals returned by the Literal visitor are enclosed within
		// double quotes (like this "\"<string>\""), their size is at least two in the worst case
		// that <string> is empty. Here we assert this invariant.
		yulAssert(literal.size() >= 2, "Proto fuzzer: String literal too short");
		// This variable stores the <string> part i.e., literal minus the first and last
		// double quote characters. This is used to compute the keccak256 hash of the
		// string literal. The hashing is done to check whether we are about to create
		// a case statement containing a case literal that has already been used in a
		// previous case statement. If the hash (u256 value) matches a previous hash,
		// then we simply don't create a new case statement.
		string noDoubleQuoteStr{""};
		if (literal.size() > 2)
		{
			// Ensure that all characters in the string literal except the first
			// and the last (double quote characters) are alphanumeric.
			yulAssert(
				boost::algorithm::all_of(literal.begin() + 1, literal.end() - 2, [=](char c) -> bool {
					return std::isalpha(c) || std::isdigit(c);
				}),
				"Proto fuzzer: Invalid string literal encountered"
			);

			// Make a copy because literal will need to be used later
			noDoubleQuoteStr = literal.substr(1, literal.size() - 2);
		}
		// Hash the result to check for duplicate case literal strings
		literalVal = u256(h256(noDoubleQuoteStr, h256::FromBinary, h256::AlignLeft));

		// Make sure that an empty string literal evaluates to zero. This is to detect creation of
		// duplicate case literals like so
		// switch (x)
		// {
		//    case "": { x := 0 }
		//    case 0: { x:= 1 } // Case statement with duplicate literal is invalid
		// } // This snippet will not be parsed successfully.
		if (noDoubleQuoteStr.empty())
			yulAssert(literalVal == 0, "Proto fuzzer: Empty string does not evaluate to zero");
	}
	else if (_x.case_lit().has_boolval())
		literalVal = _x.case_lit().boolval() ? u256(1) : u256(0);
	else
		literalVal = u256(literal);

	// Check if set insertion fails (case literal present) or succeeds (case literal
	// absent).
	bool isUnique = m_switchLiteralSetPerScope.top().insert(literalVal).second;

	// It is fine to bail out if we encounter a duplicate case literal because
	// we can be assured that the switch statement is well-formed i.e., contains
	// at least one case statement or a default block.
	if (isUnique)
	{
		m_output << "case " << literal << " ";
		visit(_x.case_block());
	}
}

void ProtoConverter::visit(SwitchStmt const& _x)
{
	if (_x.case_stmt_size() > 0 || _x.has_default_block())
	{
		std::set<u256> s;
		m_switchLiteralSetPerScope.push(s);
		m_output << "switch ";
		visit(_x.switch_expr());
		m_output << "\n";

		for (auto const& caseStmt: _x.case_stmt())
			visit(caseStmt);

		m_switchLiteralSetPerScope.pop();

		if (_x.has_default_block())
		{
			m_output << "default ";
			visit(_x.default_block());
		}
	}
}

void ProtoConverter::visit(StopInvalidStmt const& _x)
{
	switch (_x.stmt())
	{
	case StopInvalidStmt::STOP:
		m_output << "stop()\n";
		break;
	case StopInvalidStmt::INVALID:
		m_output << "invalid()\n";
		break;
	}
}

void ProtoConverter::visit(RetRevStmt const& _x)
{
	switch (_x.stmt())
	{
	case RetRevStmt::RETURN:
		m_output << "return";
		break;
	case RetRevStmt::REVERT:
		m_output << "revert";
		break;
	}
	m_output << "(";
	visit(_x.pos());
	m_output << ", ";
	visit(_x.size());
	m_output << ")\n";
}

void ProtoConverter::visit(SelfDestructStmt const& _x)
{
	m_output << "selfdestruct";
	m_output << "(";
	visit(_x.addr());
	m_output << ")\n";
}

void ProtoConverter::visit(TerminatingStmt const& _x)
{
	switch (_x.term_oneof_case())
	{
	case TerminatingStmt::kStopInvalid:
		visit(_x.stop_invalid());
		break;
	case TerminatingStmt::kRetRev:
		visit(_x.ret_rev());
		break;
	case TerminatingStmt::kSelfDes:
		visit(_x.self_des());
		break;
	case TerminatingStmt::TERM_ONEOF_NOT_SET:
		break;
	}
}

void ProtoConverter::visit(UnaryOpData const& _x)
{
	switch (_x.op())
	{
	case UnaryOpData::SIZE:
		m_output << Whiskers(R"(datasize("<id>"))")
			("id", getObjectIdentifier(_x.identifier()))
			.render();
		break;
	case UnaryOpData::OFFSET:
		m_output << Whiskers(R"(dataoffset("<id>"))")
			("id", getObjectIdentifier(_x.identifier()))
			.render();
		break;
	}
}

void ProtoConverter::visit(Statement const& _x)
{
	switch (_x.stmt_oneof_case())
	{
	case Statement::kDecl:
		visit(_x.decl());
		break;
	case Statement::kAssignment:
		// Create an assignment statement only if there is at least one variable
		// declaration that is in scope.
		if (varDeclAvailable())
			visit(_x.assignment());
		break;
	case Statement::kIfstmt:
		if (_x.ifstmt().if_body().statements_size() > 0)
			visit(_x.ifstmt());
		break;
	case Statement::kStorageFunc:
		visit(_x.storage_func());
		break;
	case Statement::kBlockstmt:
		if (_x.blockstmt().statements_size() > 0)
			visit(_x.blockstmt());
		break;
	case Statement::kForstmt:
		if (_x.forstmt().for_body().statements_size() > 0)
			visit(_x.forstmt());
		break;
	case Statement::kBoundedforstmt:
		if (_x.boundedforstmt().for_body().statements_size() > 0)
			visit(_x.boundedforstmt());
		break;
	case Statement::kSwitchstmt:
		visit(_x.switchstmt());
		break;
	case Statement::kBreakstmt:
		if (m_inForBodyScope)
			m_output << "break\n";
		break;
	case Statement::kContstmt:
		if (m_inForBodyScope)
			m_output << "continue\n";
		break;
	case Statement::kLogFunc:
		visit(_x.log_func());
		break;
	case Statement::kCopyFunc:
		visit(_x.copy_func());
		break;
	case Statement::kExtcodeCopy:
		visit(_x.extcode_copy());
		break;
	case Statement::kTerminatestmt:
		visit(_x.terminatestmt());
		break;
	case Statement::kFunctioncall:
		// Return early if a function call cannot be created
		if (functionCallNotPossible(_x.functioncall().ret()))
			return;
		visit(_x.functioncall());
		break;
	case Statement::kFuncdef:
		if (_x.funcdef().block().statements_size() > 0)
			if (!m_inForInitScope)
				visit(_x.funcdef());
		break;
	case Statement::kPop:
		visit(_x.pop());
		break;
	case Statement::kLeave:
		if (m_inFunctionDef)
			visit(_x.leave());
		break;
	case Statement::kMultidecl:
		visit(_x.multidecl());
		break;
	case Statement::STMT_ONEOF_NOT_SET:
		break;
	}
}

void ProtoConverter::openBlockScope()
{
	m_scopeFuncs.push_back({});

	// Create new block scope inside current function scope
	if (m_inFunctionDef)
	{
		yulAssert(
			!m_funcVars.empty(),
			"Proto fuzzer: Invalid data structure"
		);
		m_funcVars.back().push_back(vector<string>{});
		if (m_inForInitScope && m_forInitScopeExtEnabled)
		{
			yulAssert(
				!m_funcForLoopInitVars.empty(),
				"Proto fuzzer: Invalid data structure"
			);
			m_funcForLoopInitVars.back().push_back(vector<string>{});
		}
	}
	else
	{
		m_globalVars.push_back({});
		if (m_inForInitScope && m_forInitScopeExtEnabled)
			m_globalForLoopInitVars.push_back(vector<string>{});
	}
}

void ProtoConverter::openFunctionScope(vector<string> const& _funcParams)
{
	m_funcVars.push_back(vector<vector<string>>({_funcParams}));
	m_funcForLoopInitVars.push_back(vector<vector<string>>({}));
}

void ProtoConverter::updateFunctionMaps(string const& _var)
{
	unsigned erased = m_functionSigMap.erase(_var);

	for (auto const& i: m_functionDefMap)
		if (i.second == _var)
		{
			erased += m_functionDefMap.erase(i.first);
			break;
		}

	yulAssert(erased == 2, "Proto fuzzer: Function maps not updated");
}

void ProtoConverter::closeBlockScope()
{
	// Remove functions declared in the block that is going
	// out of scope from the global function map.
	for (auto const& f: m_scopeFuncs.back())
	{
		unsigned numFuncsRemoved = m_functions.size();
		m_functions.erase(remove(m_functions.begin(), m_functions.end(), f), m_functions.end());
		numFuncsRemoved -= m_functions.size();
		yulAssert(
			numFuncsRemoved == 1,
			"Proto fuzzer: Nothing or too much went out of scope"
		);
		updateFunctionMaps(f);
	}
	// Pop back the vector of scoped functions.
	if (!m_scopeFuncs.empty())
		m_scopeFuncs.pop_back();

	// If block belongs to function body, then remove
	// local variables in function body that are going out of scope.
	if (m_inFunctionDef)
	{
		yulAssert(!m_funcVars.empty(), "Proto fuzzer: Invalid data structure");
		if (!m_funcVars.back().empty())
			m_funcVars.back().pop_back();
	}
	// Remove variables declared in vanilla block from current
	// global scope.
	else
	{
		yulAssert(!m_globalVars.empty(), "Proto fuzzer: Invalid data structure");
		m_globalVars.pop_back();
	}
}

void ProtoConverter::closeFunctionScope()
{
	yulAssert(!m_funcVars.empty(), "Proto fuzzer: Invalid data structure");
	m_funcVars.pop_back();
	yulAssert(!m_funcForLoopInitVars.empty(), "Proto fuzzer: Invalid data structure");
	m_funcForLoopInitVars.pop_back();
}

void ProtoConverter::addVarsToScope(vector<string> const& _vars)
{
	// If we are in function definition, add the new vars to current function scope
	if (m_inFunctionDef)
	{
		// If we are directly in for-init block, add the newly created vars to the
		// stack of for-init variables.
		if (m_inForInitScope && m_forInitScopeExtEnabled)
		{
			yulAssert(
				!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
				"Proto fuzzer: Invalid data structure"
			);
			m_funcForLoopInitVars.back().back().insert(
				m_funcForLoopInitVars.back().back().end(),
				_vars.begin(),
				_vars.end()
			);
		}
		else
		{
			yulAssert(
				!m_funcVars.empty() && !m_funcVars.back().empty(),
				"Proto fuzzer: Invalid data structure"
			);
			m_funcVars.back().back().insert(
				m_funcVars.back().back().end(),
				_vars.begin(),
				_vars.end()
			);
		}
	}
	// If we are in a vanilla block, add the new vars to current global scope
	else
	{
		if (m_inForInitScope && m_forInitScopeExtEnabled)
		{
			yulAssert(
				!m_globalForLoopInitVars.empty(),
				"Proto fuzzer: Invalid data structure"
			);
			m_globalForLoopInitVars.back().insert(
				m_globalForLoopInitVars.back().end(),
				_vars.begin(),
				_vars.end()
			);
		}
		else
		{
			yulAssert(
				!m_globalVars.empty(),
				"Proto fuzzer: Invalid data structure"
			);
			m_globalVars.back().insert(
				m_globalVars.back().end(),
				_vars.begin(),
				_vars.end()
			);
		}
	}
}

void ProtoConverter::visit(Block const& _x)
{
	openBlockScope();

	// Register function declarations in this scope unless this
	// scope belongs to for-init (in which function declarations
	// are forbidden).
	for (auto const& statement: _x.statements())
		if (statement.has_funcdef() && statement.funcdef().block().statements_size() > 0 && !m_inForInitScope)
			registerFunction(&statement.funcdef());

	if (_x.statements_size() > 0)
	{
		m_output << "{\n";
		bool wasForInitScopeExtEnabled = m_forInitScopeExtEnabled;
		for (auto const& st: _x.statements())
		{
			// If statement is block or introduces one and we are in for-init block
			// then temporarily disable scope extension if it is not already disabled.
			if (
				(st.has_blockstmt() || st.has_switchstmt() || st.has_ifstmt()) &&
				m_inForInitScope &&
				m_forInitScopeExtEnabled
			)
				m_forInitScopeExtEnabled = false;
			visit(st);
			m_forInitScopeExtEnabled = wasForInitScopeExtEnabled;
		}
		m_output << "}\n";
	}
	else
		m_output << "{}\n";
	closeBlockScope();
}

vector<string> ProtoConverter::createVars(unsigned _startIdx, unsigned _endIdx)
{
	yulAssert(_endIdx > _startIdx, "Proto fuzzer: Variable indices not in range");
	string varsStr = suffixedVariableNameList("x_", _startIdx, _endIdx);
	m_output << varsStr;
	vector<string> varsVec;
	boost::split(
		varsVec,
		varsStr,
		boost::algorithm::is_any_of(", "),
		boost::algorithm::token_compress_on
	);

	yulAssert(
		varsVec.size() == (_endIdx - _startIdx),
		"Proto fuzzer: Variable count mismatch during function definition"
	);
	m_counter += varsVec.size();
	return varsVec;
}

void ProtoConverter::registerFunction(FunctionDef const* _x)
{
	unsigned numInParams = _x->num_input_params() % s_modInputParams;
	unsigned numOutParams = _x->num_output_params() % s_modOutputParams;
	NumFunctionReturns numReturns;
	if (numOutParams == 0)
		numReturns = NumFunctionReturns::None;
	else if (numOutParams == 1)
		numReturns = NumFunctionReturns::Single;
	else
		numReturns = NumFunctionReturns::Multiple;

	// Generate function name
	string funcName = functionName(numReturns);

	// Register function
	auto ret = m_functionSigMap.emplace(make_pair(funcName, make_pair(numInParams, numOutParams)));
	yulAssert(ret.second, "Proto fuzzer: Function already exists.");
	m_functions.push_back(funcName);
	m_scopeFuncs.back().push_back(funcName);
	m_functionDefMap.emplace(make_pair(_x, funcName));
}

void ProtoConverter::fillFunctionCallInput(unsigned _numInParams)
{
	for (unsigned i = 0; i < _numInParams; i++)
	{
		// Throw a 4-sided dice to choose whether to populate function input
		// argument from a pseudo-randomly chosen slot in one of the following
		// locations: calldata, memory, storage, or Yul optimizer dictionary.
		unsigned diceValue = counter() % 4;
		// Pseudo-randomly choose one of the first ten 32-byte
		// aligned slots.
		string slot = to_string((counter() % 10) * 32);
		switch (diceValue)
		{
		case 0:
			m_output << "calldataload(" << slot << ")";
			break;
		case 1:
			m_output << "mload(" << slot << ")";
			break;
		case 2:
			m_output << "sload(" << slot << ")";
			break;
		case 3:
			// Call to dictionaryToken() automatically picks a token
			// at a pseudo-random location.
			m_output << dictionaryToken();
			break;
		}
		if (i < _numInParams - 1)
			m_output << ",";
	}
}

void ProtoConverter::saveFunctionCallOutput(vector<string> const& _varsVec)
{
	for (auto const& var: _varsVec)
	{
		// Flip a dice to choose whether to save output values
		// in storage or memory.
		bool coinFlip = counter() % 2 == 0;
		// Pseudo-randomly choose one of the first ten 32-byte
		// aligned slots.
		string slot = to_string((counter() % 10) * 32);
		if (coinFlip)
			m_output << "sstore(" << slot << ", " << var << ")\n";
		else
			m_output << "mstore(" << slot << ", " << var << ")\n";
	}
}

void ProtoConverter::createFunctionCall(
	string _funcName,
	unsigned _numInParams,
	unsigned _numOutParams
)
{
	vector<string> varsVec{};
	if (_numOutParams > 0)
	{
		unsigned startIdx = counter();
		// Prints the following to output stream "let x_i,...,x_n := "
		varsVec = createVarDecls(
			startIdx,
			startIdx + _numOutParams,
			/*isAssignment=*/true
		);
	}

	// Call the function with the correct number of input parameters
	m_output << _funcName << "(";
	if (_numInParams > 0)
		fillFunctionCallInput(_numInParams);
	m_output << ")\n";

	if (!varsVec.empty())
	{
		// Save values returned by function so that they are reflected
		// in the interpreter trace.
		saveFunctionCallOutput(varsVec);
		// Add newly minted vars to current scope
		addVarsToScope(varsVec);
	}
	else
		yulAssert(_numOutParams == 0, "Proto fuzzer: Function return value not saved");
}

void ProtoConverter::createFunctionDefAndCall(
	FunctionDef const& _x,
	unsigned _numInParams,
	unsigned _numOutParams
)
{
	yulAssert(
		((_numInParams <= s_modInputParams - 1) && (_numOutParams <= s_modOutputParams - 1)),
		"Proto fuzzer: Too many function I/O parameters requested."
	);

	// Obtain function name
	yulAssert(m_functionDefMap.count(&_x), "Proto fuzzer: Unregistered function");
	string funcName = m_functionDefMap.at(&_x);

	vector<string> varsVec = {};
	m_output << "function " << funcName << "(";
	unsigned startIdx = counter();
	if (_numInParams > 0)
		varsVec = createVars(startIdx, startIdx + _numInParams);
	m_output << ")";

	vector<string> outVarsVec = {};
	// This creates -> x_n+1,...,x_r
	if (_numOutParams > 0)
	{
		m_output << " -> ";
		if (varsVec.empty())
		{
			yulAssert(_numInParams == 0, "Proto fuzzer: Input parameters not processed correctly");
			varsVec = createVars(startIdx, startIdx + _numOutParams);
		}
		else
		{
			outVarsVec = createVars(startIdx + _numInParams, startIdx + _numInParams + _numOutParams);
			varsVec.insert(varsVec.end(), outVarsVec.begin(), outVarsVec.end());
		}
	}
	yulAssert(varsVec.size() == _numInParams + _numOutParams, "Proto fuzzer: Function parameters not processed correctly");

	m_output << "\n";

	// If function definition is in for-loop body, update
	bool wasInForBody = m_inForBodyScope;
	m_inForBodyScope = false;

	bool wasInFunctionDef = m_inFunctionDef;
	m_inFunctionDef = true;

	// Create new function scope and add function input and return
	// parameters to it.
	openFunctionScope(varsVec);
	// Visit function body
	visit(_x.block());
	closeFunctionScope();

	m_inForBodyScope = wasInForBody;
	m_inFunctionDef = wasInFunctionDef;

	yulAssert(
		!m_inForInitScope,
		"Proto fuzzer: Trying to create function call inside a for-init block"
	);
	if (_x.force_call())
		createFunctionCall(funcName, _numInParams, _numOutParams);
}

void ProtoConverter::visit(FunctionDef const& _x)
{
	unsigned numInParams = _x.num_input_params() % s_modInputParams;
	unsigned numOutParams = _x.num_output_params() % s_modOutputParams;
	createFunctionDefAndCall(_x, numInParams, numOutParams);
}

void ProtoConverter::visit(PopStmt const& _x)
{
	m_output << "pop(";
	visit(_x.expr());
	m_output << ")\n";
}

void ProtoConverter::visit(LeaveStmt const&)
{
	m_output << "leave\n";
}

string ProtoConverter::getObjectIdentifier(unsigned _x)
{
	unsigned currentId = currentObjectId();
	yulAssert(m_objectScopeTree.size() > currentId, "Proto fuzzer: Error referencing object");
	std::vector<std::string> objectIdsInScope = m_objectScopeTree[currentId];
	return objectIdsInScope[_x % objectIdsInScope.size()];
}

void ProtoConverter::visit(Code const& _x)
{
	m_output << "code {\n";
	visit(_x.block());
	m_output << "}\n";
}

void ProtoConverter::visit(Data const& _x)
{
	// TODO: Generate random data block identifier
	m_output << "data \"" << s_dataIdentifier << "\" hex\"" << createHex(_x.hex()) << "\"\n";
}

void ProtoConverter::visit(Object const& _x)
{
	// object "object<n>" {
	// ...
	// }
	m_output << "object " << newObjectId() << " {\n";
	visit(_x.code());
	if (_x.has_data())
		visit(_x.data());
	if (_x.has_sub_obj())
		visit(_x.sub_obj());
	m_output << "}\n";
}

void ProtoConverter::buildObjectScopeTree(Object const& _x)
{
	// Identifies object being visited
	string objectId = newObjectId(false);
	vector<string> node{objectId};
	if (_x.has_data())
		node.push_back(s_dataIdentifier);
	if (_x.has_sub_obj())
	{
		// Identifies sub object whose numeric suffix is
		// m_objectId
		string subObjectId = "object" + to_string(m_objectId);
		node.push_back(subObjectId);
		// TODO: Add sub-object to object's ancestors once
		// nested access is implemented.
		m_objectScopeTree.push_back(node);
		buildObjectScopeTree(_x.sub_obj());
	}
	else
		m_objectScopeTree.push_back(node);
}

void ProtoConverter::visit(Program const& _x)
{
	// Initialize input size
	m_inputSize = _x.ByteSizeLong();

	// Record EVM Version
	m_evmVersion = evmVersionMapping(_x.ver());

	// Program is either a Yul object or a block of
	// statements.
	switch (_x.program_oneof_case())
	{
	case Program::kBlock:
		m_output << "{\n";
		visit(_x.block());
		m_output << "}\n";
		break;
	case Program::kObj:
		m_isObject = true;
		buildObjectScopeTree(_x.obj());
		// Reset object id counter
		m_objectId = 0;
		visit(_x.obj());
		break;
	case Program::PROGRAM_ONEOF_NOT_SET:
		// {} is a trivial Yul program
		m_output << "{}";
		break;
	}
}

string ProtoConverter::programToString(Program const& _input)
{
	visit(_input);
	return m_output.str();
}

std::string ProtoConverter::functionTypeToString(NumFunctionReturns _type)
{
	switch (_type)
	{
	case NumFunctionReturns::None:
		return "n";
	case NumFunctionReturns::Single:
		return "s";
	case NumFunctionReturns::Multiple:
		return "m";
	}
}


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

#include "frame_view_controller.h"
#include <rviz/display_context.h>
#include <rviz/viewport_mouse_event.h>
#include <rviz/properties/enum_property.h>
#include <rviz/properties/float_property.h>
#include <rviz/properties/bool_property.h>
#include <rviz/properties/vector_property.h>

#include <OgreViewport.h>
#include <OgreCamera.h>
#include <OgreSceneNode.h>
#include <Eigen/Geometry>
#include <QSignalBlocker>

namespace rviz
{
static const QString ANY_AXIS("arbitrary");

// helper function to create axis strings from option ID
inline QString fmtAxis(int i)
{
  return QString("%1%2 axis").arg(QChar(i % 2 ? '+' : '-')).arg(QChar('x' + (i - 1) / 2));
}

FrameViewController::FrameViewController()
{
  axis_property_ = new EnumProperty("Point towards", fmtAxis(6),
                                    "Point the camera along the given axis of the frame.", nullptr,
                                    SLOT(changedAxis()), this);
  axis_property_->addOption(ANY_AXIS, -1);
  this->addChild(axis_property_, yaw_property_->rowNumberInParent());
  // x,y,z axes get integers from 1..6: +x, -x, +y, -y, +z, -z
  for (int i = 1; i <= 6; ++i)
    axis_property_->addOption(fmtAxis(i), i);
  previous_axis_ = axis_property_->getOptionInt();

  locked_property_ = new BoolProperty("Lock Camera", false,
                                      "Lock camera in its current pose relative to the frame", this);
}

void FrameViewController::onInitialize()
{
  FPSViewController::onInitialize();
  changedAxis();
}

void FrameViewController::reset()
{
  camera_->setPosition(Ogre::Vector3::ZERO);
  Eigen::Vector3d axis(0, 0, 0);
  int option = previous_axis_;
  if (option >= 1 && option <= 6)
  {
    axis[(option - 1) / 2] = (option % 2) ? +1 : -1;
    Eigen::Quaterniond q = Eigen::Quaterniond::FromTwoVectors(Eigen::Vector3d::UnitX(), axis);
    camera_->setOrientation(Ogre::Quaternion(q.w(), q.x(), q.y(), q.z()) * ROBOT_TO_CAMERA_ROTATION);
  }
  setPropertiesFromCamera();
}

void FrameViewController::handleMouseEvent(ViewportMouseEvent& event)
{
  if (locked_property_->getBool())
  {
    setStatus("Unlock camera in settings to enable mouse interaction.");
    return;
  }
  FPSViewController::handleMouseEvent(event);
}

int FrameViewController::actualCameraAxisOption(double precision) const
{
  // compare current camera direction with unit axes
  Ogre::Vector3 actual =
      (camera_->getOrientation() * ROBOT_TO_CAMERA_ROTATION.Inverse()) * Ogre::Vector3::UNIT_X;
  for (unsigned int i = 0; i < 3; ++i)
  {
    Ogre::Vector3 axis(0, 0, 0);
    axis[i] = 1.0;
    auto scalar_product = axis.dotProduct(actual);
    if (std::abs(scalar_product) > 1.0 - precision)
      return 1 + 2 * i + (scalar_product > 0 ? 0 : 1);
  }
  return -1;
}

void FrameViewController::setAxisFromCamera()
{
  int actual = actualCameraAxisOption();
  if (axis_property_->getOptionInt() == actual) // no change?
    return;

  QSignalBlocker block(axis_property_);
  axis_property_->setString(actual == -1 ? ANY_AXIS : fmtAxis(actual));
  rememberAxis(actual);
}

void FrameViewController::changedOrientation()
{
  FPSViewController::changedOrientation();
  setAxisFromCamera();
}

void FrameViewController::changedAxis()
{
  rememberAxis(axis_property_->getOptionInt());
  reset();
}

inline void FrameViewController::rememberAxis(int current)
{
  if (current >= 1) // remember previous axis selection
    previous_axis_ = current;
}

void FrameViewController::onTargetFrameChanged(const Ogre::Vector3& /* old_reference_position */,
                                               const Ogre::Quaternion& /* old_reference_orientation */)
{
  // don't adapt the camera pose to the old reference position, but just jump to new frame
}

void FrameViewController::updateTargetSceneNode()
{
  if (getNewTransform())
  {
    // track both, position and orientation of reference frame
    target_scene_node_->setPosition(reference_position_);
    target_scene_node_->setOrientation(reference_orientation_);
    context_->queueRender();
  }
}

} // end namespace rviz

#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(rviz::FrameViewController, rviz::ViewController)

max_stars_repo_name: fftn/rviz

max_issues_repo_name: fftn/rviz

max_forks_repo_name: fftn/rviz


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

// GDAL OSR
#ifdef HAVE_GDAL

// Supress inclusion of cpl_serv.h per #194, perhaps remove one day
// when libgeotiff 1.4.0+ is widely used
#define CPL_SERV_H_INCLUDED

#include <ogr_srs_api.h>
#include <cpl_port.h>
#include <geo_normalize.h>
#include <geovalues.h>
#include <ogr_spatialref.h>
#include <gdal.h>
#include <xtiffio.h>
#include <cpl_multiproc.h>
#endif

#include "SpatialReference.h"
// boost
#include <boost/concept_check.hpp>
#include <boost/cstdint.hpp>
// std
#include <stdexcept>
#include <string>
#include <vector>

#ifdef HAVE_GDAL
#  include "cpl_conv.h"
#endif

using namespace boost;

namespace hsl {

SpatialReference::SpatialReference()
{
}

SpatialReference::SpatialReference(SpatialReference const& other)
    : m_wkt(other.m_wkt)
{
}

SpatialReference& SpatialReference::operator=(SpatialReference const& rhs)
{
    if (&rhs != this)
    {
        m_wkt = rhs.m_wkt;
    }
    return *this;
}

bool SpatialReference::operator==(const SpatialReference& input) const
{
#ifdef HAVE_GDAL

    OGRSpatialReferenceH current = OSRNewSpatialReference(GetWKT(eCompoundOK, false).c_str());
    OGRSpatialReferenceH other = OSRNewSpatialReference(input.GetWKT(eCompoundOK, false).c_str());

    int output = OSRIsSame(current, other);

    OSRDestroySpatialReference( current );
    OSRDestroySpatialReference( other );

    return bool(output == 1);

#else
    boost::ignore_unused_variable_warning(input);
    throw std::runtime_error ("SpatialReference equality testing not available without GDAL+libgeotiff support");
#endif

}

SpatialReference::~SpatialReference()
{
}

std::string SpatialReference::GetWKT( WKTModeFlag mode_flag) const
{
    return GetWKT(mode_flag, false);
}

/// Fetch the SRS as WKT
std::string SpatialReference::GetWKT(WKTModeFlag mode_flag , bool pretty) const
{
#ifndef HAVE_GDAL
    boost::ignore_unused_variable_warning(mode_flag);
    boost::ignore_unused_variable_warning(pretty);

    // we don't have a way of making this pretty, or of stripping the compound wrapper.
    return m_wkt;
#else

    // If we already have Well Known Text then try return it, possibly
    // after some preprocessing.
    if( m_wkt != "" )
    {
        std::string result_wkt = m_wkt;

        if( (mode_flag == eHorizontalOnly
             && strstr(result_wkt.c_str(),"COMPD_CS") != NULL)
            || pretty )
        {
            OGRSpatialReference* poSRS = (OGRSpatialReference*) OSRNewSpatialReference(result_wkt.c_str());
            char *pszWKT = NULL;

            if( mode_flag == eHorizontalOnly )
                poSRS->StripVertical();

            if (pretty)
                poSRS->exportToPrettyWkt(&pszWKT, FALSE );
            else
                poSRS->exportToWkt( &pszWKT );

            OGRSpatialReference::DestroySpatialReference( poSRS );

            result_wkt = pszWKT;
            CPLFree( pszWKT );
        }

        return result_wkt;
    }

    return std::string();
#endif
}

void SpatialReference::SetFromUserInput(std::string const& v)
{
#ifdef HAVE_GDAL

    char* poWKT = 0;
    const char* input = v.c_str();

    // OGRSpatialReference* poSRS = (OGRSpatialReference*) OSRNewSpatialReference(NULL);
    OGRSpatialReference srs(NULL);
    if (OGRERR_NONE != srs.SetFromUserInput(input))
    {
        throw std::invalid_argument("could not import coordinate system into OSRSpatialReference SetFromUserInput");
    }

    srs.exportToWkt(&poWKT);

    std::string tmp(poWKT);
    CPLFree(poWKT);

    SetWKT(tmp);
#else
    boost::ignore_unused_variable_warning(v);
    throw std::runtime_error("GDAL is not available, SpatialReference could not be set from WKT");
#endif
}

void SpatialReference::SetWKT(std::string const& v)
{
    m_wkt = v;
}

void SpatialReference::SetVerticalCS(boost::int32_t verticalCSType,
                                     std::string const& citation,
                                     boost::int32_t verticalDatum,
                                     boost::int32_t verticalUnits)
{
    boost::ignore_unused_variable_warning(citation);
    boost::ignore_unused_variable_warning(verticalUnits);
    boost::ignore_unused_variable_warning(verticalDatum);
    boost::ignore_unused_variable_warning(verticalCSType);
}

}

max_stars_repo_name: zjliucn/libHSL

max_issues_repo_name: zjliucn/libHSL

max_forks_repo_name: zjliucn/libHSL


text:
/*
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * Copyright (c) 2020 Andrey Semashev
 */
/*!
 * \file   atomic/detail/fence_arch_ops_msvc_arm.hpp
 *
 * This header contains implementation of the \c fence_arch_operations struct.
 */

#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_

#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/header.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

extern "C" void __dmb(unsigned int);
#if defined(BOOST_MSVC)
#pragma intrinsic(__dmb)
#endif

namespace boost {
namespace atomics {
namespace detail {

//! Fence operations for ARM
struct fence_arch_operations_msvc_arm
{
    static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
    {
        BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
        if (order != memory_order_relaxed)
            hardware_full_fence();
        BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
    }

    static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
    {
        if (order != memory_order_relaxed)
            BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
    }

    static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
    {
        __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
    }
};

typedef fence_arch_operations_msvc_arm fence_arch_operations;

} // namespace detail
} // namespace atomics
} // namespace boost

#include <boost/atomic/detail/footer.hpp>

#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_


text:
//
// Created by duhieub on 11/9/17.
//

#ifndef EXISTENZIA_ADATASTORE_HPP
#define EXISTENZIA_ADATASTORE_HPP

#include <map>
#include <boost/variant/variant.hpp>
#include <boost/variant/get.hpp>
#include "DataStore.hpp"

/**
 * \file DataStore.hpp
 * \brief Used to store various types of data
 * \author Marc.B
 * \version 0.1
 * \date 17 novembre 2017
 *
 * add comment here
 *
 * \namespace xzia
 * \namespace data
 * \class DataStore DataStore.hpp
 *
 */
namespace xzia
{
    using variant = boost::variant<char, int, float, long, double, std::string>;

    class DataStore
    {
    public:
        DataStore() = default;

        virtual ~DataStore() = default;

        /**
         *
         * \fn addData
         * \brief Add data of any type
         * @param data Data to be added
         * @param key Key associated to the data adding
         *
         */
        template <typename T>
        void        addData(std::string const& key, T data)
        {
            datas[key] = variant(data);
        }

        /**
         *
         * \fn getData
         * \brief Get data of any type
         * @param key Key associated to the data to get
         * @return The data to get
         *
         */
        template <typename T>
        T        getData(std::string const& key)
        {
            return boost::get<T>(datas[key]);
        }

        /**
         * \fn hasData
         * \brief Check if a data key exists in the dataStore
         * @param key to be searched
         * @return true if the key exists, false otherwise
         */
        bool    hasData(std::string const& key) const;

    protected:
        std::map<std::string, variant> datas;
    };
}

#endif //EXISTENZIA_ADATASTORE_HPP

max_stars_repo_name: PierreBougon/ExistanZIA

max_issues_repo_name: PierreBougon/ExistanZIA

max_forks_repo_name: PierreBougon/ExistenZIA


text:
#include <utility>
#include <fstream>
#include <iostream>

#include <gtest/gtest.h>
#include <gtest/gtest-param-test.h>
#include <gmock/gmock.h>
#include <boost/range/combine.hpp>

#include <SopangMatcher.h>
#include <SSEMatcher.h>
#include <ElasticDegenerateString.h>
#include <Util.h>

class MatcherTest
        : public testing::TestWithParam<std::tuple<std::shared_ptr<const ElasticDegenerateString>, std::string, std::set<unsigned>>> {
public:
    void SetUp() override {}

    void TearDown() override {}

    SopangMatcher matcher_;

    static std::vector<std::tuple<std::shared_ptr<const ElasticDegenerateString>, std::string, std::set<unsigned>>>
    GenerateTestSuiteValues() {
        std::vector<std::tuple<std::string, std::string, std::string>> files = {
                {"../data/chr1337.eds", "../data/pattern8.txt",   "../data/result8.txt"},
                {"../data/chr1337.eds", "../data/patterns8.txt",  "../data/results8.txt"},
                {"../data/chr1337.eds", "../data/patterns16.txt", "../data/results16.txt"},
                {"../data/chr1337.eds", "../data/patterns32.txt", "../data/results32.txt"},
                {"../data/chr1337.eds", "../data/patterns64.txt", "../data/results64.txt"}
        };
        std::vector<std::tuple<std::shared_ptr<const ElasticDegenerateString>, std::string, std::set<unsigned>>> cases;
        for (auto fileTuple : files) {
            auto eds = std::make_shared<const ElasticDegenerateString>(eds::util::ReadEDSFile(std::get<0>(fileTuple)));
            auto patterns = eds::util::ReadPatternFile(std::get<1>(fileTuple));
            auto results = eds::util::ReadResultsFile(std::get<2>(fileTuple));
            if (patterns.size() != results.size()) {
                throw std::logic_error("Test initialisation failure - mismatch in patterns and results size");
            }
            for (auto pr : boost::combine(patterns, results)) {
                std::string pattern;
                std::set<unsigned> result;
                boost::tie(pattern, result) = pr;
                cases.push_back({eds, pattern, result});
            }
        }
        return cases;
    }
};

TEST_P(MatcherTest, Sopang) {
    std::shared_ptr<const ElasticDegenerateString> eds = std::get<0>(GetParam());
    ASSERT_TRUE(eds->Size() > 0);
    ASSERT_TRUE(eds->Segments() > 0);

    std::string pattern = std::get<1>(GetParam());
    ASSERT_FALSE(pattern.empty());

    std::set<unsigned> expected_res = std::get<2>(GetParam());

    std::unordered_set<unsigned> res = SopangMatcher().Match(*eds, pattern, "ACGT");
    std::set<unsigned> sorted_res(std::begin(res), std::end(res));

    ASSERT_EQ(sorted_res, expected_res);
}

TEST_P(MatcherTest, SSE) {
    std::shared_ptr<const ElasticDegenerateString> eds = std::get<0>(GetParam());
    ASSERT_TRUE(eds->Size() > 0);
    ASSERT_TRUE(eds->Segments() > 0);

    std::string pattern = std::get<1>(GetParam());
    ASSERT_FALSE(pattern.empty());

    std::set<unsigned> expected_res = std::get<2>(GetParam());

    std::unordered_set<unsigned> res = eds::match::SSEMatcher("ACGT").Match(*eds, pattern);
    std::set<unsigned> sorted_res(std::begin(res), std::end(res));

    ASSERT_EQ(sorted_res, expected_res);
}

INSTANTIATE_TEST_SUITE_P(MatcherTestSuite, MatcherTest,
                         testing::ValuesIn(MatcherTest::GenerateTestSuiteValues()));

ext: cc

max_stars_repo_name: stringology-prague/parallel-eds-search

max_issues_repo_name: stringology-prague/parallel-eds-search

max_forks_repo_name: stringology-prague/parallel-eds-search


text:
#include <vu8/Context.hpp>

#include <boost/program_options.hpp>
#include <boost/filesystem/path.hpp>

#include <iostream>
#include <stdexcept>

namespace vu8 {

static inline std::string find_in_path(char const *search) {
    char const *path_env = std::getenv("PATH");
    char const *nextColon = path_env;

    std::string path;
    if ('\0' != *search) {
        for (char const *firstSlash = search; *firstSlash != '\0';
             ++firstSlash)
        {
            if ('/' == *firstSlash) {
                if (access(search, X_OK)) return "";
                else return search;
            }
        }

        while ('\0' != *nextColon) {
            for (++nextColon;
                 *nextColon != ':' && '\0' != *nextColon; ++nextColon) {}

            path.assign(path_env, nextColon);
            path.append("/").append(search);

            if (! access(path.c_str(), X_OK)) break;

            path_env = nextColon + 1;
        }
    }
    else path = "";

    return path;
}

namespace po = boost::program_options;
void usage(po::options_description const& desc) {
    std::cout << desc << std::endl;
}

int main(int argc, char *argv[]) {
    po::options_description desc("allowed options");

    std::string libPath;
    typedef std::vector<std::string> scripts_t;
    scripts_t scripts;

    po::positional_options_description positionals;
    positionals.add("script", -1);
    desc.add_options()
        ("help,h", "print this help message.")
        ("script,s", po::value(&scripts), "script to run.")
        ("library-path,l", po::value(&libPath), "path containing plugin libraries.")
        ;

    po::variables_map vm;
    try {
        po::store(po::command_line_parser(argc, argv)
            .options(desc).positional(positionals).run(), vm);
    }
    catch (po::invalid_option_value& e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }
    catch (po::multiple_occurrences& e) {
        usage(desc);
        std::cerr << "multiple occurences of same option" << std::endl;
        return 1;
    }
    catch (po::unknown_option& e) {
        usage(desc);
        std::cerr << e.what() << std::endl;
        return 1;
    }

    if (vm.count("help")) {
        usage(desc);
        return 1;
    }

    po::notify(vm);

    if (libPath.empty()) {
        std::string root = find_in_path(argv[0]);
        boost::filesystem::path libPtr(root);
        libPtr = libPtr.parent_path();
        if (libPtr.has_parent_path()) {
            libPath = libPtr.parent_path().string();
            libPath.append("/lib");
        }
        else {
            libPath = "../lib";
        }
    }

    if (scripts.empty()) {
        std::cerr << "must supply at least one script\n";
        usage(desc);
        return 1;
    }

    try {
        Context ctxt(libPath);
        for (scripts_t::const_iterator it = scripts.begin();
             it != scripts.end(); ++it)
        { ctxt.RunFile(it->c_str()); }
    }
    catch (std::runtime_error const& e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }

    v8::V8::Dispose();
    return 0;
}

}

int main(int argc, char *argv[]) {
    return vu8::main(argc, argv);
}