home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume11 / gnuplot2 / part05 < prev    next >
Encoding:
Text File  |  1990-03-25  |  72.8 KB  |  2,924 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Pixar -- Marin County, California
  3. subject: v11i070: Gnuplot 2.0 - 5 of 14
  4. From: thaw@ucbvax.Berkeley.EDU@pixar.UUCP (Tom Williams)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 11, Issue 70
  8. Submitted-by: thaw@ucbvax.Berkeley.EDU@pixar.UUCP (Tom Williams)
  9. Archive-name: gnuplot2/part05
  10.  
  11. This is gnuplot.sh05
  12.  
  13. --- CUT HERE ---
  14. #! /bin/sh
  15. echo x - command.c
  16. sed 's/^X//' >command.c <<'*-*-END-of-command.c-*-*'
  17. X/* GNUPLOT - command.c */
  18. X/*
  19. X * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  20. X *
  21. X * Permission to use, copy, and distribute this software and its
  22. X * documentation for any purpose with or without fee is hereby granted, 
  23. X * provided that the above copyright notice appear in all copies and 
  24. X * that both that copyright notice and this permission notice appear 
  25. X * in supporting documentation.
  26. X *
  27. X * Permission to modify the software is granted, but not the right to
  28. X * distribute the modified code.  Modifications are to be distributed 
  29. X * as patches to released version.
  30. X *  
  31. X * This software  is provided "as is" without express or implied warranty.
  32. X * 
  33. X *
  34. X * AUTHORS
  35. X * 
  36. X *   Original Software:
  37. X *     Thomas Williams,  Colin Kelley.
  38. X * 
  39. X *   Gnuplot 2.0 additions:
  40. X *       Russell Lang, Dave Kotz, John Campbell.
  41. X * 
  42. X * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
  43. X * 
  44. X */
  45. X
  46. X#include <stdio.h>
  47. X#include <math.h>
  48. X
  49. X#ifdef MSDOS
  50. X#include <process.h>
  51. X
  52. X#ifdef __ZTC__
  53. X#define P_WAIT 0
  54. X#include <time.h>    /* usleep() */
  55. X#else
  56. X
  57. X#ifdef __TURBOC__
  58. X#include <dos.h>    /* sleep() */
  59. X
  60. X#else    /* must be MSC */
  61. X#include <time.h>    /* kludge to provide sleep() */
  62. Xvoid sleep();        /* defined later */
  63. X#endif /* TURBOC */
  64. X#endif /* ZTC */
  65. X
  66. X#endif /* MSDOS */
  67. X
  68. X
  69. X#include "plot.h"
  70. X#include "setshow.h"
  71. X#include "help.h"
  72. X
  73. X#ifndef STDOUT
  74. X#define STDOUT 1
  75. X#endif
  76. X
  77. X#ifndef HELPFILE
  78. X#define HELPFILE "docs/gnuplot.gih" /* changed by makefile */
  79. X#endif
  80. X
  81. X#define inrange(z,min,max) ((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)) )
  82. X
  83. X/*
  84. X * instead of <strings.h>
  85. X */
  86. X
  87. Xextern char *gets(),*getenv();
  88. Xextern char *strcpy(),*strncpy(),*strcat();
  89. Xextern int strlen(), strcmp();
  90. X
  91. Xextern double magnitude(),angle(),real(),imag();
  92. Xextern struct value *const_express(), *pop(), *complex();
  93. Xextern struct at_type *temp_at(), *perm_at();
  94. Xextern struct udft_entry *add_udf();
  95. Xextern struct udvt_entry *add_udv();
  96. Xextern void squash_spaces();
  97. Xextern void lower_case();
  98. X
  99. Xextern BOOLEAN interactive;    /* from plot.c */
  100. X
  101. X/* input data, parsing variables */
  102. Xstruct lexical_unit token[MAX_TOKENS];
  103. Xchar input_line[MAX_LINE_LEN+1] = "";
  104. Xint num_tokens, c_token;
  105. Xint inline_num = 0;            /* input line number */
  106. X
  107. Xchar c_dummy_var[MAX_ID_LEN+1];         /* current dummy var */
  108. X
  109. X/* the curves of the plot */
  110. Xstruct curve_points *first_plot = NULL;
  111. Xstatic struct udft_entry plot_func;
  112. Xstruct udft_entry *dummy_func;
  113. X
  114. X/* support for replot command */
  115. Xchar replot_line[MAX_LINE_LEN+1] = "";
  116. Xstatic int plot_token;                    /* start of 'plot' command */
  117. X
  118. Xcom_line()
  119. X{
  120. X    read_line(PROMPT);
  121. X
  122. X    /* So we can flag any new output: if false at time of error, */
  123. X    /* we reprint the command line before printing caret. */
  124. X    /* TRUE for interactive terminals, since the command line is typed. */
  125. X    /* FALSE for non-terminal stdin, so command line is printed anyway. */
  126. X    /* (DFK 11/89) */
  127. X    screen_ok = interactive; 
  128. X
  129. X    do_line();
  130. X}
  131. X
  132. X
  133. Xdo_line()      /* also used in load_file */
  134. X{
  135. X    if (is_system(input_line[0])) {
  136. X        do_system();
  137. X        (void) fputs("!\n",stderr);
  138. X        return;
  139. X    }
  140. X    num_tokens = scanner(input_line);
  141. X    c_token = 0;
  142. X    while(c_token < num_tokens) {
  143. X        command();
  144. X        if (c_token < num_tokens)    /* something after command */
  145. X            if (equals(c_token,";"))
  146. X                c_token++;
  147. X            else
  148. X                    int_error("';' expected",c_token);
  149. X    }
  150. X}
  151. X
  152. X
  153. X
  154. Xcommand()
  155. X{
  156. X    char sv_file[MAX_LINE_LEN+1];
  157. X    /* string holding name of save or load file */
  158. X
  159. X    c_dummy_var[0] = '\0';        /* no dummy variable */
  160. X
  161. X    if (is_definition(c_token))
  162. X        define();
  163. X    else if (equals(c_token,"help") || equals(c_token,"?")) {
  164. X        c_token++;
  165. X        do_help();
  166. X    }
  167. X    else if (almost_equals(c_token,"test")) {
  168. X        c_token++;
  169. X        test_term();
  170. X    }
  171. X    else if (almost_equals(c_token,"pa$use")) {
  172. X        struct value a;
  173. X        int stime, text=0;
  174. X        char buf[MAX_LINE_LEN+1];
  175. X
  176. X        c_token++;
  177. X        stime = (int )real(const_express(&a));
  178. X        if (!(END_OF_COMMAND)) {
  179. X            if (!isstring(c_token))
  180. X                int_error("expecting string",c_token);
  181. X            else {
  182. X                quotel_str(buf,c_token);
  183. X                (void) fprintf (stderr, "%s",buf);
  184. X                text = 1;
  185. X            }
  186. X        }
  187. X        if (stime < 0) (void) fgets (buf,MAX_LINE_LEN,stdin);  
  188. X                        /* Hold until CR hit. */
  189. X#ifdef __ZTC__
  190. X        if (stime > 0) usleep((unsigned long) stime);
  191. X#else
  192. X        if (stime > 0) sleep((unsigned int) stime);
  193. X#endif
  194. X        if (text != 0 && stime >= 0) (void) fprintf (stderr,"\n");
  195. X        c_token++;
  196. X        screen_ok = FALSE;
  197. X    }
  198. X    else if (almost_equals(c_token,"pr$int")) {
  199. X        struct value a;
  200. X
  201. X        c_token++;
  202. X        (void) const_express(&a);
  203. X        (void) putc('\t',stderr);
  204. X        disp_value(stderr,&a);
  205. X        (void) putc('\n',stderr);
  206. X        screen_ok = FALSE;
  207. X    }
  208. X    else if (almost_equals(c_token,"p$lot")) {
  209. X        plot_token = c_token++;
  210. X        plotrequest();
  211. X    }
  212. X    else if (almost_equals(c_token,"rep$lot")) {
  213. X        if (replot_line[0] == '\0') 
  214. X            int_error("no previous plot",c_token);
  215. X        c_token++;
  216. X        replotrequest();
  217. X    }
  218. X    else if (almost_equals(c_token,"se$t"))
  219. X        set_command();
  220. X    else if (almost_equals(c_token,"sh$ow"))
  221. X        show_command();
  222. X    else if (almost_equals(c_token,"cl$ear")) {
  223. X        if (!term_init) {
  224. X            (*term_tbl[term].init)();
  225. X            term_init = TRUE;
  226. X        }
  227. X        (*term_tbl[term].graphics)();
  228. X        (*term_tbl[term].text)();
  229. X        (void) fflush(outfile);
  230. X        screen_ok = FALSE;
  231. X        c_token++;
  232. X    }
  233. X    else if (almost_equals(c_token,"she$ll")) {
  234. X        do_shell();
  235. X        screen_ok = FALSE;
  236. X        c_token++;
  237. X    }
  238. X    else if (almost_equals(c_token,"sa$ve")) {
  239. X        if (almost_equals(++c_token,"f$unctions")) {
  240. X            if (!isstring(++c_token))
  241. X                int_error("expecting filename",c_token);
  242. X            else {
  243. X                quote_str(sv_file,c_token);
  244. X                save_functions(fopen(sv_file,"w"));
  245. X            }
  246. X        }
  247. X        else if (almost_equals(c_token,"v$ariables")) {
  248. X            if (!isstring(++c_token))
  249. X                int_error("expecting filename",c_token);
  250. X            else {
  251. X                quote_str(sv_file,c_token);
  252. X                save_variables(fopen(sv_file,"w"));
  253. X            }
  254. X        }
  255. X        else if (almost_equals(c_token,"s$et")) {
  256. X            if (!isstring(++c_token))
  257. X                int_error("expecting filename",c_token);
  258. X            else {
  259. X                quote_str(sv_file,c_token);
  260. X                save_set(fopen(sv_file,"w"));
  261. X            }
  262. X        }
  263. X        else if (isstring(c_token)) {
  264. X            quote_str(sv_file,c_token);
  265. X            save_all(fopen(sv_file,"w"));
  266. X        }
  267. X        else {
  268. X            int_error(
  269. X        "filename or keyword 'functions', 'variables', or 'set' expected",
  270. X                    c_token);
  271. X        }
  272. X        c_token++;
  273. X    }
  274. X    else if (almost_equals(c_token,"l$oad")) {
  275. X        if (!isstring(++c_token))
  276. X            int_error("expecting filename",c_token);
  277. X        else {
  278. X            quote_str(sv_file,c_token);
  279. X            load_file(fopen(sv_file,"r"), sv_file);    
  280. X        /* input_line[] and token[] now destroyed! */
  281. X            c_token = num_tokens = 0;
  282. X        }
  283. X    }
  284. X    else if (almost_equals(c_token,"ex$it") ||
  285. X            almost_equals(c_token,"q$uit")) {
  286. X        done(IO_SUCCESS);
  287. X    }
  288. X    else if (!equals(c_token,";")) {        /* null statement */
  289. X        int_error("invalid command",c_token);
  290. X    }
  291. X}
  292. X
  293. Xreplotrequest()
  294. X{
  295. Xchar str[MAX_LINE_LEN+1];
  296. X        if(equals(c_token,"["))
  297. X            int_error("cannot set range with replot",c_token);
  298. X        if (!END_OF_COMMAND) {
  299. X            capture(str,c_token,num_tokens-1);
  300. X            if ( (strlen(str) + strlen(input_line)) <= MAX_LINE_LEN-1) {
  301. X                (void) strcat(replot_line,",");
  302. X                (void) strcat(replot_line,str); 
  303. X            } else {
  304. X                int_error("plot line too long with replot arguments",c_token);
  305. X            }
  306. X        }
  307. X        (void) strcpy(input_line,replot_line);
  308. X        screen_ok = FALSE;
  309. X        num_tokens = scanner(input_line);
  310. X        c_token = 1;                    /* skip the 'plot' part */
  311. X        plotrequest();
  312. X}
  313. X
  314. X
  315. Xplotrequest()
  316. X{
  317. X     BOOLEAN changed;
  318. X    int dummy_token = -1;
  319. X
  320. X     autoscale_lx = autoscale_x;
  321. X     autoscale_ly = autoscale_y;
  322. X    
  323. X    if (!term)                    /* unknown */
  324. X        int_error("use 'set term' to set terminal type first",c_token);
  325. X
  326. X    if (equals(c_token,"[")) {
  327. X        c_token++;
  328. X        if (isletter(c_token)) {
  329. X            if (equals(c_token+1,"=")) {
  330. X               dummy_token = c_token;
  331. X               c_token += 2;
  332. X            } else {
  333. X               /* oops; probably an expression with a variable. */
  334. X               /* Parse it as an xmin expression. */
  335. X               /* used to be: int_error("'=' expected",c_token); */
  336. X            }
  337. X        }
  338. X        changed = load_range(&xmin,&xmax);
  339. X        if (!equals(c_token,"]"))
  340. X            int_error("']' expected",c_token);
  341. X        c_token++;
  342. X        if (changed)
  343. X          autoscale_lx = FALSE;
  344. X    }
  345. X
  346. X    if (equals(c_token,"[")) { /* set optional y ranges */
  347. X        c_token++;
  348. X        changed = load_range(&ymin,&ymax);
  349. X        if (!equals(c_token,"]"))
  350. X            int_error("']' expected",c_token);
  351. X        c_token++;
  352. X        if (changed)
  353. X          autoscale_ly = FALSE;
  354. X    }
  355. X
  356. X     /* use the default dummy variable unless changed */
  357. X    if (dummy_token >= 0)
  358. X      copy_str(c_dummy_var,dummy_token);
  359. X    else
  360. X      (void) strcpy(c_dummy_var,dummy_var);
  361. X
  362. X    eval_plots();
  363. X}
  364. X
  365. X
  366. Xdefine()
  367. X{
  368. Xregister int start_token;  /* the 1st token in the function definition */
  369. Xregister struct udvt_entry *udv;
  370. Xregister struct udft_entry *udf;
  371. X
  372. X    if (equals(c_token+1,"(")) {
  373. X        /* function ! */
  374. X        start_token = c_token;
  375. X        copy_str(c_dummy_var, c_token + 2);
  376. X        c_token += 5; /* skip (, dummy, ) and = */
  377. X        if (END_OF_COMMAND)
  378. X            int_error("function definition expected",c_token);
  379. X        udf = dummy_func = add_udf(start_token);
  380. X        if (udf->at)                /* already a dynamic a.t. there */
  381. X            free((char *)udf->at);    /* so free it first */
  382. X        if ((udf->at = perm_at()) == (struct at_type *)NULL)
  383. X            int_error("not enough memory for function",start_token);
  384. X        m_capture(&(udf->definition),start_token,c_token-1);
  385. X    }
  386. X    else {
  387. X        /* variable ! */
  388. X        start_token = c_token;
  389. X        c_token +=2;
  390. X        udv = add_udv(start_token);
  391. X        (void) const_express(&(udv->udv_value));
  392. X        udv->udv_undef = FALSE;
  393. X    }
  394. X}
  395. X
  396. X
  397. Xget_data(this_plot)
  398. Xstruct curve_points *this_plot;
  399. X{
  400. Xstatic char data_file[MAX_LINE_LEN+1], line[MAX_LINE_LEN+1];
  401. Xregister int i, l_num, datum;
  402. Xregister FILE *fp;
  403. Xfloat x, y;
  404. Xint npoints;                /* number of points and breaks read */
  405. X
  406. X    quote_str(data_file, c_token);
  407. X    this_plot->plot_type = DATA;
  408. X    if ((fp = fopen(data_file, "r")) == (FILE *)NULL)
  409. X        os_error("can't open data file", c_token);
  410. X
  411. X    l_num = 0;
  412. X     datum = 0;
  413. X    i = 0;
  414. X     npoints = 0;
  415. X    while ( fgets(line, MAX_LINE_LEN, fp) != (char *)NULL ) {
  416. X        l_num++;
  417. X        if (is_comment(line[0]))
  418. X            continue;        /* ignore comments */
  419. X        npoints++;
  420. X        if (i >= samples)    /* should never be > samples */
  421. X          continue;        /* Overflow! keep looping to get count */
  422. X        if (!line[1]) { /* is it blank line ? */
  423. X            /* break in data, make next point undefined */
  424. X            this_plot->points[i].type = UNDEFINED;
  425. X            i++;
  426. X            continue;
  427. X        }
  428. X
  429. X        switch (sscanf(line, "%f %f", &x, &y)) {
  430. X            case 1: {        /* only one number on the line */
  431. X               y = x;        /* assign that number to y */
  432. X               x = datum;    /* and make the index into x */
  433. X               /* no break; !!! */
  434. X            }
  435. X            case 2: {
  436. X               datum++;
  437. X               this_plot->points[i].type = INRANGE;
  438. X
  439. X               if (log_x) {
  440. X                  if (x < 0.0) {
  441. X                     this_plot->points[i].type = UNDEFINED;
  442. X                  } else if (x == 0.0) {
  443. X                     this_plot->points[i].type = OUTRANGE;
  444. X                     this_plot->points[i].x = -VERYLARGE;
  445. X                  } else
  446. X                    this_plot->points[i].x = log10(x);
  447. X               } else
  448. X                this_plot->points[i].x = x;
  449. X
  450. X               if (log_y) {
  451. X                  if (y < 0.0) {
  452. X                     this_plot->points[i].type = UNDEFINED;
  453. X                  } else if (y == 0.0) {
  454. X                     this_plot->points[i].type = OUTRANGE;
  455. X                     this_plot->points[i].y = -VERYLARGE;
  456. X                  } else
  457. X                    this_plot->points[i].y = log10(y);
  458. X               } else
  459. X                this_plot->points[i].y = y;
  460. X
  461. X               if (this_plot->points[i].type == INRANGE)
  462. X                if (   (autoscale_lx || inrange(x,xmin,xmax))
  463. X                    && (autoscale_ly || inrange(y,ymin,ymax) || polar)) {
  464. X                    if (autoscale_lx) {
  465. X                       if (x < xmin) xmin = x;
  466. X                       if (x > xmax) xmax = x;
  467. X                    }
  468. X                    if (autoscale_ly) {
  469. X                       if (y < ymin) ymin = y;
  470. X                       if (y > ymax) ymax = y;
  471. X                    }
  472. X                } else {
  473. X                    this_plot->points[i].type = OUTRANGE;
  474. X                }
  475. X               i++;
  476. X               break;
  477. X            }
  478. X            default: {
  479. X               (void) sprintf(line, "bad data on line %d", l_num);
  480. X               int_error(line,c_token);
  481. X            }
  482. X        }
  483. X    }
  484. X    if (npoints > samples) {
  485. X        (void) sprintf(line,
  486. X "%d data points and breaks found--samples must be set at least this high",
  487. X                    npoints); 
  488. X        int_error(line,c_token);
  489. X    }
  490. X    this_plot->p_count = i;
  491. X     (void) fclose(fp);
  492. X}
  493. X
  494. X/* This parses the plot command after any range specifications. 
  495. X * To support autoscaling on the x axis, we want any data files to 
  496. X * define the x range, then to plot any functions using that range. 
  497. X * We thus parse the input twice, once to pick up the data files, 
  498. X * and again to pick up the functions. Definitions are processed 
  499. X * twice, but that won't hurt.
  500. X */
  501. Xeval_plots()
  502. X{
  503. Xregister int i;
  504. Xregister struct curve_points *this_plot, **tp_ptr;
  505. Xregister int start_token, mysamples;
  506. Xregister int begin_token;
  507. Xregister double x_min, x_max, y_min, y_max, x;
  508. Xregister double xdiff, temp;
  509. Xstatic struct value a;
  510. XBOOLEAN some_data_files = FALSE;
  511. Xint plot_num, line_num, point_num;
  512. X
  513. X    mysamples = samples;
  514. X
  515. X    if (autoscale_ly) {
  516. X        ymin = VERYLARGE;
  517. X        ymax = -VERYLARGE;
  518. X    } else if (log_y && (ymin <= 0.0 || ymax <= 0.0))
  519. X            int_error("y range must be above 0 for log scale!",
  520. X                NO_CARET);
  521. X
  522. X    tp_ptr = &(first_plot);
  523. X    plot_num = 0;
  524. X    line_num = 0;     /* default line type */
  525. X    point_num = 0;    /* default point type */
  526. X
  527. X     begin_token = c_token;
  528. X
  529. X/*** First Pass: Read through data files ***/
  530. X/* This pass serves to set the xrange and to parse the command, as well 
  531. X * as filling in every thing except the function data. That is done after
  532. X * the xrange is defined.
  533. X */
  534. X    while (TRUE) {
  535. X        if (END_OF_COMMAND)
  536. X            int_error("function to plot expected",c_token);
  537. X
  538. X        start_token = c_token;
  539. X
  540. X        if (is_definition(c_token)) {
  541. X            define();
  542. X        } else {
  543. X            plot_num++;
  544. X            if (*tp_ptr)
  545. X                this_plot = *tp_ptr;
  546. X            else {        /* no memory malloc()'d there yet */
  547. X                this_plot = (struct curve_points *)
  548. X                    alloc((unsigned int) (sizeof(struct curve_points) -
  549. X                    (MAX_POINTS -(samples+1))*sizeof(struct coordinate)),
  550. X                    "curve points");
  551. X                this_plot->next_cp = NULL;
  552. X                this_plot->title = NULL;
  553. X                *tp_ptr = this_plot;
  554. X            }
  555. X
  556. X            if (isstring(c_token)) {            /* data file to plot */
  557. X                if (!some_data_files && autoscale_lx) {
  558. X                    xmin = VERYLARGE;
  559. X                    xmax = -VERYLARGE;
  560. X                }
  561. X                some_data_files = TRUE;
  562. X
  563. X                this_plot->plot_type = DATA;
  564. X                this_plot->plot_style = data_style;
  565. X                get_data(this_plot);
  566. X                c_token++;
  567. X            } 
  568. X            else {                            /* function to plot */
  569. X                this_plot->plot_type = FUNC;
  570. X                this_plot->plot_style = func_style;
  571. X                dummy_func = &plot_func;
  572. X                plot_func.at = temp_at();
  573. X                /* ignore it for now */
  574. X            }
  575. X
  576. X            if (almost_equals(c_token,"t$itle")) {
  577. X                c_token++;
  578. X                if ( (input_line[token[c_token].start_index]=='\'')
  579. X                   ||(input_line[token[c_token].start_index]=='"') ) {
  580. X                    m_quote_capture(&(this_plot->title),c_token,c_token);
  581. X                }
  582. X                else {
  583. X                    int_error("expecting \"title\" for plot",c_token);
  584. X                }
  585. X                c_token++;
  586. X            }
  587. X            else {
  588. X                m_capture(&(this_plot->title),start_token,c_token-1);
  589. X            }
  590. X
  591. X            this_plot->line_type = line_num;
  592. X            this_plot->point_type = point_num;
  593. X
  594. X            if (almost_equals(c_token,"w$ith")) {
  595. X                this_plot->plot_style = get_style();
  596. X            }
  597. X
  598. X            if ( !equals(c_token,",") && !END_OF_COMMAND ) {
  599. X                struct value t;
  600. X                this_plot->line_type = (int)real(const_express(&t))-1;
  601. X            }
  602. X            if ( !equals(c_token,",") && !END_OF_COMMAND ) {
  603. X                struct value t;
  604. X                this_plot->point_type = (int)real(const_express(&t))-1;
  605. X            }
  606. X            if ( (this_plot->plot_style == POINTS) ||
  607. X                 (this_plot->plot_style == LINESPOINTS) )
  608. X                    point_num++;
  609. X            line_num++;
  610. X
  611. X            tp_ptr = &(this_plot->next_cp);
  612. X        }
  613. X
  614. X        if (equals(c_token,",")) 
  615. X            c_token++;
  616. X        else  
  617. X            break;
  618. X    }
  619. X
  620. X/*** Second Pass: Evaluate the functions ***/
  621. X/* Everything is defined now, except the function data. We expect
  622. X * no syntax errors, etc, since the above parsed it all. This makes 
  623. X * the code below simpler. If autoscale_ly, the yrange may still change.
  624. X */
  625. X     if (xmin == xmax)
  626. X      if (autoscale_lx) {
  627. X         fprintf(stderr, "Warning: empty x range [%g:%g], ", xmin,xmax);
  628. X         if (xmin == 0.0) {
  629. X            /* completely arbitary */
  630. X            xmin = -1.;
  631. X            xmax = 1.;
  632. X         } else {
  633. X            /* expand range by 10% in either direction */
  634. X            xmin = xmin * 0.9;
  635. X            xmax = xmax * 1.1;
  636. X         }
  637. X         fprintf(stderr, "adjusting to [%g:%g]\n", xmin,xmax);
  638. X      } else {
  639. X         int_error("x range is empty", c_token);
  640. X      }
  641. X
  642. X    if (log_x) {
  643. X       if (xmin <= 0.0 || xmax <= 0.0)
  644. X        int_error("x range must be greater than 0 for log scale!",NO_CARET);
  645. X       x_min = log10(xmin);
  646. X       x_max = log10(xmax);
  647. X    } else {
  648. X       x_min = xmin;
  649. X       x_max = xmax;
  650. X    }
  651. X    
  652. X    xdiff = (x_max - x_min) / mysamples;
  653. X    
  654. X    plot_num = 0;
  655. X    this_plot = first_plot;
  656. X    c_token = begin_token;    /* start over */
  657. X
  658. X    /* Read through functions */
  659. X    while (TRUE) {
  660. X        if (is_definition(c_token)) {
  661. X            define();
  662. X        } else {
  663. X            plot_num++;
  664. X            if (isstring(c_token)) {            /* data file to plot */
  665. X                /* ignore this now */
  666. X                c_token++;
  667. X            } 
  668. X            else {                            /* function to plot */
  669. X                dummy_func = &plot_func;
  670. X                plot_func.at = temp_at(); /* reparse function */
  671. X    
  672. X                for (i = 0; i <= mysamples; i++) {
  673. X                    if (i == samples+1)
  674. X                     int_error("number of points exceeded samples",
  675. X                             NO_CARET);
  676. X                    x = x_min + i*xdiff;
  677. X                    /* if (log_x) PEM fix logscale x axis */
  678. X                    /* x = pow(10.0,x); 26-Sep-89 */
  679. X                    (void) complex(&plot_func.dummy_value,
  680. X                                log_x ? pow(10.0,x) : x,
  681. X                                0.0);
  682. X                    
  683. X                    evaluate_at(plot_func.at,&a);
  684. X                    
  685. X                    if (undefined || (fabs(imag(&a)) > zero)) {
  686. X                       this_plot->points[i].type = UNDEFINED;
  687. X                       continue;
  688. X                    }
  689. X                    
  690. X                    temp = real(&a);
  691. X
  692. X                    if (log_y && temp < 0.0) {
  693. X                       this_plot->points[i].type = UNDEFINED;
  694. X                       continue;
  695. X                    }
  696. X
  697. X                    this_plot->points[i].x = x;
  698. X                    if (log_y) {
  699. X                       if (temp == 0.0) {
  700. X                          this_plot->points[i].type = OUTRANGE;
  701. X                          this_plot->points[i].y = -VERYLARGE;
  702. X                          continue;
  703. X                       } else {
  704. X                          this_plot->points[i].y = log10(temp);
  705. X                       }
  706. X                    } else
  707. X                     this_plot->points[i].y = temp;
  708. X
  709. X                    if (autoscale_ly || polar
  710. X                       || inrange(temp, ymin, ymax)) {
  711. X                       this_plot->points[i].type = INRANGE;
  712. X                       if (autoscale_ly && temp < ymin) ymin = temp;
  713. X                       if (autoscale_ly && temp > ymax) ymax = temp;
  714. X                    } else
  715. X                     this_plot->points[i].type = OUTRANGE;
  716. X                }
  717. X                this_plot->p_count = i; /* mysamples + 1 */
  718. X             }
  719. X            
  720. X            /* title was handled above */
  721. X            if (almost_equals(c_token,"t$itle")) {
  722. X                c_token++;
  723. X                c_token++;
  724. X            }
  725. X
  726. X            /* style was handled above */
  727. X            if (almost_equals(c_token,"w$ith")) {
  728. X                c_token++;
  729. X                c_token++;
  730. X            }
  731. X
  732. X            /* line and point types were handled above */
  733. X            if ( !equals(c_token,",") && !END_OF_COMMAND ) {
  734. X                struct value t;
  735. X                (void)real(const_express(&t));
  736. X            }
  737. X            if ( !equals(c_token,",") && !END_OF_COMMAND ) {
  738. X                struct value t;
  739. X                (void)real(const_express(&t));
  740. X            }
  741. X
  742. X            this_plot = this_plot->next_cp;
  743. X         }
  744. X        
  745. X        if (equals(c_token,",")) 
  746. X          c_token++;
  747. X        else  
  748. X          break;
  749. X     }
  750. X
  751. X    if (ymin == ymax)
  752. X     /* if autoscale, widen range */
  753. X     if (autoscale_ly) {
  754. X        fprintf(stderr, "Warning: empty y range [%g:%g], ", ymin, ymax);
  755. X        if (ymin == 0.0) {
  756. X            ymin = -1.;
  757. X            ymax = 1.;
  758. X        } else {
  759. X            /* expand range by 10% in either direction */
  760. X            ymin = ymin * 0.9;
  761. X            ymax = ymax * 1.1;
  762. X        }
  763. X        fprintf(stderr, "adjusting to [%g:%g]\n", ymin, ymax);
  764. X     } else {
  765. X        int_error("y range is empty", c_token);
  766. X     }
  767. X
  768. X/* Now we finally know the real ymin and ymax */
  769. X    if (log_y) {
  770. X        y_min = log10(ymin);
  771. X        y_max = log10(ymax);
  772. X    } else {
  773. X        y_min = ymin;
  774. X        y_max = ymax;
  775. X    }
  776. X    capture(replot_line,plot_token,c_token);    
  777. X    do_plot(first_plot,plot_num,x_min,x_max,y_min,y_max);
  778. X}
  779. X
  780. X
  781. X
  782. Xdone(status)
  783. Xint status;
  784. X{
  785. X    if (term && term_init)
  786. X        (*term_tbl[term].reset)();
  787. X#ifdef VMS
  788. X    vms_reset();
  789. X#endif
  790. X    exit(status);
  791. X}
  792. X
  793. X#ifdef MSDOS
  794. X#ifndef __TURBOC__    /* Turbo C already has sleep() */
  795. X#ifndef __ZTC__     /* ZTC already has usleep() */
  796. X/* kludge to provide sleep() for msc 5.1 */
  797. Xvoid sleep(delay)
  798. Xunsigned int delay;
  799. X{
  800. Xunsigned long time_is_up;
  801. X    time_is_up = time(NULL) + (unsigned long) delay; 
  802. X    while (time(NULL)<time_is_up)
  803. X        /* wait */ ;
  804. X}
  805. X#endif /* not ZTC */
  806. X#endif /* not TURBOC */
  807. X#endif /* MSDOS */
  808. X
  809. X
  810. X/* Support for input, shell, and help for various systems */
  811. X
  812. X#ifdef vms
  813. X
  814. X#include <descrip.h>
  815. X#include <rmsdef.h>
  816. X#include <errno.h>
  817. X
  818. Xextern lib$get_input(), lib$put_output();
  819. X
  820. Xint vms_len;
  821. X
  822. Xunsigned int status[2] = {1, 0};
  823. X
  824. Xstatic char help[MAX_LINE_LEN+1] = "gnuplot";
  825. X
  826. X$DESCRIPTOR(prompt_desc,PROMPT);
  827. X$DESCRIPTOR(line_desc,input_line);
  828. X
  829. X$DESCRIPTOR(help_desc,help);
  830. X$DESCRIPTOR(helpfile_desc,"GNUPLOT$HELP");
  831. X
  832. X
  833. Xread_line(prompt)
  834. Xchar *prompt;
  835. X{
  836. X    int more, start=0;
  837. X    char expand_prompt[40];
  838. X
  839. X    prompt_desc.dsc$w_length = strlen (prompt);
  840. X    prompt_desc.dsc$a_pointer = prompt;
  841. X    (void) strcpy (expand_prompt, "_");
  842. X    (void) strncat (expand_prompt, prompt, 38);
  843. X    do {
  844. X        line_desc.dsc$w_length = MAX_LINE_LEN - start;
  845. X        line_desc.dsc$a_pointer = &input_line[start];
  846. X        switch(status[1] = lib$get_input(&line_desc, &prompt_desc, &vms_len)){
  847. X          case RMS$_EOF:
  848. X          done(IO_SUCCESS);    /* ^Z isn't really an error */
  849. X          break;
  850. X          case RMS$_TNS:    /* didn't press return in time *
  851. X                           /
  852. X                           vms_len--; /* skip the last character */
  853. X          break;            /* and parse anyway */
  854. X          case RMS$_BES:    /* Bad Escape Sequence */
  855. X          case RMS$_PES:    /* Partial Escape Sequence */
  856. X          sys$putmsg(status);
  857. X          vms_len = 0;        /* ignore the line */
  858. X          break;
  859. X          case SS$_NORMAL:
  860. X          break;            /* everything's fine */
  861. X          default:
  862. X          done(status[1]);    /* give the error message */
  863. X        }
  864. X        start += vms_len;
  865. X        input_line[start] = '\0';
  866. X       inline_num++;
  867. X        if (input_line[start-1] == '\\') {
  868. X          /* Allow for a continuation line. */
  869. X          prompt_desc.dsc$w_length = strlen (expand_prompt);
  870. X          prompt_desc.dsc$a_pointer = expand_prompt;
  871. X          more = 1;
  872. X          --start;
  873. X        }
  874. X        else {
  875. X          line_desc.dsc$w_length = strlen(input_line);
  876. X          line_desc.dsc$a_pointer = input_line;
  877. X          more = 0;
  878. X        }
  879. X    } while (more);
  880. X}
  881. X
  882. X
  883. Xdo_help()
  884. X{
  885. X    help_desc.dsc$w_length = strlen(help);
  886. X    if ((vaxc$errno = lbr$output_help(lib$put_output,0,&help_desc,
  887. X        &helpfile_desc,0,lib$get_input)) != SS$_NORMAL)
  888. X            os_error("can't open GNUPLOT$HELP");
  889. X}
  890. X
  891. X
  892. Xdo_shell()
  893. X{
  894. X    if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
  895. X        os_error("spawn error",NO_CARET);
  896. X    }
  897. X}
  898. X
  899. X
  900. Xdo_system()
  901. X{
  902. X    input_line[0] = ' ';    /* an embarrassment, but... */
  903. X
  904. X    if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
  905. X        os_error("spawn error",NO_CARET);
  906. X
  907. X    (void) putc('\n',stderr);
  908. X}
  909. X
  910. X#else /* vms */
  911. X
  912. X/* do_help: (not VMS, although it would work)
  913. X * Give help to the user. 
  914. X * It parses the command line into helpbuf and supplies help for that 
  915. X * string. Then, if there are subtopics available for that key,
  916. X * it prompts the user with this string. If more input is
  917. X * given, do_help is called recursively, with the argument the index of 
  918. X * null character in the string. Thus a more specific help can be 
  919. X * supplied. This can be done repeatedly. 
  920. X * If null input is given, the function returns, effecting a
  921. X * backward climb up the tree.
  922. X * David Kotz (dfk@cs.duke.edu) 10/89
  923. X */
  924. Xdo_help()
  925. X{
  926. X    static char helpbuf[MAX_LINE_LEN] = "";
  927. X    static char prompt[MAX_LINE_LEN] = "";
  928. X    int base;                /* index of first char AFTER help string */
  929. X    int len;                /* length of current help string */
  930. X    BOOLEAN more_help;
  931. X    BOOLEAN only;            /* TRUE if only printing subtopics */
  932. X    int subtopics;            /* 0 if no subtopics for this topic */
  933. X    int start;                /* starting token of help string */
  934. X    char *help_ptr;            /* name of help file */
  935. X
  936. X    if ( (help_ptr = getenv("GNUHELP")) == (char *)NULL )
  937. X        /* if can't find environment variable then just use HELPFILE */
  938. X        help_ptr = HELPFILE;
  939. X
  940. X    len = base = strlen(helpbuf);
  941. X
  942. X    /* find the end of the help command */
  943. X    for (start = c_token; !(END_OF_COMMAND); c_token++)
  944. X     ;
  945. X    /* copy new help input into helpbuf */
  946. X    if (len > 0)
  947. X     helpbuf[len++] = ' ';    /* add a space */
  948. X    capture(helpbuf+len, start, c_token-1);
  949. X    squash_spaces(helpbuf+base); /* only bother with new stuff */
  950. X    lower_case(helpbuf+base); /* only bother with new stuff */
  951. X    len = strlen(helpbuf);
  952. X
  953. X    /* now, a lone ? will print subtopics only */
  954. X    if (strcmp(helpbuf + (base ? base+1 : 0), "?") == 0) {
  955. X       /* subtopics only */
  956. X       subtopics = 1;
  957. X       only = TRUE;
  958. X       helpbuf[base] = '\0';    /* cut off question mark */
  959. X    } else {
  960. X       /* normal help request */
  961. X       subtopics = 0;
  962. X       only = FALSE;
  963. X    }
  964. X
  965. X    switch (help(helpbuf, help_ptr, &subtopics)) {
  966. X       case H_FOUND: {
  967. X          /* already printed the help info */
  968. X          /* subtopics now is true if there were any subtopics */
  969. X          screen_ok = FALSE;
  970. X    
  971. X          do {
  972. X             if (subtopics && !only) {
  973. X                /* prompt for subtopic with current help string */
  974. X                if (len > 0)
  975. X                  (void) sprintf(prompt, "Subtopic of %s: ", helpbuf);
  976. X                else
  977. X                  (void) strcpy(prompt, "Help topic: ");
  978. X                read_line(prompt);
  979. X                num_tokens = scanner(input_line);
  980. X                c_token = 0;
  981. X                more_help = !(END_OF_COMMAND);
  982. X                if (more_help)
  983. X                  /* base for next level is all of current helpbuf */
  984. X                  do_help();
  985. X             } else 
  986. X               more_help = FALSE;
  987. X          } while(more_help);
  988. X    
  989. X          break;
  990. X       }
  991. X       case H_NOTFOUND: {
  992. X          printf("Sorry, no help for '%s'\n", helpbuf);
  993. X          break;
  994. X       }
  995. X       case H_ERROR: {
  996. X          perror(help_ptr);
  997. X          break;
  998. X       }
  999. X       default: {        /* defensive programming */
  1000. X          int_error("Impossible case in switch\n", NO_CARET);
  1001. X          /* NOTREACHED */
  1002. X       }
  1003. X    }
  1004. X    
  1005. X    helpbuf[base] = '\0';    /* cut it off where we started */
  1006. X}
  1007. X
  1008. Xdo_system()
  1009. X{
  1010. X    if (system(input_line + 1))
  1011. X        os_error("system() failed",NO_CARET);
  1012. X}
  1013. X
  1014. X#ifdef MSDOS
  1015. X
  1016. Xread_line(prompt)
  1017. X    char *prompt;
  1018. X{
  1019. X    register int i;
  1020. X    int start = 0;
  1021. X    BOOLEAN more;
  1022. X    int last;
  1023. X    
  1024. X#ifndef __ZTC__
  1025. X    if (interactive) { /* if interactive use console IO so CED will work */
  1026. X        cputs(prompt);
  1027. X        do {
  1028. X           input_line[start] = MAX_LINE_LEN - start - 1;
  1029. X           cgets(&(input_line[start]));
  1030. X           (void) putc('\n',stderr);
  1031. X           if (input_line[start+2] == 26) {
  1032. X              /* end-of-file */
  1033. X              (void) putc('\n',stderr);
  1034. X              input_line[start] = '\0';
  1035. X              inline_num++;
  1036. X              if (start > 0)    /* don't quit yet - process what we have */
  1037. X                more = FALSE;
  1038. X              else {
  1039. X                 (void) putc('\n',stderr);
  1040. X                 done(IO_SUCCESS);
  1041. X                 /* NOTREACHED */
  1042. X              }
  1043. X           } else {
  1044. X              /* normal line input */
  1045. X              register i = start;
  1046. X              while ( (input_line[i] = input_line[i+2]) != (char)NULL )
  1047. X                i++;        /* yuck!  move everything down two characters */
  1048. X
  1049. X              inline_num++;
  1050. X              last = strlen(input_line) - 1;
  1051. X              if (last + 1 >= MAX_LINE_LEN)
  1052. X                int_error("Input line too long",NO_CARET);
  1053. X                     
  1054. X              if (input_line[last] == '\\') { /* line continuation */
  1055. X                 start = last;
  1056. X                 more = TRUE;
  1057. X              } else
  1058. X                more = FALSE;
  1059. X           }
  1060. X           if (more)
  1061. X            cputs("> ");
  1062. X        } while(more);
  1063. X    }
  1064. X    else { /* not interactive */
  1065. X#endif /* not ZTC */
  1066. X        if (interactive)
  1067. X         fputs(prompt,stderr);
  1068. X        do {
  1069. X           /* grab some input */
  1070. X           if ( fgets(&(input_line[start]), MAX_LINE_LEN - start, stdin) 
  1071. X                    == (char *)NULL ) {
  1072. X              /* end-of-file */
  1073. X              if (interactive)
  1074. X                (void) putc('\n',stderr);
  1075. X              input_line[start] = '\0';
  1076. X              inline_num++;
  1077. X              if (start > 0)    /* don't quit yet - process what we have */
  1078. X                more = FALSE;
  1079. X              else
  1080. X                done(IO_SUCCESS); /* no return */
  1081. X           } else {
  1082. X              /* normal line input */
  1083. X              last = strlen(input_line) - 1;
  1084. X              if (input_line[last] == '\n') { /* remove any newline */
  1085. X                 input_line[last] = '\0';
  1086. X                 /* Watch out that we don't backup beyond 0 (1-1-1) */
  1087. X                 if (last > 0) --last;
  1088. X                 inline_num++;
  1089. X              } else if (last+1 >= MAX_LINE_LEN)
  1090. X                int_error("Input line too long",NO_CARET);
  1091. X                     
  1092. X              if (input_line[last] == '\\') { /* line continuation */
  1093. X                 start = last;
  1094. X                 more = TRUE;
  1095. X              } else
  1096. X                more = FALSE;
  1097. X           }
  1098. X            if (more && interactive)
  1099. X            fputs("> ", stderr);
  1100. X        } while(more);
  1101. X#ifndef __ZTC
  1102. X    }
  1103. X#endif
  1104. X}
  1105. X
  1106. X
  1107. Xdo_shell()
  1108. X{
  1109. Xregister char *comspec;
  1110. X    if ((comspec = getenv("COMSPEC")) == (char *)NULL)
  1111. X        comspec = "\command.com";
  1112. X    if (spawnl(P_WAIT,comspec,NULL) == -1)
  1113. X        os_error("unable to spawn shell",NO_CARET);
  1114. X}
  1115. X
  1116. X#else /* MSDOS */
  1117. X        /* plain old Unix */
  1118. X
  1119. Xread_line(prompt)
  1120. X    char *prompt;
  1121. X{
  1122. X    int start = 0;
  1123. X    BOOLEAN more;
  1124. X    int last = 0;
  1125. X
  1126. X    if (interactive)
  1127. X     fputs(prompt,stderr);
  1128. X    do {
  1129. X       /* grab some input */
  1130. X       if ( fgets(&(input_line[start]), MAX_LINE_LEN - start, stdin) 
  1131. X                == (char *)NULL ) {
  1132. X          /* end-of-file */
  1133. X          if (interactive)
  1134. X            (void) putc('\n',stderr);
  1135. X          input_line[start] = '\0';
  1136. X          inline_num++;
  1137. X          if (start > 0)    /* don't quit yet - process what we have */
  1138. X            more = FALSE;
  1139. X          else
  1140. X            done(IO_SUCCESS); /* no return */
  1141. X       } else {
  1142. X          /* normal line input */
  1143. X          last = strlen(input_line) - 1;
  1144. X          if (input_line[last] == '\n') { /* remove any newline */
  1145. X             input_line[last] = '\0';
  1146. X                /* Watch out that we don't backup beyond 0 (1-1-1) */
  1147. X             if (last > 0) --last;
  1148. X             inline_num++;
  1149. X          } else if (last+1 >= MAX_LINE_LEN)
  1150. X            int_error("Input line too long",NO_CARET);
  1151. X                 
  1152. X          if (input_line[last] == '\\') { /* line continuation */
  1153. X             start = last;
  1154. X             more = TRUE;
  1155. X          } else
  1156. X            more = FALSE;
  1157. X       }
  1158. X        if (more && interactive)
  1159. X        fputs("> ", stderr);
  1160. X    } while(more);
  1161. X}
  1162. X
  1163. X#ifdef VFORK
  1164. X
  1165. Xdo_shell()
  1166. X{
  1167. Xregister char *shell;
  1168. Xregister int p;
  1169. Xstatic int execstat;
  1170. X    if (!(shell = getenv("SHELL")))
  1171. X        shell = SHELL;
  1172. X    if ((p = vfork()) == 0) {
  1173. X        execstat = execl(shell,shell,NULL);
  1174. X        _exit(1);
  1175. X    } else if (p == -1)
  1176. X        os_error("vfork failed",c_token);
  1177. X    else
  1178. X        while (wait(NULL) != p)
  1179. X            ;
  1180. X    if (execstat == -1)
  1181. X        os_error("shell exec failed",c_token);
  1182. X    (void) putc('\n',stderr);
  1183. X}
  1184. X#else /* VFORK */
  1185. X
  1186. X#define EXEC "exec "
  1187. Xdo_shell()
  1188. X{
  1189. Xstatic char exec[100] = EXEC;
  1190. Xregister char *shell;
  1191. X    if (!(shell = getenv("SHELL")))
  1192. X        shell = SHELL;
  1193. X
  1194. X    if (system(strncpy(&exec[sizeof(EXEC)-1],shell,
  1195. X        sizeof(exec)-sizeof(EXEC)-1)))
  1196. X        os_error("system() failed",NO_CARET);
  1197. X
  1198. X    (void) putc('\n',stderr);
  1199. X}
  1200. X#endif /* VFORK */
  1201. X#endif /* MSDOS */
  1202. X#endif /* vms */
  1203. *-*-END-of-command.c-*-*
  1204. echo x - setshow.c
  1205. sed 's/^X//' >setshow.c <<'*-*-END-of-setshow.c-*-*'
  1206. X/* GNUPLOT - setshow.c */
  1207. X/*
  1208. X * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  1209. X *
  1210. X * Permission to use, copy, and distribute this software and its
  1211. X * documentation for any purpose with or without fee is hereby granted, 
  1212. X * provided that the above copyright notice appear in all copies and 
  1213. X * that both that copyright notice and this permission notice appear 
  1214. X * in supporting documentation.
  1215. X *
  1216. X * Permission to modify the software is granted, but not the right to
  1217. X * distribute the modified code.  Modifications are to be distributed 
  1218. X * as patches to released version.
  1219. X *  
  1220. X * This software  is provided "as is" without express or implied warranty.
  1221. X * 
  1222. X *
  1223. X * AUTHORS
  1224. X * 
  1225. X *   Original Software:
  1226. X *     Thomas Williams,  Colin Kelley.
  1227. X * 
  1228. X *   Gnuplot 2.0 additions:
  1229. X *       Russell Lang, Dave Kotz, John Campbell.
  1230. X * 
  1231. X * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
  1232. X * 
  1233. X */
  1234. X
  1235. X#include <stdio.h>
  1236. X#include <math.h>
  1237. X#include "plot.h"
  1238. X#include "setshow.h"
  1239. X
  1240. X#define DEF_FORMAT   "%g"    /* default format for tic mark labels */
  1241. X#define SIGNIF (0.01)        /* less than one hundredth of a tic mark */
  1242. X
  1243. X/*
  1244. X * global variables to hold status of 'set' options
  1245. X *
  1246. X */
  1247. XBOOLEAN            autoscale_x    = TRUE;
  1248. XBOOLEAN            autoscale_y    = TRUE;
  1249. XBOOLEAN            autoscale_lx    = TRUE;
  1250. XBOOLEAN            autoscale_ly    = TRUE;
  1251. XBOOLEAN                clip_points    = FALSE;
  1252. XBOOLEAN                clip_lines1    = TRUE;
  1253. XBOOLEAN                clip_lines2    = FALSE;
  1254. Xchar            dummy_var[MAX_ID_LEN+1] = "x";
  1255. Xchar            xformat[MAX_ID_LEN+1] = DEF_FORMAT;
  1256. Xchar            yformat[MAX_ID_LEN+1] = DEF_FORMAT;
  1257. Xenum PLOT_STYLE data_style    = POINTS,
  1258. X                func_style    = LINES;
  1259. XBOOLEAN            grid        = FALSE;
  1260. Xint                key            = -1;    /* default position */
  1261. Xdouble            key_x, key_y;        /* user specified position for key */
  1262. XBOOLEAN            log_x        = FALSE,
  1263. X                log_y        = FALSE;
  1264. XFILE*            outfile;
  1265. Xchar            outstr[MAX_ID_LEN+1] = "STDOUT";
  1266. XBOOLEAN            polar        = FALSE;
  1267. Xint                samples        = SAMPLES;
  1268. Xfloat            xsize        = 1.0;  /* scale factor for size */
  1269. Xfloat            ysize        = 1.0;  /* scale factor for size */
  1270. Xint                term        = 0;                /* unknown term is 0 */
  1271. Xchar            title[MAX_LINE_LEN+1] = "";
  1272. Xchar            xlabel[MAX_LINE_LEN+1] = "";
  1273. Xchar            ylabel[MAX_LINE_LEN+1] = "";
  1274. Xdouble            xmin        = -10.0,
  1275. X                xmax        = 10.0,
  1276. X                ymin        = -10.0,
  1277. X                ymax        = 10.0;
  1278. Xdouble            loff        = 0.0,
  1279. X                roff        = 0.0,
  1280. X                toff        = 0.0,
  1281. X                boff        = 0.0;
  1282. Xdouble            zero = ZERO;            /* zero threshold, not 0! */
  1283. X
  1284. XBOOLEAN xtics = TRUE;
  1285. XBOOLEAN ytics = TRUE;
  1286. X
  1287. Xstruct ticdef xticdef = {TIC_COMPUTED};
  1288. Xstruct ticdef yticdef = {TIC_COMPUTED};
  1289. X
  1290. XBOOLEAN            tic_in        = TRUE;
  1291. X
  1292. Xstruct text_label *first_label = NULL;
  1293. Xstruct arrow_def *first_arrow = NULL;
  1294. X
  1295. X/*** other things we need *****/
  1296. Xextern char *strcpy(),*strcat();
  1297. Xextern int strlen();
  1298. X
  1299. X/* input data, parsing variables */
  1300. Xextern struct lexical_unit token[];
  1301. Xextern char input_line[];
  1302. Xextern int num_tokens, c_token;
  1303. X
  1304. Xextern char replot_line[];
  1305. Xextern struct udvt_entry *first_udv;
  1306. X
  1307. Xextern double magnitude(),real();
  1308. Xextern struct value *const_express();
  1309. X
  1310. X/******** Local functions ********/
  1311. Xstatic void set_label();
  1312. Xstatic void set_nolabel();
  1313. Xstatic void set_arrow();
  1314. Xstatic void set_noarrow();
  1315. Xstatic void load_tics();
  1316. Xstatic void load_tic_user();
  1317. Xstatic void free_marklist();
  1318. Xstatic void load_tic_series();
  1319. Xstatic void load_offsets();
  1320. X
  1321. Xstatic void show_style(), show_range(), show_zero();
  1322. Xstatic void show_offsets(), show_output(), show_samples(), show_size();
  1323. Xstatic void show_title(), show_xlabel(), show_ylabel();
  1324. Xstatic void show_label(), show_arrow(), show_grid(), show_key();
  1325. Xstatic void show_polar(), show_tics(), show_ticdef();
  1326. Xstatic void show_term(), show_plot(), show_autoscale(), show_clip();
  1327. Xstatic void show_format(), show_logscale(), show_variables();
  1328. X
  1329. Xstatic void delete_label();
  1330. Xstatic int assign_label_tag();
  1331. Xstatic void delete_arrow();
  1332. Xstatic int assign_arrow_tag();
  1333. X
  1334. X/******** The 'set' command ********/
  1335. Xvoid
  1336. Xset_command()
  1337. X{
  1338. X     static char testfile[MAX_LINE_LEN+1];
  1339. X
  1340. X    c_token++;
  1341. X
  1342. X    if (almost_equals(c_token,"ar$row")) {
  1343. X        c_token++;
  1344. X        set_arrow();
  1345. X    }
  1346. X    else if (almost_equals(c_token,"noar$row")) {
  1347. X        c_token++;
  1348. X        set_noarrow();
  1349. X    }
  1350. X     else if (almost_equals(c_token,"au$toscale")) {
  1351. X        c_token++;
  1352. X        if (END_OF_COMMAND) {
  1353. X           autoscale_x = autoscale_y = TRUE;
  1354. X        } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  1355. X           autoscale_x = autoscale_y = TRUE;
  1356. X           c_token++;
  1357. X        } else if (equals(c_token, "x")) {
  1358. X           autoscale_x = TRUE;
  1359. X           c_token++;
  1360. X        } else if (equals(c_token, "y")) {
  1361. X           autoscale_y = TRUE;
  1362. X           c_token++;
  1363. X        }
  1364. X    } 
  1365. X    else if (almost_equals(c_token,"noau$toscale")) {
  1366. X        c_token++;
  1367. X        if (END_OF_COMMAND) {
  1368. X           autoscale_x = autoscale_y = FALSE;
  1369. X        } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  1370. X           autoscale_x = autoscale_y = FALSE;
  1371. X           c_token++;
  1372. X        } else if (equals(c_token, "x")) {
  1373. X           autoscale_x = FALSE;
  1374. X           c_token++;
  1375. X        } else if (equals(c_token, "y")) {
  1376. X           autoscale_y = FALSE;
  1377. X           c_token++;
  1378. X        }
  1379. X    } 
  1380. X    else if (almost_equals(c_token,"c$lip")) {
  1381. X        c_token++;
  1382. X        if (END_OF_COMMAND)
  1383. X         /* assuming same as points */
  1384. X         clip_points = TRUE;
  1385. X        else if (almost_equals(c_token, "p$oints"))
  1386. X         clip_points = TRUE;
  1387. X        else if (almost_equals(c_token, "o$ne"))
  1388. X         clip_lines1 = TRUE;
  1389. X        else if (almost_equals(c_token, "t$wo"))
  1390. X         clip_lines2 = TRUE;
  1391. X        else
  1392. X         int_error("expecting 'points', 'one', or 'two'", c_token);
  1393. X        c_token++;
  1394. X    }
  1395. X    else if (almost_equals(c_token,"noc$lip")) {
  1396. X        c_token++;
  1397. X        if (END_OF_COMMAND) {
  1398. X           /* same as all three */
  1399. X           clip_points = FALSE;
  1400. X           clip_lines1 = FALSE;
  1401. X           clip_lines2 = FALSE;
  1402. X        } else if (almost_equals(c_token, "p$oints"))
  1403. X         clip_points = FALSE;
  1404. X        else if (almost_equals(c_token, "o$ne"))
  1405. X         clip_lines1 = FALSE;
  1406. X        else if (almost_equals(c_token, "t$wo"))
  1407. X         clip_lines2 = FALSE;
  1408. X        else
  1409. X         int_error("expecting 'points', 'one', or 'two'", c_token);
  1410. X        c_token++;
  1411. X    }
  1412. X    else if (almost_equals(c_token,"d$ata")) {
  1413. X        c_token++;
  1414. X        if (!almost_equals(c_token,"s$tyle"))
  1415. X            int_error("expecting keyword 'style'",c_token);
  1416. X        data_style = get_style();
  1417. X    }
  1418. X    else if (almost_equals(c_token,"d$ummy")) {
  1419. X        c_token++;
  1420. X        copy_str(dummy_var,c_token++);
  1421. X    }
  1422. X    else if (almost_equals(c_token,"fo$rmat")) {
  1423. X        BOOLEAN setx, sety;
  1424. X        c_token++;
  1425. X        if (equals(c_token,"x")) {
  1426. X            setx = TRUE; sety = FALSE;
  1427. X            c_token++;
  1428. X        }
  1429. X        else if (equals(c_token,"y")) {
  1430. X            setx = FALSE; sety = TRUE;
  1431. X            c_token++;
  1432. X        }
  1433. X        else if (equals(c_token,"xy") || equals(c_token,"yx")) {
  1434. X            setx = sety = TRUE;
  1435. X            c_token++;
  1436. X        }
  1437. X        else if (isstring(c_token) || END_OF_COMMAND) {
  1438. X            /* Assume he wants both */
  1439. X            setx = sety = TRUE;
  1440. X        }
  1441. X        if (END_OF_COMMAND) {
  1442. X            if (setx)
  1443. X                (void) strcpy(xformat,DEF_FORMAT);
  1444. X            if (sety)
  1445. X                (void) strcpy(yformat,DEF_FORMAT);
  1446. X        }
  1447. X        else {
  1448. X            if (!isstring(c_token))
  1449. X              int_error("expecting format string",c_token);
  1450. X            else {
  1451. X                if (setx)
  1452. X                 quote_str(xformat,c_token);
  1453. X                if (sety)
  1454. X                 quote_str(yformat,c_token);
  1455. X                c_token++;
  1456. X            }
  1457. X        }
  1458. X    }
  1459. X    else if (almost_equals(c_token,"fu$nction")) {
  1460. X        c_token++;
  1461. X        if (!almost_equals(c_token,"s$tyle"))
  1462. X            int_error("expecting keyword 'style'",c_token);
  1463. X        func_style = get_style();
  1464. X    }
  1465. X    else if (almost_equals(c_token,"la$bel")) {
  1466. X        c_token++;
  1467. X        set_label();
  1468. X    }
  1469. X    else if (almost_equals(c_token,"nola$bel")) {
  1470. X        c_token++;
  1471. X        set_nolabel();
  1472. X    }
  1473. X    else if (almost_equals(c_token,"lo$gscale")) {
  1474. X        c_token++;
  1475. X        if (END_OF_COMMAND) {
  1476. X           log_x = log_y = TRUE;
  1477. X        } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  1478. X           log_x = log_y = TRUE;
  1479. X           c_token++;
  1480. X        } else if (equals(c_token, "x")) {
  1481. X           log_x = TRUE;
  1482. X           c_token++;
  1483. X        } else if (equals(c_token, "y")) {
  1484. X           log_y = TRUE;
  1485. X           c_token++;
  1486. X        }
  1487. X    }
  1488. X    else if (almost_equals(c_token,"nolo$gscale")) {
  1489. X        c_token++;
  1490. X        if (END_OF_COMMAND) {
  1491. X           log_x = log_y = FALSE;
  1492. X        } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  1493. X           log_x = log_y = FALSE;
  1494. X           c_token++;
  1495. X        } else if (equals(c_token, "x")) {
  1496. X           log_x = FALSE;
  1497. X           c_token++;
  1498. X        } else if (equals(c_token, "y")) {
  1499. X           log_y = FALSE;
  1500. X           c_token++;
  1501. X        }
  1502. X    } 
  1503. X    else if (almost_equals(c_token,"of$fsets")) {
  1504. X        c_token++;
  1505. X        if (END_OF_COMMAND) {
  1506. X            loff = roff = toff = boff = 0.0;  /* Reset offsets */
  1507. X        }
  1508. X        else {
  1509. X            load_offsets (&loff,&roff,&toff,&boff);
  1510. X        }
  1511. X    }
  1512. X    else if (almost_equals(c_token,"o$utput")) {
  1513. X        register FILE *f;
  1514. X
  1515. X        c_token++;
  1516. X        if (term && term_init)
  1517. X            (*term_tbl[term].reset)();
  1518. X        if (END_OF_COMMAND) {    /* no file specified */
  1519. X             UP_redirect (4);
  1520. X            if (outfile != stdout) /* Never close stdout */
  1521. X                (void) fclose(outfile);
  1522. X            outfile = stdout; /* Don't dup... */
  1523. X            term_init = FALSE;
  1524. X            (void) strcpy(outstr,"STDOUT");
  1525. X        } else if (!isstring(c_token))
  1526. X            int_error("expecting filename",c_token);
  1527. X        else {
  1528. X            quote_str(testfile,c_token);
  1529. X            if ((f = fopen(testfile,"w")) == (FILE *)NULL) {
  1530. X              os_error("cannot open file; output not changed",c_token);
  1531. X            }
  1532. X            if (outfile != stdout) /* Never close stdout */
  1533. X                (void) fclose(outfile);
  1534. X            outfile = f;
  1535. X            term_init = FALSE;
  1536. X            outstr[0] = '\'';
  1537. X            (void) strcat(strcpy(outstr+1,testfile),"'");
  1538. X             UP_redirect (1);
  1539. X        }
  1540. X        c_token++;
  1541. X    }
  1542. X    else if (almost_equals(c_token,"tit$le")) {
  1543. X        c_token++;
  1544. X        if (END_OF_COMMAND) {    /* no label specified */
  1545. X            title[0] = '\0';
  1546. X        } else {
  1547. X        quotel_str(title,c_token);
  1548. X        c_token++;
  1549. X        }
  1550. X    } 
  1551. X    else if (almost_equals(c_token,"xl$abel")) {
  1552. X        c_token++;
  1553. X        if (END_OF_COMMAND) {    /* no label specified */
  1554. X            xlabel[0] = '\0';
  1555. X        } else {
  1556. X        quotel_str(xlabel,c_token);
  1557. X        c_token++;
  1558. X        }
  1559. X    } 
  1560. X    else if (almost_equals(c_token,"yl$abel")) {
  1561. X        c_token++;
  1562. X        if (END_OF_COMMAND) {    /* no label specified */
  1563. X            ylabel[0] = '\0';
  1564. X        } else {
  1565. X        quotel_str(ylabel,c_token);
  1566. X        c_token++;
  1567. X        }
  1568. X    } 
  1569. X    else if (almost_equals(c_token,"pol$ar")) {
  1570. X        if (!polar) {
  1571. X           polar = TRUE;
  1572. X           xmin = 0.0;
  1573. X           xmax = 2*Pi;
  1574. X        }
  1575. X        c_token++;
  1576. X    }
  1577. X    else if (almost_equals(c_token,"nopo$lar")) {
  1578. X        if (polar) {
  1579. X           polar = FALSE;
  1580. X           xmin = -10.0;
  1581. X           xmax = 10.0;
  1582. X        }
  1583. X        c_token++;
  1584. X    }
  1585. X    else if (almost_equals(c_token,"g$rid")) {
  1586. X        grid = TRUE;
  1587. X        c_token++;
  1588. X    }
  1589. X    else if (almost_equals(c_token,"nog$rid")) {
  1590. X        grid = FALSE;
  1591. X        c_token++;
  1592. X    }
  1593. X    else if (almost_equals(c_token,"k$ey")) {
  1594. X        struct value a;
  1595. X        c_token++;
  1596. X        if (END_OF_COMMAND) {
  1597. X            key = -1;
  1598. X        } 
  1599. X        else {
  1600. X            key_x = real(const_express(&a));
  1601. X            if (!equals(c_token,","))
  1602. X                int_error("',' expected",c_token);
  1603. X            c_token++;
  1604. X            key_y = real(const_express(&a));
  1605. X            key = 1;
  1606. X        } 
  1607. X    }
  1608. X    else if (almost_equals(c_token,"nok$ey")) {
  1609. X        key = 0;
  1610. X        c_token++;
  1611. X    }
  1612. X    else if (almost_equals(c_token,"tic$s")) {
  1613. X        tic_in = TRUE;
  1614. X        c_token++;
  1615. X        if (almost_equals(c_token,"i$n")) {
  1616. X            tic_in = TRUE;
  1617. X            c_token++;
  1618. X        }
  1619. X        else if (almost_equals(c_token,"o$ut")) {
  1620. X            tic_in = FALSE;
  1621. X            c_token++;
  1622. X        }
  1623. X    }
  1624. X     else if (almost_equals(c_token,"xt$ics")) {
  1625. X        xtics = TRUE;
  1626. X        c_token++;
  1627. X        if (END_OF_COMMAND) { /* reset to default */
  1628. X           if (xticdef.type == TIC_USER) {
  1629. X              free_marklist(xticdef.def.user);
  1630. X              xticdef.def.user = NULL;
  1631. X           }
  1632. X           xticdef.type = TIC_COMPUTED;
  1633. X        }
  1634. X        else
  1635. X         load_tics(&xticdef);
  1636. X    } 
  1637. X     else if (almost_equals(c_token,"noxt$ics")) {
  1638. X        xtics = FALSE;
  1639. X        c_token++;
  1640. X    } 
  1641. X     else if (almost_equals(c_token,"yt$ics")) {
  1642. X        ytics = TRUE;
  1643. X        c_token++;
  1644. X        if (END_OF_COMMAND) { /* reset to default */
  1645. X           if (yticdef.type == TIC_USER) {
  1646. X              free_marklist(yticdef.def.user);
  1647. X              yticdef.def.user = NULL;
  1648. X           }
  1649. X           yticdef.type = TIC_COMPUTED;
  1650. X        }
  1651. X        else
  1652. X         load_tics(&yticdef);
  1653. X    } 
  1654. X     else if (almost_equals(c_token,"noyt$ics")) {
  1655. X        ytics = FALSE;
  1656. X        c_token++;
  1657. X    } 
  1658. X    else if (almost_equals(c_token,"sa$mples")) {
  1659. X        register int tsamp;
  1660. X        struct value a;
  1661. X
  1662. X        c_token++;
  1663. X        tsamp = (int)magnitude(const_express(&a));
  1664. X        if (tsamp < 1)
  1665. X            int_error("sampling rate must be > 0; sampling unchanged",
  1666. X                c_token);
  1667. X        else {
  1668. X             extern struct curve_points *first_plot;
  1669. X            register struct curve_points *f_p = first_plot;
  1670. X
  1671. X            first_plot = NULL;
  1672. X            cp_free(f_p);
  1673. X            samples = tsamp;
  1674. X        }
  1675. X    }
  1676. X    else if (almost_equals(c_token,"si$ze")) {
  1677. X        struct value s;
  1678. X        c_token++;
  1679. X        if (END_OF_COMMAND) {
  1680. X            xsize = 1.0;
  1681. X            ysize = 1.0;
  1682. X        } 
  1683. X        else {
  1684. X                xsize=real(const_express(&s));
  1685. X                if (!equals(c_token,","))
  1686. X                    int_error("',' expected",c_token);
  1687. X                c_token++;
  1688. X                ysize=real(const_express(&s));
  1689. X        } 
  1690. X    } 
  1691. X    else if (almost_equals(c_token,"t$erminal")) {
  1692. X        c_token++;
  1693. X        if (END_OF_COMMAND) {
  1694. X            list_terms();
  1695. X            screen_ok = FALSE;
  1696. X        }
  1697. X        else {
  1698. X            if (term && term_init) {
  1699. X                (*term_tbl[term].reset)();
  1700. X                (void) fflush(outfile);
  1701. X            }
  1702. X            term = set_term(c_token);
  1703. X        }
  1704. X        c_token++;
  1705. X    }
  1706. X    else if (almost_equals(c_token,"xr$ange")) {
  1707. X         BOOLEAN changed;
  1708. X        c_token++;
  1709. X        if (!equals(c_token,"["))
  1710. X            int_error("expecting '['",c_token);
  1711. X        c_token++;
  1712. X        changed = load_range(&xmin,&xmax);
  1713. X        if (!equals(c_token,"]"))
  1714. X          int_error("expecting ']'",c_token);
  1715. X        c_token++;
  1716. X        if (changed)
  1717. X          autoscale_x = FALSE;
  1718. X    }
  1719. X    else if (almost_equals(c_token,"yr$ange")) {
  1720. X         BOOLEAN changed;
  1721. X        c_token++;
  1722. X        if (!equals(c_token,"["))
  1723. X            int_error("expecting '['",c_token);
  1724. X        c_token++;
  1725. X        changed = load_range(&ymin,&ymax);
  1726. X        if (!equals(c_token,"]"))
  1727. X          int_error("expecting ']'",c_token);
  1728. X        c_token++;
  1729. X        if (changed)
  1730. X          autoscale_y = FALSE;
  1731. X    }
  1732. X    else if (almost_equals(c_token,"z$ero")) {
  1733. X        struct value a;
  1734. X        c_token++;
  1735. X        zero = magnitude(const_express(&a));
  1736. X    }
  1737. X    else
  1738. X        int_error(
  1739. X    "valid set options:  '{no}arrow', {no}autoscale', '{no}clip', data', \n\
  1740. X    'dummy', 'format', 'function', '{no}grid', '{no}key', '{no}label', \n\
  1741. X    '{no}logscale','offsets', 'output', '{no}polar', 'samples', \n\
  1742. X    'size', 'terminal', 'tics', 'title', 'xlabel', 'xrange', 'xtics', \n\
  1743. X    'ylabel', 'yrange', 'ytics', 'zero',\n\ ",
  1744. X    c_token);
  1745. X}
  1746. X
  1747. X/*********** Support functions for set_command ***********/
  1748. X
  1749. X/* process a 'set label' command */
  1750. X/* set label {tag} {label_text} {at x,y} {pos} */
  1751. Xstatic void
  1752. Xset_label()
  1753. X{
  1754. X    struct value a;
  1755. X    struct text_label *this_label = NULL;
  1756. X    struct text_label *new_label = NULL;
  1757. X    struct text_label *prev_label = NULL;
  1758. X    double x, y;
  1759. X    char text[MAX_LINE_LEN+1];
  1760. X    enum JUSTIFY just;
  1761. X    int tag;
  1762. X    BOOLEAN set_text, set_position, set_just;
  1763. X
  1764. X    /* get tag */
  1765. X    if (!END_OF_COMMAND 
  1766. X       && !isstring(c_token) 
  1767. X       && !equals(c_token, "at")
  1768. X       && !equals(c_token, "left")
  1769. X       && !equals(c_token, "center")
  1770. X       && !equals(c_token, "centre")
  1771. X       && !equals(c_token, "right")) {
  1772. X       /* must be a tag expression! */
  1773. X       tag = (int)real(const_express(&a));
  1774. X       if (tag <= 0)
  1775. X        int_error("tag must be > zero", c_token);
  1776. X    } else
  1777. X     tag = assign_label_tag(); /* default next tag */
  1778. X     
  1779. X    /* get text */
  1780. X    if (!END_OF_COMMAND && isstring(c_token)) {
  1781. X       /* get text */
  1782. X       quotel_str(text, c_token);
  1783. X       c_token++;
  1784. X       set_text = TRUE;
  1785. X    } else {
  1786. X       text[0] = '\0';        /* default no text */
  1787. X       set_text = FALSE;
  1788. X    }
  1789. X     
  1790. X    /* get justification - what the heck, let him put it here */
  1791. X    if (!END_OF_COMMAND && !equals(c_token, "at")) {
  1792. X       if (almost_equals(c_token,"l$eft")) {
  1793. X          just = LEFT;
  1794. X       }
  1795. X       else if (almost_equals(c_token,"c$entre")
  1796. X              || almost_equals(c_token,"c$enter")) {
  1797. X          just = CENTRE;
  1798. X       }
  1799. X       else if (almost_equals(c_token,"r$ight")) {
  1800. X          just = RIGHT;
  1801. X       }
  1802. X       else
  1803. X        int_error("bad syntax in set label", c_token);
  1804. X       c_token++;
  1805. X       set_just = TRUE;
  1806. X    } else {
  1807. X       just = LEFT;            /* default left justified */
  1808. X       set_just = FALSE;
  1809. X    } 
  1810. X
  1811. X    /* get position */
  1812. X    if (!END_OF_COMMAND && equals(c_token, "at")) {
  1813. X       c_token++;
  1814. X       if (END_OF_COMMAND)
  1815. X        int_error("coordinates expected", c_token);
  1816. X       /* get coordinates */
  1817. X       x = real(const_express(&a));
  1818. X       if (!equals(c_token,","))
  1819. X        int_error("',' expected",c_token);
  1820. X       c_token++;
  1821. X       y = real(const_express(&a));
  1822. X       set_position = TRUE;
  1823. X    } else {
  1824. X       x = y = 0;            /* default at origin */
  1825. X       set_position = FALSE;
  1826. X    }
  1827. X
  1828. X    /* get justification */
  1829. X    if (!END_OF_COMMAND) {
  1830. X       if (set_just)
  1831. X        int_error("only one justification is allowed", c_token);
  1832. X       if (almost_equals(c_token,"l$eft")) {
  1833. X          just = LEFT;
  1834. X       }
  1835. X       else if (almost_equals(c_token,"c$entre")
  1836. X              || almost_equals(c_token,"c$enter")) {
  1837. X          just = CENTRE;
  1838. X       }
  1839. X       else if (almost_equals(c_token,"r$ight")) {
  1840. X          just = RIGHT;
  1841. X       }
  1842. X       else
  1843. X        int_error("bad syntax in set label", c_token);
  1844. X       c_token++;
  1845. X       set_just = TRUE;
  1846. X    } 
  1847. X
  1848. X    if (!END_OF_COMMAND)
  1849. X     int_error("extraneous or out-of-order arguments in set label", c_token);
  1850. X
  1851. X    /* OK! add label */
  1852. X    if (first_label != NULL) { /* skip to last label */
  1853. X       for (this_label = first_label; this_label != NULL ; 
  1854. X           prev_label = this_label, this_label = this_label->next)
  1855. X        /* is this the label we want? */
  1856. X        if (tag <= this_label->tag)
  1857. X          break;
  1858. X    }
  1859. X    if (this_label != NULL && tag == this_label->tag) {
  1860. X       /* changing the label */
  1861. X       if (set_position) {
  1862. X          this_label->x = x;
  1863. X          this_label->y = y;
  1864. X       }
  1865. X       if (set_text)
  1866. X        (void) strcpy(this_label->text, text);
  1867. X       if (set_just)
  1868. X        this_label->pos = just;
  1869. X    } else {
  1870. X       /* adding the label */
  1871. X       new_label = (struct text_label *) 
  1872. X        alloc ( (unsigned int) sizeof(struct text_label), "label");
  1873. X       if (prev_label != NULL)
  1874. X        prev_label->next = new_label; /* add it to end of list */
  1875. X       else 
  1876. X        first_label = new_label; /* make it start of list */
  1877. X       new_label->tag = tag;
  1878. X       new_label->next = this_label;
  1879. X       new_label->x = x;
  1880. X       new_label->y = y;
  1881. X       (void) strcpy(new_label->text, text);
  1882. X       new_label->pos = just;
  1883. X    }
  1884. X}
  1885. X
  1886. X/* process 'set nolabel' command */
  1887. X/* set nolabel {tag} */
  1888. Xstatic void
  1889. Xset_nolabel()
  1890. X{
  1891. X    struct value a;
  1892. X    struct text_label *this_label;
  1893. X    struct text_label *prev_label; 
  1894. X    int tag;
  1895. X
  1896. X    if (END_OF_COMMAND) {
  1897. X       /* delete all labels */
  1898. X       while (first_label != NULL)
  1899. X        delete_label((struct text_label *)NULL,first_label);
  1900. X    }
  1901. X    else {
  1902. X       /* get tag */
  1903. X       tag = (int)real(const_express(&a));
  1904. X       if (!END_OF_COMMAND)
  1905. X        int_error("extraneous arguments to set nolabel", c_token);
  1906. X       for (this_label = first_label, prev_label = NULL;
  1907. X           this_label != NULL;
  1908. X           prev_label = this_label, this_label = this_label->next) {
  1909. X          if (this_label->tag == tag) {
  1910. X             delete_label(prev_label,this_label);
  1911. X             return;        /* exit, our job is done */
  1912. X          }
  1913. X       }
  1914. X       int_error("label not found", c_token);
  1915. X    }
  1916. X}
  1917. X
  1918. X/* assign a new label tag */
  1919. X/* labels are kept sorted by tag number, so this is easy */
  1920. Xstatic int                /* the lowest unassigned tag number */
  1921. Xassign_label_tag()
  1922. X{
  1923. X    struct text_label *this_label;
  1924. X    int last = 0;            /* previous tag value */
  1925. X
  1926. X    for (this_label = first_label; this_label != NULL;
  1927. X        this_label = this_label->next)
  1928. X     if (this_label->tag == last+1)
  1929. X       last++;
  1930. X     else
  1931. X       break;
  1932. X    
  1933. X    return (last+1);
  1934. X}
  1935. X
  1936. X/* delete label from linked list started by first_label.
  1937. X * called with pointers to the previous label (prev) and the 
  1938. X * label to delete (this).
  1939. X * If there is no previous label (the label to delete is
  1940. X * first_label) then call with prev = NULL.
  1941. X */
  1942. Xstatic void
  1943. Xdelete_label(prev,this)
  1944. X    struct text_label *prev, *this;
  1945. X{
  1946. X    if (this!=NULL)    {        /* there really is something to delete */
  1947. X       if (prev!=NULL)        /* there is a previous label */
  1948. X        prev->next = this->next; 
  1949. X       else                /* this = first_label so change first_label */
  1950. X        first_label = this->next;
  1951. X       free((char *)this);
  1952. X    }
  1953. X}
  1954. X
  1955. X
  1956. X/* process a 'set arrow' command */
  1957. X/* set arrow {tag} {from x,y} {to x,y} */
  1958. Xstatic void
  1959. Xset_arrow()
  1960. X{
  1961. X    struct value a;
  1962. X    struct arrow_def *this_arrow = NULL;
  1963. X    struct arrow_def *new_arrow = NULL;
  1964. X    struct arrow_def *prev_arrow = NULL;
  1965. X    double sx, sy;
  1966. X    double ex, ey;
  1967. X    int tag;
  1968. X    BOOLEAN set_start, set_end;
  1969. X
  1970. X    /* get tag */
  1971. X    if (!END_OF_COMMAND 
  1972. X       && !equals(c_token, "from")
  1973. X       && !equals(c_token, "to")) {
  1974. X       /* must be a tag expression! */
  1975. X       tag = (int)real(const_express(&a));
  1976. X       if (tag <= 0)
  1977. X        int_error("tag must be > zero", c_token);
  1978. X    } else
  1979. X     tag = assign_arrow_tag(); /* default next tag */
  1980. X     
  1981. X    /* get start position */
  1982. X    if (!END_OF_COMMAND && equals(c_token, "from")) {
  1983. X       c_token++;
  1984. X       if (END_OF_COMMAND)
  1985. X        int_error("start coordinates expected", c_token);
  1986. X       /* get coordinates */
  1987. X       sx = real(const_express(&a));
  1988. X       if (!equals(c_token,","))
  1989. X        int_error("',' expected",c_token);
  1990. X       c_token++;
  1991. X       sy = real(const_express(&a));
  1992. X       set_start = TRUE;
  1993. X    } else {
  1994. X       sx = sy = 0;            /* default at origin */
  1995. X       set_start = FALSE;
  1996. X    }
  1997. X
  1998. X    /* get end position */
  1999. X    if (!END_OF_COMMAND && equals(c_token, "to")) {
  2000. X       c_token++;
  2001. X       if (END_OF_COMMAND)
  2002. X        int_error("end coordinates expected", c_token);
  2003. X       /* get coordinates */
  2004. X       ex = real(const_express(&a));
  2005. X       if (!equals(c_token,","))
  2006. X        int_error("',' expected",c_token);
  2007. X       c_token++;
  2008. X       ey = real(const_express(&a));
  2009. X       set_end = TRUE;
  2010. X    } else {
  2011. X       ex = ey = 0;            /* default at origin */
  2012. X       set_end = FALSE;
  2013. X    }
  2014. X
  2015. X    /* get start position - what the heck, either order is ok */
  2016. X    if (!END_OF_COMMAND && equals(c_token, "from")) {
  2017. X       if (set_start)
  2018. X        int_error("only one 'from' is allowed", c_token);
  2019. X       c_token++;
  2020. X       if (END_OF_COMMAND)
  2021. X        int_error("start coordinates expected", c_token);
  2022. X       /* get coordinates */
  2023. X       sx = real(const_express(&a));
  2024. X       if (!equals(c_token,","))
  2025. X        int_error("',' expected",c_token);
  2026. X       c_token++;
  2027. X       sy = real(const_express(&a));
  2028. X       set_start = TRUE;
  2029. X    }
  2030. X
  2031. X    if (!END_OF_COMMAND)
  2032. X     int_error("extraneous or out-of-order arguments in set arrow", c_token);
  2033. X
  2034. X    /* OK! add arrow */
  2035. X    if (first_arrow != NULL) { /* skip to last arrow */
  2036. X       for (this_arrow = first_arrow; this_arrow != NULL ; 
  2037. X           prev_arrow = this_arrow, this_arrow = this_arrow->next)
  2038. X        /* is this the arrow we want? */
  2039. X        if (tag <= this_arrow->tag)
  2040. X          break;
  2041. X    }
  2042. X    if (this_arrow != NULL && tag == this_arrow->tag) {
  2043. X       /* changing the arrow */
  2044. X       if (set_start) {
  2045. X          this_arrow->sx = sx;
  2046. X          this_arrow->sy = sy;
  2047. X       }
  2048. X       if (set_end) {
  2049. X          this_arrow->ex = ex;
  2050. X          this_arrow->ey = ey;
  2051. X       }
  2052. X    } else {
  2053. X       /* adding the arrow */
  2054. X       new_arrow = (struct arrow_def *) 
  2055. X        alloc ( (unsigned int) sizeof(struct arrow_def), "arrow");
  2056. X       if (prev_arrow != NULL)
  2057. X        prev_arrow->next = new_arrow; /* add it to end of list */
  2058. X       else 
  2059. X        first_arrow = new_arrow; /* make it start of list */
  2060. X       new_arrow->tag = tag;
  2061. X       new_arrow->next = this_arrow;
  2062. X       new_arrow->sx = sx;
  2063. X       new_arrow->sy = sy;
  2064. X       new_arrow->ex = ex;
  2065. X       new_arrow->ey = ey;
  2066. X    }
  2067. X}
  2068. X
  2069. X/* process 'set noarrow' command */
  2070. X/* set noarrow {tag} */
  2071. Xstatic void
  2072. Xset_noarrow()
  2073. X{
  2074. X    struct value a;
  2075. X    struct arrow_def *this_arrow;
  2076. X    struct arrow_def *prev_arrow; 
  2077. X    int tag;
  2078. X
  2079. X    if (END_OF_COMMAND) {
  2080. X       /* delete all arrows */
  2081. X       while (first_arrow != NULL)
  2082. X        delete_arrow((struct arrow_def *)NULL,first_arrow);
  2083. X    }
  2084. X    else {
  2085. X       /* get tag */
  2086. X       tag = (int)real(const_express(&a));
  2087. X       if (!END_OF_COMMAND)
  2088. X        int_error("extraneous arguments to set noarrow", c_token);
  2089. X       for (this_arrow = first_arrow, prev_arrow = NULL;
  2090. X           this_arrow != NULL;
  2091. X           prev_arrow = this_arrow, this_arrow = this_arrow->next) {
  2092. X          if (this_arrow->tag == tag) {
  2093. X             delete_arrow(prev_arrow,this_arrow);
  2094. X             return;        /* exit, our job is done */
  2095. X          }
  2096. X       }
  2097. X       int_error("arrow not found", c_token);
  2098. X    }
  2099. X}
  2100. X
  2101. X/* assign a new arrow tag */
  2102. X/* arrows are kept sorted by tag number, so this is easy */
  2103. Xstatic int                /* the lowest unassigned tag number */
  2104. Xassign_arrow_tag()
  2105. X{
  2106. X    struct arrow_def *this_arrow;
  2107. X    int last = 0;            /* previous tag value */
  2108. X
  2109. X    for (this_arrow = first_arrow; this_arrow != NULL;
  2110. X        this_arrow = this_arrow->next)
  2111. X     if (this_arrow->tag == last+1)
  2112. X       last++;
  2113. X     else
  2114. X       break;
  2115. X
  2116. X    return (last+1);
  2117. X}
  2118. X
  2119. X/* delete arrow from linked list started by first_arrow.
  2120. X * called with pointers to the previous arrow (prev) and the 
  2121. X * arrow to delete (this).
  2122. X * If there is no previous arrow (the arrow to delete is
  2123. X * first_arrow) then call with prev = NULL.
  2124. X */
  2125. Xstatic void
  2126. Xdelete_arrow(prev,this)
  2127. X    struct arrow_def *prev, *this;
  2128. X{
  2129. X    if (this!=NULL)    {        /* there really is something to delete */
  2130. X       if (prev!=NULL)        /* there is a previous arrow */
  2131. X        prev->next = this->next; 
  2132. X       else                /* this = first_arrow so change first_arrow */
  2133. X        first_arrow = this->next;
  2134. X       free((char *)this);
  2135. X    }
  2136. X}
  2137. X
  2138. X
  2139. Xenum PLOT_STYLE            /* not static; used by command.c */
  2140. Xget_style()
  2141. X{
  2142. Xregister enum PLOT_STYLE ps;
  2143. X
  2144. X    c_token++;
  2145. X    if (almost_equals(c_token,"l$ines"))
  2146. X        ps = LINES;
  2147. X    else if (almost_equals(c_token,"i$mpulses"))
  2148. X        ps = IMPULSES;
  2149. X    else if (almost_equals(c_token,"p$oints"))
  2150. X        ps = POINTS;
  2151. X    else if (almost_equals(c_token,"linesp$oints"))
  2152. X        ps = LINESPOINTS;
  2153. X    else if (almost_equals(c_token,"d$ots"))
  2154. X        ps = DOTS;
  2155. X    else
  2156. X        int_error("expecting 'lines', 'points', 'linespoints', 'dots', or 'impulses'",c_token);
  2157. X    c_token++;
  2158. X    return(ps);
  2159. X}
  2160. X
  2161. X/* For set [xy]tics... command*/
  2162. Xstatic void
  2163. Xload_tics(tdef)
  2164. X    struct ticdef *tdef;    /* change this ticdef */
  2165. X{
  2166. X    if (equals(c_token,"(")) { /* set : TIC_USER */
  2167. X       c_token++;
  2168. X       load_tic_user(tdef);
  2169. X    } else {                /* series : TIC_SERIES */
  2170. X       load_tic_series(tdef);
  2171. X    }
  2172. X}
  2173. X
  2174. X/* load TIC_USER definition */
  2175. X/* (tic[,tic]...)
  2176. X * where tic is ["string"] value
  2177. X * Left paren is already scanned off before entry.
  2178. X */
  2179. Xstatic void
  2180. Xload_tic_user(tdef)
  2181. X    struct ticdef *tdef;
  2182. X{
  2183. X    struct ticmark *list = NULL; /* start of list */
  2184. X    struct ticmark *last = NULL; /* end of list */
  2185. X    struct ticmark *tic = NULL; /* new ticmark */
  2186. X    char temp_string[MAX_LINE_LEN];
  2187. X    struct value a;
  2188. X
  2189. X    while (!END_OF_COMMAND) {
  2190. X       /* parse a new ticmark */
  2191. X       tic = (struct ticmark *)alloc(sizeof(struct ticmark), (char *)NULL);
  2192. X       if (tic == (struct ticmark *)NULL) {
  2193. X          free_marklist(list);
  2194. X          int_error("out of memory for tic mark", c_token);
  2195. X       }
  2196. X
  2197. X       /* has a string with it? */
  2198. X       if (isstring(c_token)) {
  2199. X          quote_str(temp_string,c_token);
  2200. X          tic->label = alloc((unsigned int)strlen(temp_string)+1, "tic label");
  2201. X          (void) strcpy(tic->label, temp_string);
  2202. X          c_token++;
  2203. X       } else
  2204. X        tic->label = NULL;
  2205. X
  2206. X       /* in any case get the value */
  2207. X       tic->position = real(const_express(&a));
  2208. X       tic->next = NULL;
  2209. X
  2210. X       /* append to list */
  2211. X       if (list == NULL)
  2212. X        last = list = tic;    /* new list */
  2213. X       else {                /* append to list */
  2214. X          last->next = tic;
  2215. X          last = tic;
  2216. X       }
  2217. X
  2218. X       /* expect "," or ")" here */
  2219. X       if (!END_OF_COMMAND && equals(c_token, ","))
  2220. X        c_token++;        /* loop again */
  2221. X       else
  2222. X        break;            /* hopefully ")" */
  2223. X    }
  2224. X    
  2225. X    if (END_OF_COMMAND || !equals(c_token, ")")) {
  2226. X       free_marklist(list);
  2227. X       int_error("expecting right parenthesis )", c_token);
  2228. X    }
  2229. X    c_token++;
  2230. X    
  2231. X    /* successful list */
  2232. X    if (tdef->type == TIC_USER) {
  2233. X       /* remove old list */
  2234. X        /* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
  2235. X       free_marklist(tdef->def.user);
  2236. X       tdef->def.user = NULL;
  2237. X    }
  2238. X    tdef->type = TIC_USER;
  2239. X    tdef->def.user = list;
  2240. X}
  2241. X
  2242. Xstatic void
  2243. Xfree_marklist(list)
  2244. X    struct ticmark *list;
  2245. X{
  2246. X    register struct ticmark *freeable;
  2247. X
  2248. X    while (list != NULL) {
  2249. X       freeable = list;
  2250. X       list = list->next;
  2251. X       if (freeable->label != NULL)
  2252. X        free( (char *)freeable->label );
  2253. X       free( (char *)freeable );
  2254. X    }
  2255. X}
  2256. X
  2257. X/* load TIC_SERIES definition */
  2258. X/* start,incr[,end] */
  2259. Xstatic void
  2260. Xload_tic_series(tdef)
  2261. X    struct ticdef *tdef;
  2262. X{
  2263. X    double start, incr, end;
  2264. X    struct value a;
  2265. X    int incr_token;
  2266. X
  2267. X    start = real(const_express(&a));
  2268. X    if (!equals(c_token, ","))
  2269. X     int_error("expecting comma to separate start,incr", c_token);
  2270. X    c_token++;
  2271. X
  2272. X    incr_token = c_token;
  2273. X    incr = real(const_express(&a));
  2274. X
  2275. X    if (END_OF_COMMAND)
  2276. X     end = VERYLARGE;
  2277. X    else {
  2278. X       if (!equals(c_token, ","))
  2279. X        int_error("expecting comma to separate incr,end", c_token);
  2280. X       c_token++;
  2281. X
  2282. X       end = real(const_express(&a));
  2283. X    }
  2284. X    if (!END_OF_COMMAND)
  2285. X     int_error("tic series is defined by start,increment[,end]", 
  2286. X             c_token);
  2287. X    
  2288. X    if (start < end && incr <= 0)
  2289. X     int_error("increment must be positive", incr_token);
  2290. X    if (start > end && incr >= 0)
  2291. X     int_error("increment must be negative", incr_token);
  2292. X    if (start > end) {
  2293. X       /* put in order */
  2294. X        double numtics;
  2295. X        numtics = floor( (end*(1+SIGNIF) - start)/incr );
  2296. X        end = start;
  2297. X        start = end + numtics*incr;
  2298. X        incr = -incr;
  2299. X/*
  2300. X       double temp = start;
  2301. X       start = end;
  2302. X       end = temp;
  2303. X       incr = -incr;
  2304. X */
  2305. X    }
  2306. X
  2307. X    if (tdef->type == TIC_USER) {
  2308. X       /* remove old list */
  2309. X        /* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
  2310. X       free_marklist(tdef->def.user);
  2311. X       tdef->def.user = NULL;
  2312. X    }
  2313. X    tdef->type = TIC_SERIES;
  2314. X    tdef->def.series.start = start;
  2315. X    tdef->def.series.incr = incr;
  2316. X    tdef->def.series.end = end;
  2317. X}
  2318. X
  2319. Xstatic void
  2320. Xload_offsets (a, b, c, d)
  2321. Xdouble *a,*b, *c, *d;
  2322. X{
  2323. Xstruct value t;
  2324. X
  2325. X    *a = real (const_express(&t));  /* loff value */
  2326. X    c_token++;
  2327. X    if (equals(c_token,","))
  2328. X        c_token++;
  2329. X    if (END_OF_COMMAND) 
  2330. X        return;
  2331. X
  2332. X    *b = real (const_express(&t));  /* roff value */
  2333. X    c_token++;
  2334. X    if (equals(c_token,","))
  2335. X        c_token++;
  2336. X    if (END_OF_COMMAND) 
  2337. X        return;
  2338. X
  2339. X    *c = real (const_express(&t));  /* toff value */
  2340. X    c_token++;
  2341. X    if (equals(c_token,","))
  2342. X        c_token++;
  2343. X    if (END_OF_COMMAND) 
  2344. X        return;
  2345. X
  2346. X    *d = real (const_express(&t));  /* boff value */
  2347. X    c_token++;
  2348. X}
  2349. X
  2350. X
  2351. XBOOLEAN                    /* TRUE if a or b were changed */
  2352. Xload_range(a,b)            /* also used by command.c */
  2353. Xdouble *a,*b;
  2354. X{
  2355. Xstruct value t;
  2356. XBOOLEAN changed = FALSE;
  2357. X
  2358. X    if (equals(c_token,"]"))
  2359. X        return(FALSE);
  2360. X    if (END_OF_COMMAND) {
  2361. X        int_error("starting range value or ':' or 'to' expected",c_token);
  2362. X    } else if (!equals(c_token,"to") && !equals(c_token,":"))  {
  2363. X        *a = real(const_express(&t));
  2364. X        changed = TRUE;
  2365. X    }    
  2366. X    if (!equals(c_token,"to") && !equals(c_token,":"))
  2367. X        int_error("':' or keyword 'to' expected",c_token);
  2368. X    c_token++;
  2369. X    if (!equals(c_token,"]")) {
  2370. X        *b = real(const_express(&t));
  2371. X        changed = TRUE;
  2372. X     }
  2373. X     return(changed);
  2374. X}
  2375. X
  2376. X
  2377. X
  2378. X/******* The 'show' command *******/
  2379. Xvoid
  2380. Xshow_command()
  2381. X{
  2382. X    c_token++;
  2383. X
  2384. X    if (almost_equals(c_token,"ac$tion_table") ||
  2385. X             equals(c_token,"at") ) {
  2386. X        c_token++; 
  2387. X        show_at();
  2388. X        c_token++;
  2389. X    }
  2390. X    else if (almost_equals(c_token,"ar$row")) {
  2391. X        struct value a;
  2392. X        int tag = 0;
  2393. X
  2394. X        c_token++;
  2395. X        if (!END_OF_COMMAND) {
  2396. X           tag = (int)real(const_express(&a));
  2397. X           if (tag <= 0)
  2398. X            int_error("tag must be > zero", c_token);
  2399. X        }
  2400. X
  2401. X        (void) putc('\n',stderr);
  2402. X        show_arrow(tag);
  2403. X    }
  2404. X    else if (almost_equals(c_token,"au$toscale")) {
  2405. X        (void) putc('\n',stderr);
  2406. X        show_autoscale();
  2407. X        c_token++;
  2408. X    }
  2409. X    else if (almost_equals(c_token,"c$lip")) {
  2410. X        (void) putc('\n',stderr);
  2411. X        show_clip();
  2412. X        c_token++;
  2413. X    }
  2414. X    else if (almost_equals(c_token,"d$ata")) {
  2415. X        c_token++;
  2416. X        if (!almost_equals(c_token,"s$tyle"))
  2417. X            int_error("expecting keyword 'style'",c_token);
  2418. X        (void) putc('\n',stderr);
  2419. X        show_style("data",data_style);
  2420. X        c_token++;
  2421. X    }
  2422. X    else if (almost_equals(c_token,"d$ummy")) {
  2423. X        (void) fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
  2424. X        c_token++;
  2425. X    }
  2426. X    else if (almost_equals(c_token,"fo$rmat")) {
  2427. X        show_format();
  2428. X        c_token++;
  2429. X    }
  2430. X    else if (almost_equals(c_token,"f$unctions")) {
  2431. X        c_token++;
  2432. X        if (almost_equals(c_token,"s$tyle"))  {
  2433. X            (void) putc('\n',stderr);
  2434. X            show_style("functions",func_style);
  2435. X            c_token++;
  2436. X        }
  2437. X        else
  2438. X            show_functions();
  2439. X    }
  2440. X    else if (almost_equals(c_token,"lo$gscale")) {
  2441. X        (void) putc('\n',stderr);
  2442. X        show_logscale();
  2443. X        c_token++;
  2444. X    }
  2445. X    else if (almost_equals(c_token,"of$fsets")) {
  2446. X        (void) putc('\n',stderr);
  2447. X        show_offsets();
  2448. X        c_token++;
  2449. X    }
  2450. X    else if (almost_equals(c_token,"o$utput")) {
  2451. X        (void) putc('\n',stderr);
  2452. X        show_output();
  2453. X        c_token++;
  2454. X    }
  2455. X    else if (almost_equals(c_token,"tit$le")) {
  2456. X        (void) putc('\n',stderr);
  2457. X        show_title();
  2458. X        c_token++;
  2459. X    }
  2460. X    else if (almost_equals(c_token,"xl$abel")) {
  2461. X        (void) putc('\n',stderr);
  2462. X        show_xlabel();
  2463. X        c_token++;
  2464. X    }
  2465. X    else if (almost_equals(c_token,"yl$abel")) {
  2466. X        (void) putc('\n',stderr);
  2467. X        show_ylabel();
  2468. X        c_token++;
  2469. X    }
  2470. X    else if (almost_equals(c_token,"la$bel")) {
  2471. X        struct value a;
  2472. X        int tag = 0;
  2473. X
  2474. X        c_token++;
  2475. X        if (!END_OF_COMMAND) {
  2476. X           tag = (int)real(const_express(&a));
  2477. X           if (tag <= 0)
  2478. X            int_error("tag must be > zero", c_token);
  2479. X        }
  2480. X
  2481. X        (void) putc('\n',stderr);
  2482. X        show_label(tag);
  2483. X    }
  2484. X    else if (almost_equals(c_token,"g$rid")) {
  2485. X        (void) putc('\n',stderr);
  2486. X        show_grid();
  2487. X        c_token++;
  2488. X    }
  2489. X    else if (almost_equals(c_token,"k$ey")) {
  2490. X        (void) putc('\n',stderr);
  2491. X        show_key();
  2492. X        c_token++;
  2493. X    }
  2494. X    else if (almost_equals(c_token,"p$lot")) {
  2495. X        (void) putc('\n',stderr);
  2496. X        show_plot();
  2497. X        c_token++;
  2498. X    }
  2499. X    else if (almost_equals(c_token,"pol$ar")) {
  2500. X        (void) putc('\n',stderr);
  2501. X        show_polar();
  2502. X        c_token++;
  2503. X    }
  2504. X    else if (almost_equals(c_token,"ti$cs")) {
  2505. X        (void) putc('\n',stderr);
  2506. X        show_tics(TRUE, TRUE);
  2507. X        c_token++;
  2508. X    }
  2509. X    else if (almost_equals(c_token,"xti$cs")) {
  2510. X        show_tics(TRUE, FALSE);
  2511. X        c_token++;
  2512. X    }
  2513. X    else if (almost_equals(c_token,"yti$cs")) {
  2514. X        show_tics(FALSE, TRUE);
  2515. X        c_token++;
  2516. X    }
  2517. X    else if (almost_equals(c_token,"sa$mples")) {
  2518. X        (void) putc('\n',stderr);
  2519. X        show_samples();
  2520. X        c_token++;
  2521. X    }
  2522. X    else if (almost_equals(c_token,"si$ze")) {
  2523. X        (void) putc('\n',stderr);
  2524. X        show_size();
  2525. X        c_token++;
  2526. X    }
  2527. X    else if (almost_equals(c_token,"t$erminal")) {
  2528. X        (void) putc('\n',stderr);
  2529. X        show_term();
  2530. X        c_token++;
  2531. X    }
  2532. X    else if (almost_equals(c_token,"v$ariables")) {
  2533. X        show_variables();
  2534. X        c_token++;
  2535. X    }
  2536. X    else if (almost_equals(c_token,"ve$rsion")) {
  2537. X        show_version();
  2538. X        c_token++;
  2539. X    }
  2540. X    else if (almost_equals(c_token,"xr$ange")) {
  2541. X        (void) putc('\n',stderr);
  2542. X        show_range('x',xmin,xmax);
  2543. X        c_token++;
  2544. X    }
  2545. X    else if (almost_equals(c_token,"yr$ange")) {
  2546. X        (void) putc('\n',stderr);
  2547. X        show_range('y',ymin,ymax);
  2548. X        c_token++;
  2549. X    }
  2550. X    else if (almost_equals(c_token,"z$ero")) {
  2551. X        (void) putc('\n',stderr);
  2552. X        show_zero();
  2553. X        c_token++;
  2554. X    }
  2555. X    else if (almost_equals(c_token,"a$ll")) {
  2556. X        c_token++;
  2557. X        show_version();
  2558. X        show_autoscale();
  2559. X        show_clip();
  2560. X        (void) fprintf(stderr,"\tdummy variable is %s\n",dummy_var);
  2561. X        show_format();
  2562. X        show_style("data",data_style);
  2563. X        show_style("functions",func_style);
  2564. X        show_grid();
  2565. X        show_label(0);
  2566. X        show_arrow(0);
  2567. X        show_key();
  2568. X        show_logscale();
  2569. X        show_offsets();
  2570. X        show_output();
  2571. X        show_polar();
  2572. X        show_samples();
  2573. X        show_size();
  2574. X        show_term();
  2575. X        show_tics(TRUE,TRUE);
  2576. X        show_range('x',xmin,xmax);
  2577. X        show_range('y',ymin,ymax);
  2578. X        show_title();
  2579. X        show_xlabel();
  2580. X        show_ylabel();
  2581. X        show_zero();
  2582. X        show_plot();
  2583. X        show_variables();
  2584. X        show_functions();
  2585. X        c_token++;
  2586. X    }
  2587. X    else
  2588. X        int_error(
  2589. X    "valid show options:  'action_table', 'all', 'arrow', 'autoscale',  \n\
  2590. X    'clip', 'data', 'dummy', 'format', 'function', 'grid', 'key', 'label', \n\
  2591. X    'logscale', 'offsets', 'output', 'plot', 'polar', 'samples', \n\
  2592. X    'size', 'terminal', 'tics', 'title', 'variables', 'version', \n\
  2593. X    'xlabel', 'xrange', 'xtics', 'ylabel', 'yrange', 'ytics', 'zero'", c_token);
  2594. X    screen_ok = FALSE;
  2595. X    (void) putc('\n',stderr);
  2596. X}
  2597. X
  2598. X
  2599. X/*********** support functions for 'show'  **********/
  2600. Xstatic void
  2601. Xshow_style(name,style)
  2602. Xchar name[];
  2603. Xenum PLOT_STYLE style;
  2604. X{
  2605. X    fprintf(stderr,"\t%s are plotted with ",name);
  2606. X    switch (style) {
  2607. X        case LINES: fprintf(stderr,"lines\n"); break;
  2608. X        case POINTS: fprintf(stderr,"points\n"); break;
  2609. X        case IMPULSES: fprintf(stderr,"impulses\n"); break;
  2610. X        case LINESPOINTS: fprintf(stderr,"linespoints\n"); break;
  2611. X    }
  2612. X}
  2613. X
  2614. Xstatic void
  2615. Xshow_range(name,min,max)
  2616. Xchar name;
  2617. Xdouble min,max;
  2618. X{
  2619. X    fprintf(stderr,"\t%crange is [%g : %g]\n",name,min,max);
  2620. X}
  2621. X
  2622. Xstatic void
  2623. Xshow_zero()
  2624. X{
  2625. X    fprintf(stderr,"\tzero is %g\n",zero);
  2626. X}
  2627. X
  2628. Xstatic void
  2629. Xshow_offsets()
  2630. X{
  2631. X    fprintf(stderr,"\toffsets are %g, %g, %g, %g\n",loff,roff,toff,boff);
  2632. X}
  2633. X
  2634. Xstatic void
  2635. Xshow_output()
  2636. X{
  2637. X    fprintf(stderr,"\toutput is sent to %s\n",outstr);
  2638. X}
  2639. X
  2640. Xstatic void
  2641. Xshow_samples()
  2642. X{
  2643. X    fprintf(stderr,"\tsampling rate is %d\n",samples);
  2644. X}
  2645. X
  2646. Xstatic void
  2647. Xshow_size()
  2648. X{
  2649. X    fprintf(stderr,"\tsize is scaled by %g,%g\n",xsize,ysize);
  2650. X}
  2651. X
  2652. Xstatic void
  2653. Xshow_title()
  2654. X{
  2655. X    fprintf(stderr,"\ttitle is \"%s\"\n",title);
  2656. X}
  2657. X
  2658. Xstatic void
  2659. Xshow_xlabel()
  2660. X{
  2661. X    fprintf(stderr,"\txlabel is \"%s\"\n",xlabel);
  2662. X}
  2663. X
  2664. Xstatic void
  2665. Xshow_ylabel()
  2666. X{
  2667. X    fprintf(stderr,"\tylabel is \"%s\"\n",ylabel);
  2668. X}
  2669. X
  2670. Xstatic void
  2671. Xshow_label(tag)
  2672. X    int tag;                /* 0 means show all */
  2673. X{
  2674. X    struct text_label *this_label;
  2675. X    BOOLEAN showed = FALSE;
  2676. X
  2677. X    for (this_label = first_label; this_label != NULL;
  2678. X        this_label = this_label->next) {
  2679. X       if (tag == 0 || tag == this_label->tag) {
  2680. X          showed = TRUE;
  2681. X          fprintf(stderr,"\tlabel %d \"%s\" at %g,%g ",
  2682. X                this_label->tag, this_label->text, 
  2683. X                this_label->x, this_label->y);
  2684. X          switch(this_label->pos) {
  2685. X             case LEFT : {
  2686. X                fprintf(stderr,"left");
  2687. X                break;
  2688. X             }
  2689. X             case CENTRE : {
  2690. X                fprintf(stderr,"centre");
  2691. X                break;
  2692. X             }
  2693. X             case RIGHT : {
  2694. X                fprintf(stderr,"right");
  2695. X                break;
  2696. X             }
  2697. X          }
  2698. X          fputc('\n',stderr);
  2699. X       }
  2700. X    }
  2701. X    if (tag > 0 && !showed)
  2702. X     int_error("label not found", c_token);
  2703. X}
  2704. X
  2705. Xstatic void
  2706. Xshow_arrow(tag)
  2707. X    int tag;                /* 0 means show all */
  2708. X{
  2709. X    struct arrow_def *this_arrow;
  2710. X    BOOLEAN showed = FALSE;
  2711. X
  2712. X    for (this_arrow = first_arrow; this_arrow != NULL;
  2713. X        this_arrow = this_arrow->next) {
  2714. X       if (tag == 0 || tag == this_arrow->tag) {
  2715. X          showed = TRUE;
  2716. X          fprintf(stderr,"\tarrow %d from %g,%g to %g,%g\n",
  2717. X                this_arrow->tag, 
  2718. X                this_arrow->sx, this_arrow->sy,
  2719. X                this_arrow->ex, this_arrow->ey);
  2720. X       }
  2721. X    }
  2722. X    if (tag > 0 && !showed)
  2723. X     int_error("arrow not found", c_token);
  2724. X}
  2725. X
  2726. Xstatic void
  2727. Xshow_grid()
  2728. X{
  2729. X    fprintf(stderr,"\tgrid is %s\n",(grid)? "ON" : "OFF");
  2730. X}
  2731. X
  2732. Xstatic void
  2733. Xshow_key()
  2734. X{
  2735. X    switch (key) {
  2736. X        case -1 : 
  2737. X            fprintf(stderr,"\tkey is ON\n");
  2738. X            break;
  2739. X        case 0 :
  2740. X            fprintf(stderr,"\tkey is OFF\n");
  2741. X            break;
  2742. X        case 1 :
  2743. X            fprintf(stderr,"\tkey is at %g,%g\n",key_x,key_y);
  2744. X            break;
  2745. X    }
  2746. X}
  2747. X
  2748. Xstatic void
  2749. Xshow_polar()
  2750. X{
  2751. X    fprintf(stderr,"\tpolar is %s\n",(polar)? "ON" : "OFF");
  2752. X}
  2753. X
  2754. Xstatic void
  2755. Xshow_tics(showx, showy)
  2756. X    BOOLEAN showx, showy;
  2757. X{
  2758. X    fprintf(stderr,"\ttics are %s\n",(tic_in)? "IN" : "OUT");
  2759. X
  2760. X    if (showx)
  2761. X     show_ticdef(xtics, 'x', &xticdef);
  2762. X    if (showy)
  2763. X     show_ticdef(ytics, 'y', &yticdef);
  2764. X    screen_ok = FALSE;
  2765. X}
  2766. X
  2767. X/* called by show_tics */
  2768. Xstatic void
  2769. Xshow_ticdef(tics, axis, tdef)
  2770. X    BOOLEAN tics;            /* xtics or ytics */
  2771. X    char axis;            /* 'x' or 'y' */
  2772. X    struct ticdef *tdef;    /* xticdef or yticdef */
  2773. X{
  2774. X    register struct ticmark *t;
  2775. X
  2776. X    fprintf(stderr, "\t%c-axis tic labelling is ", axis);
  2777. X    if (!tics) {
  2778. X       fprintf(stderr, "OFF\n");
  2779. X       return;
  2780. X    }
  2781. X
  2782. X    switch(tdef->type) {
  2783. X       case TIC_COMPUTED: {
  2784. X          fprintf(stderr, "computed automatically\n");
  2785. X          break;
  2786. X       }
  2787. X       case TIC_SERIES: {
  2788. X          if (tdef->def.series.end == VERYLARGE)
  2789. X            fprintf(stderr, "series from %g by %g\n", 
  2790. X                  tdef->def.series.start, tdef->def.series.incr);
  2791. X          else
  2792. X            fprintf(stderr, "series from %g by %g until %g\n", 
  2793. X                  tdef->def.series.start, tdef->def.series.incr, 
  2794. X                  tdef->def.series.end);
  2795. X          break;
  2796. X       }
  2797. X       case TIC_USER: {
  2798. X          fprintf(stderr, "list (");
  2799. X          for (t = tdef->def.user; t != NULL; t=t->next) {
  2800. X             if (t->label)
  2801. X               fprintf(stderr, "\"%s\" ", t->label);
  2802. X             if (t->next)
  2803. X               fprintf(stderr, "%g, ", t->position);
  2804. X             else
  2805. X               fprintf(stderr, "%g", t->position);
  2806. X          }
  2807. X          fprintf(stderr, ")\n");
  2808. X          break;
  2809. X       }
  2810. X       default: {
  2811. X          int_error("unknown ticdef type in show_ticdef()", NO_CARET);
  2812. X          /* NOTREACHED */
  2813. X       }
  2814. X    }
  2815. X}
  2816. X
  2817. Xstatic void
  2818. Xshow_term()
  2819. X{
  2820. X    fprintf(stderr,"\tterminal type is %s\n",term_tbl[term].name);
  2821. X}
  2822. X
  2823. Xstatic void
  2824. Xshow_plot()
  2825. X{
  2826. X    fprintf(stderr,"\tlast plot command was: %s\n",replot_line);
  2827. X}
  2828. X
  2829. Xstatic void
  2830. Xshow_autoscale()
  2831. X{
  2832. X    fprintf(stderr,"\tx autoscaling is %s\n",(autoscale_x)? "ON" : "OFF");
  2833. X    fprintf(stderr,"\ty autoscaling is %s\n",(autoscale_y)? "ON" : "OFF");
  2834. X}
  2835. X
  2836. Xstatic void
  2837. Xshow_clip()
  2838. X{
  2839. X    fprintf(stderr,"\tpoint clip is %s\n",(clip_points)? "ON" : "OFF");
  2840. X
  2841. X    if (clip_lines1)
  2842. X      fprintf(stderr,
  2843. X         "\tdrawing and clipping lines between inrange and outrange points\n");
  2844. X    else
  2845. X      fprintf(stderr,
  2846. X         "\tnot drawing lines between inrange and outrange points\n");
  2847. X
  2848. X    if (clip_lines2)
  2849. X      fprintf(stderr,
  2850. X         "\tdrawing and clipping lines between two outrange points\n");
  2851. X    else
  2852. X      fprintf(stderr,
  2853. X         "\tnot drawing lines between two outrange points\n");
  2854. X}
  2855. X
  2856. Xstatic void
  2857. Xshow_format()
  2858. X{
  2859. X    fprintf(stderr, "\tx-axis tic format is \"%s\"\n", xformat);
  2860. X    fprintf(stderr, "\ty-axis tic format is \"%s\"\n", yformat);
  2861. X}
  2862. X
  2863. Xstatic void
  2864. Xshow_logscale()
  2865. X{
  2866. X    if (log_x && log_y)
  2867. X        fprintf(stderr,"\tlogscaling both x and y axes\n");
  2868. X    else if (log_x)
  2869. X        fprintf(stderr,"\tlogscaling x axis\n");
  2870. X    else if (log_y)
  2871. X        fprintf(stderr,"\tlogscaling y axis\n");
  2872. X    else
  2873. X        fprintf(stderr,"\tno logscaling\n");
  2874. X}
  2875. X
  2876. Xstatic void
  2877. Xshow_variables()
  2878. X{
  2879. Xregister struct udvt_entry *udv = first_udv;
  2880. Xint len;
  2881. X
  2882. X    fprintf(stderr,"\n\tVariables:\n");
  2883. X    while (udv) {
  2884. X         len = instring(udv->udv_name, ' ');
  2885. X        fprintf(stderr,"\t%-*s ",len,udv->udv_name);
  2886. X        if (udv->udv_undef)
  2887. X            fputs("is undefined\n",stderr);
  2888. X        else {
  2889. X            fputs("= ",stderr);
  2890. X            disp_value(stderr,&(udv->udv_value));
  2891. X            (void) putc('\n',stderr);
  2892. X        }
  2893. X        udv = udv->next_udv;
  2894. X    }
  2895. X}
  2896. X
  2897. Xvoid                /* used by plot.c */
  2898. Xshow_version()
  2899. X{
  2900. Xextern char version[];
  2901. Xextern char patchlevel[];
  2902. Xextern char date[];
  2903. Xextern char bug_email[];
  2904. Xstatic char *authors[] = {"Thomas Williams","Colin Kelley"}; /* primary */
  2905. Xint x;
  2906. Xlong time();
  2907. X
  2908. X    x = time((long *)NULL) & 1;
  2909. X    fprintf(stderr,"\n\t%s\n\t%sversion %s\n",
  2910. X        PROGRAM, OS, version); 
  2911. X    fprintf(stderr,"\tpatchlevel %s\n",patchlevel);
  2912. X     fprintf(stderr, "\tlast modified %s\n", date);
  2913. X    fprintf(stderr,"\tCopyright (C) 1986, 1987, 1990  %s, %s\n",
  2914. X        authors[x],authors[1-x]);
  2915. X#ifdef __TURBOC__
  2916. X    fprintf(stderr,"\tCreated using Turbo C, Copyright Borland 1987, 1988\n");
  2917. X#endif
  2918. X    fprintf(stderr, "\n\tSend bugs and comments to %s\n", bug_email);
  2919. X}
  2920. *-*-END-of-setshow.c-*-*
  2921. exit
  2922.  
  2923.  
  2924.