From 1eeae97a9c650421d056a8c249c29fe42244ccd8 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 25 Mar 2020 21:38:42 +0300 Subject: Add peek_file() and peek_line() functions to argv_file_scanner --- .gitattributes | 2 +- cli/runtime-header.cxx | 26 ++++++++++++++++++++++++-- cli/runtime-source.cxx | 36 +++++++++++++++++++++++++++++++----- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/.gitattributes b/.gitattributes index 9fce1b0..1631641 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,7 +10,7 @@ #*.bat text eol=crlf # Use `eol=lf` for files that should have the LF line ending both in the -# working tree (even on Windows) in the repository. +# working tree (even on Windows) and in the repository. # #*.sh text eol=lf diff --git a/cli/runtime-header.cxx b/cli/runtime-header.cxx index 3a51b20..adf70dd 100644 --- a/cli/runtime-header.cxx +++ b/cli/runtime-header.cxx @@ -12,7 +12,8 @@ generate_runtime_header (context& ctx) ostream& os (ctx.os); if (ctx.options.generate_file_scanner ()) - os << "#include " << endl; + os << "#include " << endl + << "#include " << endl; if (ctx.options.generate_description ()) os << "#include " << endl; @@ -456,6 +457,19 @@ generate_runtime_header (context& ctx) << "virtual void" << endl << "skip ();" << endl + << "// Return the file path if the peeked at argument came from a file and" << endl + << "// the empty string otherwise. The reference is guaranteed to be valid" << endl + << "// till the end of the scanner lifetime." << endl + << "//" << endl + << "const std::string&" << endl + << "peek_file ();" + << endl + << "// Return the 1-based line number if the peeked at argument came from" << endl + << "// a file and zero otherwise." << endl + << "//" << endl + << "std::size_t" << endl + << "peek_line ();" + << endl << "private:" << endl << "const option_info*" << endl << "find (const char*) const;" @@ -470,7 +484,14 @@ generate_runtime_header (context& ctx) << "const option_info* options_;" << "std::size_t options_count_;" << endl - << "std::deque args_;" + << "struct arg" + << "{" + << "std::string value;" + << "const std::string* file;" + << "std::size_t line;" + << "};" + << "std::deque args_;" + << "std::list files_;" << endl << "// Circular buffer of two arguments." << endl << "//" << endl @@ -483,6 +504,7 @@ generate_runtime_header (context& ctx) os << endl << "static int zero_argc_;" + << "static std::string empty_string_;" << "};"; } diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx index b836406..36d8968 100644 --- a/cli/runtime-source.cxx +++ b/cli/runtime-source.cxx @@ -365,6 +365,7 @@ generate_runtime_source (context& ctx, bool complete) << "//" << endl << "int argv_file_scanner::zero_argc_ = 0;" + << "std::string argv_file_scanner::empty_string_;" << endl << "bool argv_file_scanner::" << endl @@ -452,7 +453,25 @@ generate_runtime_source (context& ctx, bool complete) << "if (!more ())" << endl << "throw eos_reached ();" << endl - << "return args_.empty () ? base::peek () : args_.front ().c_str ();" + << "return args_.empty () ? base::peek () : args_.front ().value.c_str ();" + << "}" + + << "const std::string& argv_file_scanner::" << endl + << "peek_file ()" + << "{" + << "if (!more ())" << endl + << "throw eos_reached ();" + << endl + << "return args_.empty () ? empty_string_ : *args_.front ().file;" + << "}" + + << "std::size_t argv_file_scanner::" << endl + << "peek_line ()" + << "{" + << "if (!more ())" << endl + << "throw eos_reached ();" + << endl + << "return args_.empty () ? 0 : args_.front ().line;" << "}" << "const char* argv_file_scanner::" << endl @@ -465,7 +484,7 @@ generate_runtime_source (context& ctx, bool complete) << "return base::next ();" << "else" << "{" - << "hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ());" + << "hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value);" << "args_.pop_front ();" << "return hold_[i_].c_str ();" << "}" @@ -503,7 +522,12 @@ generate_runtime_source (context& ctx, bool complete) << "if (!is.is_open ())" << endl << "throw file_io_failure (file);" << endl - << "while (!is.eof ())" + << "files_.push_back (file);" + << endl + << "arg a;" + << "a.file = &*files_.rbegin ();" + << endl + << "for (a.line = 1; !is.eof (); ++a.line)" << "{" << "string line;" << "getline (is, line);" @@ -633,9 +657,11 @@ generate_runtime_source (context& ctx, bool complete) << endl << "continue;" << "}" - << "args_.push_back (s1);" + << "a.value = s1;" + << "args_.push_back (a);" << "}" - << "args_.push_back (s2);" + << "a.value = s2;" + << "args_.push_back (a);" << "}" // while << "}"; } -- cgit v1.1