Mercurial > hg > octave-lyh
comparison src/help.cc @ 7336:745a8299c2b5
[project @ 2007-12-28 20:56:55 by jwe]
author | jwe |
---|---|
date | Fri, 28 Dec 2007 20:56:58 +0000 |
parents | 05ee52d7fad6 |
children | 6873fe003323 |
comparison
equal
deleted
inserted
replaced
7335:58f5fab3ebe5 | 7336:745a8299c2b5 |
---|---|
59 #include "ov-usr-fcn.h" | 59 #include "ov-usr-fcn.h" |
60 #include "pager.h" | 60 #include "pager.h" |
61 #include "parse.h" | 61 #include "parse.h" |
62 #include "pathsearch.h" | 62 #include "pathsearch.h" |
63 #include "procstream.h" | 63 #include "procstream.h" |
64 #include "pt-pr-code.h" | |
64 #include "sighandlers.h" | 65 #include "sighandlers.h" |
65 #include "symtab.h" | 66 #include "symtab.h" |
66 #include "syswait.h" | 67 #include "syswait.h" |
67 #include "toplev.h" | 68 #include "toplev.h" |
68 #include "utils.h" | 69 #include "utils.h" |
561 make_name_list (void) | 562 make_name_list (void) |
562 { | 563 { |
563 string_vector key = names (keyword_help ()); | 564 string_vector key = names (keyword_help ()); |
564 int key_len = key.length (); | 565 int key_len = key.length (); |
565 | 566 |
566 string_vector fbi = fbi_sym_tab->name_list (); | 567 string_vector bif = symbol_table::built_in_function_names (); |
567 int fbi_len = fbi.length (); | 568 int bif_len = bif.length (); |
568 | 569 |
569 string_vector glb = global_sym_tab->name_list (); | 570 string_vector glb |
571 = symbol_table::variable_names (symbol_table::global_scope ()); | |
570 int glb_len = glb.length (); | 572 int glb_len = glb.length (); |
571 | 573 |
572 string_vector top = top_level_sym_tab->name_list (); | 574 string_vector top |
575 = symbol_table::variable_names (symbol_table::top_scope ()); | |
573 int top_len = top.length (); | 576 int top_len = top.length (); |
574 | 577 |
575 string_vector lcl; | 578 string_vector lcl; |
576 if (top_level_sym_tab != curr_sym_tab) | 579 if (! symbol_table::at_top_level ()) |
577 lcl = curr_sym_tab->name_list (); | 580 lcl = symbol_table::variable_names (); |
578 int lcl_len = lcl.length (); | 581 int lcl_len = lcl.length (); |
579 | 582 |
580 string_vector ffl = load_path::fcn_names (); | 583 string_vector ffl = load_path::fcn_names (); |
581 int ffl_len = ffl.length (); | 584 int ffl_len = ffl.length (); |
582 | 585 |
583 string_vector afl = autoloaded_functions (); | 586 string_vector afl = autoloaded_functions (); |
584 int afl_len = afl.length (); | 587 int afl_len = afl.length (); |
585 | 588 |
586 int total_len = key_len + fbi_len + glb_len + top_len + lcl_len + ffl_len + afl_len; | 589 int total_len = key_len + bif_len + glb_len + top_len + lcl_len |
590 + ffl_len + afl_len; | |
587 | 591 |
588 string_vector list (total_len); | 592 string_vector list (total_len); |
589 | 593 |
590 // Put all the symbols in one big list. | 594 // Put all the symbols in one big list. |
591 | 595 |
592 int j = 0; | 596 int j = 0; |
593 int i = 0; | 597 int i = 0; |
594 for (i = 0; i < key_len; i++) | 598 for (i = 0; i < key_len; i++) |
595 list[j++] = key[i]; | 599 list[j++] = key[i]; |
596 | 600 |
597 for (i = 0; i < fbi_len; i++) | 601 for (i = 0; i < bif_len; i++) |
598 list[j++] = fbi[i]; | 602 list[j++] = bif[i]; |
599 | 603 |
600 for (i = 0; i < glb_len; i++) | 604 for (i = 0; i < glb_len; i++) |
601 list[j++] = glb[i]; | 605 list[j++] = glb[i]; |
602 | 606 |
603 for (i = 0; i < top_len; i++) | 607 for (i = 0; i < top_len; i++) |
647 symbols.list_in_columns (os); | 651 symbols.list_in_columns (os); |
648 } | 652 } |
649 } | 653 } |
650 | 654 |
651 static void | 655 static void |
652 display_symtab_names (std::ostream& os, const string_vector& names, | 656 display_symtab_names (std::ostream& os, const std::list<std::string>& names, |
653 const std::string& desc) | 657 const std::string& desc) |
654 { | 658 { |
655 if (! names.empty ()) | 659 if (! names.empty ()) |
656 { | 660 { |
657 os << "\n*** " << desc << ":\n\n"; | 661 os << "\n*** " << desc << ":\n\n"; |
658 names.list_in_columns (os); | 662 |
659 } | 663 string_vector sv (names); |
660 } | 664 |
661 | 665 sv.list_in_columns (os); |
662 #ifdef LIST_SYMBOLS | 666 } |
663 #undef LIST_SYMBOLS | 667 } |
664 #endif | |
665 #define LIST_SYMBOLS(type, msg) \ | |
666 do \ | |
667 { \ | |
668 string_vector names \ | |
669 = fbi_sym_tab->name_list (string_vector (), true, type); \ | |
670 display_symtab_names (octave_stdout, names, msg); \ | |
671 } \ | |
672 while (0) | |
673 | 668 |
674 static void | 669 static void |
675 simple_help (void) | 670 simple_help (void) |
676 { | 671 { |
677 octave_stdout << "Help is available for the topics listed below.\n"; | 672 octave_stdout << "Help is available for the topics listed below.\n"; |
682 "operators"); | 677 "operators"); |
683 | 678 |
684 display_names_from_help_list (octave_stdout, keyword_help (), | 679 display_names_from_help_list (octave_stdout, keyword_help (), |
685 "reserved words"); | 680 "reserved words"); |
686 | 681 |
687 // FIXME -- is this distinction needed? | 682 display_symtab_names (octave_stdout, |
688 | 683 symbol_table::built_in_function_names (), |
689 LIST_SYMBOLS (symbol_record::COMMAND, "commands"); | 684 "built-in functions"); |
690 | 685 |
691 LIST_SYMBOLS (symbol_record::MAPPER_FUNCTION, "mapper functions"); | 686 // FIXME -- list functions defined on command line? |
692 | |
693 LIST_SYMBOLS (symbol_record::BUILTIN_FUNCTION, "general functions"); | |
694 | |
695 // Also need to list variables and currently compiled functions from | |
696 // the symbol table, if there are any. | |
697 | |
698 // Also need to search octave_path for script files. | |
699 | 687 |
700 load_path::display (octave_stdout); | 688 load_path::display (octave_stdout); |
701 | 689 |
702 string_vector autoloaded = autoloaded_functions (); | 690 string_vector autoloaded = autoloaded_functions (); |
703 | 691 |
942 } | 930 } |
943 | 931 |
944 return retval; | 932 return retval; |
945 } | 933 } |
946 | 934 |
947 std::string | |
948 extract_help_from_dispatch (const std::string& nm) | |
949 { | |
950 std::string retval; | |
951 | |
952 symbol_record *builtin = fbi_sym_tab->lookup ("builtin:" + nm, 0); | |
953 | |
954 if (builtin) | |
955 { | |
956 // Check that builtin is up to date. | |
957 | |
958 // Don't try to fight octave's function name handling | |
959 // mechanism. Instead, move dispatch record out of the way, | |
960 // and restore the builtin to its original name. | |
961 symbol_record *dispatch = fbi_sym_tab->lookup (nm, 0); | |
962 | |
963 if (dispatch) | |
964 { | |
965 dispatch->unprotect (); | |
966 | |
967 fbi_sym_tab->rename (nm, "dispatch:" + nm); | |
968 fbi_sym_tab->rename ("builtin:" + nm, nm); | |
969 | |
970 // Check for updates to builtin function; ignore errors | |
971 // that appear (they interfere with renaming), and remove | |
972 // the updated name from the current symbol table. FIXME -- | |
973 // check that updating a function updates it in all | |
974 // contexts. It may be that it is updated only in the | |
975 // current symbol table, and not the caller. I believe this | |
976 // won't be a problem because the caller will go through the | |
977 // same logic and end up with the newer version. | |
978 | |
979 octave_function *f = is_valid_function (nm); | |
980 | |
981 if (f) | |
982 retval = builtin->help (); | |
983 | |
984 curr_sym_tab->clear_function (nm); | |
985 | |
986 // Move the builtin function out of the way and restore the | |
987 // dispatch fuction. FIXME what if builtin wants to | |
988 // protect itself? | |
989 | |
990 fbi_sym_tab->rename (nm, "builtin:" + nm); | |
991 fbi_sym_tab->rename ("dispatch:" + nm, nm); | |
992 | |
993 dispatch->protect (); | |
994 } | |
995 else | |
996 error ("failed to find dispatch record for `builtin:%s'", nm.c_str ()); | |
997 } | |
998 | |
999 return retval; | |
1000 } | |
1001 | |
1002 static bool | 935 static bool |
1003 raw_help_from_symbol_table (const std::string& nm, std::string& h, | 936 raw_help_from_symbol_table (const std::string& nm, std::string& h, |
1004 std::string& w, bool& symbol_found) | 937 std::string& w, bool& symbol_found) |
1005 { | 938 { |
1006 bool retval = false; | 939 bool retval = false; |
1007 | 940 |
1008 symbol_record *sym_rec = lookup_by_name (nm, 0); | 941 octave_value val = symbol_table::find_function (nm); |
1009 | 942 |
1010 if (sym_rec && sym_rec->is_defined ()) | 943 if (val.is_defined ()) |
1011 { | 944 { |
1012 symbol_found = true; | 945 octave_function *fcn = val.function_value (); |
1013 | 946 |
1014 h = sym_rec->help (); | 947 if (fcn) |
1015 | 948 { |
1016 if (h.length () > 0) | 949 symbol_found = true; |
1017 { | 950 |
1018 w = sym_rec->which (); | 951 h = fcn->doc_string (); |
1019 | 952 |
1020 retval = true; | 953 if (! h.empty ()) |
954 { | |
955 retval = true; | |
956 | |
957 w = fcn->fcn_file_name (); | |
958 | |
959 if (w.empty ()) | |
960 w = fcn->is_user_function () | |
961 ? "command-line function" : "built-in function"; | |
962 } | |
1021 } | 963 } |
1022 } | 964 } |
1023 | 965 |
1024 return retval; | 966 return retval; |
1025 } | 967 } |
1035 | 977 |
1036 if (raw_help_from_symbol_table (nm, h, w, symbol_found)) | 978 if (raw_help_from_symbol_table (nm, h, w, symbol_found)) |
1037 { | 979 { |
1038 if (h.length () > 0) | 980 if (h.length () > 0) |
1039 { | 981 { |
1040 h = extract_help_from_dispatch (nm) + h; | 982 h += "\n\n@noindent\n" + symbol_table::help_for_dispatch (nm); |
1041 | 983 |
1042 display_help_text (os, h); | 984 display_help_text (os, h); |
1043 | 985 |
1044 if (w.length () > 0 && ! Vsuppress_verbose_help_message) | 986 if (w.length () > 0 && ! Vsuppress_verbose_help_message) |
1045 os << w << "\n"; | 987 os << w << "\n"; |
1191 | 1133 |
1192 return retval; | 1134 return retval; |
1193 } | 1135 } |
1194 | 1136 |
1195 static void | 1137 static void |
1138 display_file (std::ostream& os, const std::string& name, | |
1139 const std::string& fname, const std::string& type, | |
1140 bool pr_type_info, bool quiet) | |
1141 { | |
1142 std::ifstream fs (fname.c_str (), std::ios::in); | |
1143 | |
1144 if (fs) | |
1145 { | |
1146 if (pr_type_info && ! quiet) | |
1147 os << name << " is the " << type | |
1148 << " defined from: " << fname << "\n\n"; | |
1149 | |
1150 char ch; | |
1151 | |
1152 while (fs.get (ch)) | |
1153 os << ch; | |
1154 } | |
1155 else | |
1156 os << "unable to open `" << fname << "' for reading!\n"; | |
1157 } | |
1158 | |
1159 static void | |
1196 do_type (std::ostream& os, const std::string& name, bool pr_type_info, | 1160 do_type (std::ostream& os, const std::string& name, bool pr_type_info, |
1197 bool quiet, bool pr_orig_txt) | 1161 bool quiet, bool pr_orig_txt) |
1198 { | 1162 { |
1199 symbol_record *sym_rec = lookup_by_name (name, 0); | 1163 // FIXME -- should we bother with variables here (earlier versions |
1200 | 1164 // of Octave displayed them)? |
1201 if (sym_rec && sym_rec->is_defined ()) | 1165 |
1202 sym_rec->type (os, pr_type_info, quiet, pr_orig_txt); | 1166 octave_value val = symbol_table::varval (name); |
1167 | |
1168 if (val.is_defined ()) | |
1169 { | |
1170 if (pr_type_info && ! quiet) | |
1171 os << name << " is a variable\n"; | |
1172 | |
1173 val.print_raw (os, pr_orig_txt); | |
1174 | |
1175 if (pr_type_info) | |
1176 os << "\n"; | |
1177 } | |
1203 else | 1178 else |
1204 { | 1179 { |
1205 std::string ff = fcn_file_in_path (name); | 1180 val = symbol_table::find_function (name); |
1206 | 1181 |
1207 if (! ff.empty ()) | 1182 if (val.is_defined ()) |
1208 { | 1183 { |
1209 std::ifstream fs (ff.c_str (), std::ios::in); | 1184 octave_function *fcn = val.function_value (); |
1210 | 1185 |
1211 if (fs) | 1186 std::string fn = fcn ? fcn->fcn_file_name () : std::string (); |
1187 | |
1188 if (pr_orig_txt && ! fn.empty ()) | |
1189 display_file (os, name, fn, "function", pr_type_info, quiet); | |
1190 else | |
1212 { | 1191 { |
1213 if (pr_type_info && ! quiet) | 1192 if (pr_type_info && ! quiet) |
1214 os << name << " is the script file: " << ff << "\n\n"; | 1193 { |
1215 | 1194 std::string type |
1216 char ch; | 1195 = fcn->is_user_function () ? "command-line" : "built-in"; |
1217 | 1196 |
1218 while (fs.get (ch)) | 1197 os << name << " is a " << type << " function:\n\n"; |
1219 os << ch; | 1198 } |
1220 } | 1199 |
1200 tree_print_code tpc (os, "", pr_orig_txt); | |
1201 | |
1202 fcn->accept (tpc); | |
1203 } | |
1204 } | |
1205 else | |
1206 { | |
1207 std::string fn = fcn_file_in_path (name); | |
1208 | |
1209 if (! fn.empty ()) | |
1210 display_file (os, name, fn, "script", pr_type_info, quiet); | |
1221 else | 1211 else |
1222 os << "unable to open `" << ff << "' for reading!\n"; | 1212 error ("type: `%s' undefined", name.c_str ()); |
1223 } | 1213 } |
1224 else | |
1225 error ("type: `%s' undefined", name.c_str ()); | |
1226 } | 1214 } |
1227 } | 1215 } |
1228 | 1216 |
1229 DEFCMD (type, args, nargout, | 1217 DEFCMD (type, args, nargout, |
1230 "-*- texinfo -*-\n\ | 1218 "-*- texinfo -*-\n\ |
1296 } | 1284 } |
1297 | 1285 |
1298 std::string | 1286 std::string |
1299 do_which (const std::string& name) | 1287 do_which (const std::string& name) |
1300 { | 1288 { |
1301 std::string retval; | 1289 octave_value val = symbol_table::find_function (name); |
1302 | 1290 |
1303 symbol_record *sym_rec = lookup_by_name (name, 0); | 1291 if (val.is_defined ()) |
1304 | 1292 { |
1305 if (sym_rec && sym_rec->is_defined ()) | 1293 octave_function *fcn = val.function_value (); |
1306 retval = sym_rec->which (); | 1294 |
1307 else | 1295 if (fcn) |
1308 retval = fcn_file_in_path (name); | 1296 { |
1309 | 1297 std::string fn = fcn->fcn_file_name (); |
1310 return retval; | 1298 |
1299 return fn.empty () | |
1300 ? (fcn->is_user_function () | |
1301 ? "command-line function" : "built-in function") | |
1302 : fn; | |
1303 } | |
1304 } | |
1305 | |
1306 return fcn_file_in_path (name); | |
1311 } | 1307 } |
1312 | 1308 |
1313 static void | 1309 static void |
1314 do_which (std::ostream& os, const std::string& name) | 1310 do_which (std::ostream& os, const std::string& name) |
1315 { | 1311 { |
1316 symbol_record *sym_rec = lookup_by_name (name, 0); | 1312 std::string desc; |
1317 | 1313 |
1318 if (sym_rec && sym_rec->is_defined ()) | 1314 octave_value val = symbol_table::find_function (name); |
1319 sym_rec->which (os); | 1315 |
1320 else | 1316 if (val.is_defined ()) |
1321 { | 1317 { |
1322 std::string path = fcn_file_in_path (name); | 1318 octave_function *fcn = val.function_value (); |
1323 | 1319 |
1324 if (! path.empty ()) | 1320 if (fcn) |
1325 os << "which: `" << name << "' is the script file\n" | 1321 { |
1326 << path << "\n"; | 1322 desc = fcn->fcn_file_name (); |
1323 | |
1324 if (desc.empty ()) | |
1325 { | |
1326 if (fcn->is_user_function ()) | |
1327 desc = "is a command-line function"; | |
1328 else | |
1329 desc = "is a built-in function"; | |
1330 } | |
1331 else | |
1332 desc = "is the function from the file " + desc; | |
1333 } | |
1334 } | |
1335 | |
1336 if (desc.empty ()) | |
1337 { | |
1338 std::string fn = fcn_file_in_path (name); | |
1339 | |
1340 if (! fn.empty ()) | |
1341 desc = "is the script file " + fn; | |
1327 else | 1342 else |
1328 os << "which: `" << name << "' is undefined\n"; | 1343 desc = "is undefined"; |
1329 } | 1344 } |
1345 | |
1346 os << "which: `" << name << "' " << desc << std::endl; | |
1330 } | 1347 } |
1331 | 1348 |
1332 DEFCMD (which, args, nargout, | 1349 DEFCMD (which, args, nargout, |
1333 "-*- texinfo -*-\n\ | 1350 "-*- texinfo -*-\n\ |
1334 @deffn {Command} which name @dots{}\n\ | 1351 @deffn {Command} which name @dots{}\n\ |
1762 to find related functions that are not part of Octave.\n\ | 1779 to find related functions that are not part of Octave.\n\ |
1763 @seealso{help, which}\n\ | 1780 @seealso{help, which}\n\ |
1764 @end deffn") | 1781 @end deffn") |
1765 { | 1782 { |
1766 octave_value_list retval; | 1783 octave_value_list retval; |
1784 | |
1767 int nargin = args.length (); | 1785 int nargin = args.length (); |
1768 bool first_sentence_only = true; | 1786 bool first_sentence_only = true; |
1769 | 1787 |
1770 if (nargin != 1 && nargin != 2) | 1788 if (nargin != 1 && nargin != 2) |
1771 { | 1789 { |
1895 OCTAVE_QUIT; | 1913 OCTAVE_QUIT; |
1896 | 1914 |
1897 ptr++; | 1915 ptr++; |
1898 } | 1916 } |
1899 | 1917 |
1918 string_vector names; | |
1919 | |
1920 #ifdef OLD_SYMTAB | |
1900 // Check the symbol record table | 1921 // Check the symbol record table |
1901 string_vector names | 1922 names = fbi_sym_tab->name_list (string_vector (), true); |
1902 = fbi_sym_tab->name_list (string_vector (), true); | |
1903 | 1923 |
1904 for (octave_idx_type i = 0; i < names.length (); i++) | 1924 for (octave_idx_type i = 0; i < names.length (); i++) |
1905 { | 1925 { |
1906 std::string name = names (i); | 1926 std::string name = names (i); |
1907 | 1927 |
1945 print_lookfor (name, first_help_sentence (h)); | 1965 print_lookfor (name, first_help_sentence (h)); |
1946 } | 1966 } |
1947 } | 1967 } |
1948 } | 1968 } |
1949 } | 1969 } |
1970 #endif | |
1950 | 1971 |
1951 string_vector dirs = load_path::dirs (); | 1972 string_vector dirs = load_path::dirs (); |
1952 | 1973 |
1953 int len = dirs.length (); | 1974 int len = dirs.length (); |
1954 | 1975 |
1971 else if (l > 2 && name.substr (l-2) == ".m") | 1992 else if (l > 2 && name.substr (l-2) == ".m") |
1972 name = name.substr (0, l - 2); | 1993 name = name.substr (0, l - 2); |
1973 else | 1994 else |
1974 continue; | 1995 continue; |
1975 | 1996 |
1997 #ifdef OLD_SYMTAB | |
1976 // Check if already in symbol table | 1998 // Check if already in symbol table |
1977 symbol_record *sr = fbi_sym_tab->lookup (name); | 1999 symbol_record *sr = fbi_sym_tab->lookup (name); |
1978 | 2000 |
1979 if (!sr) | 2001 if (!sr) |
1980 { | 2002 { |
2035 print_lookfor (name, first_help_sentence (h)); | 2057 print_lookfor (name, first_help_sentence (h)); |
2036 } | 2058 } |
2037 } | 2059 } |
2038 } | 2060 } |
2039 } | 2061 } |
2062 #endif | |
2040 | 2063 |
2041 // Check if this function has autoloaded functions attached to it | 2064 // Check if this function has autoloaded functions attached to it |
2042 std::string file_name = load_path::find_fcn (name); | 2065 std::string file_name = load_path::find_fcn (name); |
2043 | 2066 |
2044 string_vector autoload_fcns = reverse_lookup_autoload (file_name); | 2067 string_vector autoload_fcns = reverse_lookup_autoload (file_name); |
2047 { | 2070 { |
2048 for (int k = 0; k < autoload_fcns.length (); k++) | 2071 for (int k = 0; k < autoload_fcns.length (); k++) |
2049 { | 2072 { |
2050 std::string aname = autoload_fcns (k); | 2073 std::string aname = autoload_fcns (k); |
2051 | 2074 |
2075 #ifdef OLD_SYMTAB | |
2052 // Check if already in symbol table | 2076 // Check if already in symbol table |
2053 sr = fbi_sym_tab->lookup (aname); | 2077 sr = fbi_sym_tab->lookup (aname); |
2054 | 2078 |
2055 if (!sr) | 2079 if (!sr) |
2056 { | 2080 { |
2092 else | 2116 else |
2093 print_lookfor (aname, first_help_sentence (h)); | 2117 print_lookfor (aname, first_help_sentence (h)); |
2094 } | 2118 } |
2095 } | 2119 } |
2096 } | 2120 } |
2121 #endif | |
2097 } | 2122 } |
2098 } | 2123 } |
2099 } | 2124 } |
2100 } | 2125 } |
2101 } | 2126 } |