home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / Gnuplot 3.5 Source / SOURCES 3.5 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-12  |  12.9 KB  |  636 lines  |  [TEXT/MSWD]

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