[BACK]Return to util.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

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>