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 }