void pragma_environment_save::run(const data::command::iterator&,
                                  const data::command::iterator&,
                                  const data::command::iterator& args_begin_,
                                  const data::command::iterator& args_end_,
                                  iface::displayer& displayer_) const
{
    if (_config.saving_enabled)
    {
        const std::string fn =
            boost::algorithm::trim_copy(tokens_to_string(args_begin_, args_end_));

        if (fn.empty())
        {
            displayer_.show_error(
                "Filename to save the environment into is missing.");
        }
        else
        {
            std::ofstream f(fn.c_str());
            f << _env.get_all() << std::endl;
            if (f.fail() || f.bad())
            {
                displayer_.show_error("Failed to save the environment into file " + fn);
            }
        }
    }
    else
    {
        displayer_.show_error(
            "Saving is disabled by the --disable_saving command line argument.");
    }
}
Beispiel #2
0
void pragma_switch::run(const data::command::iterator&,
                        const data::command::iterator&,
                        const data::command::iterator& args_begin_,
                        const data::command::iterator& args_end_,
                        iface::displayer& displayer_) const
{
  auto i = args_begin_;

  if (i != args_end_)
  {
    const std::string v = i->value().value();
    if (valid_argument(v))
    {
      ++i;
      if (i == args_end_)
      {
        _update(element_of(true_values, v));
      }
      else
      {
        displayer_.show_error("Invalid arguments after " + v + ": " +
                              tokens_to_string(i, args_end_).value());
      }
    }
    else
    {
      displayer_.show_error("Invalid argument " + v + ". Valid values are: " +
                            valid_arguments());
    }
  }
  displayer_.show_comment(
      data::text(_name + " is " + (_query() ? "on" : "off")));
}
Beispiel #3
0
  void mdb_shell::line_available(const std::string& line_arg,
                                 iface::displayer& displayer_,
                                 iface::history& history_)
  {

    try
    {
      using boost::algorithm::all;
      using boost::is_space;

      std::string line = line_arg;

      if (line != prev_line && !line.empty())
      {
        history_.add(line);
      }

      if (line.empty())
      {
        if (!last_command_repeatable)
        {
          return;
        }
        line = prev_line;
      }
      else
      {
        prev_line = line;
      }

      if (all(line, is_space()))
      {
        return;
      }

      auto command_arg_pair = command_handler.get_command_for_line(line);
      if (!command_arg_pair)
      {
        displayer_.show_error("Command parsing failed\n");
        last_command_repeatable = false;
        return;
      }

      mdb_command cmd;
      std::string args;
      std::tie(cmd, args) = *command_arg_pair;

      last_command_repeatable = cmd.is_repeatable();

      cmd.get_func()(*this, args, displayer_);
    }
    catch (const std::exception& ex)
    {
      displayer_.show_error(std::string("Error: ") + ex.what() + "\n");
    }
    catch (...)
    {
      displayer_.show_error("Unknown error\n");
    }
  }
void pragma_environment_add::run(
  const data::command::iterator& args_begin_,
  const data::command::iterator& args_end_,
  iface::displayer& displayer_
) const
{
  const std::string cmd = tokens_to_string(args_begin_, args_end_);

  _shell.store_in_buffer(cmd, displayer_);

  if (is_environment_setup_command(args_begin_, args_end_))
  {
    displayer_.show_comment(
      data::text(
        "You don't need the environment add pragma to add this to the"
        " environment. The following command does this as well:"
      )
    );
    displayer_.show_cpp_code(cmd);
  }
  else
  {
    displayer_.show_comment(
      data::text(
        "Metashell (incorrectly) thinks that this command should execute a"
        " metaprogram and would not add it to the environment without using"
        " the \"environment add\" pragma. Please file a bug report containing"
        " this command (" + cmd + ") at"
        " https://github.com/sabel83/metashell/issues. Thank you."
      )
    );
  }
}
Beispiel #5
0
  data::type_or_error
  mdb_shell::run_metaprogram(const boost::optional<std::string>& expression,
                             const boost::filesystem::path& output_path_,
                             iface::displayer& displayer_)
  {
    const data::result res = _engine.eval(
        env, expression, output_path_, conf.use_precompiled_headers);

    if (!res.info.empty())
    {
      displayer_.show_raw_text(res.info);
    }

    if (!res.successful)
    {
      return data::type_or_error::make_error(res.error);
    }
    else if (expression)
    {
      return data::type_or_error::make_type(data::type(res.output));
    }
    else
    {
      return data::type_or_error::make_none();
    }
  }
  std::unique_ptr<iface::event_data_sequence> metaprogram_tracer_clang::eval(
      iface::environment& env_,
      const boost::filesystem::path&,
      const boost::optional<data::cpp_code>& expression_,
      data::metaprogram_mode mode_,
      iface::displayer& displayer_)
  {
    const auto out = eval_with_templight_dump_on_stdout(
        env_, expression_, boost::none, _clang_binary);

    const data::result& res = std::get<0>(out);
    const std::string& trace = std::get<1>(out);

    if (!res.info.empty())
    {
      displayer_.show_raw_text(res.info);
    }

    if (trace.empty())
    {
      throw exception(res.successful ? "Failed to get template trace" :
                                       res.error);
    }
    else
    {
      return filter_events(
          yaml_trace(
              trace, type_or_code_or_error_from_result(res, expression_),
              expression_ ? *expression_ : data::cpp_code("<environment>"),
              mode_),
          determine_from_line(
              env_.get(), expression_, data::stdin_name_in_clang()));
    }
  }
Beispiel #7
0
 void
 mdb_shell::display_current_forwardtrace(boost::optional<int> max_depth,
                                         iface::displayer& displayer_) const
 {
   displayer_.show_call_graph(boost::make_iterator_range(
       forward_trace_iterator(*mp, max_depth), forward_trace_iterator()));
 }
Beispiel #8
0
  void mdb_shell::command_frame(const std::string& arg,
                                iface::displayer& displayer_)
  {
    if (!require_running_or_errored_metaprogram(displayer_))
    {
      return;
    }

    const auto frame_index = parse_mandatory_integer(arg);
    if (!frame_index)
    {
      display_argument_parsing_failed(displayer_);
      return;
    }

    auto backtrace = mp->get_backtrace();

    if (frame_index < 0 || *frame_index >= static_cast<int>(backtrace.size()))
    {
      displayer_.show_error("Frame index out of range");
      return;
    }

    display_frame(backtrace[*frame_index], displayer_);
  }
Beispiel #9
0
  void mdb_shell::command_continue(const std::string& arg,
                                   iface::displayer& displayer_)
  {
    if (!require_evaluated_metaprogram(displayer_))
    {
      return;
    }

    const auto continue_count = parse_defaultable_integer(arg, 1);
    if (!continue_count)
    {
      display_argument_parsing_failed(displayer_);
      return;
    }

    direction_t direction =
        *continue_count >= 0 ? direction_t::forward : direction_t::backwards;

    const breakpoint* breakpoint_ptr = nullptr;
    for (int i = 0;
         i < std::abs(*continue_count) && !mp->is_at_endpoint(direction); ++i)
    {
      breakpoint_ptr = continue_metaprogram(direction);
    }

    if (breakpoint_ptr)
    {
      displayer_.show_raw_text(breakpoint_ptr->to_string() + " reached");
    }
    display_movement_info(*continue_count != 0, displayer_);
  }
Beispiel #10
0
  bool mdb_shell::run_metaprogram_with_templight(
      const boost::optional<std::string>& expression,
      metaprogram::mode_t mode,
      iface::displayer& displayer_)
  {
    const boost::filesystem::path output_path = _mdb_temp_dir / "templight.pb";

    data::type_or_error evaluation_result =
        run_metaprogram(expression, output_path, displayer_);

    // Opening in binary mode, because some platforms interpret some characters
    // specially in text mode, which caused parsing to fail.
    std::ifstream protobuf_stream(output_path.string() + ".trace.pbf",
                                  std::ios_base::in | std::ios_base::binary);

    if (!protobuf_stream)
    {
      if (evaluation_result.is_error())
      {
        displayer_.show_error(evaluation_result.get_error());
      }
      else
      {
        // Shouldn't happen
        displayer_.show_error("Unexpected type type_or_error result");
      }
      mp = boost::none;
      return false;
    }

    mp = metaprogram::create_from_protobuf_stream(
        protobuf_stream, mode, expression ? *expression : "<environment>",
        data::file_location{}, // TODO something sensible here?
        evaluation_result);

    assert(mp);
    if (mp->is_empty() && evaluation_result.is_error())
    {
      // Most errors will cause templight to generate an empty trace
      // We're only intrested in non-empty traces
      displayer_.show_error(evaluation_result.get_error());
      mp = boost::none;
      return false;
    }

    return true;
  }
Beispiel #11
0
  void mdb_shell::command_rbreak(const std::string& arg,
                                 iface::displayer& displayer_)
  {
    if (arg.empty())
    {
      displayer_.show_error("Argument expected");
      return;
    }
    if (!require_evaluated_metaprogram(displayer_))
    {
      return;
    }
    try
    {
      breakpoint bp{next_breakpoint_id, boost::regex(arg)};
      ++next_breakpoint_id;

      unsigned match_count = 0;
      for (metaprogram::vertex_descriptor vertex : mp->get_vertices())
      {
        if (bp.match(mp->get_vertex_property(vertex).type))
        {
          match_count += mp->get_traversal_count(vertex);
        }
      }
      if (match_count == 0)
      {
        displayer_.show_raw_text("Breakpoint \"" + arg +
                                 "\" will never stop the execution");
      }
      else
      {
        displayer_.show_raw_text(
            "Breakpoint \"" + arg + "\" will stop the execution on " +
            std::to_string(match_count) +
            (match_count > 1 ? " locations" : " location"));
        breakpoints.push_back(bp);
      }
    }
    catch (const boost::regex_error&)
    {
      displayer_.show_error("\"" + arg + "\" is not a valid regex");
    }
  }
Beispiel #12
0
  void mdb_shell::display_frame(const data::frame& frame,
                                iface::displayer& displayer_) const
  {
    displayer_.show_frame(frame);

    data::file_location source_location = frame.source_location();
    if (source_location.name == _env_path)
    {
      // We don't want to show stuff from the internal header
      source_location = data::file_location();
    }
    // TODO: we should somehow compensate the file_locations returned by
    // clang for the <stdin> file. This is hard because the file clang sees
    // is just two lines (an include for the PCH and the current line)
    // Until this is figured out, printing file sections for <stdin> is
    // turned off
    // displayer_.show_file_section(source_location, env.get());
    displayer_.show_file_section(source_location, "");
  }
Beispiel #13
0
 bool
 mdb_shell::require_evaluated_metaprogram(iface::displayer& displayer_) const
 {
   if (!mp)
   {
     displayer_.show_error("Metaprogram not evaluated yet");
     return false;
   }
   return true;
 }
Beispiel #14
0
 bool mdb_shell::require_empty_args(const std::string& args,
                                    iface::displayer& displayer_) const
 {
   if (!args.empty())
   {
     displayer_.show_error("This command doesn't accept arguments");
     return false;
   }
   return true;
 }
  void pragma_config_load::run(const data::command::iterator&,
                               const data::command::iterator&,
                               const data::command::iterator& args_begin_,
                               const data::command::iterator& args_end_,
                               iface::displayer& displayer_) const
  {
    const data::shell_config_name name = data::shell_config_name(
        tokens_to_string(args_begin_, args_end_).value());

    const auto& configs = _shell.get_config().shell_configs();

    const auto cfg = std::find_if(
        configs.begin(), configs.end(),
        [&name](const data::shell_config& cfg_) { return cfg_.name == name; });

    if (cfg == configs.end())
    {
      throw exception("Config " + name + " not found.");
    }
    else
    {
      const auto old_config = _shell.get_config().active_shell_config().name;
      _shell.get_config().activate(name);
      try
      {
        _shell.rebuild_environment();
        displayer_.show_comment(data::text("Switched to config " + name));
      }
      catch (const std::exception& e)
      {
        displayer_.show_error("Error loading config " + name + ": " + e.what());
        restore_config(old_config, _shell);
      }
      catch (...)
      {
        displayer_.show_error("Error loading config " + name +
                              ": unknown exception");
        restore_config(old_config, _shell);
      }
    }
  }
Beispiel #16
0
  void mdb_shell::command_break(const std::string& arg,
                                iface::displayer& displayer_)
  {
    // TODO there will other more kinds of arguments here but needs a proper but
    // it needs a proper command parser
    if (arg != "list")
    {
      displayer_.show_error("Call break like this: \"break list\"");
      return;
    }

    if (breakpoints.empty())
    {
      displayer_.show_raw_text("No breakpoints currently set");
      return;
    }

    for (const breakpoint& bp : breakpoints)
    {
      displayer_.show_raw_text(bp.to_string());
    }
  }
Beispiel #17
0
void pragma_which::run(const data::command::iterator& name_begin_,
                       const data::command::iterator& name_end_,
                       const data::command::iterator& args_begin_,
                       const data::command::iterator& args_end_,
                       iface::displayer& displayer_) const
{
  using boost::filesystem::path;
  using boost::adaptors::transformed;
  using boost::adaptors::filtered;

  const parsed_arguments args =
      parse_arguments(data::tokens_to_string(name_begin_, name_end_).value(),
                      args_begin_, args_end_);
  const auto include_path =
      _shell.engine().header_discoverer().include_path(args.header.type);
  const auto files =
      include_path |
      transformed(std::function<path(const path&)>(
          [&args](const path& path_) { return path_ / args.header.path; })) |
      filtered([](const path& path_) { return exists(path_); });

  if (files.empty())
  {
    throw exception("Include file " +
                    data::tokens_to_string(args_begin_, args_end_).value() +
                    " not found.");
  }
  else if (args.all)
  {
    displayer_.show_filename_list(
        std::vector<path>(files.begin(), files.end()));
  }
  else
  {
    displayer_.show_filename_list({files.front()});
  }
}
Beispiel #18
0
  void mdb_shell::command_evaluate(const std::string& arg_copy,
                                   iface::displayer& displayer_)
  {
    // Easier not to use spirit here (or probably not...)
    // TODO OK. after -profile, this parsing really needs some refactoring
    std::string arg = arg_copy;

    const std::string full_flag = "-full";
    const std::string profile_flag = "-profile";

    bool has_full = false;
    bool has_profile = false;

    // Intentionally left really ugly for more motivation to refactor
    while (true)
    {
      if (boost::starts_with(arg, full_flag) &&
          (arg.size() == full_flag.size() ||
           std::isspace(arg[full_flag.size()])))
      {
        has_full = true;
        arg = boost::trim_left_copy(arg.substr(full_flag.size()));
      }
      else if (boost::starts_with(arg, profile_flag) &&
               (arg.size() == profile_flag.size() ||
                std::isspace(arg[profile_flag.size()])))
      {
        has_profile = true;
        arg = boost::trim_left_copy(arg.substr(profile_flag.size()));
      }
      else
      {
        break;
      }
    }

    if (has_full && has_profile)
    {
      displayer_.show_error(
          "-full and -profile flags cannot be used together.");
      return;
    }

    boost::optional<std::string> expression = arg;
    if (expression->empty())
    {
      if (!mp)
      {
        displayer_.show_error("Nothing has been evaluated yet.");
        return;
      }
      expression = last_evaluated_expression;
    }
    else if (*expression == "-")
    {
      expression = boost::none;
    }

    next_breakpoint_id = 1;
    breakpoints.clear();

    metaprogram::mode_t mode = [&]
    {
      if (has_full)
      {
        return metaprogram::mode_t::full;
      }
      if (has_profile)
      {
        return metaprogram::mode_t::profile;
      }
      return metaprogram::mode_t::normal;
    }();

    last_evaluated_expression = expression;
    if (!run_metaprogram_with_templight(expression, mode, displayer_))
    {
      return;
    }

    displayer_.show_raw_text("Metaprogram started");

    filter_metaprogram(bool(expression));
  }
Beispiel #19
0
 void mdb_shell::display_backtrace(iface::displayer& displayer_) const
 {
   displayer_.show_backtrace(mp->get_backtrace());
 }
Beispiel #20
0
void pragma_help::run(const data::command::iterator&,
                      const data::command::iterator&,
                      const data::command::iterator& args_begin_,
                      const data::command::iterator& args_end_,
                      iface::displayer& displayer_) const
{
  using boost::algorithm::join;

  if (args_begin_ == args_end_)
  {
    display_all(displayer_, _pragma_handlers);
  }
  else
  {
    std::vector<std::string> args;
    for (auto i = args_begin_; i != args_end_; ++i)
    {
      switch (i->category())
      {
      case data::token_category::whitespace:
      case data::token_category::comment:
        // skip token
        break;
      default:
        args.push_back(i->value().value());
      }
    }

    data::text help_text;
    bool was_pragma = false;

    for (const auto& h : _pragma_handlers)
    {
      if (prefix_of(args.begin(), args.end(), h.first.begin(), h.first.end()))
      {
        if (was_pragma)
        {
          help_text.paragraphs.push_back(data::paragraph(""));
        }
        else
        {
          was_pragma = true;
        }
        const std::string p_args = h.second.arguments();
        help_text.paragraphs.push_back(
            data::paragraph("#msh " + join(h.first, " ") +
                            (p_args.empty() ? std::string() : " " + p_args)));
        help_text.paragraphs.push_back(
            data::paragraph(h.second.description(), "    "));
      }
    }
    if (was_pragma)
    {
      displayer_.show_comment(help_text);
    }
    else
    {
      displayer_.show_error("Pragma " + join(args, " ") + " not found.");
    }
  }
}
void pragma_macros::run(iface::displayer& displayer_) const
{
  displayer_.show_cpp_code(_shell.engine().macros(_shell.env()));
}
Beispiel #22
0
 void
 mdb_shell::display_argument_parsing_failed(iface::displayer& displayer_) const
 {
   displayer_.show_error("Argument parsing failed");
 }
Beispiel #23
0
 void mdb_shell::display_metaprogram_reached_the_beginning(
     iface::displayer& displayer_) const
 {
   displayer_.show_raw_text("Metaprogram reached the beginning");
 }
Beispiel #24
0
  void mdb_shell::command_help(const std::string& arg,
                               iface::displayer& displayer_)
  {
    if (arg.empty())
    {
      displayer_.show_raw_text("List of available commands:");
      displayer_.show_raw_text("");
      for (const mdb_command& cmd : command_handler.get_commands())
      {
        displayer_.show_raw_text(cmd.get_keys().front() + " -- " +
                                 cmd.get_short_description());
      }
      displayer_.show_raw_text("");
      displayer_.show_raw_text(
          "Type \"help\" followed by a command name for more information.");
      displayer_.show_raw_text(
          "Command name abbreviations are allowed if unambiguous.");
      displayer_.show_raw_text(
          "A blank line as an input will repeat the last command,"
          " if it makes sense.");
      return;
    }

    auto command_arg_pair = command_handler.get_command_for_line(arg);
    if (!command_arg_pair)
    {
      displayer_.show_error("Command not found\n");
      return;
    }

    using boost::algorithm::join;

    mdb_command cmd;
    std::string command_args;
    std::tie(cmd, command_args) = *command_arg_pair;

    if (!command_args.empty())
    {
      displayer_.show_error("Only one argument expected\n");
      return;
    }

    displayer_.show_raw_text(join(cmd.get_keys(), "|") + " " + cmd.get_usage());
    displayer_.show_raw_text(cmd.get_full_description());
  }
Beispiel #25
0
 void
 mdb_shell::display_metaprogram_finished(iface::displayer& displayer_) const
 {
   displayer_.show_raw_text("Metaprogram finished");
   displayer_.show_type_or_error(mp->get_evaluation_result());
 }