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