home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / gnuplot.lha / gnuplot / src / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-28  |  12.7 KB  |  626 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: util.c%v 3.50 1993/07/09 05:35:24 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - util.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.  */
  35.  
  36. #include <ctype.h>
  37. #include <setjmp.h>
  38. #include <stdio.h>
  39. #include <errno.h>
  40. #include "plot.h"
  41.  
  42. TBOOLEAN screen_ok;
  43.     /* TRUE if command just typed; becomes FALSE whenever we
  44.         send some other output to screen.  If FALSE, the command line
  45.         will be echoed to the screen before the ^ error message. */
  46.  
  47. #ifndef LINUX
  48. #ifndef vms
  49. #if !defined(__ZTC__) && !defined(__PUREC__)
  50. #if !defined(__MSC__)
  51. extern int errno;
  52. #endif
  53. extern int sys_nerr;
  54. extern char *sys_errlist[];
  55. #endif
  56. #endif /* vms */
  57. #endif /* LINUX */
  58.  
  59. extern char input_line[];
  60. extern struct lexical_unit token[];
  61. #ifdef _Windows
  62. extern jmp_buf far env;    /* from plot.c */
  63. #else
  64. extern jmp_buf env;    /* from plot.c */
  65. #endif
  66. extern int inline_num;        /* from command.c */
  67. extern TBOOLEAN interactive;    /* from plot.c */
  68. extern char *infile_name;    /* from plot.c */
  69.  
  70. #ifdef sequent
  71. extern char *index();
  72. #else
  73. extern char *strchr();
  74. #endif
  75.  
  76. #ifndef AMIGA_AC_5
  77. extern double sqrt(), atan2();
  78. #endif
  79.  
  80. /*
  81.  * chr_in_str() compares the characters in the string of token number t_num
  82.  * with c, and returns TRUE if a match was found.
  83.  */
  84. chr_in_str(t_num, c)
  85. int t_num;
  86. char c;
  87. {
  88. register int i;
  89.  
  90.     if (!token[t_num].is_token)
  91.         return(FALSE);                /* must be a value--can't be equal */
  92.     for (i = 0; i < token[t_num].length; i++) {
  93.         if (input_line[token[t_num].start_index+i] == c)
  94.             return(TRUE);
  95.         }
  96.     return FALSE;
  97. }
  98.  
  99.  
  100. /*
  101.  * equals() compares string value of token number t_num with str[], and
  102.  *   returns TRUE if they are identical.
  103.  */
  104. equals(t_num, str)
  105. int t_num;
  106. char *str;
  107. {
  108. register int i;
  109.  
  110.     if (!token[t_num].is_token)
  111.         return(FALSE);                /* must be a value--can't be equal */
  112.     for (i = 0; i < token[t_num].length; i++) {
  113.         if (input_line[token[t_num].start_index+i] != str[i])
  114.             return(FALSE);
  115.         }
  116.     /* now return TRUE if at end of str[], FALSE if not */
  117.     return(str[i] == '\0');
  118. }
  119.  
  120.  
  121.  
  122. /*
  123.  * almost_equals() compares string value of token number t_num with str[], and
  124.  *   returns TRUE if they are identical up to the first $ in str[].
  125.  */
  126. almost_equals(t_num, str)
  127. int t_num;
  128. char *str;
  129. {
  130. register int i;
  131. register int after = 0;
  132. register start = token[t_num].start_index;
  133. register length = token[t_num].length;
  134.  
  135.     if (!token[t_num].is_token)
  136.         return(FALSE);                /* must be a value--can't be equal */
  137.     for (i = 0; i < length + after; i++) {
  138.         if (str[i] != input_line[start + i]) {
  139.             if (str[i] != '$')
  140.                 return(FALSE);
  141.             else {
  142.                 after = 1;
  143.                 start--;    /* back up token ptr */
  144.                 }
  145.             }
  146.         }
  147.  
  148.     /* i now beyond end of token string */
  149.  
  150.     return(after || str[i] == '$' || str[i] == '\0');
  151. }
  152.  
  153.  
  154.  
  155. isstring(t_num)
  156. int t_num;
  157. {
  158.     
  159.     return(token[t_num].is_token &&
  160.            (input_line[token[t_num].start_index] == '\'' ||
  161.            input_line[token[t_num].start_index] == '\"'));
  162. }
  163.  
  164.  
  165. isnumber(t_num)
  166. int t_num;
  167. {
  168.     return(!token[t_num].is_token);
  169. }
  170.  
  171.  
  172. isletter(t_num)
  173. int t_num;
  174. {
  175.     return(token[t_num].is_token &&
  176.             ((isalpha(input_line[token[t_num].start_index]))||
  177.              (input_line[token[t_num].start_index] == '_')));
  178. }
  179.  
  180.  
  181. /*
  182.  * is_definition() returns TRUE if the next tokens are of the form
  183.  *   identifier =
  184.  *        -or-
  185.  *   identifier ( identifer {,identifier} ) =
  186.  */
  187. is_definition(t_num)
  188. int t_num;
  189. {
  190.     /* variable? */
  191.     if(isletter(t_num) && equals(t_num+1,"="))
  192.         return 1;
  193.  
  194.     /* function? */
  195.     /* look for dummy variables */
  196.     if(isletter(t_num) && equals(t_num+1,"(") && isletter(t_num+2)) {
  197.         t_num += 3;  /* point past first dummy */
  198.         while(equals(t_num,",")) {
  199.             if(!isletter(++t_num))
  200.                 return 0;
  201.             t_num += 1;
  202.         }
  203.         return(equals(t_num,")") && equals(t_num+1,"="));
  204.     }
  205.  
  206.     /* neither */
  207.     return 0;
  208. }
  209.  
  210.  
  211.  
  212. /*
  213.  * copy_str() copies the string in token number t_num into str, appending
  214.  *   a null.  No more than MAX_ID_LEN chars are copied.
  215.  */
  216. copy_str(str, t_num)
  217. char str[];
  218. int t_num;
  219. {
  220. register int i = 0;
  221. register int start = token[t_num].start_index;
  222. register int count;
  223.  
  224.     if ((count = token[t_num].length) > MAX_ID_LEN)
  225.         count = MAX_ID_LEN;
  226.     do {
  227.         str[i++] = input_line[start++];
  228.         } while (i != count);
  229.     str[i] = '\0';
  230. }
  231.  
  232.  
  233. /*
  234.  * quote_str() does the same thing as copy_str, except it ignores the
  235.  *   quotes at both ends.  This seems redundant, but is done for
  236.  *   efficency.
  237.  */
  238. quote_str(str, t_num)
  239. char str[];
  240. int t_num;
  241. {
  242. register int i = 0;
  243. register int start = token[t_num].start_index + 1;
  244. register int count;
  245.  
  246.     if ((count = token[t_num].length - 2) > MAX_ID_LEN)
  247.         count = MAX_ID_LEN;
  248.     if (count>0) {
  249.         do {
  250.             str[i++] = input_line[start++];
  251.             } while (i != count);
  252.     }
  253.     str[i] = '\0';
  254. }
  255.  
  256.  
  257. /*
  258.  * quotel_str() does the same thing as quote_str, except it uses
  259.  * MAX_LINE_LEN instead of MAX_ID_LEN. 
  260.  */ 
  261. quotel_str(str, t_num) 
  262. char str[]; 
  263. int t_num; 
  264. {
  265. register int i = 0;
  266. register int start = token[t_num].start_index + 1;
  267. register int count;
  268.  
  269.     if ((count = token[t_num].length - 2) > MAX_LINE_LEN)
  270.         count = MAX_LINE_LEN;
  271.     if (count>0) {
  272.         do {
  273.             str[i++] = input_line[start++];
  274.             } while (i != count);
  275.     }
  276.     str[i] = '\0';
  277. }
  278.  
  279.  
  280. /*
  281.  *    capture() copies into str[] the part of input_line[] which lies between
  282.  *    the begining of token[start] and end of token[end].
  283.  */
  284. capture(str,start,end)
  285. char str[];
  286. int start,end;
  287. {
  288. register int i,e;
  289.  
  290.     e = token[end].start_index + token[end].length;
  291.     for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
  292.         *str++ = input_line[i];
  293.     *str = '\0';
  294. }
  295.  
  296.  
  297. /*
  298.  *    m_capture() is similar to capture(), but it mallocs storage for the
  299.  *  string.
  300.  */
  301. m_capture(str,start,end)
  302. char **str;
  303. int start,end;
  304. {
  305. register int i,e;
  306. register char *s;
  307.  
  308.     if (*str)        /* previous pointer to malloc'd memory there */
  309.         free(*str);
  310.     e = token[end].start_index + token[end].length;
  311.     *str = alloc((unsigned long)(e - token[start].start_index + 1), "string");
  312.      s = *str;
  313.      for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
  314.       *s++ = input_line[i];
  315.      *s = '\0';
  316. }
  317.  
  318.  
  319. /*
  320.  *    m_quote_capture() is similar to m_capture(), but it removes
  321.     quotes from either end if the string.
  322.  */
  323. m_quote_capture(str,start,end)
  324. char **str;
  325. int start,end;
  326. {
  327. register int i,e;
  328. register char *s;
  329.  
  330.     if (*str)        /* previous pointer to malloc'd memory there */
  331.         free(*str);
  332.     e = token[end].start_index + token[end].length-1;
  333.     *str = alloc((unsigned long)(e - token[start].start_index + 1), "string");
  334.      s = *str;
  335.     for (i = token[start].start_index + 1; i < e && input_line[i] != '\0'; i++)
  336.      *s++ = input_line[i];
  337.     *s = '\0';
  338. }
  339.  
  340.  
  341. convert(val_ptr, t_num)
  342. struct value *val_ptr;
  343. int t_num;
  344. {
  345.     *val_ptr = token[t_num].l_val;
  346. }
  347.  
  348. static char *num_to_str(r)
  349. double r;
  350. {
  351.     static i = 0;
  352.     static char s[4][20];
  353.     int j = i++;
  354.  
  355.     if ( i > 3 ) i = 0;
  356.  
  357.     sprintf( s[j], "%g", r );
  358. #ifdef sequent
  359.     if ( index( s[j], '.' ) == NULL &&
  360.          index( s[j], 'e' ) == NULL &&
  361.          index( s[j], 'E' ) == NULL )
  362. #else
  363.     if ( strchr( s[j], '.' ) == NULL &&
  364.          strchr( s[j], 'e' ) == NULL &&
  365.          strchr( s[j], 'E' ) == NULL )
  366. #endif
  367.         strcat( s[j], ".0" );
  368.  
  369.     return s[j];
  370.  
  371. disp_value(fp,val)
  372. FILE *fp;
  373. struct value *val;
  374. {
  375.     switch(val->type) {
  376.         case INTGR:
  377.             fprintf(fp,"%d",val->v.int_val);
  378.             break;
  379.         case CMPLX:
  380.             if (val->v.cmplx_val.imag != 0.0 )
  381.                 fprintf(fp,"{%s, %s}",
  382.                     num_to_str(val->v.cmplx_val.real),
  383.                     num_to_str(val->v.cmplx_val.imag));
  384.             else
  385.                 fprintf(fp,"%s",
  386.                     num_to_str(val->v.cmplx_val.real));
  387.             break;
  388.         default:
  389.             int_error("unknown type in disp_value()",NO_CARET);
  390.     }
  391. }
  392.  
  393.  
  394. double
  395. real(val)        /* returns the real part of val */
  396. struct value *val;
  397. {
  398.     switch(val->type) {
  399.         case INTGR:
  400.             return((double) val->v.int_val);
  401.         case CMPLX:
  402.             return(val->v.cmplx_val.real);
  403.     }
  404.     int_error("unknown type in real()",NO_CARET);
  405.     /* NOTREACHED */
  406.     return((double)0.0);
  407. }
  408.  
  409.  
  410. double
  411. imag(val)        /* returns the imag part of val */
  412. struct value *val;
  413. {
  414.     switch(val->type) {
  415.         case INTGR:
  416.             return(0.0);
  417.         case CMPLX:
  418.             return(val->v.cmplx_val.imag);
  419.     }
  420.     int_error("unknown type in imag()",NO_CARET);
  421.     /* NOTREACHED */
  422.     return((double)0.0);
  423. }
  424.  
  425.  
  426.  
  427. double
  428. magnitude(val)        /* returns the magnitude of val */
  429. struct value *val;
  430. {
  431.     switch(val->type) {
  432.         case INTGR:
  433.             return((double) abs(val->v.int_val));
  434.         case CMPLX:
  435.             return(sqrt(val->v.cmplx_val.real*
  436.                     val->v.cmplx_val.real +
  437.                     val->v.cmplx_val.imag*
  438.                     val->v.cmplx_val.imag));
  439.     }
  440.     int_error("unknown type in magnitude()",NO_CARET);
  441.     /* NOTREACHED */
  442.     return((double)0.0);
  443. }
  444.  
  445.  
  446.  
  447. double
  448. angle(val)        /* returns the angle of val */
  449. struct value *val;
  450. {
  451.     switch(val->type) {
  452.         case INTGR:
  453.             return((val->v.int_val > 0) ? 0.0 : Pi);
  454.         case CMPLX:
  455.             if (val->v.cmplx_val.imag == 0.0) {
  456.                 if (val->v.cmplx_val.real >= 0.0)
  457.                     return(0.0);
  458.                 else
  459.                     return(Pi);
  460.             }
  461.             return(atan2(val->v.cmplx_val.imag,
  462.                      val->v.cmplx_val.real));
  463.     }
  464.     int_error("unknown type in angle()",NO_CARET);
  465.     /* NOTREACHED */
  466.     return((double)0.0);
  467. }
  468.  
  469.  
  470. struct value *
  471. Gcomplex(a,realpart,imagpart)
  472. struct value *a;
  473. double realpart, imagpart;
  474. {
  475.     a->type = CMPLX;
  476.     a->v.cmplx_val.real = realpart;
  477.     a->v.cmplx_val.imag = imagpart;
  478.     return(a);
  479. }
  480.  
  481.  
  482. struct value *
  483. Ginteger(a,i)
  484. struct value *a;
  485. int i;
  486. {
  487.     a->type = INTGR;
  488.     a->v.int_val = i;
  489.     return(a);
  490. }
  491.  
  492.  
  493.  
  494. os_error(str,t_num)
  495. char str[];
  496. int t_num;
  497. {
  498. #ifdef vms
  499. static status[2] = {1, 0};        /* 1 is count of error msgs */
  500. #endif
  501.  
  502. register int i;
  503.  
  504.     /* reprint line if screen has been written to */
  505.  
  506.     if (t_num != NO_CARET) {        /* put caret under error */
  507.         if (!screen_ok)
  508.             fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
  509.  
  510.         for (i = 0; i < sizeof(PROMPT) - 1; i++)
  511.             (void) putc(' ',stderr);
  512.         for (i = 0; i < token[t_num].start_index; i++) {
  513.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  514.             }
  515.         (void) putc('^',stderr);
  516.         (void) putc('\n',stderr);
  517.     }
  518.  
  519.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  520.         (void) putc(' ',stderr);
  521.     fprintf(stderr,"%s\n",str);
  522.  
  523.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  524.         (void) putc(' ',stderr);
  525.      if (!interactive)
  526.       if (infile_name != NULL)
  527.         fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
  528.       else
  529.         fprintf(stderr,"line %d: ", inline_num);
  530.  
  531.  
  532. #ifdef vms
  533.     status[1] = vaxc$errno;
  534.     sys$putmsg(status);
  535.     (void) putc('\n',stderr);
  536. #else
  537. #ifdef __ZTC__
  538.     fprintf(stderr,"error number %d\n\n",errno);
  539. #else
  540.     if (errno >= sys_nerr)
  541.         fprintf(stderr, "unknown errno %d\n\n", errno);
  542.     else
  543.         fprintf(stderr,"(%s)\n\n",sys_errlist[errno]);
  544. #endif
  545. #endif
  546.  
  547.     longjmp(env, TRUE);    /* bail out to command line */
  548. }
  549.  
  550.  
  551. int_error(str,t_num)
  552. char str[];
  553. int t_num;
  554. {
  555. register int i;
  556.  
  557.     /* reprint line if screen has been written to */
  558.  
  559.     if (t_num != NO_CARET) {        /* put caret under error */
  560.         if (!screen_ok)
  561.             fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
  562.  
  563.         for (i = 0; i < sizeof(PROMPT) - 1; i++)
  564.             (void) putc(' ',stderr);
  565.         for (i = 0; i < token[t_num].start_index; i++) {
  566.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  567.             }
  568.         (void) putc('^',stderr);
  569.         (void) putc('\n',stderr);
  570.     }
  571.  
  572.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  573.         (void) putc(' ',stderr);
  574.      if (!interactive)
  575.       if (infile_name != NULL)
  576.         fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
  577.       else
  578.         fprintf(stderr,"line %d: ", inline_num);
  579.      fprintf(stderr,"%s\n\n", str);
  580.  
  581.     longjmp(env, TRUE);    /* bail out to command line */
  582. }
  583.  
  584. /* Lower-case the given string (DFK) */
  585. /* Done in place. */
  586. void
  587. lower_case(s)
  588.      char *s;
  589. {
  590.   register char *p = s;
  591.  
  592.   while (*p != '\0') {
  593.     if (isupper(*p))
  594.      *p = tolower(*p);
  595.     p++;
  596.   }
  597. }
  598.  
  599. /* Squash spaces in the given string (DFK) */
  600. /* That is, reduce all multiple white-space chars to single spaces */
  601. /* Done in place. */
  602. void
  603. squash_spaces(s)
  604.      char *s;
  605. {
  606.   register char *r = s;        /* reading point */
  607.   register char *w = s;        /* writing point */
  608.   TBOOLEAN space = FALSE;        /* TRUE if we've already copied a space */
  609.  
  610.   for (w = r = s; *r != '\0'; r++) {
  611.      if (isspace(*r)) {
  612.         /* white space; only copy if we haven't just copied a space */
  613.         if (!space) {
  614.             space = TRUE;
  615.             *w++ = ' ';
  616.         }                /* else ignore multiple spaces */
  617.      } else {
  618.         /* non-space character; copy it and clear flag */
  619.         *w++ = *r;
  620.         space = FALSE;
  621.      }
  622.   }
  623.   *w = '\0';                /* null terminate string */
  624. }
  625.