home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 334_02 / misc.c < prev    next >
Text File  |  1991-02-05  |  14KB  |  546 lines

  1. /* GNUPLOT - misc.c */
  2. /*
  3.  * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software  is provided "as is" without express or implied warranty.
  16.  * 
  17.  *
  18.  * AUTHORS
  19.  * 
  20.  *   Original Software:
  21.  *     Thomas Williams,  Colin Kelley.
  22.  * 
  23.  *   Gnuplot 2.0 additions:
  24.  *       Russell Lang, Dave Kotz, John Campbell.
  25.  * 
  26.  * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
  27.  * 
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32. #include "plot.h"
  33. #include "setshow.h"
  34. #include "help.h"
  35. #ifdef __TURBOC__
  36. #include <graphics.h>
  37. #endif
  38.  
  39. #ifndef _IBMR2
  40. extern char *malloc();
  41. #endif
  42.  
  43. extern int c_token;
  44. extern char replot_line[];
  45. extern struct at_type at;
  46. extern struct ft_entry ft[];
  47. extern struct udft_entry *first_udf;
  48. extern struct udvt_entry *first_udv;
  49.  
  50. extern struct at_type *temp_at();
  51.  
  52. extern BOOLEAN interactive;
  53. extern char *infile_name;
  54. extern int inline_num;
  55.  
  56. /* State information for load_file(), to recover from errors
  57.  * and properly handle recursive load_file calls
  58.  */
  59. typedef struct lf_state_struct LFS;
  60. struct lf_state_struct {
  61.     FILE *fp;                /* file pointer for load file */
  62.     char *name;            /* name of file */
  63.     BOOLEAN interactive;        /* value of interactive flag on entry */
  64.     int inline_num;            /* inline_num on entry */
  65.     LFS *prev;                /* defines a stack */
  66. } *lf_head = NULL;            /* NULL if not in load_file */
  67.  
  68. static BOOLEAN lf_pop();
  69. static void lf_push();
  70.  
  71. /*
  72.  * instead of <strings.h>
  73.  */
  74. extern int strcmp();
  75.  
  76.  
  77. /*
  78.  * cp_free() releases any memory which was previously malloc()'d to hold
  79.  *   curve points.
  80.  */
  81. cp_free(cp)
  82. struct curve_points *cp;
  83. {
  84.     if (cp) {
  85.         cp_free(cp->next_cp);
  86.         if (cp->title)
  87.             free((char *)cp->title);
  88.         free((char *)cp);
  89.     }
  90. }
  91.  
  92.  
  93.  
  94. save_functions(fp)
  95. FILE *fp;
  96. {
  97. register struct udft_entry *udf = first_udf;
  98.     
  99.     if (fp) {
  100.         while (udf) {
  101.             if (udf->definition)
  102.                 fprintf(fp,"%s\n",udf->definition);
  103.             udf = udf->next_udf;
  104.         }
  105.         (void) fclose(fp);
  106.     } else
  107.         os_error("Cannot open save file",c_token);            
  108. }
  109.  
  110.  
  111. save_variables(fp)
  112. FILE *fp;
  113. {
  114. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  115.  
  116.     if (fp) {
  117.         while (udv) {
  118.             if (!udv->udv_undef) {
  119.                 fprintf(fp,"%s = ",udv->udv_name);
  120.                 disp_value(fp,&(udv->udv_value));
  121.                 (void) putc('\n',fp);
  122.             }
  123.             udv = udv->next_udv;
  124.         }
  125.         (void) fclose(fp);
  126.     } else
  127.         os_error("Cannot open save file",c_token);            
  128. }
  129.  
  130.  
  131. save_all(fp)
  132. FILE *fp;
  133. {
  134. register struct udft_entry *udf = first_udf;
  135. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  136.  
  137.     if (fp) {
  138.         save_set_all(fp);
  139.         while (udf) {
  140.             if (udf->definition)
  141.                 fprintf(fp,"%s\n",udf->definition);
  142.             udf = udf->next_udf;
  143.         }
  144.         while (udv) {
  145.             if (!udv->udv_undef) {
  146.                 fprintf(fp,"%s = ",udv->udv_name);
  147.                 disp_value(fp,&(udv->udv_value));
  148.                 (void) putc('\n',fp);
  149.             }
  150.             udv = udv->next_udv;
  151.         }
  152.         fprintf(fp,"%s\n",replot_line);
  153.         (void) fclose(fp);
  154.     } else
  155.         os_error("Cannot open save file",c_token);            
  156. }
  157.  
  158.  
  159. save_set(fp)
  160. FILE *fp;
  161. {
  162.     if (fp) {
  163.         save_set_all(fp);
  164.         (void) fclose(fp);
  165.     } else
  166.         os_error("Cannot open save file",c_token);            
  167. }
  168.  
  169.  
  170. save_set_all(fp)
  171. FILE *fp;
  172. {
  173. struct text_label *this_label;
  174. struct arrow_def *this_arrow;
  175.     fprintf(fp,"set terminal %s\n", term_tbl[term].name);
  176.     fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
  177.     fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
  178.     fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
  179.     fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
  180.     fprintf(fp,"set dummy %s\n",dummy_var);
  181.     fprintf(fp,"set format x \"%s\"\n", xformat);
  182.     fprintf(fp,"set format y \"%s\"\n", yformat);
  183.     fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
  184.     switch (key) {
  185.         case -1 : 
  186.             fprintf(fp,"set key\n");
  187.             break;
  188.         case 0 :
  189.             fprintf(fp,"set nokey\n");
  190.             break;
  191.         case 1 :
  192.             fprintf(fp,"set key %g,%g\n",key_x,key_y);
  193.             break;
  194.     }
  195.     fprintf(fp,"set nolabel\n");
  196.     for (this_label = first_label; this_label != NULL;
  197.             this_label = this_label->next) {
  198.         fprintf(fp,"set label %d \"%s\" at %g,%g ",
  199.                this_label->tag,
  200.                this_label->text, this_label->x, this_label->y);
  201.         switch(this_label->pos) {
  202.             case LEFT : 
  203.                 fprintf(fp,"left");
  204.                 break;
  205.             case CENTRE :
  206.                 fprintf(fp,"centre");
  207.                 break;
  208.             case RIGHT :
  209.                 fprintf(fp,"right");
  210.                 break;
  211.         }
  212.         fputc('\n',fp);
  213.     }
  214.     fprintf(fp,"set noarrow\n");
  215.     for (this_arrow = first_arrow; this_arrow != NULL;
  216.             this_arrow = this_arrow->next) {
  217.         fprintf(fp,"set arrow %d from %g,%g to %g,%g\n",
  218.                this_arrow->tag,
  219.                this_arrow->sx, this_arrow->sy,
  220.                this_arrow->ex, this_arrow->ey);
  221.     }
  222.     if ((!log_x)||(!log_y))
  223.         fprintf(fp,"set nologscale xy\n");
  224.     if (log_x||log_y)
  225.         fprintf(fp,"set logscale %c%c\n", 
  226.             log_x ? 'x' : ' ', log_y ? 'y' : ' ');
  227.     fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
  228.     fprintf(fp,"set %spolar\n", (polar)? "" : "no");
  229.     fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
  230.     fprintf(fp,"set samples %d\n",samples);
  231.     fprintf(fp,"set size %g,%g\n",xsize,ysize);
  232.     fprintf(fp,"set data style ");
  233.     switch (data_style) {
  234.         case LINES: fprintf(fp,"lines\n"); break;
  235.         case POINTS: fprintf(fp,"points\n"); break;
  236.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  237.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  238.         case DOTS: fprintf(fp,"dots\n"); break;
  239.     }
  240.     fprintf(fp,"set function style ");
  241.     switch (func_style) {
  242.         case LINES: fprintf(fp,"lines\n"); break;
  243.         case POINTS: fprintf(fp,"points\n"); break;
  244.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  245.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  246.         case DOTS: fprintf(fp,"dots\n"); break;
  247.     }
  248.     fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
  249.      save_tics(fp, xtics, 'x', &xticdef);
  250.      save_tics(fp, ytics, 'y', &yticdef);
  251.     fprintf(fp,"set title \"%s\"\n",title);
  252.     fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
  253.     fprintf(fp,"set xlabel \"%s\"\n",xlabel);
  254.     fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
  255.     fprintf(fp,"set ylabel \"%s\"\n",ylabel);
  256.     fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
  257.     fprintf(fp,"set %s %c\n", 
  258.         autoscale_t ? "autoscale" : "noautoscale", 't');
  259.     fprintf(fp,"set %s %c%c\n", 
  260.         (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale", 
  261.         autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
  262.     fprintf(fp,"set zero %g\n",zero);
  263. }
  264.  
  265. save_tics(fp, onoff, axis, tdef)
  266.     FILE *fp;
  267.     BOOLEAN onoff;
  268.     char axis;
  269.     struct ticdef *tdef;
  270. {
  271.     if (onoff) {
  272.        fprintf(fp,"set %ctics", axis);
  273.        switch(tdef->type) {
  274.           case TIC_COMPUTED: {
  275.              break;
  276.           }
  277.           case TIC_SERIES: {
  278.              fprintf(fp, " %g,%g,%g", tdef->def.series.start,
  279.                     tdef->def.series.incr, tdef->def.series.end);
  280.              break;
  281.           }
  282.           case TIC_USER: {
  283.              register struct ticmark *t;
  284.              fprintf(fp, " (");
  285.              for (t = tdef->def.user; t != NULL; t=t->next) {
  286.                 if (t->label)
  287.                   fprintf(fp, "\"%s\" ", t->label);
  288.                 if (t->next)
  289.                   fprintf(fp, "%g, ", t->position);
  290.                 else
  291.                   fprintf(fp, "%g", t->position);
  292.              }
  293.              fprintf(fp, ")");
  294.              break;
  295.           } 
  296.        }
  297.        fprintf(fp, "\n");
  298.     } else {
  299.        fprintf(fp,"set no%ctics\n", axis);
  300.     }
  301. }
  302.  
  303. load_file(fp, name)
  304.     FILE *fp;
  305.     char *name;
  306. {
  307.     register int len;
  308.     extern char input_line[];
  309.  
  310.     int start, left;
  311.     int more;
  312.     int stop = FALSE;
  313.  
  314.     lf_push(fp);            /* save state for errors and recursion */
  315.  
  316.     if (fp == (FILE *)NULL) {
  317.        char errbuf[BUFSIZ];
  318.        (void) sprintf(errbuf, "Cannot open load file '%s'", name);
  319.        os_error(errbuf, c_token);
  320.     } else {
  321.        /* go into non-interactive mode during load */
  322.        /* will be undone below, or in load_file_error */
  323.        interactive = FALSE;
  324.        inline_num = 0;
  325.        infile_name = name;
  326.  
  327.        while (!stop) {        /* read all commands in file */
  328.           /* read one command */
  329.           left = MAX_LINE_LEN;
  330.           start = 0;
  331.           more = TRUE;
  332.  
  333.           while (more) {
  334.              if (fgets(&(input_line[start]), left, fp) == NULL) {
  335.                 stop = TRUE; /* EOF in file */
  336.                 input_line[start] = '\0';
  337.                 more = FALSE;    
  338.              } else {
  339.                 inline_num++;
  340.                 len = strlen(input_line) - 1;
  341.                 if (input_line[len] == '\n') { /* remove any newline */
  342.                     input_line[len] = '\0';
  343.                     /* Look, len was 1-1 = 0 before, take care here! */
  344.                     if (len > 0) --len;
  345.                 } else if (len+1 >= left)
  346.                   int_error("Input line too long",NO_CARET);
  347.                  
  348.                 if (input_line[len] == '\\') { /* line continuation */
  349.                     start = len;
  350.                     left  = MAX_LINE_LEN - start; /* left -=len;*/
  351.                 } else
  352.                   more = FALSE;
  353.              }
  354.           }
  355.  
  356.           if (strlen(input_line) > 0) {
  357.              screen_ok = FALSE;    /* make sure command line is
  358.                                echoed on error */
  359.              do_line();
  360.           }
  361.        }
  362.     }
  363.  
  364.     /* pop state */
  365.     (void) lf_pop();        /* also closes file fp */
  366. }
  367.  
  368. /* pop from load_file state stack */
  369. static BOOLEAN                /* FALSE if stack was empty */
  370. lf_pop()                    /* called by load_file and load_file_error */
  371. {
  372.     LFS *lf;
  373.  
  374.     if (lf_head == NULL)
  375.      return(FALSE);
  376.     else {
  377.        lf = lf_head;
  378.        if (lf->fp != (FILE *)NULL)
  379.         (void) fclose(lf->fp);
  380.        interactive = lf->interactive;
  381.        inline_num = lf->inline_num;
  382.        infile_name = lf->name;
  383.        lf_head = lf->prev;
  384.        free((char *)lf);
  385.        return(TRUE);
  386.     }
  387. }
  388.  
  389. /* push onto load_file state stack */
  390. /* essentially, we save information needed to undo the load_file changes */
  391. static void
  392. lf_push(fp)            /* called by load_file */
  393.     FILE *fp;
  394. {
  395.     LFS *lf;
  396.     
  397.     lf = (LFS *)alloc(sizeof(LFS), (char *)NULL);
  398.     if (lf == (LFS *)NULL) {
  399.        if (fp != (FILE *)NULL)
  400.         (void) fclose(fp);        /* it won't be otherwise */
  401.        int_error("not enough memory to load file", c_token);
  402.     }
  403.      
  404.     lf->fp = fp;            /* save this file pointer */
  405.     lf->name = infile_name;    /* save current name */
  406.     lf->interactive = interactive;    /* save current state */
  407.     lf->inline_num = inline_num; /* save current line number */
  408.     lf->prev = lf_head;        /* link to stack */
  409.     lf_head = lf;
  410. }
  411.  
  412. load_file_error()            /* called from main */
  413. {
  414.     /* clean up from error in load_file */
  415.     /* pop off everything on stack */
  416.     while(lf_pop())
  417.      ;
  418. }
  419.  
  420. /* find char c in string str; return p such that str[p]==c;
  421.  * if c not in str then p=strlen(str)
  422.  */
  423. int
  424. instring(str, c)
  425.     char *str;
  426.     char c;
  427. {
  428.     int pos = 0;
  429.  
  430.     while (str != NULL && *str != '\0' && c != *str) {
  431.        str++; 
  432.        pos++;
  433.     }
  434.     return (pos);
  435. }
  436.  
  437. show_functions()
  438. {
  439. register struct udft_entry *udf = first_udf;
  440.  
  441.     fprintf(stderr,"\n\tUser-Defined Functions:\n");
  442.  
  443.     while (udf) {
  444.         if (udf->definition)
  445.             fprintf(stderr,"\t%s\n",udf->definition);
  446.         else
  447.             fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
  448.         udf = udf->next_udf;
  449.     }
  450. }
  451.  
  452.  
  453. show_at()
  454. {
  455.     (void) putc('\n',stderr);
  456.     disp_at(temp_at(),0);
  457. }
  458.  
  459.  
  460. disp_at(curr_at, level)
  461. struct at_type *curr_at;
  462. int level;
  463. {
  464. register int i, j;
  465. register union argument *arg;
  466.  
  467.     for (i = 0; i < curr_at->a_count; i++) {
  468.         (void) putc('\t',stderr);
  469.         for (j = 0; j < level; j++)
  470.             (void) putc(' ',stderr);    /* indent */
  471.  
  472.             /* print name of instruction */
  473.  
  474.         fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
  475.         arg = &(curr_at->actions[i].arg);
  476.  
  477.             /* now print optional argument */
  478.  
  479.         switch(curr_at->actions[i].index) {
  480.           case PUSH:    fprintf(stderr," %s\n", arg->udv_arg->udv_name);
  481.                     break;
  482.           case PUSHC:    (void) putc(' ',stderr);
  483.                     disp_value(stderr,&(arg->v_arg));
  484.                     (void) putc('\n',stderr);
  485.                     break;
  486.           case PUSHD:    fprintf(stderr," %s dummy\n",
  487.                       arg->udf_arg->udf_name);
  488.                     break;
  489.           case CALL:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  490.                     if (arg->udf_arg->at) {
  491.                         (void) putc('\n',stderr);
  492.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  493.                     } else
  494.                         fputs(" (undefined)\n",stderr);
  495.                     break;
  496.           case JUMP:
  497.           case JUMPZ:
  498.           case JUMPNZ:
  499.           case JTERN:
  500.                     fprintf(stderr," +%d\n",arg->j_arg);
  501.                     break;
  502.           default:
  503.                     (void) putc('\n',stderr);
  504.         }
  505.     }
  506. }
  507.  
  508.  
  509. /* alloc:
  510.  * allocate memory 
  511.  * This is a protected version of malloc. It causes an int_error 
  512.  * if there is not enough memory, but first it tries FreeHelp() 
  513.  * to make some room, and tries again. If message is NULL, we 
  514.  * allow NULL return. Otherwise, we handle the error, using the
  515.  * message to create the int_error string.
  516.  */
  517.  
  518. char *
  519. alloc(size, message)
  520.     unsigned int size;                /* # of bytes */
  521.     char *message;            /* description of what is being allocated */
  522. {
  523.     char *p;                /* the new allocation */
  524.     char errbuf[100];        /* error message string */
  525.  
  526.     p = malloc(size);
  527.     if (p == (char *)NULL) {
  528. #ifndef VMS
  529.        FreeHelp();            /* out of memory, try to make some room */
  530. #endif
  531.        
  532.        p = malloc(size);        /* try again */
  533.        if (p == (char *)NULL) {
  534.           /* really out of memory */
  535.           if (message != NULL) {
  536.              (void) sprintf(errbuf, "out of memory for %s", message);
  537.              int_error(errbuf, NO_CARET);
  538.              /* NOTREACHED */
  539.           }
  540.           /* else we return NULL */
  541.        }
  542.     }
  543.  
  544.     return(p);
  545. }
  546.