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