/* * Initialize 'constants' stored as variables (user could mangle these) */ void init_constants() { (void) Gcomplex(&udv_pi.udv_value, M_PI, 0.0); udv_NaN = get_udv_by_name("NaN"); (void) Gcomplex(&(udv_NaN->udv_value), not_a_number(), 0.0); }
void f_mult(union argument *arg) { struct value a, b, result; double product; (void) arg; /* avoid -Wunused warning */ (void) pop(&b); (void) pop(&a); /* now do a*b */ switch (a.type) { case INTGR: switch (b.type) { case INTGR: product = (double)a.v.int_val * (double)b.v.int_val; if (fabs(product) >= (double)INT_MAX) (void) Gcomplex(&result, product, 0.0); else (void) Ginteger(&result, a.v.int_val * b.v.int_val); break; case CMPLX: (void) Gcomplex(&result, a.v.int_val * b.v.cmplx_val.real, a.v.int_val * b.v.cmplx_val.imag); break; BAD_DEFAULT } break; case CMPLX: switch (b.type) { case INTGR: (void) Gcomplex(&result, b.v.int_val * a.v.cmplx_val.real, b.v.int_val * a.v.cmplx_val.imag); break; case CMPLX: (void) Gcomplex(&result, a.v.cmplx_val.real * b.v.cmplx_val.real - a.v.cmplx_val.imag * b.v.cmplx_val.imag, a.v.cmplx_val.real * b.v.cmplx_val.imag + a.v.cmplx_val.imag * b.v.cmplx_val.real); break; BAD_DEFAULT } break; BAD_DEFAULT } push(&result); }
void f_mult(union argument *arg) { struct value a, b, result; (void) arg; /* avoid -Wunused warning */ (void) pop(&b); (void) pop(&a); /* now do a*b */ switch (a.type) { case INTGR: switch (b.type) { case INTGR: (void) Ginteger(&result, a.v.int_val * b.v.int_val); break; case CMPLX: (void) Gcomplex(&result, a.v.int_val * b.v.cmplx_val.real, a.v.int_val * b.v.cmplx_val.imag); break; BAD_DEFAULT } break; case CMPLX: switch (b.type) { case INTGR: (void) Gcomplex(&result, b.v.int_val * a.v.cmplx_val.real, b.v.int_val * a.v.cmplx_val.imag); break; case CMPLX: (void) Gcomplex(&result, a.v.cmplx_val.real * b.v.cmplx_val.real - a.v.cmplx_val.imag * b.v.cmplx_val.imag, a.v.cmplx_val.real * b.v.cmplx_val.imag + a.v.cmplx_val.imag * b.v.cmplx_val.real); break; BAD_DEFAULT } break; BAD_DEFAULT } push(&result); }
/* Convert string into seconds from year 2000 */ void f_strptime(union argument *arg) { struct value fmt, val; struct tm time_tm; double result; (void) arg; /* Avoid compiler warnings */ pop(&val); pop(&fmt); if ( fmt.type != STRING || val.type != STRING ) int_error(NO_CARET, "Both parameters to strptime must be strings"); if ( !fmt.v.string_val || !val.v.string_val ) int_error(NO_CARET, "Internal error: string not allocated"); /* string -> time_tm */ gstrptime(val.v.string_val, fmt.v.string_val, &time_tm); /* time_tm -> result */ result = gtimegm(&time_tm); FPRINTF((stderr," strptime result = %g seconds \n", result)); gpfree_string(&val); gpfree_string(&fmt); push(Gcomplex(&val, result, 0.0)); }
static void create_and_set_var( double val, char *prefix, char *base, char *suffix ) { int len; char *varname; struct udvt_entry *udv_ptr; t_value data; Gcomplex( &data, val, 0.0 ); /* data is complex, real=val, imag=0.0 */ /* In case prefix (or suffix) is NULL - make them empty strings */ prefix = prefix ? prefix : ""; suffix = suffix ? suffix : ""; len = strlen(prefix) + strlen(base) + strlen(suffix) + 1; varname = (char *)gp_alloc( len, "create_and_set_var" ); sprintf( varname, "%s%s%s", prefix, base, suffix ); /* Note that add_udv_by_name() checks if the name already exists, and * returns the existing ptr if found. It also allocates memory for * its own copy of the varname. */ udv_ptr = add_udv_by_name(varname); udv_ptr->udv_value = data; udv_ptr->udv_undef = FALSE; free( varname ); }
void f_sum(union argument *arg) { struct value beg, end, varname; /* [<var> = <start>:<end>] */ udft_entry *udf; /* function to evaluate */ udvt_entry *udv; /* iteration variable */ struct value ret; /* result */ struct value z; int i; (void) pop(&end); (void) pop(&beg); (void) pop(&varname); if (beg.type != INTGR || end.type != INTGR) int_error(NO_CARET, "range specifiers of sum must have integer values"); if (varname.type != STRING) int_error(NO_CARET, "internal error: f_sum expects argument (varname) of type string."); udv = get_udv_by_name(varname.v.string_val); if (!udv) int_error(NO_CARET, "internal error: f_sum could not access iteration variable."); udv->udv_undef = false; udf = arg->udf_arg; if (!udf) int_error(NO_CARET, "internal error: f_sum could not access summation coefficient function"); Gcomplex(&ret, 0, 0); for (i=beg.v.int_val; i<=end.v.int_val; ++i) { double x, y; /* calculate f_i = f() with user defined variable i */ Ginteger(&udv->udv_value, i); execute_at(udf->at); pop(&z); x = real(&ret) + real(&z); y = imag(&ret) + imag(&z); Gcomplex(&ret, x, y); } gpfree_string(&varname); push(Gcomplex(&z, real(&ret), imag(&ret))); }
/* Get current system time in seconds since 2000 * The type of the value popped from the stack * determines what is returned. * If integer, the result is also an integer. * If real (complex), the result is also real, * with microsecond precision (if available). * If string, it is assumed to be a format string, * and it is passed to strftime to get a formatted time string. */ void f_time(union argument *arg) { struct value val, val2; double time_now; #ifdef HAVE_SYS_TIME_H struct timeval tp; gettimeofday(&tp, NULL); tp.tv_sec -= SEC_OFFS_SYS; time_now = tp.tv_sec + (tp.tv_usec/1000000.0); #else time_now = (double) time(NULL); time_now -= SEC_OFFS_SYS; #endif (void) arg; /* Avoid compiler warnings */ pop(&val); switch(val.type) { case INTGR: push(Ginteger(&val, (int) time_now)); break; case CMPLX: push(Gcomplex(&val, time_now, 0.0)); break; case STRING: push(&val); /* format string */ push(Gcomplex(&val2, time_now, 0.0)); f_strftime(arg); break; default: int_error(NO_CARET,"internal error: invalid argument type"); } }
void f_factorial(union argument *arg) { struct value a; int i; double val = 0.0; (void) arg; /* avoid -Wunused warning */ (void) pop(&a); /* find a! (factorial) */ switch (a.type) { case INTGR: val = 1.0; for (i = a.v.int_val; i > 1; i--) /*fpe's should catch overflows */ val *= i; break; default: int_error(NO_CARET, "factorial (!) argument must be an integer"); return; /* avoid gcc -Wall warning about val */ } push(Gcomplex(&a, val, 0.0)); }
void f_power(union argument *arg) { struct value a, b, result; int i, t, count; double mag, ang; (void) arg; /* avoid -Wunused warning */ (void) pop(&b); (void) pop(&a); /* now find a**b */ switch (a.type) { case INTGR: switch (b.type) { case INTGR: count = abs(b.v.int_val); t = 1; /* this ought to use bit-masks and squares, etc */ for (i = 0; i < count; i++) t *= a.v.int_val; if (b.v.int_val >= 0) (void) Ginteger(&result, t); else if (t != 0) (void) Gcomplex(&result, 1.0 / t, 0.0); else { undefined = TRUE; (void) Gcomplex(&result, 0.0, 0.0); } break; case CMPLX: if (a.v.int_val == 0) { if (b.v.cmplx_val.imag != 0 || b.v.cmplx_val.real < 0) { undefined = TRUE; } /* return 1.0 for 0**0 */ Gcomplex(&result, b.v.cmplx_val.real == 0 ? 1.0 : 0.0, 0.0); } else { mag = pow(magnitude(&a), fabs(b.v.cmplx_val.real)); if (b.v.cmplx_val.real < 0.0) { if (mag != 0.0) mag = 1.0 / mag; else undefined = TRUE; } mag *= gp_exp(-b.v.cmplx_val.imag * angle(&a)); ang = b.v.cmplx_val.real * angle(&a) + b.v.cmplx_val.imag * log(magnitude(&a)); (void) Gcomplex(&result, mag * cos(ang), mag * sin(ang)); } break; BAD_DEFAULT } break; case CMPLX: switch (b.type) { case INTGR: if (a.v.cmplx_val.imag == 0.0) { mag = pow(a.v.cmplx_val.real, (double) abs(b.v.int_val)); if (b.v.int_val < 0) { if (mag != 0.0) mag = 1.0 / mag; else undefined = TRUE; } (void) Gcomplex(&result, mag, 0.0); } else { /* not so good, but...! */ mag = pow(magnitude(&a), (double) abs(b.v.int_val)); if (b.v.int_val < 0) { if (mag != 0.0) mag = 1.0 / mag; else undefined = TRUE; } ang = angle(&a) * b.v.int_val; (void) Gcomplex(&result, mag * cos(ang), mag * sin(ang)); } break; case CMPLX: if (a.v.cmplx_val.real == 0 && a.v.cmplx_val.imag == 0) { if (b.v.cmplx_val.imag != 0 || b.v.cmplx_val.real < 0) { undefined = TRUE; } /* return 1.0 for 0**0 */ Gcomplex(&result, b.v.cmplx_val.real == 0 ? 1.0 : 0.0, 0.0); } else { mag = pow(magnitude(&a), fabs(b.v.cmplx_val.real)); if (b.v.cmplx_val.real < 0.0) { if (mag != 0.0) mag = 1.0 / mag; else undefined = TRUE; } mag *= gp_exp(-b.v.cmplx_val.imag * angle(&a)); ang = b.v.cmplx_val.real * angle(&a) + b.v.cmplx_val.imag * log(magnitude(&a)); (void) Gcomplex(&result, mag * cos(ang), mag * sin(ang)); } break; BAD_DEFAULT } break; BAD_DEFAULT } push(&result); }
void f_div(union argument *arg) { struct value a, b, result; double square; (void) arg; /* avoid -Wunused warning */ (void) pop(&b); (void) pop(&a); /* now do a/b */ switch (a.type) { case INTGR: switch (b.type) { case INTGR: if (b.v.int_val) (void) Ginteger(&result, a.v.int_val / b.v.int_val); else { (void) Ginteger(&result, 0); undefined = TRUE; } break; case CMPLX: square = b.v.cmplx_val.real * b.v.cmplx_val.real + b.v.cmplx_val.imag * b.v.cmplx_val.imag; if (square) (void) Gcomplex(&result, a.v.int_val * b.v.cmplx_val.real / square, -a.v.int_val * b.v.cmplx_val.imag / square); else { (void) Gcomplex(&result, 0.0, 0.0); undefined = TRUE; } break; BAD_DEFAULT } break; case CMPLX: switch (b.type) { case INTGR: if (b.v.int_val) (void) Gcomplex(&result, a.v.cmplx_val.real / b.v.int_val, a.v.cmplx_val.imag / b.v.int_val); else { (void) Gcomplex(&result, 0.0, 0.0); undefined = TRUE; } break; case CMPLX: square = b.v.cmplx_val.real * b.v.cmplx_val.real + b.v.cmplx_val.imag * b.v.cmplx_val.imag; if (square) (void) Gcomplex(&result, (a.v.cmplx_val.real * b.v.cmplx_val.real + a.v.cmplx_val.imag * b.v.cmplx_val.imag) / square, (a.v.cmplx_val.imag * b.v.cmplx_val.real - a.v.cmplx_val.real * b.v.cmplx_val.imag) / square); else { (void) Gcomplex(&result, 0.0, 0.0); undefined = TRUE; } break; BAD_DEFAULT } break; BAD_DEFAULT } push(&result); }
int main(int argc, char **argv) #endif { int i; #ifdef LINUXVGA LINUX_setup(); /* setup VGA before dropping privilege DBT 4/5/99 */ drop_privilege(); #endif /* make sure that we really have revoked root access, this might happen if gnuplot is compiled without vga support but is installed suid by mistake */ #ifdef __linux__ setuid(getuid()); #endif #if defined(MSDOS) && !defined(_Windows) && !defined(__GNUC__) PC_setup(); #endif /* MSDOS !Windows */ /* HBB: Seems this isn't needed any more for DJGPP V2? */ /* HBB: disable all floating point exceptions, just keep running... */ #if defined(DJGPP) && (DJGPP!=2) _control87(MCW_EM, MCW_EM); #endif #if defined(OS2) int rc; #ifdef OS2_IPC char semInputReadyName[40]; sprintf( semInputReadyName, "\\SEM32\\GP%i_Input_Ready", getpid() ); rc = DosCreateEventSem(semInputReadyName,&semInputReady,0,0); if (rc != 0) fputs("DosCreateEventSem error\n",stderr); #endif rc = RexxRegisterSubcomExe("GNUPLOT", (PFN) RexxInterface, NULL); #endif /* malloc large blocks, otherwise problems with fragmented mem */ #ifdef MALLOCDEBUG malloc_debug(7); #endif /* get helpfile from home directory */ #ifdef __DJGPP__ { char *s; strcpy(HelpFile, argv[0]); for (s = HelpFile; *s; s++) if (*s == DIRSEP1) *s = DIRSEP2; /* '\\' to '/' */ strcpy(strrchr(HelpFile, DIRSEP2), "/gnuplot.gih"); } /* Add also some "paranoid" tests for '\\': AP */ #endif /* DJGPP */ #ifdef VMS unsigned int status[2] = { 1, 0 }; #endif #if defined(HAVE_LIBEDITLINE) rl_getc_function = getc_wrapper; #endif #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) /* T.Walter 1999-06-24: 'rl_readline_name' must be this fix name. * It is used to parse a 'gnuplot' specific section in '~/.inputrc' * or gnuplot specific commands in '.editrc' (when using editline * instead of readline) */ rl_readline_name = "Gnuplot"; rl_terminal_name = getenv("TERM"); using_history(); #endif #if defined(HAVE_LIBREADLINE) && !defined(MISSING_RL_TILDE_EXPANSION) rl_complete_with_tilde_expansion = 1; #endif for (i = 1; i < argc; i++) { if (!argv[i]) continue; if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { printf("gnuplot %s patchlevel %s\n", gnuplot_version, gnuplot_patchlevel); return 0; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { printf( "Usage: gnuplot [OPTION]... [FILE]\n" #ifdef X11 "for X11 options see 'help X11->command-line-options'\n" #endif " -V, --version\n" " -h, --help\n" " -p --persist\n" " -e \"command1; command2; ...\"\n" "gnuplot %s patchlevel %s\n" #ifdef DIST_CONTACT "Report bugs to "DIST_CONTACT"\n" " or %s\n", #else "Report bugs to %s\n", #endif gnuplot_version, gnuplot_patchlevel, bug_email); return 0; } else if (!strncmp(argv[i], "-persist", 2) || !strcmp(argv[i], "--persist")) { persist_cl = TRUE; } } #ifdef X11 /* the X11 terminal removes tokens that it recognizes from argv. */ { int n = X11_args(argc, argv); argv += n; argc -= n; } #endif setbuf(stderr, (char *) NULL); #ifdef HAVE_SETVBUF /* this was once setlinebuf(). Docs say this is * identical to setvbuf(,NULL,_IOLBF,0), but MS C * faults this (size out of range), so we try with * size of 1024 instead. [SAS/C does that, too. -lh] * Failing this, I propose we just make the call and * ignore the return : its probably not a big deal */ if (setvbuf(stdout, (char *) NULL, _IOLBF, (size_t) 1024) != 0) (void) fputs("Could not linebuffer stdout\n", stderr); #ifdef X11 /* This call used to be in x11.trm, with the following comment: * Multi-character inputs like escape sequences but also mouse-pasted * text got buffered and therefore didn't trigger the select() function * in X11_waitforinput(). Switching to unbuffered input solved this. * 23 Jan 2002 (joze) * But switching to unbuffered mode causes all characters in the input * buffer to be lost. So the only safe time to do it is on program entry. * The #ifdef X11 is probably unnecessary, but makes the change minimal. * Do any non-X platforms suffer from the same problem? * EAM - Jan 2004. */ setvbuf(stdin, (char *) NULL, _IONBF, 0); #endif #endif gpoutfile = stdout; /* Initialize pre-loaded user variables */ (void) Gcomplex(&udv_pi.udv_value, M_PI, 0.0); udv_NaN = add_udv_by_name("NaN"); (void) Gcomplex(&(udv_NaN->udv_value), not_a_number(), 0.0); udv_NaN->udv_undef = FALSE; init_memory(); interactive = FALSE; init_terminal(); /* can set term type if it likes */ push_terminal(0); /* remember the default terminal */ /* reset the terminal when exiting */ /* this is done through gp_atexit so that other terminal functions * can be registered to be executed before the terminal is reset. */ GP_ATEXIT(term_reset); # if defined(_Windows) && ! defined(WGP_CONSOLE) interactive = TRUE; # else interactive = isatty(fileno(stdin)); # endif if (argc > 1) interactive = noinputfiles = FALSE; else noinputfiles = TRUE; /* Need this before show_version is called for the first time */ #ifdef HAVE_SYS_UTSNAME_H { struct utsname uts; /* something is fundamentally wrong if this fails ... */ if (uname(&uts) > -1) { # ifdef _AIX strcpy(os_name, uts.sysname); sprintf(os_name, "%s.%s", uts.version, uts.release); # elif defined(SCO) strcpy(os_name, "SCO"); strcpy(os_rel, uts.release); # elif defined(DJGPP) if (!strncmp(uts.sysname, "??Un", 4)) /* don't print ??Unknow" */ strcpy(os_name, "Unknown"); else { strcpy(os_name, uts.sysname); strcpy(os_rel, uts.release); } # else strcpy(os_name, uts.sysname); strcpy(os_rel, uts.release); # ifdef OS2 if (!strchr(os_rel,'.')) /* write either "2.40" or "4.0", or empty -- don't print "OS/2 1" */ strcpy(os_rel, ""); # endif # endif } } #else /* ! HAVE_SYS_UTSNAME_H */ strcpy(os_name, OS); strcpy(os_rel, ""); #endif /* HAVE_SYS_UTSNAME_H */ if (interactive) show_version(stderr); else show_version(NULL); /* Only load GPVAL_COMPILE_OPTIONS */ #ifdef WGP_CONSOLE #ifdef CONSOLE_SWITCH_CP if (cp_changed && interactive) { fprintf(stderr, "\ngnuplot changed the codepage of this console from %i to %i to\n" \ "match the graph window. Some characters might only display correctly\n" \ "if you change the font to a non-raster type.\n", cp_input, GetConsoleCP()); } #else if ((GetConsoleCP() != GetACP()) && interactive) { fprintf(stderr, "\nWarning: The codepage of the graph window (%i) and that of the\n" \ "console (%i) differ. Use `set encoding` or `!chcp` if extended\n" \ "characters don't display correctly.\n", GetACP(), GetConsoleCP()); } #endif #endif update_gpval_variables(3); /* update GPVAL_ variables available to user */ #ifdef VMS /* initialise screen management routines for command recall */ if (status[1] = smg$create_virtual_keyboard(&vms_vkid) != SS$_NORMAL) done(status[1]); if (status[1] = smg$create_key_table(&vms_ktid) != SS$_NORMAL) done(status[1]); #endif /* VMS */ if (!SETJMP(command_line_env, 1)) { /* first time */ interrupt_setup(); /* should move this stuff another initialisation routine, * something like init_set() maybe */ get_user_env(); init_loadpath(); init_locale(); /* HBB: make sure all variables start in the same mode 'reset' * would set them to. Since the axis variables aren't in * initialized arrays any more, this is now necessary... */ reset_command(); init_color(); /* Initialization of color */ load_rcfile(); init_fit(); /* Initialization of fitting module */ if (interactive && term != 0) { /* not unknown */ #ifdef GNUPLOT_HISTORY FPRINTF((stderr, "Before read_history\n")); #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) expanded_history_filename = tilde_expand(GNUPLOT_HISTORY_FILE); #else expanded_history_filename = gp_strdup(GNUPLOT_HISTORY_FILE); gp_expand_tilde(&expanded_history_filename); #endif FPRINTF((stderr, "expanded_history_filename = %s\n", expanded_history_filename)); read_history(expanded_history_filename); { /* BEGIN: Go local to get environment variable */ const char *temp_env = getenv ("GNUPLOT_HISTORY_SIZE"); if (temp_env) gnuplot_history_size = strtol (temp_env, (char **) NULL, 10); } /* END: Go local to get environment variable */ /* * It is safe to ignore the return values of 'atexit()' and * 'on_exit()'. In the worst case, there is no history of your * currrent session and you have to type all again in your next * session. * This is the default behaviour (traditional reasons), too. * In case you don't have one of these functions, or you don't * want to use them, 'write_history()' is called directly. */ GP_ATEXIT(wrapper_for_write_history); #endif /* GNUPLOT_HISTORY */ fprintf(stderr, "\nTerminal type set to '%s'\n", term->name); } /* if (interactive && term != 0) */ } else { /* come back here from int_error() */ if (interactive == FALSE) exit_status = EXIT_FAILURE; #ifdef HAVE_READLINE_RESET else { /* reset properly readline after a SIGINT+longjmp */ rl_reset_after_signal (); } #endif load_file_error(); /* if we were in load_file(), cleanup */ SET_CURSOR_ARROW; #ifdef VMS /* after catching interrupt */ /* VAX stuffs up stdout on SIGINT while writing to stdout, so reopen stdout. */ if (gpoutfile == stdout) { if ((stdout = freopen("SYS$OUTPUT", "w", stdout)) == NULL) { /* couldn't reopen it so try opening it instead */ if ((stdout = fopen("SYS$OUTPUT", "w")) == NULL) { /* don't use int_error here - causes infinite loop! */ fputs("Error opening SYS$OUTPUT as stdout\n", stderr); } } gpoutfile = stdout; } #endif /* VMS */ if (!interactive && !noinputfiles) { term_reset(); exit(EXIT_FAILURE); /* exit on non-interactive error */ } } if (argc > 1) { #ifdef _Windows TBOOLEAN noend = persist_cl; #endif /* load filenames given as arguments */ while (--argc > 0) { ++argv; c_token = 0; #ifdef _Windows if (stricmp(*argv, "-noend") == 0 || stricmp(*argv, "/noend") == 0 || stricmp(*argv, "-persist") == 0) noend = TRUE; else #endif if (!strncmp(*argv, "-persist", 2) || !strcmp(*argv, "--persist")) { FPRINTF((stderr,"'persist' command line option recognized\n")); } else if (strcmp(*argv, "-") == 0) { interactive = TRUE; while (!com_line()); interactive = FALSE; } else if (strcmp(*argv, "-e") == 0) { --argc; ++argv; if (argc <= 0) { fprintf(stderr, "syntax: gnuplot -e \"commands\"\n"); return 0; } do_string(*argv); } else { load_file(loadpath_fopen(*argv, "r"), gp_strdup(*argv), FALSE); } } #ifdef _Windows if (noend) { interactive = TRUE; while (!com_line()); } #endif } else { /* take commands from stdin */ while (!com_line()); } #if (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)) && defined(GNUPLOT_HISTORY) #if !defined(HAVE_ATEXIT) && !defined(HAVE_ON_EXIT) /* You should be here if you neither have 'atexit()' nor 'on_exit()' */ wrapper_for_write_history(); #endif /* !HAVE_ATEXIT && !HAVE_ON_EXIT */ #endif /* (HAVE_LIBREADLINE || HAVE_LIBEDITLINE) && GNUPLOT_HISTORY */ #ifdef OS2 RexxDeregisterSubcom("GNUPLOT", NULL); #endif /* HBB 20040223: Not all compilers like exit() to end main() */ /* exit(exit_status); */ return exit_status; }