Mercurial > hg > octave-lyh
view doc/interpreter/munge-texi.cc @ 15524:15628a84a4fa stable
Document form of warning IDs is NAMESPACE:WARNING-NAME (bug #37559)
* errors.txi: Add explanation of warning ID form to documentation.
Correct example code to properly use warning IDs.
* error.cc (Fwarning): Document form of warning ID in warning()
docstring.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 15 Oct 2012 07:18:31 -0700 |
parents | d174210ce1ec |
children |
line wrap: on
line source
/* Copyright (C) 1999-2012 John W. Eaton This file is part of Octave. Octave 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. Octave 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 Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ #include <cctype> #include <iostream> #include <fstream> #include <string> #include <map> #include <cstdlib> #include <cstring> static std::string top_srcdir; static const char doc_delim = ''; static std::map<std::string, std::string> help_text; static void fatal (const std::string& msg) { std::cerr << msg << "\n"; exit (1); } static void usage (void) { std::cerr << "usage: munge-texi TOP-SRCDIR DOCSTRING-FILE < file\n"; exit (1); } static std::string extract_symbol_name (std::istream& is) { std::string symbol_name; int c; while ((c = is.get ()) != EOF && c != '\n') symbol_name += static_cast<char> (c); return symbol_name; } static std::string extract_docstring (std::istream& is) { std::string doc; int c; while ((c = is.get ()) != EOF && c != doc_delim) { // Expand @seealso commands to Texinfo references. if (c == '@') { char buf[16]; int i = 0; buf[i++] = static_cast<char> (c); if (( buf[i++] = static_cast<char> (is.get ())) == 's' && (buf[i++] = static_cast<char> (is.get ())) == 'e' && (buf[i++] = static_cast<char> (is.get ())) == 'e' && (buf[i++] = static_cast<char> (is.get ())) == 'a' && (buf[i++] = static_cast<char> (is.get ())) == 'l' && (buf[i++] = static_cast<char> (is.get ())) == 's' && (buf[i++] = static_cast<char> (is.get ())) == 'o' && (buf[i++] = static_cast<char> (is.get ())) == '{') { doc += "@seealso{"; bool first = true; // process @seealso parameters while ((c = is.get ()) != EOF && c != doc_delim && c != '}') { // ignore whitespace and delimiters while ( c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == ',') { c = is.get (); } // test for end of @seealso if (c == '}') break; // get function name std::string function_name; do function_name += static_cast<char> (c); while ((c = is.get ()) != EOF && c != doc_delim && c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ',' && c != '}'); if (first) first = false; else doc += ", "; if (function_name[0] == '@') function_name = "@" + function_name; doc += "@ref{doc-" + function_name + ",," + function_name + "}"; // test for end of @seealso if (c == '}') break; } if (c == '}') doc += static_cast<char> (c); } else { for (int j = 0; j < i; j++) doc += buf[j]; } } else doc += static_cast<char> (c); } return doc; } static void skip_comments (std::ifstream& is) { int c; bool in_comment = false; while ((c = is.get ()) != EOF) { if (c == '#') in_comment = true; else if (c == '\n') in_comment = false; else if (! (in_comment || ::isspace (c))) { is.putback (c); break; } } } static void process_doc_file (const std::string& fname) { std::ifstream infile (fname.c_str ()); if (infile) { skip_comments (infile); if (infile.get () != doc_delim) fatal ("invalid doc file format"); std::string symbol_name; do { symbol_name = extract_symbol_name (infile); if (! symbol_name.empty ()) { std::string doc_string = extract_docstring (infile); if (help_text.find (symbol_name) != help_text.end ()) std::cerr << "ignoring duplicate entry for " << symbol_name << "\n"; else help_text[symbol_name] = doc_string; } } while (! symbol_name.empty ()); } else fatal ("unable to open docfile"); } static bool recover_from_macro (std::ostream& os, char *buf, int i) { bool bol = false; buf[i] = '\0'; os << buf; if (buf[i - 1] == '\n') bol = true; return bol; } static void process_example_file (const std::string& file_name, std::ostream& os) { std::ifstream infile (file_name.c_str ()); if (infile) { os << "@verbatim\n"; int c; int clast = 0; while ((c = infile.get ()) != EOF) { os << static_cast<char> (c); clast = c; } if (clast != '\n') os << "\n"; os << "@end verbatim\n"; } else fatal ("unable to open example file " + file_name); } static void process_texi_input_file (std::istream& is, std::ostream& os) { os << "@c DO NOT EDIT! Generated automatically by munge-texi.\n\n"; bool bol = true; int c; while ((c = is.get ()) != EOF) { if (bol) { if (c == '@') { char buf[16]; int i = 0; buf[i++] = static_cast<char> (c); buf[i++] = c = static_cast<char> (is.get ()); if (c == 'D') { std::string symbol_name; if ( (buf[i++] = static_cast<char> (is.get ())) == 'O' && (buf[i++] = static_cast<char> (is.get ())) == 'C' && (buf[i++] = static_cast<char> (is.get ())) == 'S' && (buf[i++] = static_cast<char> (is.get ())) == 'T' && (buf[i++] = static_cast<char> (is.get ())) == 'R' && (buf[i++] = static_cast<char> (is.get ())) == 'I' && (buf[i++] = static_cast<char> (is.get ())) == 'N' && (buf[i++] = static_cast<char> (is.get ())) == 'G' && (buf[i++] = static_cast<char> (is.get ())) == '(') { while ((c = is.get ()) != EOF && c != ')') symbol_name += static_cast<char> (c); if (is.eof ()) fatal ("end of file while reading @DOCSTRING command"); else { std::string doc_string = help_text[symbol_name]; size_t len = doc_string.length (); int j = 0; // If there is a leading comment with the file // name, copy it to the output. if (len > 1 && doc_string[j] == '@' && doc_string[j+1] == 'c') { j = 2; while (doc_string[j++] != '\n') /* find eol */; os << doc_string.substr (0, j); } while (doc_string[j] == ' ') j++; if (doc_string.substr (j, 15) == "-*- texinfo -*-") { j += 15; while (isspace (doc_string[j])) j++; // Make 'see also' references in functions // possible using @anchor{TAG} (new with // Texinfo 4.0). if (symbol_name[0] == '@') symbol_name = "@" + symbol_name; os << "@anchor{doc-" << symbol_name << "}\n"; os << doc_string.substr (j); } else os << doc_string; } } else bol = recover_from_macro (os, buf, i); } else if (c == 'E') { std::string file_name; if ( (buf[i++] = static_cast<char> (is.get ())) == 'X' && (buf[i++] = static_cast<char> (is.get ())) == 'A' && (buf[i++] = static_cast<char> (is.get ())) == 'M' && (buf[i++] = static_cast<char> (is.get ())) == 'P' && (buf[i++] = static_cast<char> (is.get ())) == 'L' && (buf[i++] = static_cast<char> (is.get ())) == 'E' && (buf[i++] = static_cast<char> (is.get ())) == 'F' && (buf[i++] = static_cast<char> (is.get ())) == 'I' && (buf[i++] = static_cast<char> (is.get ())) == 'L' && (buf[i++] = static_cast<char> (is.get ())) == 'E' && (buf[i++] = static_cast<char> (is.get ())) == '(') { while ((c = is.get ()) != EOF && c != ')') file_name += static_cast<char> (c); file_name = top_srcdir + "/examples/" + file_name; process_example_file (file_name, os); } else bol = recover_from_macro (os, buf, i); } else bol = recover_from_macro (os, buf, i); } else os.put (static_cast<char> (c)); } else { if (c == '\n') bol = true; os.put (static_cast<char> (c)); } } } int main (int argc, char **argv) { int retval = 0; if (argc > 1) { top_srcdir = *++argv; while (*++argv) process_doc_file (*argv); process_texi_input_file (std::cin, std::cout); } else { usage (); retval = 1; } return retval; }