comparison src/utils.cc @ 1:78fd87e624cb

[project @ 1993-08-08 01:13:40 by jwe] Initial revision
author jwe
date Sun, 08 Aug 1993 01:13:40 +0000
parents
children a2db6687354d
comparison
equal deleted inserted replaced
0:22412e3a4641 1:78fd87e624cb
1 // utils.cc -*- C++ -*-
2 /*
3
4 Copyright (C) 1992, 1993 John W. Eaton
5
6 This file is part of Octave.
7
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, write to the Free
20 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 /*
25
26 The 11 functions listed below were adapted from a similar functions
27 from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991
28 Free Software Foundation, Inc.
29
30 polite_directory_format absolute_pathname
31 absolute_program base_pathname
32 read_octal sub_append_string
33 decode_prompt_string pathname_backup
34 make_absolute get_working_directory
35 change_to_directory
36
37 */
38
39 #ifdef __GNUG__
40 #pragma implementation
41 #endif
42
43 #include <sys/types.h>
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 #include <sys/param.h>
48 #include <setjmp.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <time.h>
53 #include <math.h>
54 #include <limits.h>
55 #include <iostream.h>
56 #include <strstream.h>
57 #include <fstream.h>
58 #include <dirent.h>
59
60 #define NLENGTH(dirent) (strlen((dirent)->d_name))
61
62 #ifdef HAVE_TERMIO_H
63 #include <termio.h>
64 #else
65 #ifdef HAVE_SGTTY_H
66 #include <sgtty.h>
67 #else
68 LOSE! LOSE!
69 #endif
70 #endif
71
72 extern "C"
73 {
74 extern int ioctl (int, int, ...);
75 char *tilde_expand (char *s); /* From readline's tilde.c */
76 }
77
78 #include "SLStack.h"
79
80 #include "statdefs.h"
81 #include "procstream.h"
82 #include "user-prefs.h"
83 #include "variables.h"
84 #include "error.h"
85 #include "utils.h"
86 #include "octave.h"
87 #include "mappers.h"
88 #include "version.h"
89 #include "tree-const.h"
90 #include "unwind-prot.h"
91 #include "octave-hist.h"
92
93 // Top level context (?)
94 extern jmp_buf toplevel;
95
96 // Pipe to gnuplot.
97 static oprocstream plot_stream;
98
99 // Non-zero means follow symbolic links that point to directories just
100 // as if they are real directories.
101 static int follow_symbolic_links = 1;
102
103 #ifndef MAXPATHLEN
104 #define MAXPATHLEN 1024
105 #endif
106
107 // The size that strings change by.
108 #ifndef DEFAULT_ARRAY_SIZE
109 #define DEFAULT_ARRAY_SIZE 512
110 #endif
111
112 // The growth rate for the prompt string.
113 #ifndef PROMPT_GROWTH
114 #define PROMPT_GROWTH 50
115 #endif
116
117 #ifndef MAX
118 #define MAX(a,b) ((a) > (b) ? (a) : (b))
119 #endif
120
121 #ifndef MIN
122 #define MIN(a,b) ((a) < (b) ? (a) : (b))
123 #endif
124
125 // Where to find the site-wide configuration file
126 #ifndef OCTAVE_HOME
127 #define OCTAVE_HOME "/usr/local"
128 #endif
129
130 // Temp storage for a path.
131 static char tdir[MAXPATHLEN];
132
133 // List of files to delete when we exit or crash.
134 static SLStack <char *> tmp_files;
135
136 /*
137 * Save a string.
138 */
139 char *
140 strsave (const char *s)
141 {
142 if (s == (char *) NULL)
143 return (char *) NULL;
144
145 int len = strlen (s);
146 char *tmp = new char [len+1];
147 tmp = strcpy (tmp, s);
148 return tmp;
149 }
150
151 /*
152 * Concatenate two strings.
153 */
154 char *
155 strconcat (const char *s, const char *t)
156 {
157 int len = strlen (s) + strlen (t);
158 char *tmp = new char [len+1];
159 strcpy (tmp, s);
160 return strcat (tmp, t);
161 }
162
163 /*
164 * Throw away input until a given character is read.
165 */
166 void
167 discard_until (istream& stream, char character)
168 {
169 int c;
170 for (;;)
171 {
172 stream >> c;
173 if (c == EOF || c == character)
174 break;
175 }
176 if (c != EOF)
177 stream.putback ((char) c);
178 }
179
180 void
181 check_dimensions (int& nr, int& nc, char *warnfor)
182 {
183 if (nr < 0 || nc < 0)
184 {
185 if (user_pref.treat_neg_dim_as_zero)
186 nr = nc = 0;
187 else
188 {
189 message (warnfor, "can't create a matrix with negative dimensions");
190 jump_to_top_level ();
191 }
192 }
193 }
194
195 /*
196 * Set terminal in raw mode. From less-177.
197 *
198 * Change terminal to "raw mode", or restore to "normal" mode.
199 * "Raw mode" means
200 * 1. An outstanding read will complete on receipt of a single keystroke.
201 * 2. Input is not echoed.
202 * 3. On output, \n is mapped to \r\n.
203 * 4. \t is NOT expanded into spaces.
204 * 5. Signal-causing characters such as ctrl-C (interrupt),
205 * etc. are NOT disabled.
206 * It doesn't matter whether an input \n is mapped to \r, or vice versa.
207 */
208 void
209 raw_mode (int on)
210 {
211 static int curr_on = 0;
212
213 // HACK! HACK!
214
215 int tty_fd = 1;
216
217 if (on == curr_on)
218 return;
219
220 #ifdef HAVE_TERMIO_H
221 {
222 struct termio s;
223 static struct termio save_term;
224
225 if (on)
226 {
227 // Get terminal modes.
228
229 ioctl(tty_fd, TCGETA, &s);
230
231 // Save modes and set certain variables dependent on modes.
232
233 save_term = s;
234 // ospeed = s.c_cflag & CBAUD;
235 // erase_char = s.c_cc[VERASE];
236 // kill_char = s.c_cc[VKILL];
237
238 // Set the modes to the way we want them.
239
240 s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
241 s.c_oflag |= (OPOST|ONLCR|TAB3);
242 s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
243 s.c_cc[VMIN] = 1;
244 s.c_cc[VTIME] = 0;
245 }
246 else
247 {
248 // Restore saved modes.
249 s = save_term;
250 }
251 ioctl(tty_fd, TCSETAW, &s);
252 }
253 #else
254 #ifdef HAVE_SGTTY_H
255 {
256 struct sgttyb s;
257 static struct sgttyb save_term;
258
259 if (on)
260 {
261 // Get terminal modes.
262
263 ioctl(tty_fd, TIOCGETP, &s);
264
265 // Save modes and set certain variables dependent on modes.
266
267 save_term = s;
268 // ospeed = s.sg_ospeed;
269 // erase_char = s.sg_erase;
270 // kill_char = s.sg_kill;
271
272 // Set the modes to the way we want them.
273
274 s.sg_flags |= CBREAK;
275 s.sg_flags &= ~(ECHO|XTABS);
276 }
277 else
278 {
279 // Restore saved modes.
280 s = save_term;
281 }
282 ioctl(tty_fd, TIOCSETN, &s);
283 }
284 #else
285 LOSE! LOSE!
286 #endif
287 #endif
288
289 curr_on = on;
290 }
291
292 /*
293 * Read one character from the terminal.
294 */
295 int
296 kbhit (void)
297 {
298 int c;
299 raw_mode (1);
300 c = cin.get ();
301 raw_mode (0);
302 return c;
303 }
304
305 char **
306 pathstring_to_vector (char *pathstring)
307 {
308 static char **path = (char **) NULL;
309
310 if (pathstring != (char *) NULL)
311 {
312 int nelem = 0;
313 pathstring = strsave (pathstring);
314 if (*pathstring != '\0')
315 {
316 nelem++;
317 char *ptr = pathstring;
318 while (*ptr != '\0')
319 {
320 if (*ptr == ':')
321 nelem++;
322 ptr++;
323 }
324 }
325
326 delete [] path;
327 path = new char * [nelem+1];
328 path[nelem] = (char *) NULL;
329
330 int i = 0;
331 char *ptr = pathstring;
332 while (i < nelem)
333 {
334 char *end = strchr (ptr, ':');
335 if (end != (char *) NULL)
336 *end = '\0';
337 char *result = tilde_expand (ptr);
338 path[i] = strsave (result);
339 free (result);
340 ptr = end + 1;
341 i++;
342 }
343
344 delete [] pathstring;
345 }
346
347 return path;
348 }
349
350 static char *
351 octave_home (void)
352 {
353 static char *home = (char *) NULL;
354 delete [] home;
355 char *oh = getenv ("OCTAVE_HOME");
356 if (oh != (char *) NULL)
357 home = strsave (oh);
358 else
359 home = strsave (OCTAVE_HOME);
360 return home;
361 }
362
363 static char *
364 octave_lib_dir (void)
365 {
366 static char *ol = (char *) NULL;
367 delete [] ol;
368 char *oh = octave_home ();
369 char *tmp = strconcat (oh, "/lib/octave/");
370 ol = strconcat (tmp, version_string);
371 return ol;
372 }
373
374 char *
375 default_path (void)
376 {
377 static char *pathstring = (char *) NULL;
378 delete [] pathstring;
379 char *oct_path = getenv ("OCTAVE_PATH");
380 if (oct_path != (char *) NULL)
381 pathstring = strsave (oct_path);
382 else
383 {
384 char *libdir = octave_lib_dir ();
385 pathstring = strconcat (".:", libdir);
386 }
387 return pathstring;
388 }
389
390 char *
391 get_site_defaults (void)
392 {
393 static char *sd = (char *) NULL;
394 delete [] sd;
395 char *libdir = octave_lib_dir ();
396 sd = strconcat (libdir, "/octaverc");
397 return sd;
398 }
399
400 char *
401 default_pager (void)
402 {
403 static char *pager_binary = (char *) NULL;
404 delete [] pager_binary;
405 char *pgr = getenv ("PAGER");
406 if (pgr != (char *) NULL)
407 pager_binary = strsave (pgr);
408 else
409 #ifdef DEFAULT_PAGER
410 pager_binary = strsave (DEFAULT_PAGER);
411 #else
412 pager_binary = strsave ("");
413 #endif
414
415 return pager_binary;
416 }
417
418 /*
419 * See if the given file is in the path.
420 */
421 char *
422 file_in_path (char *name, char *suffix)
423 {
424 char *nm = strconcat ("/", name);
425 char *tmp = nm;
426 if (suffix != (char *) NULL)
427 {
428 nm = strconcat (tmp, suffix);
429 delete [] tmp;
430 }
431
432 if (!the_current_working_directory)
433 get_working_directory ("file_in_path");
434
435 char **path = pathstring_to_vector (user_pref.loadpath);
436
437 char **ptr = path;
438 if (ptr != (char **) NULL)
439 {
440 while (*ptr != (char *) NULL)
441 {
442 char *tmp_p = strconcat (*ptr, nm);
443 char *p = make_absolute (tmp_p, the_current_working_directory);
444 delete [] tmp_p;
445 ifstream in_file (p);
446 if (in_file)
447 {
448 in_file.close ();
449 delete [] nm;
450 return p;
451 }
452 delete [] p;
453 ptr++;
454 }
455 }
456
457 delete [] nm;
458 return (char *) NULL;
459 }
460
461 /*
462 * See if there is an M-file in the path. If so, return the full path
463 * to the file.
464 */
465 char *
466 m_file_in_path (char *name)
467 {
468 return file_in_path (name, ".m");
469 }
470
471 /*
472 * Return a pretty pathname. If the first part of the pathname is the
473 * same as $HOME, then replace that with `~'.
474 */
475 char *
476 polite_directory_format (char *name)
477 {
478 int l = home_directory ? strlen (home_directory) : 0;
479
480 if (l > 1 && strncmp (home_directory, name, l) == 0
481 && (!name[l] || name[l] == '/'))
482 {
483 strcpy (tdir + 1, name + l);
484 tdir[0] = '~';
485 return (tdir);
486 }
487 else
488 return name;
489 }
490
491 /*
492 * Return 1 if STRING contains an absolute pathname, else 0.
493 */
494 int
495 absolute_pathname (char *string)
496 {
497 if (!string || !*string)
498 return 0;
499
500 if (*string == '/')
501 return 1;
502
503 if (*string++ == '.')
504 {
505 if ((!*string) || *string == '/')
506 return 1;
507
508 if (*string++ == '.')
509 if (!*string || *string == '/')
510 return 1;
511 }
512 return 0;
513 }
514
515 /*
516 * Return 1 if STRING is an absolute program name; it is absolute if
517 * it contains any slashes. This is used to decide whether or not to
518 * look up through $PATH.
519 */
520 int
521 absolute_program (char *string)
522 {
523 return (strchr (string, '/') != (char *)NULL);
524 }
525
526 /*
527 * Return the `basename' of the pathname in STRING (the stuff after
528 * the last '/'). If STRING is not a full pathname, simply return it.
529 */
530 char *
531 base_pathname (char *string)
532 {
533 char *p = strrchr (string, '/');
534
535 if (!absolute_pathname (string))
536 return (string);
537
538 if (p)
539 return (++p);
540 else
541 return (string);
542 }
543
544 /*
545 * Return the octal number parsed from STRING, or -1 to indicate that
546 * the string contained a bad number.
547 */
548 int
549 read_octal (char *string)
550 {
551 int result = 0;
552 int digits = 0;
553
554 while (*string && *string >= '0' && *string < '8')
555 {
556 digits++;
557 result = (result * 8) + *string++ - '0';
558 }
559
560 if (!digits || result > 0777 || *string)
561 result = -1;
562
563 return result;
564 }
565
566 /*
567 * Append SOURCE to TARGET at INDEX. SIZE is the current amount of
568 * space allocated to TARGET. SOURCE can be NULL, in which case
569 * nothing happens. Gets rid of SOURCE by free ()ing it. Returns
570 * TARGET in case the location has changed.
571 */
572 char *
573 sub_append_string (char *source, char *target, int *index, int *size)
574 {
575 if (source)
576 {
577 while ((int)strlen (source) >= (int)(*size - *index))
578 {
579 char *tmp = new char [*size += DEFAULT_ARRAY_SIZE];
580 strcpy (tmp, target);
581 delete [] target;
582 target = tmp;
583 }
584
585 strcat (target, source);
586 *index += strlen (source);
587
588 delete [] source;
589 }
590 return target;
591 }
592
593 /*
594 * Return a string which will be printed as a prompt. The string may
595 * contain special characters which are decoded as follows:
596 *
597 * \t the time
598 * \d the date
599 * \n CRLF
600 * \s the name of the shell (program)
601 * \w the current working directory
602 * \W the last element of PWD
603 * \u your username
604 * \h the hostname
605 * \# the command number of this command
606 * \! the history number of this command
607 * \$ a $ or a # if you are root
608 * \<octal> character code in octal
609 * \\ a backslash
610 */
611 char *
612 decode_prompt_string (char *string)
613 {
614 int result_size = PROMPT_GROWTH;
615 int result_index = 0;
616 char *result = new char [PROMPT_GROWTH];
617 int c;
618 char *temp = (char *)NULL;
619
620 result[0] = 0;
621 while (c = *string++)
622 {
623 if (c == '\\')
624 {
625 c = *string;
626
627 switch (c)
628 {
629 case '0':
630 case '1':
631 case '2':
632 case '3':
633 case '4':
634 case '5':
635 case '6':
636 case '7':
637 {
638 char octal_string[4];
639 int n;
640
641 strncpy (octal_string, string, 3);
642 octal_string[3] = '\0';
643
644 n = read_octal (octal_string);
645
646 temp = strsave ("\\");
647 if (n != -1)
648 {
649 string += 3;
650 temp[0] = n;
651 }
652
653 c = 0;
654 goto add_string;
655 }
656
657 case 't':
658 case 'd':
659 /* Make the current time/date into a string. */
660 {
661 long the_time = time (0);
662 char *ttemp = ctime (&the_time);
663 temp = strsave (ttemp);
664
665 if (c == 't')
666 {
667 strcpy (temp, temp + 11);
668 temp[8] = '\0';
669 }
670 else
671 temp[10] = '\0';
672
673 goto add_string;
674 }
675
676 case 'n':
677 if (!no_line_editing)
678 temp = strsave ("\r\n");
679 else
680 temp = strsave ("\n");
681 goto add_string;
682
683 case 's':
684 {
685 temp = base_pathname (prog_name);
686 temp = strsave (temp);
687 goto add_string;
688 }
689
690 case 'w':
691 case 'W':
692 {
693 char t_string[MAXPATHLEN];
694 #define EFFICIENT
695 #ifdef EFFICIENT
696
697 // Use the value of PWD because it is much more effecient.
698
699 temp = user_pref.pwd;
700
701 if (!temp)
702 getcwd (t_string, MAXPATHLEN);
703 else
704 strcpy (t_string, temp);
705 #else
706 getcwd (t_string, MAXPATHLEN);
707 #endif /* EFFICIENT */
708
709 if (c == 'W')
710 {
711 char *dir = strrchr (t_string, '/');
712 if (dir && dir != t_string)
713 strcpy (t_string, dir + 1);
714 temp = strsave (t_string);
715 }
716 else
717 temp = strsave (polite_directory_format (t_string));
718 goto add_string;
719 }
720
721 case 'u':
722 {
723 temp = strsave (user_name);
724
725 goto add_string;
726 }
727
728 case 'h':
729 {
730 char *t_string;
731
732 temp = strsave (host_name);
733 if (t_string = strchr (temp, '.'))
734 *t_string = '\0';
735
736 goto add_string;
737 }
738
739 case '#':
740 {
741 char number_buffer[20];
742 sprintf (number_buffer, "%d", current_command_number);
743 temp = strsave (number_buffer);
744 goto add_string;
745 }
746
747 case '!':
748 {
749 char number_buffer[20];
750 int num = current_history_number ();
751 if (num > 0)
752 sprintf (number_buffer, "%d", num);
753 else
754 strcpy (number_buffer, "!");
755 temp = strsave (number_buffer);
756 goto add_string;
757 }
758
759 case '$':
760 temp = strsave (geteuid () == 0 ? "#" : "$");
761 goto add_string;
762
763 case '\\':
764 temp = strsave ("\\");
765 goto add_string;
766
767 default:
768 temp = strsave ("\\ ");
769 temp[1] = c;
770
771 add_string:
772 if (c)
773 string++;
774 result =
775 (char *)sub_append_string (temp, result,
776 &result_index, &result_size);
777 temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
778 result[result_index] = '\0';
779 break;
780 }
781 }
782 else
783 {
784 while (3 + result_index > result_size)
785 {
786 char *tmp = new char [result_size += PROMPT_GROWTH];
787 strcpy (tmp, result);
788 delete [] result;
789 result = tmp;
790 }
791 result[result_index++] = c;
792 result[result_index] = '\0';
793 }
794 }
795
796 #if 0
797 /* I don't really think that this is a good idea. Do you? */
798 if (!find_variable ("NO_PROMPT_VARS"))
799 {
800 WORD_LIST *expand_string (), *list;
801 char *string_list ();
802
803 list = expand_string (result, 1);
804 free (result);
805 result = string_list (list);
806 dispose_words (list);
807 }
808 #endif
809
810 return result;
811 }
812
813 /*
814 * Remove the last N directories from PATH. Do not PATH blank.
815 * PATH must contain enoung space for MAXPATHLEN characters.
816 */
817 void
818 pathname_backup (char *path, int n)
819 {
820 register char *p;
821
822 if (!*path)
823 return;
824
825 p = path + (strlen (path) - 1);
826
827 while (n--)
828 {
829 while (*p == '/' && p != path)
830 p--;
831
832 while (*p != '/' && p != path)
833 p--;
834
835 *++p = '\0';
836 }
837 }
838
839 /*
840 * Turn STRING (a pathname) into an absolute pathname, assuming that
841 * DOT_PATH contains the symbolic location of '.'. This always
842 * returns a new string, even if STRING was an absolute pathname to
843 * begin with.
844 */
845 char *
846 make_absolute (char *string, char *dot_path)
847 {
848 static char current_path[MAXPATHLEN];
849 register char *cp;
850
851 if (!dot_path || *string == '/')
852 return strsave (string);
853
854 strcpy (current_path, dot_path);
855
856 if (!current_path[0])
857 strcpy (current_path, "./");
858
859 cp = current_path + (strlen (current_path) - 1);
860
861 if (*cp++ != '/')
862 *cp++ = '/';
863
864 *cp = '\0';
865
866 while (*string)
867 {
868 if (*string == '.')
869 {
870 if (!string[1])
871 return strsave (current_path);
872
873 if (string[1] == '/')
874 {
875 string += 2;
876 continue;
877 }
878
879 if (string[1] == '.' && (string[2] == '/' || !string[2]))
880 {
881 string += 2;
882
883 if (*string)
884 string++;
885
886 pathname_backup (current_path, 1);
887 cp = current_path + strlen (current_path);
888 continue;
889 }
890 }
891
892 while (*string && *string != '/')
893 *cp++ = *string++;
894
895 if (*string)
896 *cp++ = *string++;
897
898 *cp = '\0';
899 }
900 return strsave (current_path);
901 }
902
903 /*
904 * Return a consed string which is the current working directory.
905 * FOR_WHOM is the name of the caller for error printing.
906 */
907 char *
908 get_working_directory (char *for_whom)
909 {
910 if (!follow_symbolic_links)
911 {
912 if (the_current_working_directory)
913 delete [] the_current_working_directory;
914
915 the_current_working_directory = (char *)NULL;
916 }
917
918 if (!the_current_working_directory)
919 {
920 char *directory;
921
922 the_current_working_directory = new char [MAXPATHLEN];
923 directory = getcwd (the_current_working_directory, MAXPATHLEN);
924 if (!directory)
925 {
926 message (for_whom, the_current_working_directory);
927 delete [] the_current_working_directory;
928 the_current_working_directory = (char *)NULL;
929 return (char *)NULL;
930 }
931 }
932
933 return the_current_working_directory;
934 }
935
936 /*
937 * Do the work of changing to the directory NEWDIR. Handle symbolic
938 * link following, etc.
939 */
940 int
941 change_to_directory (char *newdir)
942 {
943 char *t;
944
945 if (follow_symbolic_links)
946 {
947 if (!the_current_working_directory)
948 get_working_directory ("cd_links");
949
950 if (the_current_working_directory)
951 t = make_absolute (newdir, the_current_working_directory);
952 else
953 t = strsave (newdir);
954
955 /* Get rid of trailing `/'. */
956 {
957 register int len_t = strlen (t);
958 if (len_t > 1)
959 {
960 --len_t;
961 if (t[len_t] == '/')
962 t[len_t] = '\0';
963 }
964 }
965
966 if (chdir (t) < 0)
967 {
968 delete [] t;
969 return 0;
970 }
971
972 if (the_current_working_directory)
973 strcpy (the_current_working_directory, t);
974
975 delete [] t;
976 return 1;
977 }
978 else
979 {
980 if (chdir (newdir) < 0)
981 return 0;
982 else
983 return 1;
984 }
985 }
986
987 /*
988 * Has file `A' been modified after time `T'?
989 *
990 * case:
991 *
992 * a newer than t returns 1
993 * a older than t returns 0
994 * stat on a fails returns -1
995 */
996 int
997 is_newer (char *fa, time_t t)
998 {
999 struct stat fa_sb;
1000 register int fa_stat;
1001 register int status = 0;
1002
1003 fa_stat = stat (fa, &fa_sb);
1004 if (fa_stat != 0)
1005 status = -1;
1006
1007 if (status != 0)
1008 return status;
1009
1010 return (fa_sb.st_mtime > t);
1011 }
1012
1013 /*
1014 * Return to the main command loop in octave.cc.
1015 */
1016 volatile void
1017 jump_to_top_level (void)
1018 {
1019 run_all_unwind_protects ();
1020
1021 longjmp (toplevel, 1);
1022 }
1023
1024 /*
1025 * Gag.
1026 */
1027 char *
1028 s_plural (int i)
1029 {
1030 static char *empty = "";
1031 static char *s = "s";
1032 return i == 1 ? empty : s;
1033 }
1034
1035 char *
1036 es_plural (int i)
1037 {
1038 static char *empty = "";
1039 static char *es = "es";
1040 return i == 1 ? es : empty;
1041 }
1042
1043 char *
1044 save_in_tmp_file (tree_constant& t, int ndim = 2, int parametric = 0)
1045 {
1046 char *name = strsave (tmpnam ((char *) NULL));
1047 if (name != (char *) NULL)
1048 {
1049 ofstream file (name);
1050 if (file)
1051 {
1052 switch (ndim)
1053 {
1054 case 2:
1055 t.save (file);
1056 break;
1057 case 3:
1058 t.save_three_d (file, parametric);
1059 break;
1060 default:
1061 panic_impossible ();
1062 break;
1063 }
1064 }
1065 else
1066 {
1067 error ("couldn't open temporary output file `%s'", name);
1068 delete [] name;
1069 name = (char *) NULL;
1070 }
1071 }
1072 return name;
1073 }
1074
1075 void
1076 mark_for_deletion (const char *filename)
1077 {
1078 char *tmp = strsave (filename);
1079 tmp_files.push (tmp);
1080 }
1081
1082 void
1083 cleanup_tmp_files (void)
1084 {
1085 while (! tmp_files.empty ())
1086 {
1087 char *filename = tmp_files.pop ();
1088 unlink (filename);
1089 delete [] filename;
1090 }
1091 }
1092
1093 int
1094 send_to_plot_stream (const char *cmd)
1095 {
1096 // From sighandlers.cc:
1097 extern int pipe_handler_error_count;
1098
1099 static int initialized = 0;
1100
1101 if (! plot_stream.is_open ())
1102 {
1103 char *plot_prog = user_pref.gnuplot_binary;
1104 if (plot_prog != (char *) NULL)
1105 {
1106 plot_stream.open (plot_prog);
1107 if (! plot_stream.is_open ())
1108 {
1109 warning ("plot: unable to open pipe to `%s'",
1110 plot_prog);
1111
1112 if (strcmp (plot_prog, "gnuplot") != 0)
1113 {
1114 message ("plot", "trying again with `gnuplot'");
1115 goto last_chance;
1116 }
1117 }
1118 }
1119 else
1120 {
1121 last_chance:
1122
1123 plot_stream.open ("gnuplot");
1124
1125 if (! plot_stream.is_open ())
1126 {
1127 error ("plot: unable to open pipe to `%s'", plot_prog);
1128 return -1;
1129 }
1130 }
1131 }
1132
1133 if (! initialized)
1134 {
1135 initialized = 1;
1136 plot_stream << "set data style lines\n";
1137 }
1138
1139 plot_stream << cmd;
1140 plot_stream.flush ();
1141 pipe_handler_error_count = 0;
1142
1143 return 0;
1144 }
1145
1146 void
1147 close_plot_stream (void)
1148 {
1149 if (plot_stream.is_open ())
1150 plot_stream.close ();
1151 }
1152
1153 int
1154 almost_match (char *std, char *s, int min_match_len = 1)
1155 {
1156 int stdlen = strlen (std);
1157 int slen = strlen (s);
1158
1159 return (slen <= stdlen
1160 && slen >= min_match_len
1161 && strncmp (std, s, slen) == 0);
1162 }
1163
1164 char **
1165 get_m_file_names (int& num, char *dir, int no_suffix)
1166 {
1167 static int num_max = 256;
1168 char **retval = new char * [num_max];
1169 int i = 0;
1170
1171 DIR *dirp = opendir (dir);
1172 if (dirp != (DIR *) NULL)
1173 {
1174 struct dirent *entry;
1175 while ((entry = readdir (dirp)) != (struct dirent *) NULL)
1176 {
1177 int len = NLENGTH (entry);
1178 if (len > 2
1179 && entry->d_name[len-2] == '.'
1180 && entry->d_name[len-1] == 'm')
1181 {
1182 retval[i] = strsave (entry->d_name);
1183 if (no_suffix)
1184 retval[i][len-2] = '\0';
1185
1186 i++;
1187
1188 if (i == num_max - 1)
1189 {
1190 num_max += 256;
1191 char **tmp = new char * [num_max];
1192 for (int j = 0; j < i; j++)
1193 tmp[j] = retval[j];
1194
1195 retval = tmp;
1196 }
1197 }
1198 }
1199 free (dirp);
1200 }
1201
1202 retval[i] = (char *) NULL;
1203 num = i;
1204
1205 return retval;
1206 }
1207
1208 char **
1209 get_m_file_names (int& num, int no_suffix)
1210 {
1211 static int num_max = 1024;
1212 char **retval = new char * [num_max];
1213 int i = 0;
1214
1215 char **path = pathstring_to_vector (user_pref.loadpath);
1216
1217 char **ptr = path;
1218 if (ptr != (char **) NULL)
1219 {
1220 while (*ptr != (char *) NULL)
1221 {
1222 int tmp_num;
1223 char **names = get_m_file_names (tmp_num, *ptr, no_suffix);
1224
1225 if (i + tmp_num >= num_max - 1)
1226 {
1227 num_max += 1024;
1228 char **tmp = new char * [num_max];
1229 for (int j = 0; j < i; j++)
1230 tmp[j] = retval[j];
1231
1232 retval = tmp;
1233 }
1234
1235 int k = 0;
1236 while (k < tmp_num)
1237 retval[i++] = names[k++];
1238
1239 ptr++;
1240 }
1241 }
1242
1243 retval[i] = (char *) NULL;
1244 num = i;
1245
1246 return retval;
1247 }
1248
1249 int
1250 NINT (double x)
1251 {
1252 if (x > INT_MAX)
1253 return INT_MAX;
1254 else if (x < INT_MIN)
1255 return INT_MIN;
1256 else
1257 return (x > 0) ? ((int) (x + 0.5)) : ((int) (x - 0.5));
1258 }
1259
1260 double
1261 D_NINT (double x)
1262 {
1263 if (xisinf (x) || xisnan (x))
1264 return x;
1265 else
1266 return floor (x + 0.5);
1267 }
1268
1269 /*
1270 ;;; Local Variables: ***
1271 ;;; mode: C++ ***
1272 ;;; page-delimiter: "^/\\*" ***
1273 ;;; End: ***
1274 */