[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.3

1.1       maekawa     1: #ifndef lint
1.1.1.3 ! ohara       2: static char *RCSid = "$Id: util.c,v 1.10.2.3 2002/03/11 16:09:00 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:
1.1.1.3 ! ohara     311: /* Our own version of strdup()
        !           312:  * Make copy of string into gp_alloc'd memory
        !           313:  * As with all conforming str*() functions,
        !           314:  * it is the caller's responsibility to pass
        !           315:  * valid parameters!
        !           316:  */
        !           317: char *
        !           318: gp_strdup(s)
        !           319: char *s;
        !           320: {
        !           321:     char *d;
        !           322:
        !           323: #ifndef HAVE_STRDUP
        !           324:     d = gp_alloc(strlen(s) + 1, "gp_strdup");
        !           325:     if (d)
        !           326:        memcpy (d, s, strlen(s) + 1);
        !           327: #else
        !           328:     d = strdup(s);
        !           329: #endif
        !           330:     return d;
        !           331: }
1.1       maekawa   332:
                    333: void convert(val_ptr, t_num)
                    334: struct value *val_ptr;
                    335: int t_num;
                    336: {
                    337:     *val_ptr = token[t_num].l_val;
                    338: }
                    339:
                    340: static char *num_to_str(r)
                    341: double r;
                    342: {
                    343:     static int i = 0;
                    344:     static char s[4][25];
                    345:     int j = i++;
                    346:
                    347:     if (i > 3)
                    348:        i = 0;
                    349:
                    350:     sprintf(s[j], "%.15g", r);
                    351:     if (strchr(s[j], '.') == NULL &&
                    352:        strchr(s[j], 'e') == NULL &&
                    353:        strchr(s[j], 'E') == NULL)
                    354:        strcat(s[j], ".0");
                    355:
                    356:     return s[j];
                    357: }
                    358:
                    359: void disp_value(fp, val)
                    360: FILE *fp;
                    361: struct value *val;
                    362: {
                    363:     switch (val->type) {
                    364:     case INTGR:
                    365:        fprintf(fp, "%d", val->v.int_val);
                    366:        break;
                    367:     case CMPLX:
                    368:        if (val->v.cmplx_val.imag != 0.0)
                    369:            fprintf(fp, "{%s, %s}",
                    370:                    num_to_str(val->v.cmplx_val.real),
                    371:                    num_to_str(val->v.cmplx_val.imag));
                    372:        else
                    373:            fprintf(fp, "%s",
                    374:                    num_to_str(val->v.cmplx_val.real));
                    375:        break;
                    376:     default:
                    377:        int_error("unknown type in disp_value()", NO_CARET);
                    378:     }
                    379: }
                    380:
                    381:
                    382: double real(val)               /* returns the real part of val */
                    383: struct value *val;
                    384: {
                    385:     switch (val->type) {
                    386:     case INTGR:
                    387:        return ((double) val->v.int_val);
                    388:     case CMPLX:
                    389:        return (val->v.cmplx_val.real);
                    390:     }
                    391:     int_error("unknown type in real()", NO_CARET);
                    392:     /* NOTREACHED */
                    393:     return ((double) 0.0);
                    394: }
                    395:
                    396:
                    397: double imag(val)               /* returns the imag part of val */
                    398: struct value *val;
                    399: {
                    400:     switch (val->type) {
                    401:     case INTGR:
                    402:        return (0.0);
                    403:     case CMPLX:
                    404:        return (val->v.cmplx_val.imag);
                    405:     }
                    406:     int_error("unknown type in imag()", NO_CARET);
                    407:     /* NOTREACHED */
                    408:     return ((double) 0.0);
                    409: }
                    410:
                    411:
                    412:
                    413: double magnitude(val)          /* returns the magnitude of val */
                    414: struct value *val;
                    415: {
                    416:     switch (val->type) {
                    417:     case INTGR:
                    418:        return ((double) abs(val->v.int_val));
                    419:     case CMPLX:
                    420:        return (sqrt(val->v.cmplx_val.real *
                    421:                     val->v.cmplx_val.real +
                    422:                     val->v.cmplx_val.imag *
                    423:                     val->v.cmplx_val.imag));
                    424:     }
                    425:     int_error("unknown type in magnitude()", NO_CARET);
                    426:     /* NOTREACHED */
                    427:     return ((double) 0.0);
                    428: }
                    429:
                    430:
                    431:
                    432: double angle(val)              /* returns the angle of val */
                    433: struct value *val;
                    434: {
                    435:     switch (val->type) {
                    436:     case INTGR:
1.1.1.3 ! ohara     437:        return ((val->v.int_val >= 0) ? 0.0 : M_PI);
1.1       maekawa   438:     case CMPLX:
                    439:        if (val->v.cmplx_val.imag == 0.0) {
                    440:            if (val->v.cmplx_val.real >= 0.0)
                    441:                return (0.0);
                    442:            else
1.1.1.3 ! ohara     443:                return (M_PI);
1.1       maekawa   444:        }
                    445:        return (atan2(val->v.cmplx_val.imag,
                    446:                      val->v.cmplx_val.real));
                    447:     }
                    448:     int_error("unknown type in angle()", NO_CARET);
                    449:     /* NOTREACHED */
                    450:     return ((double) 0.0);
                    451: }
                    452:
                    453:
                    454: struct value *
                    455:  Gcomplex(a, realpart, imagpart)
                    456: struct value *a;
                    457: double realpart, imagpart;
                    458: {
                    459:     a->type = CMPLX;
                    460:     a->v.cmplx_val.real = realpart;
                    461:     a->v.cmplx_val.imag = imagpart;
                    462:     return (a);
                    463: }
                    464:
                    465:
                    466: struct value *
                    467:  Ginteger(a, i)
                    468: struct value *a;
                    469: int i;
                    470: {
                    471:     a->type = INTGR;
                    472:     a->v.int_val = i;
                    473:     return (a);
                    474: }
                    475:
                    476:
                    477: void os_error(str, t_num)
                    478: char str[];
                    479: int t_num;
                    480: {
                    481: #ifdef VMS
                    482:     static status[2] =
                    483:     {1, 0};                    /* 1 is count of error msgs */
                    484: #endif /* VMS */
                    485:
                    486:     register int i;
                    487:
                    488:     /* reprint line if screen has been written to */
                    489:
                    490:     if (t_num != NO_CARET) {   /* put caret under error */
                    491:        if (!screen_ok)
                    492:            fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
                    493:
                    494:        for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    495:            (void) putc(' ', stderr);
                    496:        for (i = 0; i < token[t_num].start_index; i++) {
                    497:            (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
                    498:        }
                    499:        (void) putc('^', stderr);
                    500:        (void) putc('\n', stderr);
                    501:     }
                    502:     for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    503:        (void) putc(' ', stderr);
                    504:     fputs(str, stderr);
                    505:     putc('\n', stderr);
                    506:
                    507:     for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    508:        (void) putc(' ', stderr);
                    509:     if (!interactive) {
                    510:        if (infile_name != NULL)
                    511:            fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
                    512:        else
                    513:            fprintf(stderr, "line %d: ", inline_num);
                    514:     }
                    515:
                    516:
                    517: #ifdef VMS
                    518:     status[1] = vaxc$errno;
                    519:     sys$putmsg(status);
                    520:     (void) putc('\n', stderr);
                    521: #else /* VMS */
                    522:     fprintf(stderr, "(%s)\n\n", strerror(errno));
                    523: #endif /* VMS */
                    524:
                    525:     bail_to_command_line();
                    526: }
                    527:
                    528:
                    529: void int_error(str, t_num)
                    530: char str[];
                    531: int t_num;
                    532: {
                    533:     register int i;
                    534:
                    535:     /* reprint line if screen has been written to */
                    536:
                    537:     if (t_num != NO_CARET) {   /* put caret under error */
                    538:        if (!screen_ok)
                    539:            fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
                    540:
                    541:        for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    542:            (void) putc(' ', stderr);
                    543:        for (i = 0; i < token[t_num].start_index; i++) {
                    544:            (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
                    545:        }
                    546:        (void) putc('^', stderr);
                    547:        (void) putc('\n', stderr);
                    548:     }
                    549:     for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    550:        (void) putc(' ', stderr);
                    551:     if (!interactive) {
                    552:        if (infile_name != NULL)
                    553:            fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
                    554:        else
                    555:            fprintf(stderr, "line %d: ", inline_num);
                    556:     }
                    557:     fputs(str, stderr);
                    558:     fputs("\n\n", stderr);
                    559:
                    560:     bail_to_command_line();
                    561: }
                    562:
                    563: /* Warn without bailing out to command line. Not a user error */
                    564: void int_warn(str, t_num)
                    565: char str[];
                    566: int t_num;
                    567: {
                    568:     register int i;
                    569:
                    570:     /* reprint line if screen has been written to */
                    571:
                    572:     if (t_num != NO_CARET) {   /* put caret under error */
                    573:        if (!screen_ok)
                    574:            fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
                    575:
                    576:        for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    577:            (void) putc(' ', stderr);
                    578:        for (i = 0; i < token[t_num].start_index; i++) {
                    579:            (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
                    580:        }
                    581:        (void) putc('^', stderr);
                    582:        (void) putc('\n', stderr);
                    583:     }
                    584:     for (i = 0; i < sizeof(PROMPT) - 1; i++)
                    585:        (void) putc(' ', stderr);
                    586:     if (!interactive) {
                    587:        if (infile_name != NULL)
                    588:            fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
                    589:        else
                    590:            fprintf(stderr, "line %d: ", inline_num);
                    591:     }
                    592:     fprintf(stderr, "warning: %s\n", str);
                    593:
                    594: }                              /* int_warn */
                    595:
                    596: /* Lower-case the given string (DFK) */
                    597: /* Done in place. */
                    598: void lower_case(s)
                    599: char *s;
                    600: {
                    601:     register char *p = s;
                    602:
                    603:     while (*p != NUL) {
                    604:        if (isupper((int)*p))
                    605:            *p = tolower(*p);
                    606:        p++;
                    607:     }
                    608: }
                    609:
                    610: /* Squash spaces in the given string (DFK) */
                    611: /* That is, reduce all multiple white-space chars to single spaces */
                    612: /* Done in place. */
                    613: void squash_spaces(s)
                    614: char *s;
                    615: {
                    616:     register char *r = s;      /* reading point */
                    617:     register char *w = s;      /* writing point */
                    618:     TBOOLEAN space = FALSE;    /* TRUE if we've already copied a space */
                    619:
                    620:     for (w = r = s; *r != NUL; r++) {
                    621:        if (isspace((int)*r)) {
                    622:            /* white space; only copy if we haven't just copied a space */
                    623:            if (!space) {
                    624:                space = TRUE;
                    625:                *w++ = ' ';
                    626:            }                   /* else ignore multiple spaces */
                    627:        } else {
                    628:            /* non-space character; copy it and clear flag */
                    629:            *w++ = *r;
                    630:            space = FALSE;
                    631:        }
                    632:     }
                    633:     *w = NUL;                  /* null terminate string */
                    634: }
                    635:
                    636:
                    637: static void parse_esc(instr)
                    638: char *instr;
                    639: {
                    640:     char *s = instr, *t = instr;
                    641:
                    642:     /* the string will always get shorter, so we can do the
                    643:      * conversion in situ
                    644:      */
                    645:
                    646:     while (*s != NUL) {
                    647:        if (*s == '\\') {
                    648:            s++;
                    649:            if (*s == '\\') {
                    650:                *t++ = '\\';
                    651:                s++;
                    652:            } else if (*s == 'n') {
                    653:                *t++ = '\n';
                    654:                s++;
                    655:            } else if (*s == 'r') {
                    656:                *t++ = '\r';
                    657:                s++;
                    658:            } else if (*s == 't') {
                    659:                *t++ = '\t';
                    660:                s++;
                    661:            } else if (*s == '\"') {
                    662:                *t++ = '\"';
                    663:                s++;
                    664:            } else if (*s >= '0' && *s <= '7') {
                    665:                int i, n;
                    666:                if (sscanf(s, "%o%n", &i, &n) > 0) {
                    667:                    *t++ = i;
                    668:                    s += n;
                    669:                } else {
                    670:                    /* int_error("illegal octal number ", c_token); */
                    671:                    *t++ = '\\';
                    672:                    *t++ = *s++;
                    673:                }
                    674:            }
                    675:        } else {
                    676:            *t++ = *s++;
                    677:        }
                    678:     }
                    679:     *t = NUL;
                    680: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>