Index: octave/src/symtab.cc =================================================================== RCS file: /cvs/octave/src/symtab.cc,v retrieving revision 1.99 diff -c -p -r1.99 symtab.cc *** a/octave/src/symtab.cc 18 Dec 2003 15:35:09 -0000 1.99 --- b/octave/src/symtab.cc 19 Apr 2004 03:21:24 -0000 *************** Software Foundation, 59 Temple Place - S *** 47,52 **** --- 47,55 ---- #include "utils.h" #include "variables.h" + #include "gripes.h" + #include "lo-mappers.h" + unsigned long int symbol_table::symtab_count = 0; // Should variables be allowed to hide functions of the same name? A *************** static int Vvariables_can_hide_functions *** 57,62 **** --- 60,68 ---- // Nonzero means we print debugging info about symbol table lookups. static int Vdebug_symtab_lookups; + // Defines layout for the whos/who -long command + std::string Vwhos_line_format; + octave_allocator symbol_record::symbol_def::allocator (sizeof (symbol_record::symbol_def)); *************** symbol_record::pop_context (void) *** 410,442 **** } } ! void ! symbol_record::print_symbol_info_line (std::ostream& os) const { ! os << (is_read_only () ? " r-" : " rw") ! << (is_static () || is_eternal () ? "-" : "d") ! << " " ! << std::setiosflags (std::ios::left) << std::setw (24) ! << type_name () . c_str (); ! os << std::resetiosflags (std::ios::left); ! int nr = rows (); ! int nc = columns (); ! if (nr < 0) ! os << " -"; ! else ! os << std::setiosflags (std::ios::right) << std::setw (7) << nr; ! if (nc < 0) ! os << " -"; ! else ! os << std::setiosflags (std::ios::right) << std::setw (7) << nc; ! os << std::resetiosflags (std::ios::right); ! os << " " << name () << "\n"; } void --- 416,653 ---- } } ! int ! symbol_record::dimensions_string_req_first_space (int print_dims) const { ! // This method calculates how much space needs to be reserved for the ! // first part of the dimensions string. ! // Example: mat is a 12x3 matrix ! // ^^ => 2 columns ! long dim = 0; ! int first_param_space = 0; ! // Calculating dimensions ! std::string dim_str = ""; ! std::stringstream ss; ! dim_vector dimensions; ! if (is_variable ()) ! { ! if (is_matrix_type ()) ! { ! dimensions = dims (); ! dim = dimensions.length (); ! } ! } ! first_param_space = (first_param_space >= 1 ? first_param_space : 1); ! // Preparing dimension string ! if ((dim <= print_dims || print_dims < 0) && print_dims != 0) ! { ! // Dimensions string must be printed like this: 2x3x4x2 ! if (dim == 0 || dim == 1) ! first_param_space = 1; // First parameter is 1 ! else ! { ! ss << dimensions (0); ! ! dim_str = ss.str (); ! first_param_space = dim_str.length (); ! } ! } ! else ! { ! // Printing dimension string as: a-D ! ss << dim; ! ! dim_str = ss.str (); ! first_param_space = dim_str.length (); ! } ! ! return first_param_space; ! } ! ! int ! symbol_record::dimensions_string_req_total_space (int print_dims) const ! { ! // This method calculates how much space needs to be reserved for the ! // the dimensions string. ! // Example: mat is a 12x3 matrix ! // ^^^^ => 4 columns ! ! std::string dim_str = ""; ! std::stringstream ss; ! ss << make_dimensions_string (print_dims); ! dim_str = ss.str (); ! return dim_str.length (); ! } ! ! std::string ! symbol_record::make_dimensions_string (int print_dims) const ! { ! // This method makes the dimensions-string, which is a string that tells ! // how large a object is, dimensionally. ! // Example: mat is a 2x3 matrix ! // ^^^ ! ! long dim = 0; ! ! // Calculating dimensions ! std::string dim_str = ""; ! std::stringstream ss; ! dim_vector dimensions; ! ! if (is_variable ()) ! { ! if (is_matrix_type ()) ! { ! dimensions = dims (); ! dim = dimensions.length (); ! } ! } ! ! // Preparing dimension string ! if ((dim <= print_dims || print_dims < 0) && print_dims != 0) ! { ! // Only printing the dimension string as: axbxc... ! if (dim == 0) ! ss << "1x1"; ! else ! { ! for (int i = 0; i < dim; i++) ! { ! if (i == 0) ! { ! if (dim == 1) ! // Looks like this is not going to happen in Octave, but ... ! ss << "1x" << dimensions (i); ! else ! ss << dimensions (i); ! } ! else if (i < dim && dim != 1) ! ss << "x" << dimensions (i); ! } ! } ! } ! else ! { ! // Printing dimension string as: a-D ! ss << dim << "-D"; ! } ! ! dim_str = ss.str (); ! ! return dim_str; ! } ! ! void ! symbol_record::print_symbol_info_line (std::ostream& os, ! std::list& params) const ! { ! // This method prints a line of information on a given symbol ! std::list::iterator i = params.begin (); ! while (i != params.end ()) ! { ! whos_parameter param = * i; ! ! if (param.command != '\0') ! { ! // Do the actual printing ! switch (param.modifier) ! { ! case 'l': ! os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length); ! break; ! ! case 'r': ! os << std::setiosflags (std::ios::right) << std::setw (param.parameter_length); ! break; ! ! case 'c': ! if (param.command == 's') ! { ! int front = param.first_parameter_length - ! dimensions_string_req_first_space (param.dimensions); ! int back = param.parameter_length - ! dimensions_string_req_total_space (param.dimensions) - ! front; ! front = (front > 0) ? front : 0; ! back = (back > 0) ? back : 0; ! ! os << std::setiosflags (std::ios::left) ! << std::setw (front) ! << "" << std::resetiosflags (std::ios::left) ! << make_dimensions_string (param.dimensions) ! << std::setiosflags (std::ios::left) ! << std::setw (back) ! << "" << std::resetiosflags (std::ios::left); ! } ! else ! { ! os << std::setiosflags (std::ios::left) ! << std::setw (param.parameter_length); ! } ! break; ! ! default: ! error ("whos_line_format: modifier `%c' unknown", param.modifier); ! os << std::setiosflags (std::ios::right) ! << std::setw (param.parameter_length); ! } ! ! switch (param.command) ! { ! case 'b': ! os << byte_size (); ! break; ! ! case 'e': ! os << numel (); ! break; ! ! case 'n': ! os << name (); ! break; ! ! case 'p': ! { ! std::stringstream ss; ! std::string str; ! ! ss << (is_read_only () ? "r-" : "rw") ! << (is_static () || is_eternal () ? "-" : "d"); ! str = ss.str (); ! ! os << str; ! } ! break; ! ! case 's': ! if (param.modifier != 'c') ! os << make_dimensions_string (param.dimensions); ! break; ! ! case 't': ! os << type_name (); ! break; ! ! default: ! error ("whos_line_format: command `%c' unknown", param.command); ! } ! ! os << std::resetiosflags (std::ios::left) ! << std::resetiosflags (std::ios::right); ! i++; ! } ! else ! { ! os << param.text; ! i++; ! } ! } } void *************** maybe_list_cmp_fcn (const void *a_arg, c *** 908,918 **** --- 1119,1403 ---- return a_nm.compare (b_nm); } + void + symbol_table::print_descriptor (std::ostream& os, + std::list params) const + { + // This method prints a line of information on a given symbol + std::list::iterator i = params.begin (); + while (i != params.end ()) + { + whos_parameter param = * i; + + if (param.command != '\0') + { + // Do the actual printing + switch (param.modifier) + { + case 'l': + os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length); + break; + + case 'r': + os << std::setiosflags (std::ios::right) << std::setw (param.parameter_length); + break; + + case 'c': + if (param.command != 's') + { + os << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + } + break; + + default: + os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length); + } + + if (param.command == 's' && param.modifier == 'c') + { + int a, b; + + if (param.modifier == 'c') + { + a = param.first_parameter_length - param.balance; + a = (a < 0 ? 0 : a); + b = param.parameter_length - a - param.text . length (); + b = (b < 0 ? 0 : b); + os << std::setiosflags (std::ios::left) << std::setw (a) + << "" << std::resetiosflags (std::ios::left) << param.text + << std::setiosflags (std::ios::left) + << std::setw (b) << "" + << std::resetiosflags (std::ios::left); + } + } + else + os << param.text; + + os << std::resetiosflags (std::ios::left) + << std::resetiosflags (std::ios::right); + i++; + } + else + { + os << param.text; + i++; + } + } + + } + + std::list + symbol_table::parse_whos_line_format (Array& symbols) const + { + // This method parses the string whos_line_format, and returns + // a parameter list, containing all information needed to print + // the given attributtes of the symbols + int idx; + size_t format_len = Vwhos_line_format.length (); + char garbage; + std::list params; + + size_t bytes1; + int elements1; + + int len = symbols.length (), i; + + std::string param_string = "benpst"; + Array param_length(param_string.length ()); + Array param_names(param_string.length ()); + size_t pos_b, pos_t, pos_e, pos_n, pos_p, pos_s; + + pos_b = param_string.find ('b'); // Bytes + pos_t = param_string.find ('t'); // (Type aka) Class + pos_e = param_string.find ('e'); // Elements + pos_n = param_string.find ('n'); // Name + pos_p = param_string.find ('p'); // Protected + pos_s = param_string.find ('s'); // Size + + param_names(pos_b) = "Bytes"; + param_names(pos_t) = "Class"; + param_names(pos_e) = "Elements"; + param_names(pos_n) = "Name"; + param_names(pos_p) = "Protected"; + param_names(pos_s) = "Size"; + + for (i = 0; i < 6; i++) + param_length(i) = param_names(i) . length (); + + // Calculating necessary spacing for name column, + // bytes column, elements column and class column + for (i = 0; i < static_cast (len); i++) + { + std::stringstream ss1, ss2; + std::string str; + + str = symbols(i)->name (); + param_length(pos_n) = ((str.length () > static_cast (param_length(pos_n))) ? + str.length () : param_length(pos_n)); + + str = symbols(i)->type_name (); + param_length(pos_t) = ((str.length () > static_cast (param_length(pos_t))) ? + str.length () : param_length(pos_t)); + + elements1 = symbols(i)->numel (); + ss1 << elements1; + str = ss1.str (); + param_length(pos_e) = ((str.length () > static_cast (param_length(pos_e))) ? + str.length () : param_length(pos_e)); + + bytes1 = symbols(i)->byte_size (); + ss2 << bytes1; + str = ss2.str (); + param_length(pos_b) = ((str.length () > static_cast (param_length(pos_b))) ? + str.length () : param_length (pos_b)); + } + + idx = 0; + while (static_cast (idx) < format_len) + { + whos_parameter param; + param.command = '\0'; + + if (Vwhos_line_format[idx] == '%') + { + bool _error = false; + param.modifier = 'r'; + param.parameter_length = 0; + param.dimensions = 8; + + int a = 0, b = -1, c = 8, balance = 1; + unsigned int items; + size_t pos; + std::string cmd; + + // Parse one command from whos_line_format + cmd = Vwhos_line_format.substr (idx, Vwhos_line_format.length ()); + pos = cmd.find (';'); + if (pos != NPOS) + cmd = cmd.substr (0, pos+1); + else + error ("parameter without ; in whos_line_format"); + + idx += cmd.length (); + + if (cmd.find_first_of ("crl") != 1) + items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d:%d;", + &garbage, ¶m.command, &a, &b, &c, &balance); + else + items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d:%d;", + &garbage, ¶m.modifier, ¶m.command, &a, &b, &c, &balance) - 1; + + if (items < 2) + { + error ("whos_line_format: parameter structure without command in whos_line_format"); + _error = true; + } + + // Insert data into parameter + param.first_parameter_length = 0; + pos = param_string.find (param.command); + if (pos != NPOS) + { + param.parameter_length = param_length(pos); + param.text = param_names(pos); + } + else + { + error ("whos_line_format: '%c' is not a command", + param.command); + _error = true; + } + + if (param.command == 's') + { + // Have to calculate space needed for printing matrix dimensions + // Space needed for Size column is hard to determine in prior, + // because it depends on dimensions to be shown. That is why it is + // recalculated for each Size-command + int j, first = 0, rest = 0, total = 0; + param.dimensions = c; + + for (j = 0; j < len; j++) + { + int first1 = symbols(j)->dimensions_string_req_first_space (param.dimensions); + int total1 = symbols(j)->dimensions_string_req_total_space (param.dimensions); + int rest1 = total1 - first1; + rest = (rest1 > rest ? rest1 : rest); + first = (first1 > first ? first1 : first); + total = (total1 > total ? total1 : total); + } + + if (param.modifier == 'c') + { + if (first < balance) + first += balance - first; + if (rest + balance < param.parameter_length) + rest += param.parameter_length - rest - balance; + + param.parameter_length = first + rest; + param.first_parameter_length = first; + param.balance = balance; + } + else + { + param.parameter_length = total; + param.first_parameter_length = 0; + } + } + else if (param.modifier == 'c') + { + error ("whos_line_format: modifier 'c' not available for command '%c'", + param.command); + _error = true; + } + + // What happens if whos_line_format contains negative numbers + // at param_length positions? + param.balance = ((b < 0) ? 0 : param.balance); + param.first_parameter_length = ((b < 0) ? 0 : + param.first_parameter_length); + param.parameter_length = ((a < 0) ? 0 : + (param.parameter_length < + param_length (pos_s)) ? + param_length (pos_s) : + param.parameter_length); + + // Parameter will not be pushed into parameter list if ... + if (! _error) + params.push_back (param); + } + else + { + // Text string, to be printed as it is ... + std::string text; + size_t pos; + text = Vwhos_line_format.substr (idx, Vwhos_line_format.length ()); + pos = text.find ('%'); + if (pos != NPOS) + text = text.substr (0, pos); + + // Push parameter into list ... + idx += text.length (); + param.text=text; + params.push_back (param); + } + } + + return params; + } + int symbol_table::maybe_list (const char *header, const string_vector& argv, std::ostream& os, bool show_verbose, unsigned type, unsigned scope) { + // This method prints information for sets of symbols, but only one set + // at a time (like, for instance: all variables, og all + // built-in-functions) + + // This method invokes print_symbol_info_line to print info on every symbol + int status = 0; if (show_verbose) *************** symbol_table::maybe_list (const char *he *** 923,936 **** if (len > 0) { ! os << "\n" << header << "\n\n" ! << "prot type rows cols name\n" ! << "==== ==== ==== ==== ====\n"; symbols.qsort (maybe_list_cmp_fcn); for (int i = 0; i < len; i++) ! symbols(i)->print_symbol_info_line (os); status = 1; } --- 1408,1436 ---- if (len > 0) { ! int bytes = 0, elements = 0; ! std::list params; ! ! os << "\n" << header << "\n\n"; symbols.qsort (maybe_list_cmp_fcn); + params = parse_whos_line_format (symbols); + + print_descriptor (os, params); + + os << "\n"; + for (int i = 0; i < len; i++) ! { ! symbols(i)->print_symbol_info_line (os, params); ! elements += symbols(i)->numel (); ! bytes += symbols(i)->byte_size (); ! } ! ! os << "\nGrand total is " << elements ! << " element" << ((elements > 1) ? "s" : "") << " using " ! << bytes << " byte" << ((bytes > 1) ? "s" : "") << "\n"; status = 1; } *************** symbol_table::maybe_list (const char *he *** 940,950 **** string_vector symbols = name_list (argv, 1, type, scope); if (! symbols.empty ()) ! { ! os << "\n" << header << "\n\n"; symbols.list_in_columns (os); status = 1; } } --- 1440,1452 ---- string_vector symbols = name_list (argv, 1, type, scope); if (! symbols.empty ()) ! { ! os << "\nYour variables are:\n\n"; symbols.list_in_columns (os); + os << "\n"; + status = 1; } } *************** debug_symtab_lookups (void) *** 1107,1112 **** --- 1609,1622 ---- return 0; } + static int + whos_line_format (void) + { + Vwhos_line_format = builtin_string_variable ("whos_line_format"); + + return 0; + } + void symbols_of_symtab (void) { *************** will cause Octave to print a warning, bu *** 1122,1128 **** "-*- texinfo -*-\n\ @defvr debug_symtab_lookups\n\ If the value of htis variable is nonzero, print debugging info when\n\ ! searching for symbols in the symbol tables"); } --- 1632,1685 ---- "-*- texinfo -*-\n\ @defvr debug_symtab_lookups\n\ If the value of htis variable is nonzero, print debugging info when\n\ ! searching for symbols in the symbol tables\n\ ! @end defvr"); ! ! DEFVAR (whos_line_format, " %ln:6; %cs:16:6:8:1; %rb:12; %lt:-1;\n", whos_line_format, ! "-*- texinfo -*-\n\ ! @defvr {Built-in Variable} whos_line_format\n\ ! This string decides in what order attributtes of variables are to be printed.\n\ ! The following commands are used:\n\ ! @table @code\n\ ! @item %b\n\ ! Prints number of bytes occupied by variables.\n\ ! @item %e\n\ ! Prints elements held by variables.\n\ ! @item %n\n\ ! Prints variable names.\n\ ! @item %p\n\ ! Prints protection attributtes of variables.\n\ ! @item %s\n\ ! Prints dimensions of variables.\n\ ! @item %t\n\ ! Prints type names of variables.\n\ ! @end table\n\ ! \n\ ! Every command may also have a modifier:\n\ ! @table @code\n\ ! @item l\n\ ! Left alignment.\n\ ! @item r\n\ ! Right alignment (this is the default).\n\ ! @item c\n\ ! Centered (may only be applied to command %s).\n\ ! @end table\n\ ! \n\ ! A command is composed like this:\n\ ! %[modifier][:size_of_parameter[:center-specific[:print_dims[:balance]]]];\n\ ! \n\ ! Command and modifier is already explained. Size_of_parameter\n\ ! tells how many columns the parameter will need for printing.\n\ ! print_dims tells how many dimensions to print. If number of\n\ ! dimensions exceeds print_dims, dimensions will be printed like\n\ ! x-D.\n\ ! center-specific and print_dims may only be applied to command\n\ ! %s. A negative value for print_dims will cause Octave to print all\n\ ! dimensions whatsoever.\n\ ! balance specifies the offset for printing of the dimensions string.\n\ ! \n\ ! Default format is \" %ln:6; %cs:16:6:8:1; %rb:12; %lt:-1;\\n\".\n\ ! @end defvr\n"); } Index: octave/src/symtab.h =================================================================== RCS file: /cvs/octave/src/symtab.h,v retrieving revision 1.66 diff -c -p -r1.66 symtab.h *** a/octave/src/symtab.h 13 Feb 2003 21:03:04 -0000 1.66 --- b/octave/src/symtab.h 19 Apr 2004 03:21:24 -0000 *************** class string_vector; *** 45,50 **** --- 45,58 ---- class symbol_record; class symbol_table; + struct + whos_parameter + { + char command, modifier; + int parameter_length, first_parameter_length, dimensions, balance; + std::string text; + }; + // Individual records in a symbol table. class *************** private: *** 146,151 **** --- 154,171 ---- bool is_eternal (void) const { return eternal; } + bool is_matrix_type (void) const + { return definition.is_matrix_type (); } + + size_t byte_size (void) const + { return definition.byte_size (); }; + + int numel (void) const + { return definition.numel (); }; + + dim_vector dims (void) const + { return definition.dims (); } + int rows (void) const { return definition.rows (); } int columns (void) const { return definition.columns (); } *************** public: *** 325,330 **** --- 345,367 ---- bool is_static (void) const { return tagged_static; } void unmark_static (void) { tagged_static = false; } + bool is_matrix_type (void) const + { return definition->is_matrix_type (); } + + size_t byte_size (void) const + { return definition->byte_size (); }; + + int numel (void) const + { return definition->numel (); }; + + dim_vector dims (void) const { return definition->dims (); } + + int dimensions_string_req_first_space (int print_dims) const; + + int dimensions_string_req_total_space (int print_dims) const; + + std::string make_dimensions_string (int print_dims) const; + int rows (void) const { return definition->rows (); } int columns (void) const { return definition->columns (); } *************** public: *** 351,357 **** void pop_context (void); ! void print_symbol_info_line (std::ostream& os) const; void print_info (std::ostream& os, const std::string& prefix = std::string ()) const; --- 388,395 ---- void pop_context (void); ! void print_symbol_info_line (std::ostream& os, ! std::list& params) const; void print_info (std::ostream& os, const std::string& prefix = std::string ()) const; *************** private: *** 511,516 **** --- 549,561 ---- static unsigned long int symtab_count; + void + print_descriptor (std::ostream& os, + std::list params) const; + + std::list + parse_whos_line_format (Array& symbols) const; + unsigned int hash (const std::string& s); // No copying! *************** private: *** 520,525 **** --- 565,573 ---- symbol_table& operator = (const symbol_table&); }; + // Defines layout for the whos/who -long command. + extern std::string Vwhos_line_format; + #endif /*