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