Annotation of OpenXM_contrib/gnuplot/plot.c, Revision 1.1.1.1
1.1 maekawa 1: #ifndef lint
2: static char *RCSid = "$Id: plot.c,v 1.87 1998/04/14 00:16:05 drd Exp $";
3: #endif
4:
5: /* GNUPLOT - plot.c */
6:
7: /*[
8: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
9: *
10: * Permission to use, copy, and distribute this software and its
11: * documentation for any purpose with or without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and
13: * that both that copyright notice and this permission notice appear
14: * in supporting documentation.
15: *
16: * Permission to modify the software is granted, but not the right to
17: * distribute the complete modified source code. Modifications are to
18: * be distributed as patches to the released version. Permission to
19: * distribute binaries produced by compiling modified sources is granted,
20: * provided you
21: * 1. distribute the corresponding source modifications from the
22: * released version in the form of a patch file along with the binaries,
23: * 2. add special version identification to distinguish your version
24: * in addition to the base release version number,
25: * 3. provide your name and address as the primary contact for the
26: * support of your modified version, and
27: * 4. retain our contact information in regard to use of the base
28: * software.
29: * Permission to distribute the released version of the source code along
30: * with corresponding source modifications in the form of a patch file is
31: * granted with same provisions 2 through 4 for binary distributions.
32: *
33: * This software is provided "as is" without express or implied warranty
34: * to the extent permitted by applicable law.
35: ]*/
36:
37: #include <signal.h>
38:
39: #include "plot.h"
40: #include "fit.h"
41: #include "setshow.h"
42: #include "fnproto.h"
43: #include <setjmp.h>
44:
45: #if defined(MSDOS) || defined(DOS386) || defined(__EMX__)
46: # include <io.h>
47: #endif
48:
49: /* HBB: for the control87 function, if used with DJGPP V1: */
50: #if defined(DJGPP) && (DJGPP!=2)
51: # include "ctrl87.h"
52: #endif
53:
54: #ifdef VMS
55: # ifndef __GNUC__
56: # include <unixio.h>
57: # endif
58: # include <smgdef.h>
59: extern int vms_vkid;
60: extern smg$create_virtual_keyboard();
61: extern int vms_ktid;
62: extern smg$create_key_table();
63: #endif /* VMS */
64:
65: #ifdef AMIGA_SC_6_1
66: # include <proto/dos.h>
67: #endif
68:
69: #ifdef _Windows
70: # include <windows.h>
71: # ifndef SIGINT
72: # define SIGINT 2 /* for MSC */
73: # endif
74: #endif /* _Windows */
75:
76: extern FILE *gpoutfile;
77:
78: TBOOLEAN interactive = TRUE; /* FALSE if stdin not a terminal */
79: TBOOLEAN noinputfiles = TRUE; /* FALSE if there are script files */
80:
81: /* these 2 could be in misc.c, but are here with all the other globals */
82: TBOOLEAN do_load_arg_substitution = FALSE;
83: char *call_args[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
84:
85: char *infile_name = NULL; /* name of command file; NULL if terminal */
86:
87: #ifdef GNU_READLINE
88: extern char *rl_readline_name;
89: extern int rl_complete_with_tilde_expansion;
90: #endif
91:
92: #ifdef X11
93: extern int X11_args __PROTO((int, char **));
94: #endif
95:
96: /* patch to get home dir, see command.c */
97: #if (defined (__TURBOC__) && (defined (MSDOS) || defined(DOS386))) || defined(DJGPP)
98: # include <dir.h> /* MAXPATH */
99: char HelpFile[MAXPATH];
100: #endif /* - DJL */
101:
102: #ifndef STDOUT
103: # define STDOUT 1
104: #endif
105:
106: /* a longjmp buffer to get back to the command line */
107: #ifdef _Windows
108: static jmp_buf far command_line_env;
109: #else
110: static jmp_buf command_line_env;
111: #endif
112:
113: static void load_rcfile __PROTO((void));
114: RETSIGTYPE inter __PROTO((int anint));
115:
116: /* built-in function table */
117: struct ft_entry GPFAR ft[] =
118: {
119: /* internal functions: */
120: {"push", (FUNC_PTR) f_push},
121: {"pushc", (FUNC_PTR) f_pushc},
122: {"pushd1", (FUNC_PTR) f_pushd1},
123: {"pushd2", (FUNC_PTR) f_pushd2},
124: {"pushd", (FUNC_PTR) f_pushd},
125: {"call", (FUNC_PTR) f_call},
126: {"calln", (FUNC_PTR) f_calln},
127: {"lnot", (FUNC_PTR) f_lnot},
128: {"bnot", (FUNC_PTR) f_bnot},
129: {"uminus", (FUNC_PTR) f_uminus},
130: {"lor", (FUNC_PTR) f_lor},
131: {"land", (FUNC_PTR) f_land},
132: {"bor", (FUNC_PTR) f_bor},
133: {"xor", (FUNC_PTR) f_xor},
134: {"band", (FUNC_PTR) f_band},
135: {"eq", (FUNC_PTR) f_eq},
136: {"ne", (FUNC_PTR) f_ne},
137: {"gt", (FUNC_PTR) f_gt},
138: {"lt", (FUNC_PTR) f_lt},
139: {"ge", (FUNC_PTR) f_ge},
140: {"le", (FUNC_PTR) f_le},
141: {"plus", (FUNC_PTR) f_plus},
142: {"minus", (FUNC_PTR) f_minus},
143: {"mult", (FUNC_PTR) f_mult},
144: {"div", (FUNC_PTR) f_div},
145: {"mod", (FUNC_PTR) f_mod},
146: {"power", (FUNC_PTR) f_power},
147: {"factorial", (FUNC_PTR) f_factorial},
148: {"bool", (FUNC_PTR) f_bool},
149: {"dollars", (FUNC_PTR) f_dollars}, /* for using extension */
150: {"jump", (FUNC_PTR) f_jump},
151: {"jumpz", (FUNC_PTR) f_jumpz},
152: {"jumpnz", (FUNC_PTR) f_jumpnz},
153: {"jtern", (FUNC_PTR) f_jtern},
154:
155: /* standard functions: */
156: {"real", (FUNC_PTR) f_real},
157: {"imag", (FUNC_PTR) f_imag},
158: {"arg", (FUNC_PTR) f_arg},
159: {"conjg", (FUNC_PTR) f_conjg},
160: {"sin", (FUNC_PTR) f_sin},
161: {"cos", (FUNC_PTR) f_cos},
162: {"tan", (FUNC_PTR) f_tan},
163: {"asin", (FUNC_PTR) f_asin},
164: {"acos", (FUNC_PTR) f_acos},
165: {"atan", (FUNC_PTR) f_atan},
166: {"atan2", (FUNC_PTR) f_atan2},
167: {"sinh", (FUNC_PTR) f_sinh},
168: {"cosh", (FUNC_PTR) f_cosh},
169: {"tanh", (FUNC_PTR) f_tanh},
170: {"int", (FUNC_PTR) f_int},
171: {"abs", (FUNC_PTR) f_abs},
172: {"sgn", (FUNC_PTR) f_sgn},
173: {"sqrt", (FUNC_PTR) f_sqrt},
174: {"exp", (FUNC_PTR) f_exp},
175: {"log10", (FUNC_PTR) f_log10},
176: {"log", (FUNC_PTR) f_log},
177: {"besj0", (FUNC_PTR) f_besj0},
178: {"besj1", (FUNC_PTR) f_besj1},
179: {"besy0", (FUNC_PTR) f_besy0},
180: {"besy1", (FUNC_PTR) f_besy1},
181: {"erf", (FUNC_PTR) f_erf},
182: {"erfc", (FUNC_PTR) f_erfc},
183: {"gamma", (FUNC_PTR) f_gamma},
184: {"lgamma", (FUNC_PTR) f_lgamma},
185: {"ibeta", (FUNC_PTR) f_ibeta},
186: {"igamma", (FUNC_PTR) f_igamma},
187: {"rand", (FUNC_PTR) f_rand},
188: {"floor", (FUNC_PTR) f_floor},
189: {"ceil", (FUNC_PTR) f_ceil},
190:
191: {"norm", (FUNC_PTR) f_normal}, /* XXX-JG */
192: {"inverf", (FUNC_PTR) f_inverse_erf}, /* XXX-JG */
193: {"invnorm", (FUNC_PTR) f_inverse_normal}, /* XXX-JG */
194: {"asinh", (FUNC_PTR) f_asinh},
195: {"acosh", (FUNC_PTR) f_acosh},
196: {"atanh", (FUNC_PTR) f_atanh},
197:
198: {"column", (FUNC_PTR) f_column}, /* for using */
199: {"valid", (FUNC_PTR) f_valid}, /* for using */
200: {"timecolumn", (FUNC_PTR) f_timecolumn}, /* for using */
201:
202: {"tm_sec", (FUNC_PTR) f_tmsec}, /* for timeseries */
203: {"tm_min", (FUNC_PTR) f_tmmin}, /* for timeseries */
204: {"tm_hour", (FUNC_PTR) f_tmhour}, /* for timeseries */
205: {"tm_mday", (FUNC_PTR) f_tmmday}, /* for timeseries */
206: {"tm_mon", (FUNC_PTR) f_tmmon}, /* for timeseries */
207: {"tm_year", (FUNC_PTR) f_tmyear}, /* for timeseries */
208: {"tm_wday", (FUNC_PTR) f_tmwday}, /* for timeseries */
209: {"tm_yday", (FUNC_PTR) f_tmyday}, /* for timeseries */
210:
211: {NULL, NULL}
212: };
213:
214: static struct udvt_entry udv_pi = { NULL, "pi", FALSE };
215: /* first in linked list */
216: struct udvt_entry *first_udv = &udv_pi;
217: struct udft_entry *first_udf = NULL;
218:
219: #ifdef OS2
220: # define INCL_DOS
221: # define INCL_REXXSAA
222: # include <os2.h>
223: # include <process.h>
224: ULONG RexxInterface(PRXSTRING, PUSHORT, PRXSTRING);
225: int ExecuteMacro(char *, int);
226: void PM_intc_cleanup();
227: void PM_setup();
228: #endif /* OS2 */
229:
230: #if defined(ATARI) || defined(MTOS)
231: /* For findfile () (?) */
232: # include <support.h>
233: void appl_exit(void);
234: void MTOS_open_pipe(void);
235: extern int aesid;
236: #endif
237:
238: RETSIGTYPE inter(anint)
239: int anint;
240: {
241: #ifdef OS2
242: (void) signal(anint, SIG_ACK);
243: #else
244: (void) signal(SIGINT, (sigfunc) inter);
245: #endif
246:
247: #ifndef DOSX286
248: (void) signal(SIGFPE, SIG_DFL); /* turn off FPE trapping */
249: #endif
250: #ifdef OS2
251: PM_intc_cleanup();
252: #else
253: term_reset();
254: (void) putc('\n', stderr);
255: longjmp(command_line_env, TRUE); /* return to prompt */
256: #endif
257: }
258:
259:
260: /* a wrapper for longjmp so we can keep everything local */
261: void bail_to_command_line()
262: {
263: longjmp(command_line_env, TRUE);
264: }
265:
266: #if defined(_Windows) || defined(_Macintosh)
267: int gnu_main(argc, argv)
268: #else
269: int main(argc, argv)
270: #endif
271: int argc;
272: char **argv;
273: {
274: #ifdef LINUXVGA
275: LINUX_setup();
276: #endif
277: /* make sure that we really have revoked root access, this might happen if
278: gnuplot is compiled without vga support but is installed suid by mistake */
279: #ifdef __linux__
280: setuid(getuid());
281: #endif
282: #if defined(MSDOS) && !defined(_Windows) && !defined(__GNUC__)
283: PC_setup();
284: #endif /* MSDOS !Windows */
285: /* HBB: Seems this isn't needed any more for DJGPP V2? */
286: /* HBB: disable all floating point exceptions, just keep running... */
287: #if defined(DJGPP) && (DJGPP!=2)
288: _control87(MCW_EM, MCW_EM);
289: #endif
290:
291: #if defined(OS2)
292: int rc;
293: if (_osmode == OS2_MODE) {
294: PM_setup();
295: rc = RexxRegisterSubcomExe("GNUPLOT", (PFN) RexxInterface, NULL);
296: }
297: #endif
298:
299: /* malloc large blocks, otherwise problems with fragmented mem */
300: #ifdef OSK
301: _mallocmin(102400);
302: #endif
303:
304: #ifdef MALLOCDEBUG
305: malloc_debug(7);
306: #endif
307:
308: /* get helpfile from home directory */
309: #ifndef DOSX286
310: # ifndef _Windows
311: # if defined (__TURBOC__) && (defined (MSDOS) || defined(DOS386))
312: strcpy(HelpFile, argv[0]);
313: strcpy(strrchr(HelpFile, DIRSEP1), "\\gnuplot.gih");
314: # endif /* - DJL */
315: # endif /* !_Windows */
316: #endif /* !DOSX286 */
317: #ifdef __DJGPP__
318: {
319: char *s;
320: strcpy(HelpFile, argv[0]);
321: for (s = HelpFile; *s; s++)
322: if (*s == DIRSEP1)
323: *s = DIRSEP2; /* '\\' to '/' */
324: strcpy(strrchr(HelpFile, DIRSEP2), "/gnuplot.gih");
325: } /* Add also some "paranoid" tests for '\\': AP */
326: #endif /* DJGPP */
327:
328: #ifdef VMS
329: unsigned int status[2] = { 1, 0 };
330: #endif
331:
332: #ifdef GNU_READLINE
333: rl_readline_name = argv[0];
334: rl_complete_with_tilde_expansion = 1;
335: #endif
336:
337: #ifdef X11
338: {
339: int n = X11_args(argc, argv);
340: argv += n;
341: argc -= n;
342: }
343: #endif
344:
345: #ifdef apollo
346: apollo_pfm_catch();
347: #endif
348:
349: /* moved to ATARI_init in atariaes.trm */
350: /* #ifdef ATARI
351: void application_init(void);
352: application_init();
353: #endif */
354:
355: #ifdef MTOS
356: MTOS_open_pipe();
357: #endif
358:
359: setbuf(stderr, (char *) NULL);
360:
361: #ifndef NO_SETVBUF
362: /* this was once setlinebuf(). Docs say this is
363: * identical to setvbuf(,NULL,_IOLBF,0), but MS C
364: * faults this (size out of range), so we try with
365: * size of 1024 instead. [SAS/C does that, too. -lh]
366: * Failing this, I propose we just make the call and
367: * ignore the return : its probably not a big deal
368: */
369: if (setvbuf(stdout, (char *) NULL, _IOLBF, (size_t) 1024) != 0)
370: fputs("Could not linebuffer stdout\n", stderr);
371: #endif
372:
373: gpoutfile = stdout;
374: (void) Gcomplex(&udv_pi.udv_value, Pi, 0.0);
375:
376: init_memory();
377:
378: interactive = FALSE;
379: init_terminal(); /* can set term type if it likes */
380:
381: #ifdef AMIGA_SC_6_1
382: if (IsInteractive(Input()) == DOSTRUE)
383: interactive = TRUE;
384: else
385: interactive = FALSE;
386: #else
387: # if (defined(__MSC__) && defined(_Windows)) || defined(__WIN32__)
388: interactive = TRUE;
389: # else
390: interactive = isatty(fileno(stdin));
391: # endif
392: #endif /* !AMIGA_SC_6_1 */
393:
394: if (argc > 1)
395: interactive = noinputfiles = FALSE;
396: else
397: noinputfiles = TRUE;
398:
399: if (interactive)
400: show_version(stderr);
401:
402: #ifdef VMS
403: /* initialise screen management routines for command recall */
404: if (status[1] = smg$create_virtual_keyboard(&vms_vkid) != SS$_NORMAL)
405: done(status[1]);
406: if (status[1] = smg$create_key_table(&vms_ktid) != SS$_NORMAL)
407: done(status[1]);
408: #endif /* VMS */
409:
410: if (!setjmp(command_line_env)) {
411: /* first time */
412: interrupt_setup();
413: load_rcfile();
414: init_fit(); /* Initialization of fitting module */
415:
416: if (interactive && term != 0) /* not unknown */
417: fprintf(stderr, "\nTerminal type set to '%s'\n", term->name);
418: } else {
419: /* come back here from int_error() */
420: #ifdef AMIGA_SC_6_1
421: (void) rawcon(0);
422: #endif
423: load_file_error(); /* if we were in load_file(), cleanup */
424: #ifdef _Windows
425: SetCursor(LoadCursor((HINSTANCE) NULL, IDC_ARROW));
426: #endif
427:
428: #ifdef VMS
429: /* after catching interrupt */
430: /* VAX stuffs up stdout on SIGINT while writing to stdout,
431: so reopen stdout. */
432: if (gpoutfile == stdout) {
433: if ((stdout = freopen("SYS$OUTPUT", "w", stdout)) == NULL) {
434: /* couldn't reopen it so try opening it instead */
435: if ((stdout = fopen("SYS$OUTPUT", "w")) == NULL) {
436: /* don't use int_error here - causes infinite loop! */
437: fputs("Error opening SYS$OUTPUT as stdout\n", stderr);
438: }
439: }
440: gpoutfile = stdout;
441: }
442: #endif /* VMS */
443: if (!interactive && !noinputfiles) {
444: term_reset();
445: #if defined(ATARI) || defined(MTOS)
446: if (aesid > -1)
447: atexit(appl_exit);
448: #endif
449: return (IO_ERROR); /* exit on non-interactive error */
450: }
451: }
452:
453: if (argc > 1) {
454: #ifdef _Windows
455: int noend = 0;
456: #endif
457:
458: /* load filenames given as arguments */
459: while (--argc > 0) {
460: ++argv;
461: c_token = NO_CARET; /* in case of file not found */
462: #ifdef _Windows
463: if (stricmp(*argv, "-noend") == 0 || stricmp(*argv, "/noend") == 0)
464: noend = 1;
465: else
466: #endif
467: if (strcmp(*argv, "-") == 0) {
468: /* DBT 10-7-98 go interactive if "-" on command line */
469:
470: interactive = TRUE;
471: /* will this work on all platforms? */
472:
473: while (!com_line());
474:
475: /* interactive = FALSE; /* should this be here? */
476:
477: } else
478: load_file(fopen(*argv, "r"), *argv, FALSE);
479: }
480: #ifdef _Windows
481: if (noend) {
482: interactive = TRUE;
483: while (!com_line());
484: }
485: #endif
486: } else {
487: /* take commands from stdin */
488: while (!com_line());
489: }
490:
491: term_reset();
492:
493: #ifdef OS2
494: if (_osmode == OS2_MODE)
495: RexxDeregisterSubcom("GNUPLOT", NULL);
496: #endif
497:
498: #if defined(ATARI) || defined(MTOS)
499: if (aesid > -1)
500: atexit(appl_exit);
501: #endif
502: return (IO_SUCCESS);
503: }
504:
505: #if (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
506: int purec_matherr(struct exception *e)
507: {
508: char *c;
509: switch (e->type) {
510: case DOMAIN:
511: c = "domain error";
512: break;
513: case SING:
514: c = "argument singularity";
515: break;
516: case OVERFLOW:
517: c = "overflow range";
518: break;
519: case UNDERFLOW:
520: c = "underflow range";
521: break;
522: default:
523: c = "(unknown error";
524: break;
525: }
526: fprintf(stderr, "\
527: math exception : %s\n\
528: name : %s\n\
529: arg 1: %e\n\
530: arg 2: %e\n\
531: ret : %e\n",
532: c,
533: e->name,
534: e->arg1,
535: e->arg2,
536: e->retval);
537:
538: return 1;
539: }
540: #endif /* (ATARI || MTOS) && PUREC */
541:
542:
543: /* Set up to catch interrupts */
544: void interrupt_setup()
545: {
546: #ifdef __PUREC__
547: setmatherr(purec_matherr);
548: #endif
549:
550: (void) signal(SIGINT, (sigfunc) inter);
551:
552: #ifdef SIGPIPE
553: /* ignore pipe errors, this might happen with set output "|head" */
554: (void) signal(SIGPIPE, SIG_IGN);
555: #endif /* SIGPIPE */
556: }
557:
558:
559: /* Look for a gnuplot init file in . or home directory */
560: static void load_rcfile()
561: {
562: FILE *plotrc = NULL;
563: char home[80];
564: char rcfile[sizeof(PLOTRC) + 80];
565: char *tmp_home = NULL;
566: #ifndef VMS
567: char *p; /* points to last char in home path, or to \0, if none */
568:
569: tmp_home = getenv(HOME);
570: if (tmp_home) {
571: safe_strncpy(home, tmp_home, sizeof(home));
572: if (strlen(home))
573: p = &home[strlen(home) - 1];
574: else
575: p = home;
576: if ((*p != DIRSEP1) && (*p != DIRSEP2) && (*p != NUL)) {
577: assert(p >= home && p <= (home + sizeof(home) - 1 - 2));
578: if (*p)
579: p++;
580: *p++ = DIRSEP1;
581: *p = NUL;
582: }
583: }
584: #else /* VMS */
585: safe_strncpy(home, HOME, sizeof(home));
586: tmp_home = home;
587: #endif /* VMS */
588:
589: #ifdef NOCWDRC
590: /* inhibit check of init file in current directory for security reasons */
591: #else
592: (void) strcpy(rcfile, PLOTRC);
593: plotrc = fopen(rcfile, "r");
594: #endif /* !NOCWDRC */
595:
596: if (plotrc == NULL) {
597: if (tmp_home) {
598: (void) sprintf(rcfile, "%s%s", home, PLOTRC);
599: plotrc = fopen(rcfile, "r");
600: #if defined(ATARI) || defined(MTOS)
601: if (plotrc == NULL) {
602: char const *const ext[] = { NULL };
603: char *ini_ptr = findfile(PLOTRC, getenv("GNUPLOTPATH"), ext);
604:
605: if (ini_ptr)
606: plotrc = fopen(ini_ptr, "r");
607: }
608: #endif /* ATARI || MTOS */
609: }
610: }
611: if (plotrc)
612: load_file(plotrc, rcfile, FALSE);
613: }
614:
615: #ifdef OS2
616:
617: int ExecuteMacro(char *argv, int namelength)
618: {
619: RXSTRING rxRc;
620: RXSTRING rxArg;
621: char pszName[CCHMAXPATH];
622: short sRc;
623: int rc;
624:
625: safe_strncpy(pszName, argv, sizeof(pszName));
626: MAKERXSTRING(rxArg, argv, strlen(argv));
627: rc = RexxStart(1,
628: &rxArg,
629: pszName,
630: NULL,
631: "GNUPLOT",
632: RXCOMMAND,
633: NULL,
634: &sRc,
635: &rxRc);
636: if (rc == -4)
637: rc = 0; /* run was cancelled-don't give error message */
638:
639: /* We don't use this value ?
640: BTW, don't use free() instead since it's allocated inside RexxStart() */
641: DosFreeMem(rxRc.strptr);
642: return rc;
643: }
644:
645: ULONG RexxInterface(PRXSTRING rxCmd, PUSHORT pusErr, PRXSTRING rxRc)
646: /*
647: ** Rexx command line interface
648: */
649: {
650: int rc;
651: static jmp_buf keepenv;
652: int cmdlen;
653:
654: memcpy(keepenv, command_line_env, sizeof(jmp_buf));
655: if (!setjmp(command_line_env)) {
656: /* set variable input_line.
657: * Watch out for line length of NOT_ZERO_TERMINATED strings ! */
658: cmdlen = rxCmd->strlength + 1;
659: safe_strncpy(input_line, rxCmd->strptr, cmdlen);
660: input_line[cmdlen] = NUL;
661:
662: rc = do_line();
663: *pusErr = RXSUBCOM_OK;
664: rxRc->strptr[0] = rc + '0';
665: rxRc->strptr[1] = NUL;
666: rxRc->strlength = strlen(rxRc->strptr);
667: } else {
668: *pusErr = RXSUBCOM_ERROR;
669: RexxSetHalt(getpid(), 1);
670: }
671: memcpy(command_line_env, keepenv, sizeof(jmp_buf));
672: return 0;
673: }
674: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>