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

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