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

  1. /*
  2.  *
  3.  *    G N U P L O T  --  util.c
  4.  *
  5.  *  Copyright (C) 1986 Thomas Williams, Colin Kelley
  6.  *
  7.  *  You may use this code as you wish if credit is given and this message
  8.  *  is retained.
  9.  *
  10.  *  Please e-mail any useful additions to vu-vlsi!plot so they may be
  11.  *  included in later releases.
  12.  *
  13.  *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  14.  */
  15.  
  16. #include <ctype.h>
  17. #include <setjmp.h>
  18. #include <stdio.h>
  19. #include <errno.h>
  20. #include "plot.h"
  21.  
  22. #ifndef vms
  23. extern int errno, sys_nerr;
  24. extern char *sys_errlist[];
  25. #endif /* vms */
  26.  
  27. extern int inline;            /* line number of input */
  28. extern char input_line[MAX_LINE_LEN];
  29. extern struct lexical_unit token[MAX_TOKENS];
  30. extern jmp_buf env;    /* from plot.c */
  31.  
  32. /*
  33.  * equals() compares string value of token number t_num with str[], and
  34.  *   returns TRUE if they are identical.
  35.  */
  36. equals(t_num, str)
  37. int t_num;
  38. char *str;
  39. {
  40. register int i;
  41.  
  42.     if (!token[t_num].is_token)
  43.         return(FALSE);                /* must be a value--can't be equal */
  44.     for (i = 0; i < token[t_num].length; i++) {
  45.         if (input_line[token[t_num].start_index+i] != str[i])
  46.             return(FALSE);
  47.         }
  48.     /* now return TRUE if at end of str[], FALSE if not */
  49.     return(str[i] == '\0');
  50. }
  51.  
  52.  
  53.  
  54. /*
  55.  * almost_equals() compares string value of token number t_num with str[], and
  56.  *   returns TRUE if they are identical up to the first $ in str[].
  57.  */
  58. almost_equals(t_num, str)
  59. int t_num;
  60. char *str;
  61. {
  62. register int i;
  63. register int after = 0;
  64. register start = token[t_num].start_index;
  65. register length = token[t_num].length;
  66.  
  67.     if (!token[t_num].is_token)
  68.         return(FALSE);                /* must be a value--can't be equal */
  69.     for (i = 0; i < length + after; i++) {
  70.         if (str[i] != input_line[start + i]) {
  71.             if (str[i] != '$')
  72.                 return(FALSE);
  73.             else {
  74.                 after = 1;
  75.                 start--;    /* back up token ptr */
  76.                 }
  77.             }
  78.         }
  79.  
  80.     /* i now beyond end of token string */
  81.  
  82.     return(after || str[i] == '$' || str[i] == '\0');
  83. }
  84.  
  85.  
  86.  
  87. isstring(t_num)
  88. int t_num;
  89. {
  90.     
  91.     return(token[t_num].is_token &&
  92.            (input_line[token[t_num].start_index] == '\'' ||
  93.            input_line[token[t_num].start_index] == '\"'));
  94. }
  95.  
  96.  
  97. isnumber(t_num)
  98. int t_num;
  99. {
  100.     return(!token[t_num].is_token);
  101. }
  102.  
  103.  
  104. isletter(t_num)
  105. int t_num;
  106. {
  107.     return(token[t_num].is_token &&
  108.             (isalpha(input_line[token[t_num].start_index])));
  109. }
  110.  
  111.  
  112. /*
  113.  * is_definition() returns TRUE if the next tokens are of the form
  114.  *   identifier =
  115.  *        -or-
  116.  *   identifier ( identifer ) =
  117.  */
  118. is_definition(t_num)
  119. int t_num;
  120. {
  121.     return (isletter(t_num) &&
  122.             (equals(t_num+1,"=") ||            /* variable */
  123.             (equals(t_num+1,"(") &&        /* function */
  124.              isletter(t_num+2)   &&
  125.              equals(t_num+3,")") &&
  126.              equals(t_num+4,"=") )
  127.         ));
  128. }
  129.  
  130.  
  131.  
  132. /*
  133.  * copy_str() copies the string in token number t_num into str, appending
  134.  *   a null.  No more than MAX_ID_LEN chars are copied.
  135.  */
  136. copy_str(str, t_num)
  137. char str[];
  138. int t_num;
  139. {
  140. register int i = 0;
  141. register int start = token[t_num].start_index;
  142. register int count;
  143.  
  144.     if ((count = token[t_num].length) > MAX_ID_LEN)
  145.         count = MAX_ID_LEN;
  146.     do {
  147.         str[i++] = input_line[start++];
  148.         } while (i != count);
  149.     str[i] = '\0';
  150. }
  151.  
  152.  
  153. /*
  154.  * quote_str() does the same thing as copy_str, except it ignores the
  155.  *   quotes at both ends.  This seems redundant, but is done for 
  156.  *   efficency.
  157.  */
  158. quote_str(str, t_num)
  159. char str[];
  160. int t_num;
  161. {
  162. register int i = 0;
  163. register int start = token[t_num].start_index + 1;
  164. register int count;
  165.  
  166.     if ((count = token[t_num].length - 2) > MAX_ID_LEN)
  167.         count = MAX_ID_LEN;
  168.     while (i != count) {
  169.         str[i++] = input_line[start++];
  170.      }
  171.     str[i] = '\0';
  172. }
  173.  
  174. /*
  175.  *    capture() returns in str[] the the part of input_line[] which lies
  176.  *    between the begining of token[start] and end of token[end]
  177.  */
  178. capture(str,start,end)
  179. char str[];
  180. int start,end;
  181. {
  182. register int i,j;
  183. char *s = str;
  184.  
  185.     j = token[end].start_index + token[end].length;
  186.     for (i = token[start].start_index; i < j && input_line[i] != '\0'; i++)
  187.         *s++ = input_line[i];
  188.     *s = '\0';
  189. }
  190.  
  191.  
  192. convert(val_ptr, t_num)
  193. struct value *val_ptr;
  194. int t_num;
  195. {
  196.     *val_ptr = token[t_num].l_val;
  197. }
  198.  
  199.  
  200.  
  201. show_value(fp,val)
  202. FILE *fp;
  203. struct value *val;
  204. {
  205.         switch(val->type) {
  206.             case INT:
  207.                 fprintf(fp,"%d",val->v.int_val);
  208.                 break;
  209.             case CMPLX:
  210.                 if (val->v.cmplx_val.imag != 0.0 )
  211.                     fprintf(fp,"{%g, %g}",
  212.                         val->v.cmplx_val.real,val->v.cmplx_val.imag);
  213.                 else
  214.                     fprintf(fp,"%g", val->v.cmplx_val.real);
  215.                 break;
  216.             default:
  217.                 int_error("unknown type in show_value()",NO_CARET);
  218.         }
  219. }
  220.  
  221.  
  222. double
  223. real(val)        /* returns the real part of val */
  224. struct value *val;
  225. {
  226.     switch(val->type) {
  227.         case INT:
  228.             return((double) val->v.int_val);
  229.             break;
  230.         case CMPLX:
  231.             return(val->v.cmplx_val.real);
  232.     }
  233.     int_error("unknown type in real()",NO_CARET);
  234.     /* NOTREACHED */
  235. }
  236.  
  237.  
  238. double
  239. imag(val)        /* returns the imag part of val */
  240. struct value *val;
  241. {
  242.     switch(val->type) {
  243.         case INT:
  244.             return(0.0);
  245.             break;
  246.         case CMPLX:
  247.             return(val->v.cmplx_val.imag);
  248.     }
  249.     int_error("unknown type in real()",NO_CARET);
  250.     /* NOTREACHED */
  251. }
  252.  
  253.  
  254.  
  255. double
  256. magnitude(val)        /* returns the magnitude of val */
  257. struct value *val;
  258. {
  259.     double sqrt();
  260.  
  261.     switch(val->type) {
  262.         case INT:
  263.             return((double) abs(val->v.int_val));
  264.             break;
  265.         case CMPLX:
  266.             return(sqrt(val->v.cmplx_val.real*
  267.                     val->v.cmplx_val.real +
  268.                     val->v.cmplx_val.imag*
  269.                     val->v.cmplx_val.imag));
  270.     }
  271.     int_error("unknown type in magnitude()",NO_CARET);
  272.     /* NOTREACHED */
  273. }
  274.  
  275.  
  276.  
  277. double
  278. angle(val)        /* returns the angle of val */
  279. struct value *val;
  280. {
  281.     double atan2();
  282.  
  283.     switch(val->type) {
  284.         case INT:
  285.             return((val->v.int_val > 0) ? 0.0 : Pi);
  286.             break;
  287.         case CMPLX:
  288.             if (val->v.cmplx_val.imag == 0.0) {
  289.                 if (val->v.cmplx_val.real >= 0.0)
  290.                     return(0.0);
  291.                 else
  292.                     return(Pi);
  293.             }
  294.             return(atan2(val->v.cmplx_val.imag,
  295.                      val->v.cmplx_val.real));
  296.     }
  297.     int_error("unknown type in angle()",NO_CARET);
  298.     /* NOTREACHED */
  299. }
  300.  
  301.  
  302. struct value *
  303. complex(a,realpart,imagpart)
  304. struct value *a;
  305. double realpart, imagpart;
  306. {
  307.     a->type = CMPLX;
  308.     a->v.cmplx_val.real = realpart;
  309.     a->v.cmplx_val.imag = imagpart;
  310.     return(a);
  311. }
  312.  
  313.  
  314. struct value *
  315. integer(a,i)
  316. struct value *a;
  317. int i;
  318. {
  319.     a->type = INT;
  320.     a->v.int_val = i;
  321.     return(a);
  322. }
  323.  
  324. /* Lower-case the given string (DFK) */
  325. /* Done in place. */
  326. void
  327. lower_case(s)
  328.      char *s;
  329. {
  330.   register char *p = s;
  331.  
  332.   while (*p != '\0') {
  333.     if (*p >= 'A' && *p <= 'Z')
  334.       *p = *p - 'A' + 'a';
  335.     p++;
  336.   }
  337. }
  338.  
  339.  
  340. int space_count(line, t_num)
  341.     int line;
  342.     int t_num;
  343. {
  344.     char string[20];
  345.  
  346.     sprintf(string, "---%d: ", line);
  347.     return(strlen(string) + token[t_num].start_index);
  348. }
  349.  
  350. show_line(always)
  351.     BOOLEAN always;
  352. {
  353.     static int last_line_printed = 0;    /* number of line printed out last. */
  354.  
  355.     if (always || inline != last_line_printed) {
  356.        /* print line if not printed yet */
  357.        fprintf(stderr,"\n---%d: %s\n", inline, input_line);
  358.        last_line_printed = inline;
  359.     }
  360. }
  361.  
  362. os_error(str,t_num)
  363. char str[];
  364. int t_num;
  365. {
  366. #ifdef vms
  367. static status[2] = {1, 0};        /* 1 is count of error msgs */
  368. #endif
  369.  
  370. register int i;
  371. int count;
  372.  
  373.     show_line(TRUE);
  374.  
  375.     if (t_num != NO_CARET) {        /* put caret under error */
  376.         count = space_count(inline, t_num);
  377.         for (i = 0; i < count; i++) {
  378.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  379.             }
  380.         (void) putc('^',stderr);
  381.         (void) putc('\n',stderr);
  382.     }
  383.  
  384.     fprintf(stderr,"###%d: %s\n",str);
  385.  
  386. #ifdef vms
  387.     status[1] = vaxc$errno;
  388.     sys$putmsg(status);
  389.     (void) putc('\n',stderr);
  390. #else
  391.     if (errno >= sys_nerr)
  392.         fprintf(stderr, "unknown errno %d\n\n", errno);
  393.     else
  394.         fprintf(stderr,"(%s)\n",sys_errlist[errno]);
  395. #endif
  396.  
  397.     longjmp(env, TRUE);    /* bail out to command line */
  398. }
  399.  
  400. /* fatal error for this line; no return */
  401. int_error(str,t_num)
  402. char str[];
  403. int t_num;
  404. {
  405.     register int i;
  406.     int count;
  407.  
  408.     show_line(TRUE);
  409.  
  410.     if (t_num != NO_CARET) {    /* put caret under error */
  411.        count = space_count(inline, t_num);
  412.        for (i = 0; i < count; i++) {
  413.           (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  414.        }
  415.        (void) putc('^',stderr);
  416.        (void) putc('\n',stderr);
  417.     }
  418.  
  419.     fprintf(stderr,"###%d: %s\n", inline, str);
  420.  
  421.     longjmp(env, TRUE);        /* bail out to command line */
  422. }
  423.  
  424. /* print an error for this line and return */
  425. err_msg(str)
  426.     char str[];
  427. {
  428.     show_line(FALSE);
  429.     fprintf(stderr,"***%d: %s\n", inline, str);
  430. }
  431.  
  432.  
  433. /* find char c in string str; return p such that str[p]==c;
  434.  * if c not in str then p=strlen(str)
  435.  */
  436. int
  437. instring(str, c)
  438.     char *str;
  439.     char c;
  440. {
  441.     int pos = 0;
  442.  
  443.     while (str != NULL && *str != '\0' && c != *str) {
  444.        str++; 
  445.        pos++;
  446.     }
  447.     return (pos);
  448. }
  449.  
  450.