home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume8 / gnuplot1.10A / part01 / command.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-09  |  23.4 KB  |  1,081 lines

  1. /*
  2.  *
  3.  *    G N U P L O T  --  command.c
  4.  *
  5.  *  Copyright (C) 1986, 1987  Thomas Williams, Colin Kelley
  6.  *
  7.  *  You may use this code as you wish if credit is given and this message
  8.  *  is retained.
  9.  *
  10.  *  Please e-mail any useful additions to vu-vlsi!plot so they may be
  11.  *  included in later releases.
  12.  *
  13.  *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <math.h>
  18.  
  19. #ifdef MSDOS
  20. #include <process.h>
  21. #endif
  22.  
  23. #include "plot.h"
  24.  
  25. #ifndef STDOUT
  26. #define STDOUT 1
  27. #endif
  28.  
  29. /*
  30.  * global variables to hold status of 'set' options
  31.  *
  32.  */
  33. BOOLEAN            polar        = FALSE; 
  34. BOOLEAN            autoscale    = TRUE;
  35. char            dummy_var[MAX_ID_LEN+1] = "x";
  36. enum PLOT_STYLE data_style    = POINTS,
  37.                 func_style    = LINES;
  38. BOOLEAN            log_x        = FALSE,
  39.                 log_y        = FALSE;
  40. FILE*            outfile;
  41. char            outstr[MAX_ID_LEN+1] = "STDOUT";
  42. int                samples        = SAMPLES;
  43. int                term        = 0;                /* unknown term is 0 */
  44. double            xmin        = -10.0,
  45.                 xmax        = 10.0,
  46.                 ymin        = -10.0,
  47.                 ymax        = 10.0;
  48. double            loff        = 0.0,
  49.                 roff        = 0.0,
  50.                 toff        = 0.0,
  51.                 boff        = 0.0;
  52. double            zero = ZERO;            /* zero threshold, not 0! */
  53.  
  54.  
  55. BOOLEAN screen_ok;
  56. BOOLEAN term_init;
  57. BOOLEAN undefined;
  58.  
  59. /*
  60.  * instead of <strings.h>
  61.  */
  62.  
  63. char *gets(),*getenv();
  64. char *strcpy(),*strncpy(),*strcat();
  65.  
  66. char *malloc();
  67.  
  68. double magnitude(),angle(),real(),imag();
  69. struct value *const_express(), *pop(), *complex();
  70. struct at_type *temp_at(), *perm_at();
  71. struct udft_entry *add_udf();
  72. struct udvt_entry *add_udv();
  73.  
  74. extern struct termentry term_tbl[];
  75.  
  76. struct lexical_unit token[MAX_TOKENS];
  77. char input_line[MAX_LINE_LEN+1] = "set term ";
  78. char c_dummy_var[MAX_ID_LEN+1];         /* current dummy var */
  79. int num_tokens, c_token;
  80.  
  81. struct curve_points *first_plot = NULL;
  82. struct udft_entry plot_func, *dummy_func;
  83.  
  84. static char replot_line[MAX_LINE_LEN+1];
  85. static int plot_token;                    /* start of 'plot' command */
  86. static char help[MAX_LINE_LEN] = HELP;
  87.  
  88. com_line()
  89. {
  90.     read_line();
  91.  
  92.     screen_ok = TRUE; /* so we can flag any new output */
  93.  
  94.     do_line();
  95. }
  96.  
  97.  
  98. do_line()      /* also used in load_file */
  99. {
  100.     if (is_comment(input_line[0]))
  101.         return;
  102.     if (is_system(input_line[0])) {
  103.         do_system();
  104.         fputs("!\n",stderr);
  105.         return;
  106.     }
  107.     num_tokens = scanner(input_line);
  108.     c_token = 0;
  109.     while(c_token < num_tokens) {
  110.         command();
  111.         if (c_token < num_tokens)    /* something after command */
  112.             if (equals(c_token,";"))
  113.                 c_token++;
  114.             else
  115.                     int_error("';' expected",c_token);
  116.     }
  117. }
  118.  
  119.  
  120.  
  121. command()
  122. {
  123. static char sv_file[MAX_LINE_LEN+1];
  124.             /* string holding name of save or load file */
  125.  
  126.     c_dummy_var[0] = '\0';        /* no dummy variable */
  127.  
  128.     if (is_definition(c_token))
  129.         define();
  130.     else if (equals(c_token,"help") || equals(c_token,"?")) {
  131.         register int len;
  132.         register char *help_ptr;
  133.  
  134.         c_token++;
  135.         if ((help_ptr = getenv("GNUHELP")))    /* initial command */
  136.             (void) strncpy(help,help_ptr,sizeof(help) - 1);
  137.         else
  138.             (void) strncpy(help,HELP,sizeof(help) - 1);
  139.  
  140.         while (!(END_OF_COMMAND)) {
  141.             len = strlen(help);
  142.             help[len] = ' ';   /* put blank between help segments */
  143.             copy_str(help+len+1,c_token++);
  144.         }
  145.         do_help();
  146.         screen_ok = FALSE;
  147.         c_token++;
  148.     }
  149.     else if (almost_equals(c_token,"pa$use")) {
  150.         struct value a;
  151.         int stime, text=0, len;
  152.         char buf[MAX_LINE_LEN+1], *ptr;
  153.  
  154.         c_token++;
  155.         stime = (int )real(const_express(&a));
  156.         if (!(END_OF_COMMAND)) {
  157.             if (!isstring(c_token))
  158.                 int_error("expecting string",c_token);
  159.             else {
  160.             /*    Unfortunately, quote_str has a ID limit. */
  161.                 len = token[c_token].length - 2;
  162.                 ptr = &input_line[token[c_token].start_index+1];
  163.                 fprintf (stderr, "%.*s", len,ptr);
  164.                 text = 1;
  165.             }
  166.         }
  167.         if (stime < 0) fgets (buf,MAX_LINE_LEN,stdin);  /* Hold until CR hit. */
  168.         if (stime > 0) sleep(stime);
  169.         if (text != 0 && stime >= 0) fprintf (stderr,"\n");
  170.         c_token++;
  171.         screen_ok = FALSE;
  172.     }
  173.     else if (almost_equals(c_token,"pr$int")) {
  174.         struct value a;
  175.  
  176.         c_token++;
  177.         (void) const_express(&a);
  178.         (void) putc('\t',stderr);
  179.         disp_value(stderr,&a);
  180.         (void) putc('\n',stderr);
  181.         screen_ok = FALSE;
  182.     }
  183.     else if (almost_equals(c_token,"p$lot")) {
  184.         plot_token = c_token++;
  185.         plotrequest();
  186.     }
  187.     else if (almost_equals(c_token,"rep$lot")) {
  188.         if (replot_line[0] == '\0') 
  189.             int_error("no previous plot",c_token);
  190.         (void) strcpy(input_line,replot_line);
  191.         screen_ok = FALSE;
  192.         num_tokens = scanner(input_line);
  193.         c_token = 1;                    /* skip the 'plot' part */
  194.         plotrequest();
  195.     }
  196.     else if (almost_equals(c_token,"se$t"))
  197.         set_stuff();
  198.     else if (almost_equals(c_token,"sh$ow"))
  199.         show_stuff();
  200.     else if (almost_equals(c_token,"cl$ear")) {
  201.         if (!term_init) {
  202.             (*term_tbl[term].init)();
  203.             term_init = TRUE;
  204.         }
  205.         (*term_tbl[term].graphics)();
  206.         (*term_tbl[term].text)();
  207.         (void) fflush(outfile);
  208.         screen_ok = FALSE;
  209.         c_token++;
  210.     }
  211.     else if (almost_equals(c_token,"she$ll")) {
  212.         do_shell();
  213.         screen_ok = FALSE;
  214.         c_token++;
  215.     }
  216.     else if (almost_equals(c_token,"sa$ve")) {
  217.         if (almost_equals(++c_token,"f$unctions")) {
  218.             if (!isstring(++c_token))
  219.                 int_error("expecting filename",c_token);
  220.             else {
  221.                 quote_str(sv_file,c_token);
  222.                 save_functions(fopen(sv_file,"w"));
  223.             }
  224.         }
  225.         else if (almost_equals(c_token,"v$ariables")) {
  226.             if (!isstring(++c_token))
  227.                 int_error("expecting filename",c_token);
  228.             else {
  229.                 quote_str(sv_file,c_token);
  230.                 save_variables(fopen(sv_file,"w"));
  231.             }
  232.         }
  233.         else if (isstring(c_token)) {
  234.             quote_str(sv_file,c_token);
  235.             save_all(fopen(sv_file,"w"));
  236.         }
  237.         else {
  238.             int_error(
  239.         "filename or keyword 'functions' or 'variables' expected",c_token);
  240.         }
  241.         c_token++;
  242.     }
  243.     else if (almost_equals(c_token,"l$oad")) {
  244.         if (!isstring(++c_token))
  245.             int_error("expecting filename",c_token);
  246.         else {
  247.             quote_str(sv_file,c_token);
  248.             load_file(fopen(sv_file,"r"));    
  249.         /* input_line[] and token[] now destroyed! */
  250.             c_token = num_tokens = 0;
  251.         }
  252.     }
  253.     else if (almost_equals(c_token,"ex$it") ||
  254.             almost_equals(c_token,"q$uit")) {
  255.         done(IO_SUCCESS);
  256.     }
  257.     else if (!equals(c_token,";")) {        /* null statement */
  258.         int_error("invalid command",c_token);
  259.     }
  260. }
  261.  
  262.  
  263. enum PLOT_STYLE
  264. get_style()
  265. {
  266. register enum PLOT_STYLE ps;
  267.  
  268.     c_token++;
  269.     if (almost_equals(c_token,"l$ines"))
  270.         ps = LINES;
  271.     else if (almost_equals(c_token,"i$mpulses"))
  272.         ps = IMPULSES;
  273.     else if (almost_equals(c_token,"p$oints"))
  274.         ps = POINTS;
  275.     else
  276.         int_error("expecting 'lines', 'points', or 'impulses'",c_token);
  277.     c_token++;
  278.     return(ps);
  279. }
  280.  
  281.  
  282. set_stuff()
  283. {
  284. static char testfile[MAX_LINE_LEN+1];
  285.  
  286.     if (almost_equals(++c_token,"a$utoscale")) {
  287.         autoscale = TRUE;
  288.         c_token++;
  289.     }
  290.     else if (almost_equals(c_token,"noa$utoscale")) {
  291.         autoscale = FALSE;
  292.         c_token++;
  293.     }
  294.     else if (almost_equals(c_token,"po$lar")) {
  295.         polar = TRUE;
  296.         xmin = 0.0;
  297.         xmax = 2*Pi;
  298.         c_token++;
  299.     }
  300.     else if (almost_equals(c_token,"nopo$lar")) {
  301.         polar = FALSE;
  302.         xmin = -10.0;
  303.         xmax = 10.0;
  304.         c_token++;
  305.     }
  306.     else if (almost_equals(c_token,"d$ata")) {
  307.         c_token++;
  308.         if (!almost_equals(c_token,"s$tyle"))
  309.             int_error("expecting keyword 'style'",c_token);
  310.         data_style = get_style();
  311.     }
  312.     else if (almost_equals(c_token,"d$ummy")) {
  313.         c_token++;
  314.         copy_str(dummy_var,c_token++);
  315.     }
  316.     else if (almost_equals(c_token,"f$unction")) {
  317.         c_token++;
  318.         if (!almost_equals(c_token,"s$tyle"))
  319.             int_error("expecting keyword 'style'",c_token);
  320.         func_style = get_style();
  321.     }
  322.     else if (almost_equals(c_token,"l$ogscale")) {
  323.         c_token++;
  324.         if (equals(c_token,"x")) {
  325.             log_y = FALSE;
  326.             log_x = TRUE;
  327.             c_token++;
  328.         }
  329.         else if (equals(c_token,"y")) {
  330.             log_x = FALSE;
  331.             log_y = TRUE;
  332.             c_token++;
  333.         }
  334.         else if (equals(c_token,"xy") || equals(c_token,"yx")) {
  335.             log_x = log_y = TRUE;
  336.             c_token++;
  337.         }
  338.         else
  339.             int_error("expecting 'x', 'y', or 'xy'",c_token);
  340.     }
  341.     else if (almost_equals(c_token,"nol$ogscale")) {
  342.         log_x = log_y = FALSE;
  343.         c_token++;
  344.     }
  345.     else if (almost_equals(c_token,"of$fsets")) {
  346.         c_token++;
  347.         if (END_OF_COMMAND) {
  348.             loff = roff = toff = boff = 0.0;  /* Reset offsets */
  349.         }
  350.         else {
  351.             load_offsets (&loff,&roff,&toff,&boff);
  352.         }
  353.     }
  354.     else if (almost_equals(c_token,"o$utput")) {
  355.         register FILE *f;
  356.  
  357.         c_token++;
  358.         if (END_OF_COMMAND) {    /* no file specified */
  359.              UP_redirect (4);
  360. #ifdef VMS
  361.             if (outfile != stdout) /* Never close stdout */
  362. #endif
  363.             (void) fclose(outfile);
  364. #ifdef VMS
  365.             outfile = stdout; /* Avoid the dup... */
  366. #else
  367.             outfile = fdopen(dup(STDOUT), "w");
  368. #endif
  369.             term_init = FALSE;
  370.             (void) strcpy(outstr,"STDOUT");
  371.         } else if (!isstring(c_token))
  372.             int_error("expecting filename",c_token);
  373.         else {
  374.             quote_str(testfile,c_token);
  375.             if (!(f = fopen(testfile,"w"))) {
  376.               os_error("cannot open file; output not changed",c_token);
  377.             }
  378. #ifdef VMS
  379.             if (outfile != stdout) /* Never close stdout */
  380. #endif
  381.             (void) fclose(outfile);
  382.             outfile = f;
  383.             term_init = FALSE;
  384.             outstr[0] = '\'';
  385.             (void) strcat(strcpy(outstr+1,testfile),"'");
  386.              UP_redirect (1);
  387.         }
  388.         c_token++;
  389.     }
  390.     else if (almost_equals(c_token,"sa$mples")) {
  391.         register int tsamp;
  392.         struct value a;
  393.  
  394.         c_token++;
  395.         tsamp = (int)magnitude(const_express(&a));
  396.         if (tsamp < 1)
  397.             int_error("sampling rate must be > 0; sampling unchanged",
  398.                 c_token);
  399.         else {
  400.             register struct curve_points *f_p = first_plot;
  401.  
  402.             first_plot = NULL;
  403.             cp_free(f_p);
  404.             samples = tsamp;
  405.         }
  406.     }
  407.     else if (almost_equals(c_token,"t$erminal")) {
  408.         c_token++;
  409.         if (END_OF_COMMAND) {
  410.             list_terms();
  411.             screen_ok = FALSE;
  412.         }
  413.         else
  414.             term = set_term(c_token);
  415.         c_token++;
  416.     }
  417.     else if (almost_equals(c_token,"x$range")) {
  418.         c_token++;
  419.         if (!equals(c_token,"["))
  420.             int_error("expecting '['",c_token);
  421.         c_token++;
  422.         load_range(&xmin,&xmax);
  423.         if (!equals(c_token,"]"))
  424.             int_error("expecting ']'",c_token);
  425.         c_token++;
  426.     }
  427.     else if (almost_equals(c_token,"y$range")) {
  428.         c_token++;
  429.         if (!equals(c_token,"["))
  430.             int_error("expecting '['",c_token);
  431.         c_token++;
  432.         load_range(&ymin,&ymax);
  433.         autoscale = FALSE;
  434.         if (!equals(c_token,"]"))
  435.             int_error("expecting ']'",c_token);
  436.         c_token++;
  437.     }
  438.     else if (almost_equals(c_token,"z$ero")) {
  439.         struct value a;
  440.         c_token++;
  441.         zero = magnitude(const_express(&a));
  442.     }
  443.     else
  444.         int_error(
  445.     "valid set options:  '[no]autoscale', 'data', 'dummy', 'function',\n\
  446. '[no]logscale', 'offsets', 'output', '[no]polar', 'samples',\n\
  447. 'terminal', 'xrange', 'yrange', 'zero'",
  448.     c_token);
  449. }
  450.  
  451.  
  452. show_stuff()
  453. {
  454.     if (almost_equals(++c_token,"ac$tion_table") ||
  455.              equals(c_token,"at") ) {
  456.         c_token++;
  457.         show_at();
  458.         c_token++;
  459.     }
  460.     else if (almost_equals(c_token,"au$toscale")) {
  461.         (void) putc('\n',stderr);
  462.         show_autoscale();
  463.         c_token++;
  464.     }
  465.     else if (almost_equals(c_token,"d$ata")) {
  466.         c_token++;
  467.         if (!almost_equals(c_token,"s$tyle"))
  468.             int_error("expecting keyword 'style'",c_token);
  469.         (void) putc('\n',stderr);
  470.         show_style("data",data_style);
  471.         c_token++;
  472.     }
  473.     else if (almost_equals(c_token,"d$ummy")) {
  474.         fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
  475.         c_token++;
  476.     }
  477.     else if (almost_equals(c_token,"f$unctions")) {
  478.         c_token++;
  479.         if (almost_equals(c_token,"s$tyle"))  {
  480.             (void) putc('\n',stderr);
  481.             show_style("functions",func_style);
  482.             c_token++;
  483.         }
  484.         else
  485.             show_functions();
  486.     }
  487.     else if (almost_equals(c_token,"l$ogscale")) {
  488.         (void) putc('\n',stderr);
  489.         show_logscale();
  490.         c_token++;
  491.     }
  492.     else if (almost_equals(c_token,"of$fsets")) {
  493.         (void) putc('\n',stderr);
  494.         show_offsets();
  495.         c_token++;
  496.     }
  497.     else if (almost_equals(c_token,"o$utput")) {
  498.         (void) putc('\n',stderr);
  499.         show_output();
  500.         c_token++;
  501.     }
  502.     else if (almost_equals(c_token,"po$lar")) {
  503.         (void) putc('\n',stderr);
  504.         show_polar();
  505.         c_token++;
  506.     }
  507.     else if (almost_equals(c_token,"sa$mples")) {
  508.         (void) putc('\n',stderr);
  509.         show_samples();
  510.         c_token++;
  511.     }
  512.     else if (almost_equals(c_token,"t$erminal")) {
  513.         (void) putc('\n',stderr);
  514.         show_term();
  515.         c_token++;
  516.     }
  517.     else if (almost_equals(c_token,"v$ariables")) {
  518.         show_variables();
  519.         c_token++;
  520.     }
  521.     else if (almost_equals(c_token,"ve$rsion")) {
  522.         show_version();
  523.         c_token++;
  524.     }
  525.     else if (almost_equals(c_token,"x$range")) {
  526.         (void) putc('\n',stderr);
  527.         show_range('x',xmin,xmax);
  528.         c_token++;
  529.     }
  530.     else if (almost_equals(c_token,"y$range")) {
  531.         (void) putc('\n',stderr);
  532.         show_range('y',ymin,ymax);
  533.         c_token++;
  534.     }
  535.     else if (almost_equals(c_token,"z$ero")) {
  536.         (void) putc('\n',stderr);
  537.         show_zero();
  538.         c_token++;
  539.     }
  540.     else if (almost_equals(c_token,"a$ll")) {
  541.         c_token++;
  542.         show_version();
  543.         show_polar();
  544.         fprintf(stderr,"\tdummy variable is %s\n",dummy_var);
  545.         show_style("data",data_style);
  546.         show_style("functions",func_style);
  547.         show_output();
  548.         show_term();
  549.         show_samples();
  550.         show_logscale();
  551.         show_autoscale();
  552.         show_zero();
  553.         show_range('x',xmin,xmax);
  554.         show_range('y',ymin,ymax);
  555.         show_offsets();
  556.         show_variables();
  557.         show_functions();
  558.         c_token++;
  559.     }
  560.     else
  561.         int_error(
  562.     "valid show options:  'action_table', 'all', 'autoscale', 'data',\n\
  563. 'dummy', 'function', 'logscale', 'offsets', 'output', 'polar',\n\
  564. 'samples', 'terminal', 'variables', 'version', 'xrange', 'yrange', 'zero'",
  565. c_token);
  566.     screen_ok = FALSE;
  567.     (void) putc('\n',stderr);
  568. }
  569.  
  570.  
  571. load_offsets (a, b, c, d)
  572. double *a,*b, *c, *d;
  573. {
  574. struct value t;
  575.  
  576.     *a = real (const_express(&t));  /* loff value */
  577.     c_token++;
  578.     if (equals(c_token,","))
  579.         c_token++;
  580.     if (END_OF_COMMAND) 
  581.         return;
  582.  
  583.     *b = real (const_express(&t));  /* roff value */
  584.     c_token++;
  585.     if (equals(c_token,","))
  586.         c_token++;
  587.     if (END_OF_COMMAND) 
  588.         return;
  589.  
  590.     *c = real (const_express(&t));  /* toff value */
  591.     c_token++;
  592.     if (equals(c_token,","))
  593.         c_token++;
  594.     if (END_OF_COMMAND) 
  595.         return;
  596.  
  597.     *d = real (const_express(&t));  /* boff value */
  598.     c_token++;
  599. }
  600.  
  601.  
  602. load_range(a,b)
  603. double *a,*b;
  604. {
  605. struct value t;
  606.  
  607.     if (equals(c_token,"]"))
  608.         return;
  609.     if (END_OF_COMMAND) {
  610.         int_error("starting range value or ':' expected",c_token);
  611.     } else if (!equals(c_token,"to") && !equals(c_token,":"))  {
  612.         *a = real(const_express(&t));
  613.     }    
  614.     if (!equals(c_token,"to") && !equals(c_token,":"))
  615.         int_error("':' expected",c_token);
  616.     c_token++;
  617.     if (!equals(c_token,"]"))
  618.         *b = real(const_express(&t));
  619. }
  620.  
  621.  
  622. plotrequest()
  623. {
  624.     
  625.     if (!term)                    /* unknown */
  626.         int_error("use 'set term' to set terminal type first",c_token);
  627.  
  628.     if (equals(c_token,"[")) {
  629.         c_token++;
  630.         if (isletter(c_token)) {
  631.             copy_str(c_dummy_var,c_token++);
  632.             if (equals(c_token,"="))
  633.                 c_token++;
  634.             else
  635.                 int_error("'=' expected",c_token);
  636.         }
  637.         load_range(&xmin,&xmax);
  638.         if (!equals(c_token,"]"))
  639.             int_error("']' expected",c_token);
  640.         c_token++;
  641.     }
  642.  
  643.     if (equals(c_token,"[")) { /* set optional y ranges */
  644.         c_token++;
  645.         load_range(&ymin,&ymax);
  646.         autoscale = FALSE;
  647.         if (!equals(c_token,"]"))
  648.             int_error("']' expected",c_token);
  649.         c_token++;
  650.     }
  651.  
  652.     eval_plots();
  653. }
  654.  
  655.  
  656. define()
  657. {
  658. register int start_token;  /* the 1st token in the function definition */
  659. register struct udvt_entry *udv;
  660. register struct udft_entry *udf;
  661.  
  662.     if (equals(c_token+1,"(")) {
  663.         /* function ! */
  664.         start_token = c_token;
  665.         copy_str(c_dummy_var, c_token + 2);
  666.         c_token += 5; /* skip (, dummy, ) and = */
  667.         if (END_OF_COMMAND)
  668.             int_error("function definition expected",c_token);
  669.         udf = dummy_func = add_udf(start_token);
  670.         if (udf->at)                /* already a dynamic a.t. there */
  671.             free((char *)udf->at);    /* so free it first */
  672.         if (!(udf->at = perm_at()))
  673.             int_error("not enough memory for function",start_token);
  674.         m_capture(&(udf->definition),start_token,c_token-1);
  675.     }
  676.     else {
  677.         /* variable ! */
  678.         start_token = c_token;
  679.         c_token +=2;
  680.         udv = add_udv(start_token);
  681.         (void) const_express(&(udv->udv_value));
  682.         udv->udv_undef = FALSE;
  683.     }
  684. }
  685.  
  686.  
  687. get_data(this_plot)
  688. struct curve_points *this_plot;
  689. {
  690. static char data_file[MAX_LINE_LEN+1], line[MAX_LINE_LEN+1];
  691. register int i, overflow, l_num;
  692. register FILE *fp;
  693. float x, y;
  694.  
  695.     quote_str(data_file, c_token);
  696.     this_plot->plot_type = DATA;
  697.     if (!(fp = fopen(data_file, "r")))
  698.         os_error("can't open data file", c_token);
  699.  
  700.     l_num = 0;
  701.  
  702.     overflow = i = 0;
  703.  
  704.     while (fgets(line, MAX_LINE_LEN, fp)) {
  705.         l_num++;
  706.         if (is_comment(line[0]) || ! line[1])    /* line[0] will be '\n' */
  707.             continue;        /* ignore comments  and blank lines */
  708.  
  709.         if (i == samples+1) {
  710.             overflow = i;    /* keep track for error message later */
  711.             i--;            /* so we don't fall off end of points[i] */
  712.         }
  713.         switch (sscanf(line, "%f %f", &x, &y)) {
  714.             case 1:            /* only one number on the line */
  715.                 y = x;        /* so use it as the y value, */
  716.                 x = i;        /* and use the index as the x */
  717.             /* no break; !!! */
  718.             case 2:
  719.                 this_plot->points[i].undefined = TRUE;
  720.                 if (x >= xmin && x <= xmax && (autoscale ||
  721.                     (y >= ymin && y <= ymax))) {
  722.                     if (log_x) {
  723.                         if (x <= 0.0)
  724.                             break;
  725.                         this_plot->points[i].x = log10(x);
  726.                     } else
  727.                         this_plot->points[i].x = x;
  728.                     if (log_y) {
  729.                         if (y <= 0.0)
  730.                             break;
  731.                         this_plot->points[i].y = log10(y);
  732.                     } else
  733.                         this_plot->points[i].y = y;
  734.                     if (autoscale) {
  735.                         if (y < ymin) ymin = y;
  736.                         if (y > ymax) ymax = y;
  737.                     }
  738.  
  739.                     this_plot->points[i].undefined = FALSE;
  740.                 }
  741.                 if (overflow)
  742.                     overflow++;
  743.                 else
  744.                     i++;
  745.                 break;
  746.  
  747.             default:
  748.                 (void) sprintf(line, "bad data on line %d", l_num);
  749.                 int_error(line,c_token);
  750.         }
  751.     }
  752.     if (overflow) {
  753.         (void) sprintf(line,
  754.     "%d data points found--samples must be set at least this high",overflow);
  755.                 /* actually, samples can be one less! */
  756.         int_error(line,c_token);
  757.     }
  758.     this_plot->p_count = i;
  759.     (void) fclose(fp);
  760. }
  761.  
  762.  
  763. eval_plots()
  764. {
  765. register int i;
  766. register struct curve_points *this_plot, **tp_ptr;
  767. register int start_token, mysamples;
  768. register double x_min, x_max, y_min, y_max, x;
  769. register double xdiff, temp;
  770. register int plot_num;
  771. static struct value a;
  772.  
  773.     /* don't sample higher than output device can handle! */
  774.     mysamples = (samples <= term_tbl[term].xmax) ?samples :term_tbl[term].xmax;
  775.  
  776.     if (log_x) {
  777.         if (xmin < 0.0 || xmax < 0.0)
  778.             int_error("x range must be above 0 for log scale!",NO_CARET);
  779.         x_min = log10(xmin);
  780.         x_max = log10(xmax);
  781.     } else {
  782.         x_min = xmin;
  783.         x_max = xmax;
  784.     }
  785.  
  786.     if (autoscale) {
  787.         ymin = HUGE;
  788.         ymax = -HUGE;
  789.     } else if (log_y && (ymin <= 0.0 || ymax <= 0.0))
  790.             int_error("y range must be above 0 for log scale!",
  791.                 NO_CARET);
  792.  
  793.     xdiff = (x_max - x_min) / mysamples;
  794.  
  795.     tp_ptr = &(first_plot);
  796.     plot_num = 0;
  797.  
  798.     while (TRUE) {
  799.         if (END_OF_COMMAND)
  800.             int_error("function to plot expected",c_token);
  801.  
  802.         start_token = c_token;
  803.  
  804.         if (is_definition(c_token)) {
  805.             define();
  806.         } else {
  807.             plot_num++;
  808.             if (*tp_ptr)
  809.                 this_plot = *tp_ptr;
  810.             else {        /* no memory malloc()'d there yet */
  811.                 this_plot = (struct curve_points *)
  812.                     malloc((unsigned int) (sizeof(struct curve_points) -
  813.                     (MAX_POINTS - (samples+1))*sizeof(struct coordinate)));
  814.                 if (!this_plot)
  815.                     int_error("out of memory",c_token);
  816.                 this_plot->next_cp = NULL;
  817.                 this_plot->title = NULL;
  818.                 *tp_ptr = this_plot;
  819.             }
  820.  
  821.             if (isstring(c_token)) {            /* data file to plot */
  822.                 this_plot->plot_type = DATA;
  823.                 this_plot->plot_style = data_style;
  824.                 get_data(this_plot);
  825.                 c_token++;
  826.             }
  827.             else {                            /* function to plot */
  828.                 this_plot->plot_type = FUNC;
  829.                 this_plot->plot_style = func_style;
  830.  
  831.                 (void) strcpy(c_dummy_var,dummy_var);
  832.                 dummy_func = &plot_func;
  833.  
  834.                 plot_func.at = temp_at();
  835.  
  836.                 for (i = 0; i <= mysamples; i++) {
  837.                     if (i == samples+1)
  838.                         int_error("number of points exceeded samples",
  839.                             NO_CARET);
  840.                     x = x_min + i*xdiff;
  841.                     if (log_x)
  842.                         x = pow(10.0,x);
  843.                     (void) complex(&plot_func.dummy_value, x, 0.0);
  844.                     
  845.                     evaluate_at(plot_func.at,&a);
  846.  
  847.                     if (this_plot->points[i].undefined =
  848.                         undefined || (fabs(imag(&a)) > zero))
  849.                             continue;
  850.                 /*    
  851.                     The old code used plot_type to generate x, but with
  852.                     polar and offset concepts we need to record the x
  853.                     value.
  854.                 */
  855.                     this_plot->points[i].x = x;
  856.  
  857.                     temp = real(&a);
  858.  
  859.                     if (log_y && temp <= 0.0) {
  860.                             this_plot->points[i].undefined = TRUE;
  861.                             continue;
  862.                     }
  863.                     if (autoscale) {
  864.                         if (temp < ymin) ymin = temp;
  865.                         if (temp > ymax) ymax = temp;
  866.                     } else if (temp < ymin || temp > ymax) {
  867.                         this_plot->points[i].undefined = TRUE;
  868.                         continue;
  869.                     }
  870.  
  871.                     this_plot->points[i].y = log_y ? log10(temp) : temp;
  872.                 }
  873.                 this_plot->p_count = i; /* mysamples + 1 */
  874.             }
  875.             m_capture(&(this_plot->title),start_token,c_token-1);
  876.             if (almost_equals(c_token,"w$ith"))
  877.                 this_plot->plot_style = get_style();
  878.             tp_ptr = &(this_plot->next_cp);
  879.         }
  880.  
  881.         if (equals(c_token,","))
  882.             c_token++;
  883.         else
  884.             break;
  885.     }
  886.  
  887.     if (autoscale && (ymin == ymax))
  888.         ymax += 1.0;    /* kludge to avoid divide-by-zero in do_plot */
  889.  
  890.     if (log_y) {
  891.         y_min = log10(ymin);
  892.         y_max = log10(ymax);
  893.     } else {
  894.         y_min = ymin;
  895.         y_max = ymax;
  896.     }
  897.     capture(replot_line,plot_token,c_token);    
  898.     do_plot(first_plot,plot_num,x_min,x_max,y_min,y_max);
  899. }
  900.  
  901.  
  902.  
  903. done(status)
  904. int status;
  905. {
  906.     if (term)
  907.         (*term_tbl[term].reset)();
  908.     exit(status);
  909. }
  910.  
  911.  
  912. #ifdef vms
  913.  
  914. #include <descrip.h>
  915. #include <rmsdef.h>
  916. #include <errno.h>
  917.  
  918. extern lib$get_input(), lib$put_output();
  919.  
  920. int vms_len;
  921.  
  922. unsigned int status[2] = {1, 0};
  923.  
  924. $DESCRIPTOR(prompt_desc,PROMPT);
  925. $DESCRIPTOR(line_desc,input_line);
  926.  
  927. $DESCRIPTOR(help_desc,help);
  928. $DESCRIPTOR(helpfile_desc,"GNUPLOT$HELP");
  929.  
  930.  
  931. read_line()
  932. {
  933.     switch(status[1] = lib$get_input(&line_desc, &prompt_desc, &vms_len)){
  934.         case RMS$_EOF:
  935.             done(IO_SUCCESS);    /* ^Z isn't really an error */
  936.             break;
  937.         case RMS$_TNS:            /* didn't press return in time */
  938.             vms_len--;        /* skip the last character */
  939.             break;            /* and parse anyway */
  940.         case RMS$_BES:            /* Bad Escape Sequence */
  941.         case RMS$_PES:            /* Partial Escape Sequence */
  942.             sys$putmsg(status);
  943.             vms_len = 0;        /* ignore the line */
  944.             break;
  945.         case SS$_NORMAL:
  946.             break;            /* everything's fine */
  947.         default:
  948.             done(status[1]);    /* give the error message */
  949.     }
  950.     input_line[vms_len] = '\0';
  951. }
  952.  
  953.  
  954. do_help()
  955. {
  956.     help_desc.dsc$w_length = strlen(help);
  957.     if ((vaxc$errno = lbr$output_help(lib$put_output,0,&help_desc,
  958.         &helpfile_desc,0,lib$get_input)) != SS$_NORMAL)
  959.             os_error("can't open GNUPLOT$HELP");
  960. }
  961.  
  962.  
  963. do_shell()
  964. {
  965.     if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
  966.         os_error("spawn error",NO_CARET);
  967.     }
  968. }
  969.  
  970.  
  971. do_system()
  972. {
  973.     input_line[0] = ' ';    /* an embarrassment, but... */
  974.  
  975.     if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
  976.         os_error("spawn error",NO_CARET);
  977.  
  978.     (void) putc('\n',stderr);
  979. }
  980.  
  981. #else /* vms */
  982.  
  983. do_help()
  984. {
  985.     if (system(help))
  986.         os_error("can't spawn help",c_token);
  987. }
  988.  
  989.  
  990. do_system()
  991. {
  992.     if (system(input_line + 1))
  993.         os_error("system() failed",NO_CARET);
  994. }
  995.  
  996. #ifdef MSDOS
  997.  
  998. read_line()
  999. {
  1000. register int i;
  1001.  
  1002.     input_line[0] = MAX_LINE_LEN - 1;
  1003.     cputs(PROMPT);
  1004.     cgets(input_line);            /* console input so CED will work */
  1005.     (void) putc('\n',stderr);
  1006.     if (input_line[2] == 26) {
  1007.         (void) putc('\n',stderr);        /* end-of-file */
  1008.         done(IO_SUCCESS);
  1009.     }
  1010.  
  1011.     i = 0;
  1012.     while (input_line[i] = input_line[i+2])
  1013.         i++;        /* yuck!  move everything down two characters */
  1014. }
  1015.  
  1016.  
  1017. do_shell()
  1018. {
  1019. register char *comspec;
  1020.     if (!(comspec = getenv("COMSPEC")))
  1021.         comspec = "\command.com";
  1022.     if (spawnl(P_WAIT,comspec,NULL) == -1)
  1023.         os_error("unable to spawn shell",NO_CARET);
  1024. }
  1025.  
  1026. #else /* MSDOS */
  1027.         /* plain old Unix */
  1028.  
  1029. read_line()
  1030. {
  1031.     fputs(PROMPT,stderr);
  1032.     if (!fgets(input_line, MAX_LINE_LEN, stdin)) {
  1033.         (void) putc('\n',stderr);        /* end-of-file */
  1034.         done(IO_SUCCESS);
  1035.     }
  1036.     else {
  1037.         input_line[strlen(input_line)-1] = '\0';  /* Remove trailing \n */
  1038.     }
  1039. }
  1040.  
  1041. #ifdef VFORK
  1042.  
  1043. do_shell()
  1044. {
  1045. register char *shell;
  1046. register int p;
  1047. static int execstat;
  1048.     if (!(shell = getenv("SHELL")))
  1049.         shell = SHELL;
  1050.     if ((p = vfork()) == 0) {
  1051.         execstat = execl(shell,shell,NULL);
  1052.         _exit(1);
  1053.     } else if (p == -1)
  1054.         os_error("vfork failed",c_token);
  1055.     else
  1056.         while (wait(NULL) != p)
  1057.             ;
  1058.     if (execstat == -1)
  1059.         os_error("shell exec failed",c_token);
  1060.     (void) putc('\n',stderr);
  1061. }
  1062. #else /* VFORK */
  1063.  
  1064. #define EXEC "exec "
  1065. do_shell()
  1066. {
  1067. static char exec[100] = EXEC;
  1068. register char *shell;
  1069.     if (!(shell = getenv("SHELL")))
  1070.         shell = SHELL;
  1071.  
  1072.     if (system(strncpy(&exec[sizeof(EXEC)-1],shell,
  1073.         sizeof(exec)-sizeof(EXEC)-1)))
  1074.         os_error("system() failed",NO_CARET);
  1075.  
  1076.     (void) putc('\n',stderr);
  1077. }
  1078. #endif /* VFORK */
  1079. #endif /* MSDOS */
  1080. #endif /* vms */
  1081.