home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / Gnuplot / Source / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-02  |  25.3 KB  |  954 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: misc.c%v 3.38.2.78 1993/02/20 02:59:43 woo Exp woo $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - misc.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Thomas Williams,  Colin Kelley.
  27.  * 
  28.  *   Gnuplot 2.0 additions:
  29.  *       Russell Lang, Dave Kotz, John Campbell.
  30.  *
  31.  *   Gnuplot 3.0 additions:
  32.  *       Gershon Elber and many others.
  33.  *
  34.  * 19 September 1992  Lawrence Crowl  (crowl@cs.orst.edu)
  35.  * Added user-specified bases for log scaling.
  36.  * 
  37.  * Send your comments or suggestions to 
  38.  *  info-gnuplot@dartmouth.edu.
  39.  * This is a mailing list; to join it send a note to 
  40.  *  info-gnuplot-request@dartmouth.edu.  
  41.  * Send bug reports to
  42.  *  bug-gnuplot@dartmouth.edu.
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <math.h>
  47. #ifndef __PUREC__
  48. #ifndef VMS
  49. #include <sys/types.h>
  50. #else
  51. #include <types.h>
  52. #endif
  53. #endif /* __PUREC__ */
  54. #include "plot.h"
  55. #include "setshow.h"
  56. #ifndef _Windows
  57. #include "help.h"
  58. #endif
  59.  
  60. #if !defined(__TURBOC__) && !defined (_IBMR2) && !defined (ATARI) && !defined (AMIGA_SC_6_1) && !defined(OSF1)
  61. extern char *malloc();
  62. extern char *realloc();
  63. #endif
  64.  
  65. #if defined(__TURBOC__) && (defined(MSDOS) || defined(_Windows))
  66. #include <alloc.h>        /* for malloc, farmalloc, farrealloc */
  67. #endif
  68. #if defined(sequent)
  69. typedef unsigned long size_t;
  70. #endif
  71.  
  72. extern int c_token;
  73. extern char replot_line[];
  74. extern struct at_type at;
  75. extern struct ft_entry ft[];
  76. extern struct udft_entry *first_udf;
  77. extern struct udvt_entry *first_udv;
  78.  
  79. extern struct at_type *temp_at();
  80.  
  81. extern TBOOLEAN interactive;
  82. extern char *infile_name;
  83. extern int inline_num;
  84.  
  85. /* State information for load_file(), to recover from errors
  86.  * and properly handle recursive load_file calls
  87.  */
  88. typedef struct lf_state_struct LFS;
  89. struct lf_state_struct {
  90.     FILE *fp;                /* file pointer for load file */
  91.     char *name;            /* name of file */
  92.     TBOOLEAN interactive;        /* value of interactive flag on entry */
  93.     int inline_num;            /* inline_num on entry */
  94.     LFS *prev;                /* defines a stack */
  95. } *lf_head = NULL;            /* NULL if not in load_file */
  96.  
  97. static TBOOLEAN lf_pop();
  98. static void lf_push();
  99. FILE *lf_top();
  100.  
  101.  
  102. /*
  103.  * instead of <strings.h>
  104.  */
  105. #ifdef _Windows
  106. #include <string.h>
  107. #else
  108. #ifndef AMIGA_SC_6_1
  109. extern int strcmp();
  110. #endif /* !AMIGA_SC_6_1 */
  111. #endif
  112.  
  113. /* alloc:
  114.  * allocate memory 
  115.  * This is a protected version of malloc. It causes an int_error 
  116.  * if there is not enough memory, but first it tries FreeHelp() 
  117.  * to make some room, and tries again. If message is NULL, we 
  118.  * allow NULL return. Otherwise, we handle the error, using the
  119.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  120.  * so it depends on this using malloc().
  121.  */
  122.  
  123. char *
  124. alloc(size, message)
  125.     unsigned long size;        /* # of bytes */
  126.     char *message;            /* description of what is being allocated */
  127. {
  128.     char *p;                /* the new allocation */
  129.     char errbuf[100];        /* error message string */
  130.  
  131.     p = malloc((size_t)size);
  132.     if (p == (char *)NULL) {
  133. #ifndef vms
  134. #ifndef _Windows
  135.        FreeHelp();            /* out of memory, try to make some room */
  136. #endif
  137. #endif
  138.        p = malloc((size_t)size);        /* try again */
  139.        if (p == (char *)NULL) {
  140.           /* really out of memory */
  141.           if (message != NULL) {
  142.              (void) sprintf(errbuf, "out of memory for %s", message);
  143.              int_error(errbuf, NO_CARET);
  144.              /* NOTREACHED */
  145.           }
  146.           /* else we return NULL */
  147.        }
  148.     }
  149.     return(p);
  150. }
  151.  
  152. /*
  153.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  154.  * points.
  155.  */
  156. struct curve_points *
  157. cp_alloc(num)
  158.     int num;
  159. {
  160.     struct curve_points *cp;
  161.     cp = (struct curve_points *) alloc((unsigned long)sizeof(struct curve_points), "curve");
  162.     cp->p_max = (num >= 0 ? num : 0);
  163.     if (num > 0) {
  164.        cp->points = (struct coordinate GPHUGE *)
  165.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  166.     } else
  167.        cp->points = (struct coordinate GPHUGE *) NULL;
  168.     cp->next_cp = NULL;
  169.     cp->title = NULL;
  170.     return(cp);
  171. }
  172.  
  173.  
  174. /*
  175.  * cp_extend() reallocates a curve_points structure to hold "num"
  176.  * points. This will either expand or shrink the storage.
  177.  */
  178. cp_extend(cp, num)
  179.     struct curve_points *cp;
  180.     int num;
  181. {
  182.     struct coordinate GPHUGE *new;
  183.  
  184. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  185.     /* Make sure we do not allocate more than 64k points in msdos since 
  186.      * indexing is done with 16-bit int
  187.      * Leave some bytes for malloc maintainance.
  188.      */
  189.     if (num > 32700)
  190.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  191. #endif /* MSDOS */
  192.  
  193.     if (num == cp->p_max) return(0);
  194.  
  195.     if (num > 0) {
  196.        if (cp->points == NULL) {
  197.           cp->points = (struct coordinate GPHUGE *)
  198.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  199.        } else {
  200.           new = (struct coordinate GPHUGE *)
  201.             gpfarrealloc(cp->points, (unsigned long)num * sizeof(struct coordinate));
  202.           if (new == (struct coordinate GPHUGE *) NULL) {
  203.              int_error("No memory available for expanding curve points",
  204.                      NO_CARET);
  205.              /* NOTREACHED */
  206.           }
  207.           cp->points = new;
  208.        }
  209.        cp->p_max = num;
  210.     } else {
  211.        if (cp->points != (struct coordinate GPHUGE *) NULL)
  212.         gpfarfree(cp->points);
  213.        cp->points = (struct coordinate GPHUGE *) NULL;
  214.        cp->p_max = 0;
  215.     }
  216. }
  217.  
  218. /*
  219.  * cp_free() releases any memory which was previously malloc()'d to hold
  220.  *   curve points (and recursively down the linked list).
  221.  */
  222. cp_free(cp)
  223. struct curve_points *cp;
  224. {
  225.     if (cp) {
  226.         cp_free(cp->next_cp);
  227.         if (cp->title)
  228.             free((char *)cp->title);
  229.         if (cp->points)
  230.             gpfarfree((char *)cp->points);
  231.         free((char *)cp);
  232.     }
  233. }
  234.  
  235. /*
  236.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  237.  * points.
  238.  */
  239. struct iso_curve *
  240. iso_alloc(num)
  241.     int num;
  242. {
  243.     struct iso_curve *ip;
  244.     ip = (struct iso_curve *) alloc((unsigned long)sizeof(struct iso_curve), "iso curve");
  245.     ip->p_max = (num >= 0 ? num : 0);
  246.     if (num > 0) {
  247.        ip->points = (struct coordinate GPHUGE *)
  248.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  249.     } else
  250.        ip->points = (struct coordinate GPHUGE *) NULL;
  251.     ip->next = NULL;
  252.     return(ip);
  253. }
  254.  
  255. /*
  256.  * iso_extend() reallocates a iso_curve structure to hold "num"
  257.  * points. This will either expand or shrink the storage.
  258.  */
  259. iso_extend(ip, num)
  260.     struct iso_curve *ip;
  261.     int num;
  262. {
  263.     struct coordinate GPHUGE *new;
  264.  
  265.     if (num == ip->p_max) return(0);
  266.  
  267. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  268.     /* Make sure we do not allocate more than 64k points in msdos since 
  269.      * indexing is done with 16-bit int
  270.      * Leave some bytes for malloc maintainance.
  271.      */
  272.     if (num > 32700)
  273.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  274. #endif /* MSDOS */
  275.  
  276.     if (num > 0) {
  277.        if (ip->points == NULL) {
  278.           ip->points = (struct coordinate GPHUGE *)
  279.             alloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  280.        } else {
  281.           new = (struct coordinate GPHUGE *)
  282.             gpfarrealloc(ip->points, (unsigned long)num * sizeof(struct coordinate));
  283.           if (new == (struct coordinate GPHUGE *) NULL) {
  284.              int_error("No memory available for expanding curve points",
  285.                      NO_CARET);
  286.              /* NOTREACHED */
  287.           }
  288.           ip->points = new;
  289.        }
  290.        ip->p_max = num;
  291.     } else {
  292.        if (ip->points != (struct coordinate GPHUGE *) NULL)
  293.         gpfarfree(ip->points);
  294.        ip->points = (struct coordinate GPHUGE *) NULL;
  295.        ip->p_max = 0;
  296.     }
  297. }
  298.  
  299. /*
  300.  * iso_free() releases any memory which was previously malloc()'d to hold
  301.  *   iso curve points.
  302.  */
  303. iso_free(ip)
  304. struct iso_curve *ip;
  305. {
  306.     if (ip) {
  307.         if (ip->points)
  308.             gpfarfree((char *)ip->points);
  309.         free((char *)ip);
  310.     }
  311. }
  312.  
  313. /*
  314.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
  315.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  316.  * 'num_samp_1' samples.
  317.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  318.  */
  319. struct surface_points *
  320. sp_alloc(num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  321.     int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  322. {
  323.     struct surface_points *sp;
  324.  
  325.     sp = (struct surface_points *) alloc((unsigned long)sizeof(struct surface_points), "surface");
  326.     sp->next_sp = NULL;
  327.     sp->title = NULL;
  328.     sp->contours = NULL;
  329.     sp->iso_crvs = NULL;
  330.     sp->num_iso_read = 0;
  331.  
  332.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  333.     int i;
  334.     struct iso_curve *icrv;
  335.  
  336.     for (i = 0; i < num_iso_1; i++) {
  337.         icrv = iso_alloc(num_samp_2);
  338.         icrv->next = sp->iso_crvs;
  339.         sp->iso_crvs = icrv;
  340.     }
  341.     for (i = 0; i < num_iso_2; i++) {
  342.         icrv = iso_alloc(num_samp_1);
  343.         icrv->next = sp->iso_crvs;
  344.         sp->iso_crvs = icrv;
  345.     }
  346.     } else
  347.     sp->iso_crvs = (struct iso_curve *) NULL;
  348.  
  349.     return(sp);
  350. }
  351.  
  352. /*
  353.  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
  354.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  355.  * 'num_samp_1' samples.
  356.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  357.  */
  358. sp_replace(sp,num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  359.        struct surface_points *sp;
  360.        int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  361. {
  362.     int i;
  363.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  364.  
  365.     while ( icrvs ) {
  366.     icrv = icrvs;
  367.     icrvs = icrvs->next;
  368.     iso_free( icrv );
  369.     }
  370.     sp->iso_crvs = NULL;
  371.     
  372.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  373.     for (i = 0; i < num_iso_1; i++) {
  374.         icrv = iso_alloc(num_samp_2);
  375.         icrv->next = sp->iso_crvs;
  376.         sp->iso_crvs = icrv;
  377.     }
  378.     for (i = 0; i < num_iso_2; i++) {
  379.         icrv = iso_alloc(num_samp_1);
  380.         icrv->next = sp->iso_crvs;
  381.         sp->iso_crvs = icrv;
  382.     }
  383.     } else
  384.     sp->iso_crvs = (struct iso_curve *) NULL;
  385. }
  386.  
  387. /*
  388.  * sp_free() releases any memory which was previously malloc()'d to hold
  389.  *   surface points.
  390.  */
  391. sp_free(sp)
  392. struct surface_points *sp;
  393. {
  394.     if (sp) {
  395.         sp_free(sp->next_sp);
  396.         if (sp->title)
  397.             free((char *)sp->title);
  398.         if (sp->contours) {
  399.             struct gnuplot_contours *cntr, *cntrs = sp->contours;
  400.  
  401.             while (cntrs) {
  402.                 cntr = cntrs;
  403.                 cntrs = cntrs->next;
  404.                 gpfarfree(cntr->coords);
  405.                 free(cntr);
  406.             }
  407.         }
  408.         if (sp->iso_crvs) {
  409.             struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  410.  
  411.             while (icrvs) {
  412.                 icrv = icrvs;
  413.                 icrvs = icrvs->next;
  414.                 iso_free(icrv);
  415.             }
  416.         }
  417.         free((char *)sp);
  418.     }
  419. }
  420.  
  421.  
  422.  
  423. save_functions(fp)
  424. FILE *fp;
  425. {
  426. register struct udft_entry *udf = first_udf;
  427.  
  428.     if (fp) {
  429.         while (udf) {
  430.             if (udf->definition)
  431.                 fprintf(fp,"%s\n",udf->definition);
  432.             udf = udf->next_udf;
  433.         }
  434.         (void) fclose(fp);
  435.     } else
  436.         os_error("Cannot open save file",c_token);            
  437. }
  438.  
  439.  
  440. save_variables(fp)
  441. FILE *fp;
  442. {
  443. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  444.  
  445.     if (fp) {
  446.         while (udv) {
  447.             if (!udv->udv_undef) {
  448.                 fprintf(fp,"%s = ",udv->udv_name);
  449.                 disp_value(fp,&(udv->udv_value));
  450.                 (void) putc('\n',fp);
  451.             }
  452.             udv = udv->next_udv;
  453.         }
  454.         (void) fclose(fp);
  455.     } else
  456.         os_error("Cannot open save file",c_token);            
  457. }
  458.  
  459.  
  460. save_all(fp)
  461. FILE *fp;
  462. {
  463. register struct udft_entry *udf = first_udf;
  464. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  465.  
  466.     if (fp) {
  467.         save_set_all(fp);
  468.         while (udf) {
  469.             if (udf->definition)
  470.                 fprintf(fp,"%s\n",udf->definition);
  471.             udf = udf->next_udf;
  472.         }
  473.         while (udv) {
  474.             if (!udv->udv_undef) {
  475.                 fprintf(fp,"%s = ",udv->udv_name);
  476.                 disp_value(fp,&(udv->udv_value));
  477.                 (void) putc('\n',fp);
  478.             }
  479.             udv = udv->next_udv;
  480.         }
  481.         fprintf(fp,"%s\n",replot_line);
  482.         (void) fclose(fp);
  483.     } else
  484.         os_error("Cannot open save file",c_token);            
  485. }
  486.  
  487.  
  488. save_set(fp)
  489. FILE *fp;
  490. {
  491.     if (fp) {
  492.         save_set_all(fp);
  493.         (void) fclose(fp);
  494.     } else
  495.         os_error("Cannot open save file",c_token);            
  496. }
  497.  
  498.  
  499. save_set_all(fp)
  500. FILE *fp;
  501. {
  502. struct text_label *this_label;
  503. struct arrow_def *this_arrow;
  504. char *quote;
  505.     fprintf(fp,"set terminal %s %s\n", term_tbl[term].name, term_options);
  506.     fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
  507.     fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
  508.     fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
  509.     fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
  510.     fprintf(fp,"set %sborder\n",draw_border ? "" : "no");
  511.     if (boxwidth<0.0)
  512.         fprintf(fp,"set boxwidth\n");
  513.     else
  514.         fprintf(fp,"set boxwidth %g\n",boxwidth);
  515.     fprintf(fp,"set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
  516.     fprintf(fp,"set format x \"%s\"\n", xformat);
  517.     fprintf(fp,"set format y \"%s\"\n", yformat);
  518.     fprintf(fp,"set format z \"%s\"\n", zformat);
  519.     fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
  520.     switch (key) {
  521.         case -1 :
  522.             fprintf(fp,"set key\n");
  523.             break;
  524.         case 0 :
  525.             fprintf(fp,"set nokey\n");
  526.             break;
  527.         case 1 :
  528.             fprintf(fp,"set key %g,%g,%g\n",key_x,key_y,key_z);
  529.             break;
  530.     }
  531.     fprintf(fp,"set nolabel\n");
  532.     for (this_label = first_label; this_label != NULL;
  533.             this_label = this_label->next) {
  534.         fprintf(fp,"set label %d \"%s\" at %g,%g,%g ",
  535.                this_label->tag,
  536.                this_label->text, this_label->x,
  537.                          this_label->y,
  538.                          this_label->z);
  539.         switch(this_label->pos) {
  540.             case LEFT :
  541.                 fprintf(fp,"left");
  542.                 break;
  543.             case CENTRE :
  544.                 fprintf(fp,"centre");
  545.                 break;
  546.             case RIGHT :
  547.                 fprintf(fp,"right");
  548.                 break;
  549.         }
  550.         fputc('\n',fp);
  551.     }
  552.     fprintf(fp,"set noarrow\n");
  553.     for (this_arrow = first_arrow; this_arrow != NULL;
  554.             this_arrow = this_arrow->next) {
  555.         fprintf(fp,"set arrow %d from %g,%g,%g to %g,%g,%g%s\n",
  556.                this_arrow->tag,
  557.                this_arrow->sx, this_arrow->sy, this_arrow->sz,
  558.                this_arrow->ex, this_arrow->ey, this_arrow->ez,
  559.                this_arrow->head ? "" : " nohead");
  560.     }
  561.     fprintf(fp,"set nologscale\n");
  562.     if (is_log_x) fprintf(fp,"set logscale x %g\n", base_log_x);
  563.     if (is_log_y) fprintf(fp,"set logscale y %g\n", base_log_y);
  564.     if (is_log_z) fprintf(fp,"set logscale z %g\n", base_log_z);
  565.     fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
  566.     fprintf(fp,"set %spolar\n", (polar)? "" : "no");
  567.     fprintf(fp,"set angles %s\n", (angles_format == ANGLES_RADIANS)?
  568.                         "radians" : "degrees");
  569.     fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
  570.     fprintf(fp,"set view %g, %g, %g, %g\n",
  571.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale);
  572.     fprintf(fp,"set samples %d, %d\n",samples_1,samples_2);
  573.     fprintf(fp,"set isosamples %d, %d\n",iso_samples_1,iso_samples_2);
  574.     fprintf(fp,"set %ssurface\n",(draw_surface) ? "" : "no");
  575.     fprintf(fp,"set %scontour",(draw_contour) ? "" : "no");
  576.     switch (draw_contour) {
  577.         case CONTOUR_NONE: fprintf(fp, "\n"); break;
  578.         case CONTOUR_BASE: fprintf(fp, " base\n"); break;
  579.         case CONTOUR_SRF:  fprintf(fp, " surface\n"); break;
  580.         case CONTOUR_BOTH: fprintf(fp, " both\n"); break;
  581.     }
  582.      fprintf(fp,"set %sclabel\n",(label_contours) ? "" : "no");
  583.     fprintf(fp,"set %shidden3d\n",(hidden3d) ? "" : "no");
  584.     fprintf(fp,"set cntrparam order %d\n", contour_order);
  585.     fprintf(fp,"set cntrparam ");
  586.     switch (contour_kind) {
  587.         case CONTOUR_KIND_LINEAR:    fprintf(fp, "linear\n"); break;
  588.         case CONTOUR_KIND_CUBIC_SPL: fprintf(fp, "cubicspline\n"); break;
  589.         case CONTOUR_KIND_BSPLINE:   fprintf(fp, "bspline\n"); break;
  590.     }
  591.     fprintf(fp,"set cntrparam levels ");
  592.     switch (levels_kind) {
  593.         int i;
  594.         case LEVELS_AUTO:
  595.             fprintf(fp, "auto %d\n", contour_levels);
  596.             break;
  597.         case LEVELS_INCREMENTAL:
  598.             fprintf(fp, "incremental %g,%g,%g\n",
  599.                 levels_list[0], levels_list[1], 
  600.                 levels_list[0]+levels_list[1]*contour_levels);
  601.             break;
  602.         case LEVELS_DISCRETE:
  603.             fprintf(fp, "discrete ");
  604.                 fprintf(fp, "%g", levels_list[0]);
  605.             for(i = 1; i < contour_levels; i++)
  606.                 fprintf(fp, ",%g ", levels_list[i]);
  607.             fprintf(fp, "\n");
  608.     }
  609.     fprintf(fp,"set cntrparam points %d\n", contour_pts);
  610.     fprintf(fp,"set size %g,%g\n",xsize,ysize);
  611.     fprintf(fp,"set data style ");
  612.     switch (data_style) {
  613.         case LINES: fprintf(fp,"lines\n"); break;
  614.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  615.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  616.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  617.         case DOTS: fprintf(fp,"dots\n"); break;
  618.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  619.         case BOXES: fprintf(fp,"boxes\n"); break;
  620.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  621.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  622.     }
  623.     fprintf(fp,"set function style ");
  624.     switch (func_style) {
  625.         case LINES: fprintf(fp,"lines\n"); break;
  626.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  627.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  628.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  629.         case DOTS: fprintf(fp,"dots\n"); break;
  630.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  631.         case BOXES: fprintf(fp,"boxes\n"); break;
  632.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  633.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  634.     }
  635.         fprintf(fp,"set %sxzeroaxis\n", (xzeroaxis)? "" : "no");
  636.         fprintf(fp,"set %syzeroaxis\n", (yzeroaxis)? "" : "no");
  637.         fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
  638.         fprintf(fp,"set ticslevel %g\n", ticslevel);
  639.         save_tics(fp, xtics, 'x', &xticdef);
  640.         save_tics(fp, ytics, 'y', &yticdef);
  641.         save_tics(fp, ztics, 'z', &zticdef);
  642.         for (quote = &(title[0]); quote && *quote && (*quote != '"'); quote++)
  643.             ;
  644.         fprintf(fp,"set title %c%s%c %d,%d\n",*quote ? '\'' : '"',title,*quote ? '\'' : '"',title_xoffset,title_yoffset);
  645.     
  646.         if (timedate)
  647.         fprintf(fp,"set time %d,%d\n",time_xoffset,time_yoffset);
  648.     else
  649.         fprintf(fp,"set notime\n");
  650.      fprintf(fp,"set rrange [%g : %g]\n",rmin,rmax);
  651.     fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
  652.     fprintf(fp,"set urange [%g : %g]\n",umin,umax);
  653.     fprintf(fp,"set vrange [%g : %g]\n",vmin,vmax);
  654.         for (quote = &(xlabel[0]); quote && *quote && (*quote != '"'); quote++)
  655.             ;
  656.         fprintf(fp,"set xlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',xlabel,*quote ? '\'' : '"',xlabel_xoffset,xlabel_yoffset);
  657.         fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
  658.         for (quote = &(ylabel[0]); quote && *quote && (*quote != '"'); quote++)
  659.             ;
  660.         fprintf(fp,"set ylabel %c%s%c %d,%d\n",*quote ? '\'' : '"',ylabel,*quote ? '\'' : '"',ylabel_xoffset,ylabel_yoffset);
  661.         fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
  662.         for (quote = &(zlabel[0]); quote && *quote && (*quote != '"'); quote++)
  663.             ;
  664.         fprintf(fp,"set zlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',zlabel,*quote ? '\'' : '"',zlabel_xoffset,zlabel_yoffset);
  665.     fprintf(fp,"set zrange [%g : %g]\n",zmin,zmax);
  666.     fprintf(fp,"set %s %c\n", 
  667.         autoscale_r ? "autoscale" : "noautoscale", 'r');
  668.     fprintf(fp,"set %s %c\n", 
  669.         autoscale_t ? "autoscale" : "noautoscale", 't');
  670.     fprintf(fp,"set %s %c%c\n", 
  671.         (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale", 
  672.         autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
  673.     fprintf(fp,"set %s %c\n", 
  674.         autoscale_z ? "autoscale" : "noautoscale", 'z');
  675.     fprintf(fp,"set zero %g\n",zero);
  676. }
  677.  
  678. save_tics(fp, onoff, axis, tdef)
  679.     FILE *fp;
  680.     TBOOLEAN onoff;
  681.     char axis;
  682.     struct ticdef *tdef;
  683. {
  684.     if (onoff) {
  685.        fprintf(fp,"set %ctics", axis);
  686.        switch(tdef->type) {
  687.           case TIC_COMPUTED: {
  688.              break;
  689.           }
  690.           case TIC_MONTH:{
  691.               fprintf(fp,"\nset %cmtics",axis);
  692.             break;
  693.           }
  694.             case TIC_DAY:{
  695.             fprintf(fp,"\nset %cdtics",axis);
  696.             break;
  697.             }
  698.           case TIC_SERIES: {
  699.                  if (tdef->def.series.end >= VERYLARGE)
  700.                  fprintf(fp, " %g,%g", tdef->def.series.start,
  701.                                         tdef->def.series.incr);
  702.                          else
  703.                  fprintf(fp, " %g,%g,%g", tdef->def.series.start,
  704.                                         tdef->def.series.incr, tdef->def.series.end);
  705.              break;
  706.           }
  707.           case TIC_USER: {
  708.              register struct ticmark *t;
  709.              fprintf(fp, " (");
  710.              for (t = tdef->def.user; t != NULL; t=t->next) {
  711.                 if (t->label)
  712.                   fprintf(fp, "\"%s\" ", t->label);
  713.                 if (t->next)
  714.                   fprintf(fp, "%g, ", t->position);
  715.                 else
  716.                   fprintf(fp, "%g", t->position);
  717.              }
  718.              fprintf(fp, ")");
  719.              break;
  720.           } 
  721.        }
  722.        fprintf(fp, "\n");
  723.     } else {
  724.        fprintf(fp,"set no%ctics\n", axis);
  725.     }
  726. }
  727.  
  728. load_file(fp, name)
  729.     FILE *fp;
  730.     char *name;
  731. {
  732.     register int len;
  733.     extern char input_line[];
  734.  
  735.     int start, left;
  736.     int more;
  737.     int stop = FALSE;
  738.  
  739.     lf_push(fp);            /* save state for errors and recursion */
  740.  
  741.     if (fp == (FILE *)NULL) {
  742.        char errbuf[BUFSIZ];
  743.        (void) sprintf(errbuf, "Cannot open load file '%s'", name);
  744.        os_error(errbuf, c_token);
  745.     } else {
  746.        /* go into non-interactive mode during load */
  747.        /* will be undone below, or in load_file_error */
  748.        interactive = FALSE;
  749.        inline_num = 0;
  750.        infile_name = name;
  751.  
  752.        while (!stop) {        /* read all commands in file */
  753.           /* read one command */
  754.           left = MAX_LINE_LEN;
  755.           start = 0;
  756.           more = TRUE;
  757.  
  758.           while (more) {
  759.              if (fgets(&(input_line[start]), left, fp) == (char *)NULL) {
  760.                 stop = TRUE; /* EOF in file */
  761.                 input_line[start] = '\0';
  762.                 more = FALSE;    
  763.              } else {
  764.                 inline_num++;
  765.                 len = strlen(input_line) - 1;
  766.                 if (input_line[len] == '\n') { /* remove any newline */
  767.                     input_line[len] = '\0';
  768.                     /* Look, len was 1-1 = 0 before, take care here! */
  769.                     if (len > 0) --len;
  770.                 } else if (len+1 >= left)
  771.                   int_error("Input line too long",NO_CARET);
  772.                  
  773.                 if (input_line[len] == '\\') { /* line continuation */
  774.                     start = len;
  775.                     left  = MAX_LINE_LEN - start; /* left -=len;*/
  776.                 } else
  777.                   more = FALSE;
  778.              }
  779.           }
  780.  
  781.           if (strlen(input_line) > 0) {
  782.              screen_ok = FALSE;    /* make sure command line is
  783.                                echoed on error */
  784.              do_line();
  785.           }
  786.        }
  787.     }
  788.  
  789.     /* pop state */
  790.     (void) lf_pop();        /* also closes file fp */
  791. }
  792.  
  793. /* pop from load_file state stack */
  794. static TBOOLEAN                /* FALSE if stack was empty */
  795. lf_pop()                    /* called by load_file and load_file_error */
  796. {
  797.     LFS *lf;
  798.  
  799.     if (lf_head == NULL)
  800.      return(FALSE);
  801.     else {
  802.        lf = lf_head;
  803.        if (lf->fp != (FILE *)NULL)
  804.         (void) fclose(lf->fp);
  805.        interactive = lf->interactive;
  806.        inline_num = lf->inline_num;
  807.        infile_name = lf->name;
  808.        lf_head = lf->prev;
  809.        free((char *)lf);
  810.        return(TRUE);
  811.     }
  812. }
  813.  
  814. /* push onto load_file state stack */
  815. /* essentially, we save information needed to undo the load_file changes */
  816. static void
  817. lf_push(fp)            /* called by load_file */
  818.     FILE *fp;
  819. {
  820.     LFS *lf;
  821.     
  822.     lf = (LFS *)alloc((unsigned long)sizeof(LFS), (char *)NULL);
  823.     if (lf == (LFS *)NULL) {
  824.        if (fp != (FILE *)NULL)
  825.         (void) fclose(fp);        /* it won't be otherwise */
  826.        int_error("not enough memory to load file", c_token);
  827.     }
  828.      
  829.     lf->fp = fp;            /* save this file pointer */
  830.     lf->name = infile_name;    /* save current name */
  831.     lf->interactive = interactive;    /* save current state */
  832.     lf->inline_num = inline_num; /* save current line number */
  833.     lf->prev = lf_head;        /* link to stack */
  834.     lf_head = lf;
  835. }
  836.  
  837. FILE *lf_top()        /* used for reread  vsnyder@math.jpl.nasa.gov */
  838. {   if (lf_head == (LFS *) NULL) return((FILE *)NULL);
  839.     return(lf_head->fp);
  840. }
  841.  
  842.  
  843. load_file_error()            /* called from main */
  844. {
  845.     /* clean up from error in load_file */
  846.     /* pop off everything on stack */
  847.     while(lf_pop())
  848.      ;
  849. }
  850.  
  851. /* find char c in string str; return p such that str[p]==c;
  852.  * if c not in str then p=strlen(str)
  853.  */
  854. int
  855. instring(str, c)
  856.     char *str;
  857.     char c;
  858. {
  859.     int pos = 0;
  860.  
  861.     while (str != NULL && *str != '\0' && c != *str) {
  862.        str++; 
  863.        pos++;
  864.     }
  865.     return (pos);
  866. }
  867.  
  868. show_functions()
  869. {
  870. register struct udft_entry *udf = first_udf;
  871.  
  872.     fprintf(stderr,"\n\tUser-Defined Functions:\n");
  873.  
  874.     while (udf) {
  875.         if (udf->definition)
  876.             fprintf(stderr,"\t%s\n",udf->definition);
  877.         else
  878.             fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
  879.         udf = udf->next_udf;
  880.     }
  881. }
  882.  
  883.  
  884. show_at()
  885. {
  886.     (void) putc('\n',stderr);
  887.     disp_at(temp_at(),0);
  888. }
  889.  
  890.  
  891. disp_at(curr_at, level)
  892. struct at_type *curr_at;
  893. int level;
  894. {
  895. register int i, j;
  896. register union argument *arg;
  897.  
  898.     for (i = 0; i < curr_at->a_count; i++) {
  899.         (void) putc('\t',stderr);
  900.         for (j = 0; j < level; j++)
  901.             (void) putc(' ',stderr);    /* indent */
  902.  
  903.             /* print name of instruction */
  904.  
  905.         fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
  906.         arg = &(curr_at->actions[i].arg);
  907.  
  908.             /* now print optional argument */
  909.  
  910.         switch(curr_at->actions[i].index) {
  911.           case PUSH:    fprintf(stderr," %s\n", arg->udv_arg->udv_name);
  912.                     break;
  913.           case PUSHC:    (void) putc(' ',stderr);
  914.                     disp_value(stderr,&(arg->v_arg));
  915.                     (void) putc('\n',stderr);
  916.                     break;
  917.           case PUSHD1:    fprintf(stderr," %c dummy\n",
  918.                       arg->udf_arg->udf_name[0]);
  919.                     break;
  920.           case PUSHD2:    fprintf(stderr," %c dummy\n",
  921.                       arg->udf_arg->udf_name[1]);
  922.                     break;
  923.           case CALL:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  924.                     if(level < 6) {
  925.                     if (arg->udf_arg->at) {
  926.                         (void) putc('\n',stderr);
  927.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  928.                     } else
  929.                         fputs(" (undefined)\n",stderr);
  930.                     } else
  931.                         (void) putc('\n',stderr);
  932.                     break;
  933.           case CALLN:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  934.                     if(level < 6) {
  935.                     if (arg->udf_arg->at) {
  936.                         (void) putc('\n',stderr);
  937.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  938.                     } else
  939.                         fputs(" (undefined)\n",stderr);
  940.                     } else
  941.                         (void) putc('\n',stderr);
  942.                     break;
  943.           case JUMP:
  944.           case JUMPZ:
  945.           case JUMPNZ:
  946.           case JTERN:
  947.                     fprintf(stderr," +%d\n",arg->j_arg);
  948.                     break;
  949.           default:
  950.                     (void) putc('\n',stderr);
  951.         }
  952.     }
  953. }
  954.