Mercurial > hg > octave-nkf
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++ *** |