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

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