# HG changeset patch # User John W. Eaton # Date 1470121851 14400 # Node ID f6181638f6c57aadb980c363316e902a9faadee1 # Parent e43d83253e28ee13133c931bc043ec1cf36748aa search docstrings file for built-in and dld function help text (bug #48554) Load help text as needed from the built-in docstrings file for built-in and dynamically loaded .oct file functions. * help.h, help.cc (install_built_in_docstrings): Delete. (raw_help_from_docstrings_file): New static function. (raw_help): Call raw_help_from_docstrings_file if help text is not found or if it is marked as external. * mk-builtins.sh: Don't emit call to install_built_in_docstrings. diff -r e43d83253e28 -r f6181638f6c5 build-aux/mk-builtins.sh --- a/build-aux/mk-builtins.sh Mon Aug 01 12:40:18 2016 -0400 +++ b/build-aux/mk-builtins.sh Tue Aug 02 03:10:51 2016 -0400 @@ -214,10 +214,7 @@ done cat << \EOF - - install_built_in_docstrings (); } - EOF fi diff -r e43d83253e28 -r f6181638f6c5 libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Mon Aug 01 12:40:18 2016 -0400 +++ b/libinterp/corefcn/help.cc Tue Aug 02 03:10:51 2016 -0400 @@ -28,8 +28,9 @@ #include #include +#include #include -#include +#include #include #include @@ -967,6 +968,123 @@ return symbol_found; } +static bool +raw_help_from_docstrings_file (const std::string& nm, std::string& h, + bool& symbol_found) +{ + typedef std::pair txt_limits_type; + typedef std::map help_txt_map_type; + + static help_txt_map_type help_txt_map; + static bool initialized = false; + + h = ""; + symbol_found = false; + + // FIXME: Should we cache the timestamp of the file and reload the + // offsets if it changes? Or just warn about that? Or just ignore + // it, and assume it won't change? + + if (! initialized) + { + std::string fname = Vbuilt_in_docstrings_file; + + std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary); + + if (! file) + error ("failed to open docstrings file: %s", fname.c_str ()); + + // Ignore header; + file.ignore (std::numeric_limits::max(), 0x1d); + + if (file.eof ()) + error ("invalid built-in-docstrings file!"); + + // FIXME: eliminate fixed buffer size. + size_t bufsize = 1000; + OCTAVE_LOCAL_BUFFER (char, buf, bufsize); + + while (! file.eof ()) + { + std::string name; + int i = 0; + int c; + while (file && (c = file.get ()) != std::istream::traits_type::eof ()) + { + if (c == '\n' || c == '\r') + { + buf[i] = '\0'; + name = buf; + break; + } + else + buf[i++] = c; + } + + // Skip @c FILENAME which is part of current DOCSTRINGS + // syntax. This may disappear if a specific format for + // docstring files is developed. + while (file + && (c = file.get ()) != std::istream::traits_type::eof () + && c != '\n' && c != '\r') + ; // skip text + + // skip newline characters + while (file + && (c = file.get ()) != std::istream::traits_type::eof () + && c == '\n' && c == '\r') + ; // skip text + + file.unget (); + + // Position of beginning of help text. + std::streampos beg = file.tellg (); + + // Skip help text. + file.ignore (std::numeric_limits::max(), 0x1d); + + // Position of end of help text. + std::streamoff len = file.tellg () - beg - 1; + + help_txt_map[name] = txt_limits_type (beg, len); + } + + initialized = true; + } + + help_txt_map_type::const_iterator it = help_txt_map.find (nm); + + if (it != help_txt_map.end ()) + { + txt_limits_type txt_limits = it->second; + + std::streampos beg = txt_limits.first; + std::streamoff len = txt_limits.second; + + std::string fname = Vbuilt_in_docstrings_file; + + std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary); + + if (! file) + error ("failed to open docstrings file: %s", fname.c_str ()); + + file.seekg (beg); + + size_t txt_len = len; + OCTAVE_LOCAL_BUFFER (char, buf, txt_len + 1); + + file.read (buf, txt_len); + + buf[txt_len] = '\0'; + + h = buf; + + symbol_found = true; + } + + return symbol_found; +} + std::string raw_help (const std::string& nm, bool& symbol_found) { @@ -987,10 +1105,13 @@ found = raw_help_from_map (nm, h, operators_map, symbol_found); if (! found) - raw_help_from_map (nm, h, keywords_map, symbol_found); + found = raw_help_from_map (nm, h, keywords_map, symbol_found); } } + if (! found || h == "external-doc") + raw_help_from_docstrings_file (nm, h, symbol_found); + return h; } @@ -1017,79 +1138,6 @@ return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (built_in_docstrings_file); } -void -install_built_in_docstrings (void) -{ - std::string fname = Vbuilt_in_docstrings_file; - - std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary); - - if (file) - { - // Ignore header; - file.ignore (1000, 0x1d); - - if (file.gcount () == 1000) - { - // We use std::cerr here instead of calling Octave's warning - // function because install_built_in_docstrings is called - // before the interpreter is initialized, so warning messages - // won't work properly. - - std::cerr << "warning: is builtin-docstrings file corrupted?" - << std::endl; - return; - } - - // FIXME: eliminate fixed buffer size. - size_t bufsize = 100000; - - OCTAVE_LOCAL_BUFFER (char, buf, bufsize); - - while (! file.eof ()) - { - file.getline (buf, bufsize, 0x1d); - - std::string tmp (buf); - - size_t pos = tmp.find ('\n'); - - std::string fcn = tmp.substr (0, pos); - - octave_value ov = symbol_table::find_built_in_function (fcn); - - if (ov.is_defined ()) - { - octave_function *fp = ov.function_value (); - - if (fp) - { - tmp = tmp.substr (pos+1); - - // Strip @c FILENAME which is part of current DOCSTRINGS - // syntax. This may disappear if a specific format for - // docstring files is developed. - while (tmp.length () > 2 && tmp[0] == '@' && tmp[1] == 'c') - { - pos = tmp.find ('\n'); - tmp = tmp.substr (pos+1); - } - - fp->document (tmp); - } - } - } - } - else - { - // See note above about using std::cerr instead of warning. - - std::cerr << "warning: docstring file '" << fname << "' not found" - << std::endl; - } - -} - static void do_get_help_text (const std::string& name, std::string& text, std::string& format) diff -r e43d83253e28 -r f6181638f6c5 libinterp/corefcn/help.h --- a/libinterp/corefcn/help.h Mon Aug 01 12:40:18 2016 -0400 +++ b/libinterp/corefcn/help.h Tue Aug 02 03:10:51 2016 -0400 @@ -34,8 +34,6 @@ extern OCTINTERP_API std::string raw_help (const std::string&, bool&); -extern OCTINTERP_API void install_built_in_docstrings (void); - // Name of the doc cache file specified on the command line. // (--doc-cache-file file) extern OCTINTERP_API std::string Vdoc_cache_file;