comparison src/variables.cc @ 529:7ea224e713cd

[project @ 1994-07-20 18:54:27 by jwe]
author jwe
date Wed, 20 Jul 1994 19:19:08 +0000
parents 0f388340e607
children 682393bf54f7
comparison
equal deleted inserted replaced
528:e1e6e33e26f8 529:7ea224e713cd
28 #include <sys/types.h> 28 #include <sys/types.h>
29 #ifdef HAVE_UNISTD_H 29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h> 30 #include <unistd.h>
31 #endif 31 #endif
32 #include <ctype.h> 32 #include <ctype.h>
33 #include <float.h>
34 #include <string.h>
35 #include <fstream.h>
33 #include <iostream.h> 36 #include <iostream.h>
34 #include <strstream.h> 37 #include <strstream.h>
35 38
36 #include "statdefs.h" 39 #include "statdefs.h"
37 #include "tree-const.h" 40 #include "tree-const.h"
38 #include "variables.h" 41 #include "variables.h"
42 #include "mappers.h"
39 #include "user-prefs.h" 43 #include "user-prefs.h"
44 #include "version.h"
40 #include "symtab.h" 45 #include "symtab.h"
41 #include "builtins.h" 46 #include "defaults.h"
42 #include "g-builtins.h" 47 #include "dirfns.h"
43 #include "t-builtins.h" 48 #include "pager.h"
49 #include "sysdep.h"
50 #include "octave.h"
51 #include "oct-obj.h"
44 #include "error.h" 52 #include "error.h"
45 #include "utils.h" 53 #include "utils.h"
46 #include "tree.h" 54 #include "tree.h"
47 #include "help.h" 55 #include "help.h"
56 #include "defun.h"
57
58 extern "C"
59 {
60 #include <readline/tilde.h>
61
62 #include "fnmatch.h"
63 }
48 64
49 // Symbol table for symbols at the top level. 65 // Symbol table for symbols at the top level.
50 symbol_table *top_level_sym_tab; 66 symbol_table *top_level_sym_tab;
51 67
52 // Symbol table for the current scope. 68 // Symbol table for the current scope.
75 int ignore = user_pref.ignore_function_time_stamp; 91 int ignore = user_pref.ignore_function_time_stamp;
76 92
77 if (ignore == 2) 93 if (ignore == 2)
78 return 0; 94 return 0;
79 95
80 if (sr != (symbol_record *) NULL) 96 if (sr)
81 { 97 {
82 tree_fvc *ans = sr->def (); 98 tree_fvc *ans = sr->def ();
83 if (ans != (tree_fvc *) NULL) 99 if (ans)
84 { 100 {
85 char *ff = ans->fcn_file_name (); 101 char *ff = ans->fcn_file_name ();
86 if (! (ff == (char *) NULL 102 if (ff && ! (ignore && ans->is_system_fcn_file ()))
87 || (ignore && ans->is_system_fcn_file ())))
88 { 103 {
89 time_t tp = ans->time_parsed (); 104 time_t tp = ans->time_parsed ();
90 char *fname = fcn_file_in_path (ff); 105 char *fname = fcn_file_in_path (ff);
91 int status = is_newer (fname, tp); 106 int status = is_newer (fname, tp);
92 delete [] fname; 107 delete [] fname;
106 error ("sorry, can't redefine help for builtin variables"); 121 error ("sorry, can't redefine help for builtin variables");
107 } 122 }
108 else 123 else
109 { 124 {
110 symbol_record *sym_rec = curr_sym_tab->lookup (name, 0); 125 symbol_record *sym_rec = curr_sym_tab->lookup (name, 0);
111 if (sym_rec == (symbol_record *) NULL) 126 if (sym_rec)
112 { 127 sym_rec->document (help);
113 error ("document: no such symbol `%s'", name);
114 }
115 else 128 else
116 { 129 error ("document: no such symbol `%s'", name);
117 sym_rec->document (help);
118 }
119 } 130 }
120 } 131 }
121 132
122 void 133 void
123 install_builtin_mapper_function (builtin_mapper_functions *mf) 134 install_builtin_mapper (builtin_mapper_function *mf)
124 { 135 {
125 symbol_record *sym_rec = global_sym_tab->lookup (mf->name, 1); 136 symbol_record *sym_rec = global_sym_tab->lookup (mf->name, 1);
126 sym_rec->unprotect (); 137 sym_rec->unprotect ();
127 138
128 Mapper_fcn mfcn; 139 Mapper_fcn mfcn;
141 sym_rec->make_eternal (); 152 sym_rec->make_eternal ();
142 sym_rec->protect (); 153 sym_rec->protect ();
143 } 154 }
144 155
145 void 156 void
146 install_builtin_text_function (builtin_text_functions *tf) 157 install_builtin_function (builtin_function *f)
147 { 158 {
148 symbol_record *sym_rec = global_sym_tab->lookup (tf->name, 1); 159 symbol_record *sym_rec = global_sym_tab->lookup (f->name, 1);
149 sym_rec->unprotect (); 160 sym_rec->unprotect ();
150 161
151 tree_builtin *def = new tree_builtin (tf->nargin_max, 1, 162 tree_builtin *def = new tree_builtin (f->nargin_max, f->nargout_max,
152 tf->text_fcn, tf->name); 163 f->fcn, f->name);
153 164
154 sym_rec->define (def); 165 sym_rec->define (def, f->is_text_fcn);
155 166
156 sym_rec->document (tf->help_string); 167 sym_rec->document (f->help_string);
157 sym_rec->make_eternal (); 168 sym_rec->make_eternal ();
158 sym_rec->protect (); 169 sym_rec->protect ();
159
160 } 170 }
161 171
162 void 172 void
163 install_builtin_general_function (builtin_general_functions *gf) 173 install_builtin_variable (builtin_variable *v)
164 { 174 {
165 symbol_record *sym_rec = global_sym_tab->lookup (gf->name, 1); 175 if (v->install_as_function)
166 sym_rec->unprotect (); 176 install_builtin_variable_as_function (v->name, v->value, v->protect,
167 177 v->eternal, v->help_string);
168 tree_builtin *def = new tree_builtin (gf->nargin_max, 178 else
169 gf->nargout_max, 179 bind_builtin_variable (v->name, v->value, v->protect, v->eternal,
170 gf->general_fcn, gf->name); 180 v->sv_function, v->help_string);
171
172 sym_rec->define (def);
173
174 sym_rec->document (gf->help_string);
175 sym_rec->make_eternal ();
176 sym_rec->protect ();
177 }
178
179 void
180 install_builtin_variable (builtin_string_variables *sv)
181 {
182 tree_constant *val = new tree_constant (sv->value);
183
184 bind_builtin_variable (sv->name, val, 0, 1, sv->sv_function,
185 sv->help_string);
186 } 181 }
187 182
188 void 183 void
189 install_builtin_variable_as_function (const char *name, tree_constant *val, 184 install_builtin_variable_as_function (const char *name, tree_constant *val,
190 int protect = 0, int eternal = 0) 185 int protect, int eternal,
186 const char *help)
191 { 187 {
192 symbol_record *sym_rec = global_sym_tab->lookup (name, 1); 188 symbol_record *sym_rec = global_sym_tab->lookup (name, 1);
193 sym_rec->unprotect (); 189 sym_rec->unprotect ();
194 190
195 char *tmp_help = sym_rec->help (); 191 const char *tmp_help = help;
192 if (! help)
193 tmp_help = sym_rec->help ();
196 194
197 sym_rec->define_as_fcn (val); 195 sym_rec->define_as_fcn (val);
198 196
199 sym_rec->document (tmp_help); 197 sym_rec->document (tmp_help);
200 198
228 * Give a global variable a definition. This will insert the symbol 226 * Give a global variable a definition. This will insert the symbol
229 * in the global table if necessary. 227 * in the global table if necessary.
230 */ 228 */
231 void 229 void
232 bind_builtin_variable (const char *varname, tree_constant *val, 230 bind_builtin_variable (const char *varname, tree_constant *val,
233 int protect = 0, int eternal = 0, 231 int protect, int eternal, sv_Function sv_fcn,
234 sv_Function sv_fcn = (sv_Function) 0, 232 const char *help)
235 const char *help = (char *) 0)
236 { 233 {
237 symbol_record *sr = global_sym_tab->lookup (varname, 1, 0); 234 symbol_record *sr = global_sym_tab->lookup (varname, 1, 0);
238 235
239 // It is a programming error for a builtin symbol to be missing. 236 // It is a programming error for a builtin symbol to be missing.
240 // Besides, we just inserted it, so it must be there. 237 // Besides, we just inserted it, so it must be there.
241 238
242 assert (sr != (symbol_record *) NULL); 239 assert (sr);
243 240
244 sr->unprotect (); 241 sr->unprotect ();
245 242
246 // Must do this before define, since define will call the special 243 // Must do this before define, since define will call the special
247 // variable function only if it knows about it, and it needs to, so 244 // variable function only if it knows about it, and it needs to, so
262 sr->document (help); 259 sr->document (help);
263 } 260 }
264 261
265 /* 262 /*
266 * Look for the given name in the global symbol table. If it refers 263 * Look for the given name in the global symbol table. If it refers
267 * to a string, return a new copy. If not, return NULL. 264 * to a string, return a new copy. If not, return 0;
268 */ 265 */
269 char * 266 char *
270 builtin_string_variable (const char *name) 267 builtin_string_variable (const char *name)
271 { 268 {
272 symbol_record *sr = global_sym_tab->lookup (name, 0, 0); 269 symbol_record *sr = global_sym_tab->lookup (name, 0, 0);
273 270
274 // It is a prorgramming error to look for builtins that aren't. 271 // It is a prorgramming error to look for builtins that aren't.
275 272
276 assert (sr != (symbol_record *) NULL); 273 assert (sr);
277 274
278 char *retval = (char *) NULL; 275 char *retval = 0;
279 276
280 tree_fvc *defn = sr->def (); 277 tree_fvc *defn = sr->def ();
281 278
282 if (defn != (tree_fvc *) NULL) 279 if (defn)
283 { 280 {
284 tree_constant val = defn->eval (0); 281 tree_constant val = defn->eval (0);
285 282
286 if (! error_state && val.is_string_type ()) 283 if (! error_state && val.is_string_type ())
287 { 284 {
288 char *s = val.string_value (); 285 char *s = val.string_value ();
289 if (s != (char *) NULL) 286 if (s)
290 retval = strsave (s); 287 retval = strsave (s);
291 } 288 }
292 } 289 }
293 290
294 return retval; 291 return retval;
305 int status = -1; 302 int status = -1;
306 symbol_record *sr = global_sym_tab->lookup (name, 0, 0); 303 symbol_record *sr = global_sym_tab->lookup (name, 0, 0);
307 304
308 // It is a prorgramming error to look for builtins that aren't. 305 // It is a prorgramming error to look for builtins that aren't.
309 306
310 assert (sr != (symbol_record *) NULL); 307 assert (sr);
311 308
312 tree_fvc *defn = sr->def (); 309 tree_fvc *defn = sr->def ();
313 310
314 if (defn != (tree_fvc *) NULL) 311 if (defn)
315 { 312 {
316 tree_constant val = defn->eval (0); 313 tree_constant val = defn->eval (0);
317 314
318 if (! error_state 315 if (! error_state
319 && val.const_type () == tree_constant_rep::scalar_constant) 316 && val.const_type () == tree_constant_rep::scalar_constant)
349 346
350 if (sr->is_variable ()) 347 if (sr->is_variable ())
351 { 348 {
352 // Would be nice not to have this cast. XXX FIXME XXX 349 // Would be nice not to have this cast. XXX FIXME XXX
353 tree_constant *tmp = (tree_constant *) sr->def (); 350 tree_constant *tmp = (tree_constant *) sr->def ();
354 if (tmp == NULL_TREE_CONST) 351 if (tmp)
352 tmp = new tree_constant (*tmp);
353 else
355 tmp = new tree_constant (); 354 tmp = new tree_constant ();
356 else
357 tmp = new tree_constant (*tmp);
358 gsr->define (tmp); 355 gsr->define (tmp);
359 } 356 }
360 else 357 else
361 { 358 sr->clear ();
362 sr->clear ();
363 }
364 359
365 // If the global symbol is currently defined as a function, we need to 360 // If the global symbol is currently defined as a function, we need to
366 // hide it with a variable. 361 // hide it with a variable.
367 362
368 if (gsr->is_function ()) 363 if (gsr->is_function ())
369 gsr->define (NULL_TREE_CONST); 364 gsr->define ((tree_constant *) 0);
370 365
371 sr->alias (gsr, 1); 366 sr->alias (gsr, 1);
372 sr->mark_as_linked_to_global (); 367 sr->mark_as_linked_to_global ();
373 } 368 }
374 369
379 void 374 void
380 link_to_builtin_variable (symbol_record *sr) 375 link_to_builtin_variable (symbol_record *sr)
381 { 376 {
382 symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0); 377 symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0);
383 378
384 if (tmp_sym != (symbol_record *) NULL) 379 if (tmp_sym && tmp_sym->is_builtin_variable ())
385 { 380 sr->alias (tmp_sym);
386 if (tmp_sym->is_builtin_variable ())
387 {
388 sr->alias (tmp_sym);
389 }
390 }
391 } 381 }
392 382
393 /* 383 /*
394 * Make the definition of the symbol record sr be the same as the 384 * Make the definition of the symbol record sr be the same as the
395 * definition of the builtin variable or function, or user function of 385 * definition of the builtin variable or function, or user function of
399 void 389 void
400 link_to_builtin_or_function (symbol_record *sr) 390 link_to_builtin_or_function (symbol_record *sr)
401 { 391 {
402 symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0); 392 symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0);
403 393
404 if (tmp_sym != (symbol_record *) NULL) 394 if (tmp_sym
405 { 395 && (tmp_sym->is_builtin_variable () || tmp_sym->is_function ())
406 if ((tmp_sym->is_builtin_variable () || tmp_sym->is_function ()) 396 && ! tmp_sym->is_formal_parameter ())
407 && ! tmp_sym->is_formal_parameter ()) 397 sr->alias (tmp_sym);
408 {
409 sr->alias (tmp_sym);
410 }
411 }
412 } 398 }
413 399
414 /* 400 /*
415 * Force a link to a function in the current symbol table. This is 401 * Force a link to a function in the current symbol table. This is
416 * used just after defining a function to avoid different behavior 402 * used just after defining a function to avoid different behavior
430 symbol_record *csr = curr_sym_tab->lookup (id_name, 1, 0); 416 symbol_record *csr = curr_sym_tab->lookup (id_name, 1, 0);
431 csr->alias (gsr); 417 csr->alias (gsr);
432 } 418 }
433 } 419 }
434 420
435 /* 421 DEFUN ("is_global", Fis_global, Sis_global, 2, 1,
436 * Return 1 if the argument names a globally visible variable. 422 "is_global (X): return 1 if the string X names a global variable\n\
437 * Otherwise, return 0. 423 otherwise, return 0.")
438 */ 424 {
439 int 425 Octave_object retval (0.0);
440 is_globally_visible (const char *name) 426
441 { 427 int nargin = args.length ();
428
429 if (nargin != 2 || ! args(1).is_string_type ())
430 {
431 print_usage ("is_global");
432 return retval;
433 }
434
435 char *name = args(1).string_value ();
436
442 symbol_record *sr = curr_sym_tab->lookup (name, 0, 0); 437 symbol_record *sr = curr_sym_tab->lookup (name, 0, 0);
443 return (sr != (symbol_record *) NULL && sr->is_linked_to_global ()); 438
439 retval = (double) (sr && sr->is_linked_to_global ());
440
441 return retval;
444 } 442 }
445 443
446 /* 444 /*
447 * Extract a keyword and its value from a file. Input should look 445 * Extract a keyword and its value from a file. Input should look
448 * something like: 446 * something like:
455 char * 453 char *
456 extract_keyword (istream& is, char *keyword) 454 extract_keyword (istream& is, char *keyword)
457 { 455 {
458 ostrstream buf; 456 ostrstream buf;
459 457
460 char *retval = (char *) NULL; 458 char *retval = 0;
461 459
462 char c; 460 char c;
463 while (is.get (c)) 461 while (is.get (c))
464 { 462 {
465 if (c == '#') 463 if (c == '#')
574 * Is `s' a valid identifier? 572 * Is `s' a valid identifier?
575 */ 573 */
576 int 574 int
577 valid_identifier (char *s) 575 valid_identifier (char *s)
578 { 576 {
579 if (s == (char *) NULL || ! (isalnum (*s) || *s == '_')) 577 if (! s || ! (isalnum (*s) || *s == '_'))
580 return 0; 578 return 0;
581 579
582 while (*++s != '\0') 580 while (*++s != '\0')
583 if (! (isalnum (*s) || *s == '_')) 581 if (! (isalnum (*s) || *s == '_'))
584 return 0; 582 return 0;
585 583
586 return 1; 584 return 1;
587 } 585 }
588 586
589 /* 587 DEFUN ("exist", Fexist, Sexist, 2, 1,
590 * See if the identifier is in scope. 588 "exist (NAME): check if variable or file exists\n\
591 */ 589 \n\
592 int 590 return 0 if NAME is undefined, 1 if it is a variable, or 2 if it is\n\
593 identifier_exists (char *name) 591 a function.")
594 { 592 {
593 Octave_object retval;
594
595 int nargin = args.length ();
596
597 if (nargin != 2 || ! args(1).is_string_type ())
598 {
599 print_usage ("exist");
600 return retval;
601 }
602
603 char *name = args(1).string_value ();
604
595 symbol_record *sr = curr_sym_tab->lookup (name, 0, 0); 605 symbol_record *sr = curr_sym_tab->lookup (name, 0, 0);
596 if (sr == (symbol_record *) NULL) 606 if (! sr)
597 sr = global_sym_tab->lookup (name, 0, 0); 607 sr = global_sym_tab->lookup (name, 0, 0);
598 608
599 if (sr != (symbol_record *) NULL && sr->is_variable () && sr->is_defined ()) 609 retval = 0.0;
600 return 1; 610
601 else if (sr != (symbol_record *) NULL && sr->is_function ()) 611 if (sr && sr->is_variable () && sr->is_defined ())
602 return 2; 612 retval = 1.0;
613 else if (sr && sr->is_function ())
614 retval = 2.0;
603 else 615 else
604 { 616 {
605 char *path = fcn_file_in_path (name); 617 char *path = fcn_file_in_path (name);
606 if (path != (char *) NULL) 618 if (path)
607 { 619 {
608 delete [] path; 620 delete [] path;
609 return 2; 621 retval = 2.0;
610 } 622 }
611 else 623 else
612 { 624 {
613 struct stat buf; 625 struct stat buf;
614 if (stat (name, &buf) == 0 && S_ISREG (buf.st_mode)) 626 if (stat (name, &buf) == 0 && S_ISREG (buf.st_mode))
615 return 2; 627 retval = 2.0;
616 } 628 }
617 } 629 }
618 return 0; 630
631 return retval;
619 } 632 }
620 633
621 /* 634 /*
622 * Is this variable a builtin? 635 * Is this variable a builtin?
623 */ 636 */
624 int 637 int
625 is_builtin_variable (const char *name) 638 is_builtin_variable (const char *name)
626 { 639 {
627 symbol_record *sr = global_sym_tab->lookup (name, 0, 0); 640 symbol_record *sr = global_sym_tab->lookup (name, 0, 0);
628 return (sr != (symbol_record *) NULL && sr->is_builtin_variable ()); 641 return (sr && sr->is_builtin_variable ());
629 } 642 }
630 643
631 /* 644 /*
632 * Is this tree_constant a valid function? 645 * Is this tree_constant a valid function?
633 */ 646 */
634 tree_fvc * 647 tree_fvc *
635 is_valid_function (tree_constant& arg, char *warn_for, int warn = 0) 648 is_valid_function (const tree_constant& arg, char *warn_for, int warn)
636 { 649 {
637 tree_fvc *ans = (tree_fvc *) NULL; 650 tree_fvc *ans = 0;
638 651
639 if (! arg.is_string_type ()) 652 if (! arg.is_string_type ())
640 { 653 {
641 if (warn) 654 if (warn)
642 error ("%s: expecting function name as argument", warn_for); 655 error ("%s: expecting function name as argument", warn_for);
644 } 657 }
645 658
646 char *fcn_name = arg.string_value (); 659 char *fcn_name = arg.string_value ();
647 symbol_record *sr = global_sym_tab->lookup (fcn_name, 0, 0); 660 symbol_record *sr = global_sym_tab->lookup (fcn_name, 0, 0);
648 661
649 if (sr == (symbol_record *) NULL) 662 if (sr && symbol_out_of_date (sr))
663 {
664 tree_identifier tmp (sr);
665 tmp.parse_fcn_file (0);
666 }
667 else
650 { 668 {
651 sr = global_sym_tab->lookup (fcn_name, 1, 0); 669 sr = global_sym_tab->lookup (fcn_name, 1, 0);
652 tree_identifier tmp (sr); 670 tree_identifier tmp (sr);
653 tmp.parse_fcn_file (0); 671 tmp.parse_fcn_file (0);
654 } 672 }
655 else if (symbol_out_of_date (sr))
656 {
657 tree_identifier tmp (sr);
658 tmp.parse_fcn_file (0);
659 }
660 673
661 ans = sr->def (); 674 ans = sr->def ();
662 if (ans == (tree_fvc *) NULL || ! sr->is_function ()) 675 if (! ans || ! sr->is_function ())
663 { 676 {
664 if (warn) 677 if (warn)
665 error ("%s: the symbol `%s' is not valid as a function", 678 error ("%s: the symbol `%s' is not valid as a function",
666 warn_for, fcn_name); 679 warn_for, fcn_name);
667 ans = (tree_fvc *) NULL; 680 ans = 0;
668 } 681 }
669 682
670 return ans; 683 return ans;
671 } 684 }
672 685
673 /* 686 /*
674 * Does this function take the right number of arguments? 687 * Does this function take the right number of arguments?
675 */ 688 */
676 int 689 int
677 takes_correct_nargs (tree_fvc *fcn, int expected_nargin, char *warn_for, 690 takes_correct_nargs (tree_fvc *fcn, int expected_nargin, char *warn_for,
678 int warn = 0) 691 int warn)
679 { 692 {
680 int nargin = fcn->max_expected_args () - 1; 693 int nargin = fcn->max_expected_args () - 1;
681 int e_nargin = expected_nargin - 1; 694 int e_nargin = expected_nargin - 1;
682 if (nargin != e_nargin) 695 if (nargin != e_nargin)
683 { 696 {
684 if (warn) 697 if (warn)
685 error ("%s: expecting function to take %d argument%c", 698 error ("%s: expecting function to take %d argument%c",
686 warn_for, e_nargin, s_plural (e_nargin)); 699 warn_for, e_nargin, (e_nargin == 1 ? "" : "s"));
687 return 0; 700 return 0;
688 } 701 }
689 return 1; 702 return 1;
690 } 703 }
691 704
698 int glb_len = 0; 711 int glb_len = 0;
699 int top_len = 0; 712 int top_len = 0;
700 int lcl_len = 0; 713 int lcl_len = 0;
701 int ffl_len = 0; 714 int ffl_len = 0;
702 715
703 char **key = (char **) NULL; 716 char **key = 0;
704 char **glb = (char **) NULL; 717 char **glb = 0;
705 char **top = (char **) NULL; 718 char **top = 0;
706 char **lcl = (char **) NULL; 719 char **lcl = 0;
707 char **ffl = (char **) NULL; 720 char **ffl = 0;
708 721
709 // Each of these functions returns a new vector of pointers to new 722 // Each of these functions returns a new vector of pointers to new
710 // strings. 723 // strings.
711 724
712 key = names (keyword_help (), key_len); 725 key = names (keyword_help (), key_len);
739 list[j++] = lcl[i]; 752 list[j++] = lcl[i];
740 753
741 for (i = 0; i < ffl_len; i++) 754 for (i = 0; i < ffl_len; i++)
742 list[j++] = ffl[i]; 755 list[j++] = ffl[i];
743 756
744 list[j] = (char *) NULL; 757 list[j] = 0;
745 758
746 delete [] key; 759 delete [] key;
747 delete [] glb; 760 delete [] glb;
748 delete [] top; 761 delete [] top;
749 delete [] lcl; 762 delete [] lcl;
750 delete [] ffl; 763 delete [] ffl;
751 764
752 return list; 765 return list;
766 }
767
768 int
769 is_text_function_name (const char *s)
770 {
771 symbol_record *sr = global_sym_tab->lookup (s);
772 return (sr && sr->is_text_function ());
773 }
774
775 /*
776 * Help stuff.
777 */
778 help_list *
779 builtin_mapper_functions_help (void)
780 {
781 #if 0
782 int count = 0;
783 builtin_mapper_functions *mfptr;
784
785 mfptr = mapper_functions;
786 while (mfptr->name)
787 {
788 count++;
789 mfptr++;
790 }
791
792 if (count == 0)
793 return 0;
794
795 help_list *hl = new help_list [count+1];
796
797 int i = 0;
798 mfptr = mapper_functions;
799 while (mfptr->name)
800 {
801 hl[i].name = mfptr->name;
802 hl[i].help = mfptr->help_string;
803 i++;
804 mfptr++;
805 }
806
807 hl[count].name = 0;
808 hl[count].help = 0;
809
810 return hl;
811 #endif
812
813 return 0;
814 }
815
816 help_list *
817 builtin_general_functions_help (void)
818 {
819 #if 0
820 int count = 0;
821 builtin_general_functions *gfptr;
822
823 gfptr = general_functions;
824 while (gfptr->name)
825 {
826 count++;
827 gfptr++;
828 }
829
830 if (count == 0)
831 return 0;
832
833 help_list *hl = new help_list [count+1];
834
835 int i = 0;
836 gfptr = general_functions;
837 while (gfptr->name)
838 {
839 hl[i].name = gfptr->name;
840 hl[i].help = gfptr->help_string;
841 i++;
842 gfptr++;
843 }
844
845 hl[count].name = 0;
846 hl[count].help = 0;
847
848 return hl;
849 #endif
850
851 return 0;
852 }
853
854 help_list *
855 builtin_text_functions_help (void)
856 {
857 #if 0
858 int count = 0;
859 builtin_text_functions *tfptr;
860
861 tfptr = text_functions;
862 while (tfptr->name)
863 {
864 count++;
865 tfptr++;
866 }
867
868 if (count == 0)
869 return 0;
870
871 help_list *hl = new help_list [count+1];
872
873 int i = 0;
874 tfptr = text_functions;
875 while (tfptr->name)
876 {
877 hl[i].name = tfptr->name;
878 hl[i].help = tfptr->help_string;
879 i++;
880 tfptr++;
881 }
882
883 hl[count].name = 0;
884 hl[count].help = 0;
885
886 return hl;
887 #endif
888
889 return 0;
890 }
891
892 help_list *
893 builtin_variables_help (void)
894 {
895 #if 0
896 int count = 0;
897
898 builtin_string_variables *svptr;
899
900 svptr = string_variables;
901 while (svptr->name)
902 {
903 count++;
904 svptr++;
905 }
906
907 if (count == 0)
908 return 0;
909
910 help_list *hl = new help_list [count+1];
911
912 int i = 0;
913 svptr = string_variables;
914 while (svptr->name)
915 {
916 hl[i].name = svptr->name;
917 hl[i].help = svptr->help_string;
918 i++;
919 svptr++;
920 }
921
922 hl[count].name = 0;
923 hl[count].help = 0;
924
925 return hl;
926 #endif
927
928 return 0;
929 }
930
931 int
932 help_from_list (ostrstream& output_buf, const help_list *list,
933 const char *string, int usage)
934 {
935 char *name;
936 while ((name = list->name) != 0)
937 {
938 if (strcmp (name, string) == 0)
939 {
940 if (usage)
941 output_buf << "\nusage: ";
942 else
943 {
944 output_buf << "\n*** " << string << ":\n\n";
945 }
946
947 output_buf << list->help << "\n";
948
949 return 1;
950 }
951 list++;
952 }
953 return 0;
954 }
955
956 void
957 additional_help_message (ostrstream& output_buf)
958 {
959 output_buf
960 << "\n"
961 << "Additional help for builtin functions, operators, and variables\n"
962 << "is available in the on-line version of the manual.\n"
963 << "\n"
964 << "Use the command `help -i <topic>' to search the manual index.\n";
965 }
966
967 void
968 print_usage (const char *string, int just_usage)
969 {
970 ostrstream output_buf;
971
972 help_list *gf_help_list = builtin_general_functions_help ();
973 help_list *tf_help_list = builtin_text_functions_help ();
974 help_list *mf_help_list = builtin_mapper_functions_help ();
975
976 if (help_from_list (output_buf, gf_help_list, string, 1)
977 || help_from_list (output_buf, tf_help_list, string, 1)
978 || help_from_list (output_buf, mf_help_list, string, 1))
979 {
980 if (! just_usage)
981 additional_help_message (output_buf);
982 output_buf << ends;
983 maybe_page_output (output_buf);
984 }
985 }
986
987 void
988 install_builtin_variables (void)
989 {
990 // XXX FIXME XX -- these should probably be moved to where they
991 // logically belong instead of being all grouped here.
992
993 DEFVAR ("EDITOR", SBV_EDITOR, editor, 0, 0, 1, sv_editor,
994 "name of the editor to be invoked by the edit_history command");
995
996 DEFVAR ("I", SBV_I, Complex (0.0, 1.0), 0, 1, 1, 0,
997 "sqrt (-1)");
998
999 DEFVAR ("Inf", SBV_Inf, octave_Inf, 0, 1, 1, 0,
1000 "infinity");
1001
1002 DEFVAR ("INFO_FILE", SBV_INFO_FILE, info_file, 0, 0, 1, sv_info_file,
1003 "name of the Octave info file");
1004
1005 DEFVAR ("J", SBV_J, Complex (0.0, 1.0), 0, 1, 1, 0,
1006 "sqrt (-1)");
1007
1008 #if defined (HAVE_ISNAN)
1009 DEFVAR ("NaN", SBV_NaN, octave_NaN, 0, 1, 1, 0,
1010 "not a number");
1011 #endif
1012
1013 DEFVAR ("LOADPATH", SBV_LOADPATH, load_path, 0, 0, 1, sv_loadpath,
1014 "colon separated list of directories to search for scripts");
1015
1016 DEFVAR ("PAGER", SBV_PAGER, default_pager (), 0, 0, 1, sv_pager_binary,
1017 "path to pager binary");
1018
1019 DEFVAR ("PS1", SBV_PS1, "\\s:\\#> ", 0, 0, 1, sv_ps1,
1020 "primary prompt string");
1021
1022 DEFVAR ("PS2", SBV_PS2, "> ", 0, 0, 1, sv_ps2,
1023 "secondary prompt string");
1024
1025 DEFVAR ("PWD", SBV_PWD, get_working_directory ("initialize_globals"),
1026 0, 1, 1, sv_pwd,
1027 "current working directory");
1028
1029 DEFVAR ("SEEK_SET", SBV_SEEK_SET, 0.0, 0, 1, 1, 0,
1030 "used with fseek to position file relative to the beginning");
1031
1032 DEFVAR ("SEEK_CUR", SBV_SEEK_CUR, 1.0, 0, 1, 1, 0,
1033 "used with fseek to position file relative to the current position");
1034
1035 DEFVAR ("SEEK_END", SBV_SEEK_END, 2.0, 0, 1, 1, 0,
1036 "used with fseek to position file relative to the end");
1037
1038 DEFVAR ("ans", SBV_ans, , 0, 0, 1, 0,
1039 "");
1040
1041 DEFVAR ("commas_in_literal_matrix", SBV_commas_in_literal_matrix, "",
1042 0, 0, 1, commas_in_literal_matrix,
1043 "control auto-insertion of commas in literal matrices");
1044
1045 DEFVAR ("do_fortran_indexing", SBV_do_fortran_indexing, "false", 0, 0,
1046 1, do_fortran_indexing,
1047 "allow single indices for matrices");
1048
1049 DEFVAR ("empty_list_elements_ok", SBV_empty_list_elements_ok, "warn",
1050 0, 0, 1, empty_list_elements_ok,
1051 "ignore the empty element in expressions like `a = [[], 1]'");
1052
1053 DEFVAR ("eps", SBV_eps, DBL_EPSILON, 0, 1, 1, 0,
1054 "machine precision");
1055
1056 DEFVAR ("gnuplot_binary", SBV_gnuplot_binary, "gnuplot", 0, 0, 1,
1057 sv_gnuplot_binary,
1058 "path to gnuplot binary");
1059
1060 DEFVAR ("i", SBV_i, Complex (0.0, 1.0), 1, 1, 1, 0,
1061 "sqrt (-1)");
1062
1063 DEFVAR ("ignore_function_time_stamp", SBV_ignore_function_time_stamp,
1064 "system", 0, 0, 1,
1065 ignore_function_time_stamp,
1066 "don't check to see if function files have changed since they were\n\
1067 last compiled. Possible values are \"system\" and \"all\"");
1068
1069 DEFVAR ("implicit_str_to_num_ok", SBV_implicit_str_to_num_ok, "false",
1070 0, 0, 1, implicit_str_to_num_ok,
1071 "allow implicit string to number conversion");
1072
1073 DEFVAR ("inf", SBV_inf, octave_Inf, 0, 1, 1, 0,
1074 "infinity");
1075
1076 DEFVAR ("j", SBV_j, Complex (0.0, 1.0), 1, 1, 1, 0,
1077 "sqrt (-1)");
1078
1079 #if defined (HAVE_ISNAN)
1080 DEFVAR ("nan", SBV_nan, octave_NaN, 0, 1, 1, 0,
1081 "not a number");
1082 #endif
1083
1084 DEFVAR ("ok_to_lose_imaginary_part", SBV_ok_to_lose_imaginary_part,
1085 "warn", 0, 0, 1, ok_to_lose_imaginary_part,
1086 "silently convert from complex to real by dropping imaginary part");
1087
1088 DEFVAR ("output_max_field_width", SBV_output_max_field_width, 10.0, 0,
1089 0, 1, set_output_max_field_width,
1090 "maximum width of an output field for numeric output");
1091
1092 DEFVAR ("output_precision", SBV_output_precision, 5.0, 0, 0, 1,
1093 set_output_precision,
1094 "number of significant figures to display for numeric output");
1095
1096 DEFVAR ("page_screen_output", SBV_page_screen_output, "true", 0, 0, 1,
1097 page_screen_output,
1098 "if possible, send output intended for the screen through the pager");
1099
1100 DEFVAR ("pi", SBV_pi, 4.0 * atan (1.0), 0, 1, 1, 0,
1101 "ratio of the circumference of a circle to its diameter");
1102
1103 DEFVAR ("prefer_column_vectors", SBV_prefer_column_vectors, "true", 0,
1104 0, 1, prefer_column_vectors,
1105 "prefer column/row vectors");
1106
1107 DEFVAR ("prefer_zero_one_indexing", SBV_prefer_zero_one_indexing,
1108 "false", 0, 0, 1, prefer_zero_one_indexing,
1109 "when there is a conflict, prefer zero-one style indexing");
1110
1111 DEFVAR ("print_answer_id_name", SBV_print_answer_id_name, "true", 0,
1112 0, 1, print_answer_id_name,
1113 "set output style to print `var_name = ...'");
1114
1115 DEFVAR ("print_empty_dimensions", SBV_print_empty_dimensions, "true",
1116 0, 0, 1, print_empty_dimensions,
1117 "also print dimensions of empty matrices");
1118
1119 DEFVAR ("propagate_empty_matrices", SBV_propagate_empty_matrices,
1120 "true", 0, 0, 1, propagate_empty_matrices,
1121 "operations on empty matrices return an empty matrix, not an error");
1122
1123 DEFVAR ("resize_on_range_error", SBV_resize_on_range_error, "true", 0,
1124 0, 1, resize_on_range_error,
1125 "enlarge matrices on assignment");
1126
1127 DEFVAR ("return_last_computed_value", SBV_return_last_computed_value,
1128 "false", 0, 0, 1,
1129 return_last_computed_value,
1130 "if a function does not return any values explicitly, return the\n\
1131 last computed value");
1132
1133 DEFVAR ("save_precision", SBV_save_precision, 17.0, 0, 0, 1,
1134 set_save_precision,
1135 "number of significant figures kept by the ASCII save command");
1136
1137 DEFVAR ("silent_functions", SBV_silent_functions, "false", 0, 0, 1,
1138 silent_functions,
1139 "suppress printing results in called functions");
1140
1141 DEFVAR ("split_long_rows", SBV_split_long_rows, "true", 0, 0, 1,
1142 split_long_rows,
1143 "split long matrix rows instead of wrapping");
1144
1145 DEFVAR ("stdin", SBV_stdin, 0.0, 0, 1, 1, 0,
1146 "file number of the standard input stream");
1147
1148 DEFVAR ("stdout", SBV_stdout, 1.0, 0, 1, 1, 0,
1149 "file number of the standard output stream");
1150
1151 DEFVAR ("stderr", SBV_stderr, 2.0, 0, 1, 1, 0,
1152 "file number of the standard error stream");
1153
1154 DEFVAR ("treat_neg_dim_as_zero", SBV_treat_neg_dim_as_zero, "false",
1155 0, 0, 1, treat_neg_dim_as_zero,
1156 "convert negative dimensions to zero");
1157
1158 DEFVAR ("warn_assign_as_truth_value", SBV_warn_assign_as_truth_value,
1159 "true", 0, 0, 1,
1160 warn_assign_as_truth_value,
1161 "produce warning for assignments used as truth values");
1162
1163 DEFVAR ("warn_comma_in_global_decl", SBV_warn_comma_in_global_decl,
1164 "true", 0, 0, 1, warn_comma_in_global_decl,
1165 "produce warning for commas in global declarations");
1166
1167 DEFVAR ("warn_divide_by_zero", SBV_warn_divide_by_zero, "true", 0, 0,
1168 1, warn_divide_by_zero,
1169 "on IEEE machines, allow divide by zero errors to be suppressed");
1170 }
1171
1172 /*
1173 * List variable names.
1174 */
1175 static void
1176 print_symbol_info_line (ostrstream& output_buf, const symbol_record_info& s)
1177 {
1178 output_buf << (s.is_read_only () ? " -" : " w");
1179 output_buf << (s.is_eternal () ? "- " : "d ");
1180 #if 0
1181 output_buf << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-"));
1182 #endif
1183 output_buf.form (" %-16s", s.type_as_string ());
1184 if (s.is_function ())
1185 output_buf << " - -";
1186 else
1187 {
1188 output_buf.form ("%7d", s.rows ());
1189 output_buf.form ("%7d", s.columns ());
1190 }
1191 output_buf << " " << s.name () << "\n";
1192 }
1193
1194 static void
1195 print_long_listing (ostrstream& output_buf, symbol_record_info *s)
1196 {
1197 if (! s)
1198 return;
1199
1200 symbol_record_info *ptr = s;
1201 while (ptr->is_defined ())
1202 {
1203 print_symbol_info_line (output_buf, *ptr);
1204 ptr++;
1205 }
1206 }
1207
1208 static int
1209 maybe_list (const char *header, ostrstream& output_buf,
1210 int show_verbose, symbol_table *sym_tab, unsigned type,
1211 unsigned scope)
1212 {
1213 int count;
1214 int status = 0;
1215 if (show_verbose)
1216 {
1217 symbol_record_info *symbols;
1218 symbols = sym_tab->long_list (count, 1, type, scope);
1219 if (symbols && count > 0)
1220 {
1221 output_buf << "\n" << header << "\n\n"
1222 << "prot type rows cols name\n"
1223 << "==== ==== ==== ==== ====\n";
1224
1225 print_long_listing (output_buf, symbols);
1226 status = 1;
1227 }
1228 delete [] symbols;
1229 }
1230 else
1231 {
1232 char **symbols = sym_tab->list (count, 1, type, scope);
1233 if (symbols && count > 0)
1234 {
1235 output_buf << "\n" << header << "\n\n";
1236 list_in_columns (output_buf, symbols);
1237 status = 1;
1238 }
1239 delete [] symbols;
1240 }
1241 return status;
1242 }
1243
1244 DEFUN_TEXT ("clear", Fclear, Sclear, -1, 1,
1245 "clear [name ...]\n\
1246 \n\
1247 clear symbol(s) matching a list of globbing patterns\n\
1248 if no arguments are given, clear all user-defined variables and functions")
1249 {
1250 Octave_object retval;
1251
1252 DEFINE_ARGV("clear");
1253
1254 // Always clear the local table, but don't clear currently compiled
1255 // functions unless we are at the top level. (Allowing that to happen
1256 // inside functions would result in pretty odd behavior...)
1257
1258 int clear_user_functions = (curr_sym_tab == top_level_sym_tab);
1259
1260 if (argc == 1)
1261 {
1262 curr_sym_tab->clear ();
1263 global_sym_tab->clear (clear_user_functions);
1264 }
1265 else
1266 {
1267 int lcount;
1268 char **lvars = curr_sym_tab->list (lcount, 0,
1269 symbol_def::USER_VARIABLE,
1270 SYMTAB_LOCAL_SCOPE);
1271 int gcount;
1272 char **gvars = curr_sym_tab->list (gcount, 0,
1273 symbol_def::USER_VARIABLE,
1274 SYMTAB_GLOBAL_SCOPE);
1275 int fcount;
1276 char **fcns = curr_sym_tab->list (fcount, 0,
1277 symbol_def::USER_FUNCTION,
1278 SYMTAB_ALL_SCOPES);
1279
1280 while (--argc > 0)
1281 {
1282 argv++;
1283 if (*argv)
1284 {
1285 int i;
1286 for (i = 0; i < lcount; i++)
1287 {
1288 if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0)
1289 curr_sym_tab->clear (lvars[i]);
1290 }
1291
1292 int count;
1293 for (i = 0; i < gcount; i++)
1294 {
1295 if (fnmatch (*argv, gvars[i], __FNM_FLAGS) == 0)
1296 {
1297 count = curr_sym_tab->clear (gvars[i]);
1298 if (count > 0)
1299 global_sym_tab->clear (gvars[i], clear_user_functions);
1300 }
1301 }
1302
1303 for (i = 0; i < fcount; i++)
1304 {
1305 if (fnmatch (*argv, fcns[i], __FNM_FLAGS) == 0)
1306 {
1307 count = curr_sym_tab->clear (fcns[i]);
1308 if (count > 0)
1309 global_sym_tab->clear (fcns[i], clear_user_functions);
1310 }
1311 }
1312 }
1313 }
1314
1315 delete [] lvars;
1316 delete [] gvars;
1317 delete [] fcns;
1318
1319 }
1320
1321 DELETE_ARGV;
1322
1323 return retval;
1324 }
1325
1326 DEFUN_TEXT ("document", Fdocument, Sdocument, -1, 1,
1327 "document symbol string ...\n\
1328 \n\
1329 Associate a cryptic message with a variable name.")
1330 {
1331 Octave_object retval;
1332
1333 DEFINE_ARGV("document");
1334
1335 if (argc == 3)
1336 document_symbol (argv[1], argv[2]);
1337 else
1338 print_usage ("document");
1339
1340 DELETE_ARGV;
1341
1342 return retval;
1343 }
1344
1345 static int
1346 load_variable (char *nm, int force, istream& is)
1347 {
1348 // Is there already a symbol by this name? If so, what is it?
1349
1350 symbol_record *lsr = curr_sym_tab->lookup (nm, 0, 0);
1351
1352 int is_undefined = 1;
1353 int is_variable = 0;
1354 int is_function = 0;
1355 int is_global = 0;
1356
1357 if (lsr)
1358 {
1359 is_undefined = ! lsr->is_defined ();
1360 is_variable = lsr->is_variable ();
1361 is_function = lsr->is_function ();
1362 is_global = lsr->is_linked_to_global ();
1363 }
1364
1365 // Try to read data for this name.
1366
1367 tree_constant tc;
1368 int global = tc.load (is);
1369
1370 if (tc.const_type () == tree_constant_rep::unknown_constant)
1371 {
1372 error ("load: unable to load variable `%s'", nm);
1373 return 0;
1374 }
1375
1376 symbol_record *sr = 0;
1377
1378 if (global)
1379 {
1380 if (is_global || is_undefined)
1381 {
1382 if (force || is_undefined)
1383 {
1384 lsr = curr_sym_tab->lookup (nm, 1, 0);
1385 link_to_global_variable (lsr);
1386 sr = lsr;
1387 }
1388 else
1389 {
1390 warning ("load: global variable name `%s' exists.", nm);
1391 warning ("use `load -force' to overwrite");
1392 }
1393 }
1394 else if (is_function)
1395 {
1396 if (force)
1397 {
1398 lsr = curr_sym_tab->lookup (nm, 1, 0);
1399 link_to_global_variable (lsr);
1400 sr = lsr;
1401 }
1402 else
1403 {
1404 warning ("load: `%s' is currently a function in this scope", nm);
1405 warning ("`load -force' will load variable and hide function");
1406 }
1407 }
1408 else if (is_variable)
1409 {
1410 if (force)
1411 {
1412 lsr = curr_sym_tab->lookup (nm, 1, 0);
1413 link_to_global_variable (lsr);
1414 sr = lsr;
1415 }
1416 else
1417 {
1418 warning ("load: local variable name `%s' exists.", nm);
1419 warning ("use `load -force' to overwrite");
1420 }
1421 }
1422 else
1423 panic_impossible ();
1424 }
1425 else
1426 {
1427 if (is_global)
1428 {
1429 if (force || is_undefined)
1430 {
1431 lsr = curr_sym_tab->lookup (nm, 1, 0);
1432 link_to_global_variable (lsr);
1433 sr = lsr;
1434 }
1435 else
1436 {
1437 warning ("load: global variable name `%s' exists.", nm);
1438 warning ("use `load -force' to overwrite");
1439 }
1440 }
1441 else if (is_function)
1442 {
1443 if (force)
1444 {
1445 lsr = curr_sym_tab->lookup (nm, 1, 0);
1446 link_to_global_variable (lsr);
1447 sr = lsr;
1448 }
1449 else
1450 {
1451 warning ("load: `%s' is currently a function in this scope", nm);
1452 warning ("`load -force' will load variable and hide function");
1453 }
1454 }
1455 else if (is_variable || is_undefined)
1456 {
1457 if (force || is_undefined)
1458 {
1459 lsr = curr_sym_tab->lookup (nm, 1, 0);
1460 sr = lsr;
1461 }
1462 else
1463 {
1464 warning ("load: local variable name `%s' exists.", nm);
1465 warning ("use `load -force' to overwrite");
1466 }
1467 }
1468 else
1469 panic_impossible ();
1470 }
1471
1472 if (sr)
1473 {
1474 tree_constant *tmp_tc = new tree_constant (tc);
1475 sr->define (tmp_tc);
1476 return 1;
1477 }
1478 else
1479 error ("load: unable to load variable `%s'", nm);
1480
1481 return 0;
1482 }
1483
1484 DEFUN_TEXT ("load", Fload, Sload, -1, 1,
1485 "load [-force] file\n
1486 \n\
1487 load variables from a file")
1488 {
1489 Octave_object retval;
1490
1491 DEFINE_ARGV("load");
1492
1493 argc--;
1494 argv++;
1495
1496 int force = 0;
1497 if (argc > 0 && strcmp (*argv, "-force") == 0)
1498 {
1499 force++;
1500 argc--;
1501 argv++;
1502 }
1503
1504 if (argc < 1)
1505 {
1506 error ("load: you must specify a single file to read");
1507 DELETE_ARGV;
1508 return retval;
1509 }
1510
1511 static istream stream;
1512 static ifstream file;
1513 if (strcmp (*argv, "-") == 0)
1514 {
1515 stream = cin;
1516 }
1517 else
1518 {
1519 char *fname = tilde_expand (*argv);
1520 file.open (fname);
1521 if (! file)
1522 {
1523 error ("load: couldn't open input file `%s'", *argv);
1524 DELETE_ARGV;
1525 return retval;
1526 }
1527 stream = file;
1528 }
1529
1530 int count = 0;
1531 char *nm = 0;
1532 for (;;)
1533 {
1534 // Read name for this entry or break on EOF.
1535 delete [] nm;
1536 nm = extract_keyword (stream, "name");
1537 if (nm)
1538 count++;
1539 else
1540 {
1541 if (count == 0)
1542 {
1543 error ("load: no name keywords found in file `%s'", *argv);
1544 error ("Are you sure this is an octave data file?");
1545 }
1546 break;
1547 }
1548
1549 if (! *nm)
1550 continue;
1551
1552 if (! valid_identifier (nm))
1553 {
1554 warning ("load: skipping bogus identifier `%s'");
1555 continue;
1556 }
1557
1558 load_variable (nm, force, stream);
1559
1560 if (error_state)
1561 {
1562 error ("reading file %s", *argv);
1563 break;
1564 }
1565 }
1566
1567 if (file);
1568 file.close ();
1569
1570 DELETE_ARGV;
1571
1572 return retval;
1573 }
1574
1575 /*
1576 * Return nonzero if PATTERN has any special globbing chars in it.
1577 */
1578 static int
1579 glob_pattern_p (char *pattern)
1580 {
1581 char *p = pattern;
1582 char c;
1583 int open = 0;
1584
1585 while ((c = *p++) != '\0')
1586 {
1587 switch (c)
1588 {
1589 case '?':
1590 case '*':
1591 return 1;
1592
1593 case '[': // Only accept an open brace if there is a close
1594 open++; // brace to match it. Bracket expressions must be
1595 continue; // complete, according to Posix.2
1596
1597 case ']':
1598 if (open)
1599 return 1;
1600 continue;
1601
1602 case '\\':
1603 if (*p++ == '\0')
1604 return 0;
1605
1606 default:
1607 continue;
1608 }
1609 }
1610
1611 return 0;
1612 }
1613
1614 DEFUN_TEXT ("save", Fsave, Ssave, -1, 1,
1615 "save file [var ...]\n\
1616 \n\
1617 save variables in a file")
1618 {
1619 Octave_object retval;
1620
1621 #if 0
1622 DEFINE_ARGV("save");
1623
1624 if (argc < 2)
1625 {
1626 print_usage ("save");
1627 DELETE_ARGV;
1628 return retval;
1629 }
1630
1631 argc--;
1632 argv++;
1633
1634 static ostream stream;
1635 static ofstream file;
1636 if (strcmp (*argv, "-") == 0)
1637 {
1638 // XXX FIXME XXX -- should things intended for the screen end up in a
1639 // tree_constant (string)?
1640 stream = cout;
1641 }
1642 else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things
1643 { // like `save a*',
1644 print_usage ("save"); // which are probably
1645 DELETE_ARGV; // mistakes...
1646 return retval;
1647 }
1648 else
1649 {
1650 char *fname = tilde_expand (*argv);
1651 file.open (fname);
1652 if (! file)
1653 {
1654 error ("save: couldn't open output file `%s'", *argv);
1655 DELETE_ARGV;
1656 return retval;
1657 }
1658 stream = file;
1659
1660 }
1661
1662 int prec = user_pref.save_precision;
1663
1664 if (argc == 1)
1665 {
1666 int count;
1667 char **vars = curr_sym_tab->list (count, 0,
1668 symbol_def::USER_VARIABLE,
1669 SYMTAB_ALL_SCOPES);
1670
1671 for (int i = 0; i < count; i++)
1672 curr_sym_tab->save (stream, vars[i],
1673 is_globally_visible (vars[i]), prec);
1674
1675 delete [] vars;
1676 }
1677 else
1678 {
1679 while (--argc > 0)
1680 {
1681 argv++;
1682
1683 int count;
1684 char **lvars = curr_sym_tab->list (count, 0,
1685 symbol_def::USER_VARIABLE);
1686
1687 int saved_or_error = 0;
1688 int i;
1689 for (i = 0; i < count; i++)
1690 {
1691 if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0
1692 && curr_sym_tab->save (stream, lvars[i],
1693 is_globally_visible (lvars[i]),
1694 prec) != 0)
1695 saved_or_error++;
1696 }
1697
1698 char **bvars = global_sym_tab->list (count, 0,
1699 symbol_def::BUILTIN_VARIABLE);
1700
1701 for (i = 0; i < count; i++)
1702 {
1703 if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0
1704 && global_sym_tab->save (stream, bvars[i], 0, prec) != 0)
1705 saved_or_error++;
1706 }
1707
1708 delete [] lvars;
1709 delete [] bvars;
1710
1711 if (! saved_or_error)
1712 warning ("save: no such variable `%s'", *argv);
1713 }
1714 }
1715
1716 if (file);
1717 file.close ();
1718
1719 DELETE_ARGV;
1720 #endif
1721
1722 return retval;
1723 }
1724
1725 DEFUN_TEXT ("who", Fwho, Swho, -1, 1,
1726 "who [-all] [-builtins] [-functions] [-long] [-variables]\n\
1727 \n\
1728 List currently defined symbol(s). Options may be shortened to one\n\
1729 character, but may not be combined.")
1730 {
1731 Octave_object retval;
1732
1733 DEFINE_ARGV("who");
1734
1735 int show_builtins = 0;
1736 int show_functions = (curr_sym_tab == top_level_sym_tab);
1737 int show_variables = 1;
1738 int show_verbose = 0;
1739
1740 if (argc > 1)
1741 {
1742 show_functions = 0;
1743 show_variables = 0;
1744 }
1745
1746 for (int i = 1; i < argc; i++)
1747 {
1748 argv++;
1749 if (strcmp (*argv, "-all") == 0 || strcmp (*argv, "-a") == 0)
1750 {
1751 show_builtins++;
1752 show_functions++;
1753 show_variables++;
1754 }
1755 else if (strcmp (*argv, "-builtins") == 0
1756 || strcmp (*argv, "-b") == 0)
1757 show_builtins++;
1758 else if (strcmp (*argv, "-functions") == 0
1759 || strcmp (*argv, "-f") == 0)
1760 show_functions++;
1761 else if (strcmp (*argv, "-long") == 0
1762 || strcmp (*argv, "-l") == 0)
1763 show_verbose++;
1764 else if (strcmp (*argv, "-variables") == 0
1765 || strcmp (*argv, "-v") == 0)
1766 show_variables++;
1767 else
1768 warning ("who: unrecognized option `%s'", *argv);
1769 }
1770
1771 // If the user specified -l and nothing else, show variables. If
1772 // evaluating this at the top level, also show functions.
1773
1774 if (show_verbose && ! (show_builtins || show_functions || show_variables))
1775 {
1776 show_functions = (curr_sym_tab == top_level_sym_tab);
1777 show_variables = 1;
1778 }
1779
1780 ostrstream output_buf;
1781 int pad_after = 0;
1782
1783 if (show_builtins)
1784 {
1785 pad_after += maybe_list ("*** built-in variables:",
1786 output_buf, show_verbose, global_sym_tab,
1787 symbol_def::BUILTIN_VARIABLE,
1788 SYMTAB_ALL_SCOPES);
1789
1790 pad_after += maybe_list ("*** built-in functions:",
1791 output_buf, show_verbose, global_sym_tab,
1792 symbol_def::BUILTIN_FUNCTION,
1793 SYMTAB_ALL_SCOPES);
1794 }
1795
1796 if (show_functions)
1797 {
1798 pad_after += maybe_list ("*** currently compiled functions:",
1799 output_buf, show_verbose, global_sym_tab,
1800 symbol_def::USER_FUNCTION,
1801 SYMTAB_ALL_SCOPES);
1802 }
1803
1804 if (show_variables)
1805 {
1806 pad_after += maybe_list ("*** local user variables:",
1807 output_buf, show_verbose, curr_sym_tab,
1808 symbol_def::USER_VARIABLE,
1809 SYMTAB_LOCAL_SCOPE);
1810
1811 pad_after += maybe_list ("*** globally visible user variables:",
1812 output_buf, show_verbose, curr_sym_tab,
1813 symbol_def::USER_VARIABLE,
1814 SYMTAB_GLOBAL_SCOPE);
1815 }
1816
1817 if (pad_after)
1818 output_buf << "\n";
1819
1820 output_buf << ends;
1821 maybe_page_output (output_buf);
1822
1823 DELETE_ARGV;
1824
1825 return retval;
1826 }
1827
1828 // XXX FIXME XXX -- should these really be here?
1829
1830 char *
1831 octave_home (void)
1832 {
1833 #ifdef RUN_IN_PLACE
1834 static char *home = OCTAVE_HOME;
1835 return home;
1836 #else
1837 static char *home = 0;
1838 delete [] home;
1839 char *oh = getenv ("OCTAVE_HOME");
1840 if (oh)
1841 home = strsave (oh);
1842 else
1843 home = strsave (OCTAVE_HOME);
1844 return home;
1845 #endif
1846 }
1847
1848 char *
1849 octave_lib_dir (void)
1850 {
1851 #ifdef RUN_IN_PLACE
1852 static char *ol = OCTAVE_LIB_DIR;
1853 return ol;
1854 #else
1855 static char *ol = 0;
1856 delete [] ol;
1857 char *oh = octave_home ();
1858 char *tmp = strconcat (oh, "/lib/octave/");
1859 ol = strconcat (tmp, version_string);
1860 delete [] tmp;
1861 return ol;
1862 #endif
1863 }
1864
1865 char *
1866 octave_info_dir (void)
1867 {
1868 #ifdef RUN_IN_PLACE
1869 static char *oi = OCTAVE_INFO_DIR;
1870 return oi;
1871 #else
1872 static char *oi = 0;
1873 delete [] oi;
1874 char *oh = octave_home ();
1875 oi = strconcat (oh, "/info/");
1876 return oi;
1877 #endif
1878 }
1879
1880 /*
1881 * Handle OCTAVE_PATH from the environment like TeX handles TEXINPUTS.
1882 * If the path starts with `:', prepend the standard path. If it ends
1883 * with `:' append the standard path. If it begins and ends with
1884 * `:', do both (which is useless, but the luser asked for it...).
1885 *
1886 * This function may eventually be called more than once, so be
1887 * careful not to create memory leaks.
1888 */
1889 char *
1890 default_path (void)
1891 {
1892 static char *pathstring = 0;
1893 delete [] pathstring;
1894
1895 static char *std_path = 0;
1896 delete [] std_path;
1897
1898 char *libdir = octave_lib_dir ();
1899
1900 std_path = strconcat (".:", libdir);
1901
1902 char *oct_path = getenv ("OCTAVE_PATH");
1903
1904 if (oct_path)
1905 {
1906 pathstring = strsave (oct_path);
1907
1908 if (pathstring[0] == ':')
1909 {
1910 char *tmp = pathstring;
1911 pathstring = strconcat (std_path, pathstring);
1912 delete [] tmp;
1913 }
1914
1915 int tmp_len = strlen (pathstring);
1916 if (pathstring[tmp_len-1] == ':')
1917 {
1918 char *tmp = pathstring;
1919 pathstring = strconcat (pathstring, std_path);
1920 delete [] tmp;
1921 }
1922 }
1923 else
1924 pathstring = strsave (std_path);
1925
1926 return pathstring;
1927 }
1928
1929 char *
1930 default_info_file (void)
1931 {
1932 static char *info_file_string = 0;
1933 delete [] info_file_string;
1934 char *oct_info_file = getenv ("OCTAVE_INFO_FILE");
1935 if (oct_info_file)
1936 info_file_string = strsave (oct_info_file);
1937 else
1938 {
1939 char *infodir = octave_info_dir ();
1940 info_file_string = strconcat (infodir, "/octave.info");
1941 }
1942 return info_file_string;
1943 }
1944
1945 char *
1946 default_editor (void)
1947 {
1948 static char *editor_string = 0;
1949 delete [] editor_string;
1950 char *env_editor = getenv ("EDITOR");
1951 if (env_editor && *env_editor)
1952 editor_string = strsave (env_editor);
1953 else
1954 editor_string = strsave ("vi");
1955 return editor_string;
1956 }
1957
1958 char *
1959 get_site_defaults (void)
1960 {
1961 static char *sd = 0;
1962 delete [] sd;
1963 char *libdir = octave_lib_dir ();
1964 sd = strconcat (libdir, "/octaverc");
1965 return sd;
1966 }
1967
1968 char *
1969 default_pager (void)
1970 {
1971 static char *pager_binary = 0;
1972 delete [] pager_binary;
1973 char *pgr = getenv ("PAGER");
1974 if (pgr)
1975 pager_binary = strsave (pgr);
1976 else
1977 #ifdef DEFAULT_PAGER
1978 pager_binary = strsave (DEFAULT_PAGER);
1979 #else
1980 pager_binary = strsave ("");
1981 #endif
1982
1983 return pager_binary;
753 } 1984 }
754 1985
755 /* 1986 /*
756 ;;; Local Variables: *** 1987 ;;; Local Variables: ***
757 ;;; mode: C++ *** 1988 ;;; mode: C++ ***