command_stream.cc 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // The definition of the Command_stream class. It is constructed from a
  2. // standard stream and defines an input operator for Argm objects. It also
  3. // handles the calling of .prompt.
  4. //
  5. // Copyright (C) 2005-2018 Samuel Newbold
  6. #include <iostream>
  7. #include <list>
  8. #include <map>
  9. #include <string>
  10. #include <set>
  11. #include <sstream>
  12. #include <sys/time.h>
  13. #include <vector>
  14. #include "arg_spec.h"
  15. #include "rwsh_stream.h"
  16. #include "variable_map.h"
  17. #include "argm.h"
  18. #include "arg_script.h"
  19. #include "call_stack.h"
  20. #include "clock.h"
  21. #include "command_stream.h"
  22. #include "executable.h"
  23. #include "executable_map.h"
  24. #include "prototype.h"
  25. #include "function.h"
  26. Command_stream::Command_stream(Rwsh_istream_p& s, bool subprompt_i) :
  27. src(s), subprompt(subprompt_i) {}
  28. // write the next command to dest. run .prompt as appropriate
  29. Command_stream& Command_stream::getline(Command_block& dest,
  30. Error_list& errors) {
  31. if (this->fail()) return *this;
  32. std::string cmd;
  33. for (bool cmd_is_incomplete=true; cmd_is_incomplete;) {
  34. errors.reset(); // If this is the first execution of the loop, then errors
  35. // should be empty, if a subsequent execution, then we will regenerate all
  36. // the errors again. Obviously this should go away when this gets fixed to
  37. // be single-pass.
  38. std::string line;
  39. struct timeval before_input, after_input;
  40. gettimeofday(&before_input, rwsh_clock.no_timezone);
  41. src.getline(line);
  42. gettimeofday(&after_input, rwsh_clock.no_timezone);
  43. rwsh_clock.user_wait(before_input, after_input);
  44. std::string::size_type point = 0;
  45. if (fail()) {
  46. if (cmd.size()) { // EOF without a complete command
  47. Exception raw_command(Argm::Raw_command, cmd);
  48. executable_map.run_handling_exceptions(raw_command, errors);
  49. Command_block(cmd, point, 0, errors);} // will throw the right exception
  50. return *this;}
  51. else cmd += line;
  52. dest = Command_block(cmd, point, 0, errors);
  53. if (global_stack.remove_exceptions(".unclosed_brace", errors) ||
  54. global_stack.remove_exceptions(".unclosed_parenthesis", errors))
  55. cmd += '\n';
  56. else if (global_stack.unwind_stack()) {
  57. Exception raw_command(Argm::Raw_command, cmd);
  58. global_stack.catch_one(raw_command, errors);
  59. return *this;}
  60. else cmd_is_incomplete = false;}
  61. Exception raw_command(Argm::Raw_command, cmd);
  62. executable_map.run_handling_exceptions(raw_command, errors);
  63. return *this;}
  64. // returns true if the last command could not be read
  65. bool Command_stream::fail() const {
  66. return global_stack.exit_requested || src.fail();}