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

Annotation of OpenXM_contrib/gnuplot/misc.c, Revision 1.1.1.1

1.1       maekawa     1: #ifndef lint
                      2: static char *RCSid = "$Id: misc.c,v 1.79 1998/04/14 00:16:02 drd Exp $";
                      3: #endif
                      4:
                      5: /* GNUPLOT - misc.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: #ifdef AMIGA_AC_5
                     38: # include <exec/types.h>
                     39: #endif /* AMIGA_AC_5 */
                     40:
                     41: #include "plot.h"
                     42: #include "setshow.h"
                     43:
                     44: extern int key_vpos, key_hpos, key_just;
                     45: extern int datatype[];
                     46: extern char timefmt[];
                     47:
                     48: static void save_range __PROTO((FILE * fp, int axis, double min, double max, int autosc, char *text));
                     49: static void save_tics __PROTO((FILE * fp, int where, int axis, struct ticdef * tdef, TBOOLEAN rotate, char *text));
                     50: static void save_position __PROTO((FILE * fp, struct position * pos));
                     51: static void save_functions__sub __PROTO((FILE * fp));
                     52: static void save_variables__sub __PROTO((FILE * fp));
                     53: static int lf_pop __PROTO((void));
                     54: static void lf_push __PROTO((FILE * fp));
                     55: static int find_maxl_cntr __PROTO((struct gnuplot_contours * contours, int *count));
                     56:
                     57:
                     58: #define SAVE_NUM_OR_TIME(fp, x, axis) \
                     59: do{if (datatype[axis]==TIME) { \
                     60:   char s[80]; char *p; \
                     61:   putc('"', fp);   \
                     62:   gstrftime(s,80,timefmt,(double)(x)); \
                     63:   for(p=s; *p; ++p) {\
                     64:    if ( *p == '\t' ) fputs("\\t",fp);\
                     65:    else if (*p == '\n') fputs("\\n",fp); \
                     66:    else if ( *p > 126 || *p < 32 ) fprintf(fp,"\\%03o",*p);\
                     67:    else putc(*p, fp);\
                     68:   }\
                     69:   putc('"', fp);\
                     70:  } else {\
                     71:   fprintf(fp,"%g",x);\
                     72: }} while(0)
                     73:
                     74:
                     75: /* State information for load_file(), to recover from errors
                     76:  * and properly handle recursive load_file calls
                     77:  */
                     78: typedef struct lf_state_struct LFS;
                     79: struct lf_state_struct {
                     80:     FILE *fp;                  /* file pointer for load file */
                     81:     char *name;                        /* name of file */
                     82:     TBOOLEAN interactive;      /* value of interactive flag on entry */
                     83:     TBOOLEAN do_load_arg_substitution; /* likewise ... */
                     84:     int inline_num;            /* inline_num on entry */
                     85:     LFS *prev;                 /* defines a stack */
                     86:     char *call_args[10];       /* args when file is 'call'ed instead of 'load'ed */
                     87: } *lf_head = NULL;             /* NULL if not in load_file */
                     88:
                     89: /* these two could be in load_file, except for error recovery */
                     90: extern TBOOLEAN do_load_arg_substitution;
                     91: extern char *call_args[10];
                     92:
                     93: /*
                     94:  * cp_alloc() allocates a curve_points structure that can hold 'num'
                     95:  * points.
                     96:  */
                     97: struct curve_points *
                     98:  cp_alloc(num)
                     99: int num;
                    100: {
                    101:     struct curve_points *cp;
                    102:
                    103:     cp = (struct curve_points *) gp_alloc((unsigned long) sizeof(struct curve_points), "curve");
                    104:     cp->p_max = (num >= 0 ? num : 0);
                    105:
                    106:     if (num > 0) {
                    107:        cp->points = (struct coordinate GPHUGE *)
                    108:            gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
                    109:     } else
                    110:        cp->points = (struct coordinate GPHUGE *) NULL;
                    111:     cp->next_cp = NULL;
                    112:     cp->title = NULL;
                    113:     return (cp);
                    114: }
                    115:
                    116:
                    117: /*
                    118:  * cp_extend() reallocates a curve_points structure to hold "num"
                    119:  * points. This will either expand or shrink the storage.
                    120:  */
                    121: void cp_extend(cp, num)
                    122: struct curve_points *cp;
                    123: int num;
                    124: {
                    125:
                    126: #if defined(DOS16) || defined(WIN16)
                    127:     /* Make sure we do not allocate more than 64k points in msdos since
                    128:        * indexing is done with 16-bit int
                    129:        * Leave some bytes for malloc maintainance.
                    130:      */
                    131:     if (num > 32700)
                    132:        int_error("Array index must be less than 32k in msdos", NO_CARET);
                    133: #endif /* MSDOS */
                    134:
                    135:     if (num == cp->p_max)
                    136:        return;
                    137:
                    138:     if (num > 0) {
                    139:        if (cp->points == NULL) {
                    140:            cp->points = (struct coordinate GPHUGE *)
                    141:                gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
                    142:        } else {
                    143:            cp->points = (struct coordinate GPHUGE *)
                    144:                gp_realloc(cp->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
                    145:        }
                    146:        cp->p_max = num;
                    147:     } else {
                    148:        if (cp->points != (struct coordinate GPHUGE *) NULL)
                    149:            free(cp->points);
                    150:        cp->points = (struct coordinate GPHUGE *) NULL;
                    151:        cp->p_max = 0;
                    152:     }
                    153: }
                    154:
                    155: /*
                    156:  * cp_free() releases any memory which was previously malloc()'d to hold
                    157:  *   curve points (and recursively down the linked list).
                    158:  */
                    159: void cp_free(cp)
                    160: struct curve_points *cp;
                    161: {
                    162:     if (cp) {
                    163:        cp_free(cp->next_cp);
                    164:        if (cp->title)
                    165:            free((char *) cp->title);
                    166:        if (cp->points)
                    167:            free((char *) cp->points);
                    168:        free((char *) cp);
                    169:     }
                    170: }
                    171:
                    172: /*
                    173:  * iso_alloc() allocates a iso_curve structure that can hold 'num'
                    174:  * points.
                    175:  */
                    176: struct iso_curve *
                    177:  iso_alloc(num)
                    178: int num;
                    179: {
                    180:     struct iso_curve *ip;
                    181:     ip = (struct iso_curve *) gp_alloc((unsigned long) sizeof(struct iso_curve), "iso curve");
                    182:     ip->p_max = (num >= 0 ? num : 0);
                    183:     if (num > 0) {
                    184:        ip->points = (struct coordinate GPHUGE *)
                    185:            gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
                    186:     } else
                    187:        ip->points = (struct coordinate GPHUGE *) NULL;
                    188:     ip->next = NULL;
                    189:     return (ip);
                    190: }
                    191:
                    192: /*
                    193:  * iso_extend() reallocates a iso_curve structure to hold "num"
                    194:  * points. This will either expand or shrink the storage.
                    195:  */
                    196: void iso_extend(ip, num)
                    197: struct iso_curve *ip;
                    198: int num;
                    199: {
                    200:     if (num == ip->p_max)
                    201:        return;
                    202:
                    203: #if defined(DOS16) || defined(WIN16)
                    204:     /* Make sure we do not allocate more than 64k points in msdos since
                    205:        * indexing is done with 16-bit int
                    206:        * Leave some bytes for malloc maintainance.
                    207:      */
                    208:     if (num > 32700)
                    209:        int_error("Array index must be less than 32k in msdos", NO_CARET);
                    210: #endif /* 16bit (Win)Doze */
                    211:
                    212:     if (num > 0) {
                    213:        if (ip->points == NULL) {
                    214:            ip->points = (struct coordinate GPHUGE *)
                    215:                gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
                    216:        } else {
                    217:            ip->points = (struct coordinate GPHUGE *)
                    218:                gp_realloc(ip->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
                    219:        }
                    220:        ip->p_max = num;
                    221:     } else {
                    222:        if (ip->points != (struct coordinate GPHUGE *) NULL)
                    223:            free(ip->points);
                    224:        ip->points = (struct coordinate GPHUGE *) NULL;
                    225:        ip->p_max = 0;
                    226:     }
                    227: }
                    228:
                    229: /*
                    230:  * iso_free() releases any memory which was previously malloc()'d to hold
                    231:  *   iso curve points.
                    232:  */
                    233: void iso_free(ip)
                    234: struct iso_curve *ip;
                    235: {
                    236:     if (ip) {
                    237:        if (ip->points)
                    238:            free((char *) ip->points);
                    239:        free((char *) ip);
                    240:     }
                    241: }
                    242:
                    243: /*
                    244:  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
                    245:  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
                    246:  * 'num_samp_1' samples.
                    247:  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
                    248:  */
                    249: struct surface_points *
                    250:  sp_alloc(num_samp_1, num_iso_1, num_samp_2, num_iso_2)
                    251: int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
                    252: {
                    253:     struct surface_points *sp;
                    254:
                    255:     sp = (struct surface_points *) gp_alloc((unsigned long) sizeof(struct surface_points), "surface");
                    256:     sp->next_sp = NULL;
                    257:     sp->title = NULL;
                    258:     sp->contours = NULL;
                    259:     sp->iso_crvs = NULL;
                    260:     sp->num_iso_read = 0;
                    261:
                    262:     if (num_iso_2 > 0 && num_samp_1 > 0) {
                    263:        int i;
                    264:        struct iso_curve *icrv;
                    265:
                    266:        for (i = 0; i < num_iso_1; i++) {
                    267:            icrv = iso_alloc(num_samp_2);
                    268:            icrv->next = sp->iso_crvs;
                    269:            sp->iso_crvs = icrv;
                    270:        }
                    271:        for (i = 0; i < num_iso_2; i++) {
                    272:            icrv = iso_alloc(num_samp_1);
                    273:            icrv->next = sp->iso_crvs;
                    274:            sp->iso_crvs = icrv;
                    275:        }
                    276:     } else
                    277:        sp->iso_crvs = (struct iso_curve *) NULL;
                    278:
                    279:     return (sp);
                    280: }
                    281:
                    282: /*
                    283:  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
                    284:  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
                    285:  * 'num_samp_1' samples.
                    286:  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
                    287:  */
                    288: void sp_replace(sp, num_samp_1, num_iso_1, num_samp_2, num_iso_2)
                    289: struct surface_points *sp;
                    290: int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
                    291: {
                    292:     int i;
                    293:     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
                    294:
                    295:     while (icrvs) {
                    296:        icrv = icrvs;
                    297:        icrvs = icrvs->next;
                    298:        iso_free(icrv);
                    299:     }
                    300:     sp->iso_crvs = NULL;
                    301:
                    302:     if (num_iso_2 > 0 && num_samp_1 > 0) {
                    303:        for (i = 0; i < num_iso_1; i++) {
                    304:            icrv = iso_alloc(num_samp_2);
                    305:            icrv->next = sp->iso_crvs;
                    306:            sp->iso_crvs = icrv;
                    307:        }
                    308:        for (i = 0; i < num_iso_2; i++) {
                    309:            icrv = iso_alloc(num_samp_1);
                    310:            icrv->next = sp->iso_crvs;
                    311:            sp->iso_crvs = icrv;
                    312:        }
                    313:     } else
                    314:        sp->iso_crvs = (struct iso_curve *) NULL;
                    315: }
                    316:
                    317: /*
                    318:  * sp_free() releases any memory which was previously malloc()'d to hold
                    319:  *   surface points.
                    320:  */
                    321: void sp_free(sp)
                    322: struct surface_points *sp;
                    323: {
                    324:     if (sp) {
                    325:        sp_free(sp->next_sp);
                    326:        if (sp->title)
                    327:            free((char *) sp->title);
                    328:        if (sp->contours) {
                    329:            struct gnuplot_contours *cntr, *cntrs = sp->contours;
                    330:
                    331:            while (cntrs) {
                    332:                cntr = cntrs;
                    333:                cntrs = cntrs->next;
                    334:                free(cntr->coords);
                    335:                free(cntr);
                    336:            }
                    337:        }
                    338:        if (sp->iso_crvs) {
                    339:            struct iso_curve *icrv, *icrvs = sp->iso_crvs;
                    340:
                    341:            while (icrvs) {
                    342:                icrv = icrvs;
                    343:                icrvs = icrvs->next;
                    344:                iso_free(icrv);
                    345:            }
                    346:        }
                    347:        free((char *) sp);
                    348:     }
                    349: }
                    350:
                    351:
                    352: /*
                    353:  *  functions corresponding to the arguments of the GNUPLOT `save` command
                    354:  */
                    355: void save_functions(fp)
                    356: FILE *fp;
                    357: {
                    358:     if (fp) {
                    359:        show_version(fp);               /* I _love_ information written */
                    360:        save_functions__sub(fp);        /* at the top and the end of an */
                    361:        fputs("#    EOF\n", fp);        /* human readable ASCII file.   */
                    362:        (void) fclose(fp);      /*                        (JFi) */
                    363:     } else
                    364:        os_error("Cannot open save file", c_token);
                    365: }
                    366:
                    367:
                    368: void save_variables(fp)
                    369: FILE *fp;
                    370: {
                    371:     if (fp) {
                    372:        show_version(fp);
                    373:        save_variables__sub(fp);
                    374:        fputs("#    EOF\n", fp);
                    375:        (void) fclose(fp);
                    376:     } else
                    377:        os_error("Cannot open save file", c_token);
                    378: }
                    379:
                    380:
                    381: void save_set(fp)
                    382: FILE *fp;
                    383: {
                    384:     if (fp) {
                    385:        show_version(fp);
                    386:        save_set_all(fp);
                    387:        fputs("#    EOF\n", fp);
                    388:        (void) fclose(fp);
                    389:     } else
                    390:        os_error("Cannot open save file", c_token);
                    391: }
                    392:
                    393:
                    394: void save_all(fp)
                    395: FILE *fp;
                    396: {
                    397:     if (fp) {
                    398:        show_version(fp);
                    399:        save_set_all(fp);
                    400:        save_functions__sub(fp);
                    401:        save_variables__sub(fp);
                    402:        fprintf(fp, "%s\n", replot_line);
                    403:         if (wri_to_fil_last_fit_cmd(NULL)) {
                    404:            fputs("## ", fp);
                    405:            wri_to_fil_last_fit_cmd(fp);
                    406:            putc('\n', fp);
                    407:         }
                    408:        fputs("#    EOF\n", fp);
                    409:        (void) fclose(fp);
                    410:     } else
                    411:        os_error("Cannot open save file", c_token);
                    412: }
                    413:
                    414: /*
                    415:  *  auxiliary functions
                    416:  */
                    417:
                    418: static void save_functions__sub(fp)
                    419: FILE *fp;
                    420: {
                    421:     register struct udft_entry *udf = first_udf;
                    422:
                    423:     while (udf) {
                    424:        if (udf->definition) {
                    425:            fprintf(fp, "%s\n", udf->definition);
                    426:        }
                    427:        udf = udf->next_udf;
                    428:     }
                    429: }
                    430:
                    431: static void save_variables__sub(fp)
                    432: FILE *fp;
                    433: {
                    434:     register struct udvt_entry *udv = first_udv->next_udv;     /* always skip pi */
                    435:
                    436:     while (udv) {
                    437:        if (!udv->udv_undef) {
                    438:            fprintf(fp, "%s = ", udv->udv_name);
                    439:            disp_value(fp, &(udv->udv_value));
                    440:            (void) putc('\n', fp);
                    441:        }
                    442:        udv = udv->next_udv;
                    443:     }
                    444: }
                    445:
                    446: void save_set_all(fp)
                    447: FILE *fp;
                    448: {
                    449:     struct text_label *this_label;
                    450:     struct arrow_def *this_arrow;
                    451:     struct linestyle_def *this_linestyle;
                    452:     char str[MAX_LINE_LEN + 1];
                    453:
                    454:     /* opinions are split as to whether we save term and outfile
                    455:      * as a compromise, we output them as comments !
                    456:      */
                    457:     if (term)
                    458:        fprintf(fp, "# set terminal %s %s\n", term->name, term_options);
                    459:     else
                    460:        fputs("# set terminal unknown\n", fp);
                    461:
                    462:     if (outstr)
                    463:        fprintf(fp, "# set output '%s'\n", outstr);
                    464:     else
                    465:        fputs("# set output\n", fp);
                    466:
                    467:     fprintf(fp, "\
                    468: set %sclip points\n\
                    469: set %sclip one\n\
                    470: set %sclip two\n\
                    471: set bar %f\n",
                    472:            (clip_points) ? "" : "no",
                    473:            (clip_lines1) ? "" : "no",
                    474:            (clip_lines2) ? "" : "no",
                    475:            bar_size);
                    476:
                    477:     if (draw_border)
                    478:        /* HBB 980609: handle border linestyle, too */
                    479:        fprintf(fp, "set border %d lt %d lw %.3f\n", draw_border, border_lp.l_type + 1, border_lp.l_width);
                    480:     else
                    481:        fprintf(fp, "set noborder\n");
                    482:
                    483:     fprintf(fp, "\
                    484: set xdata%s\n\
                    485: set ydata%s\n\
                    486: set zdata%s\n\
                    487: set x2data%s\n\
                    488: set y2data%s\n",
                    489:            datatype[FIRST_X_AXIS] == TIME ? " time" : "",
                    490:            datatype[FIRST_Y_AXIS] == TIME ? " time" : "",
                    491:            datatype[FIRST_Z_AXIS] == TIME ? " time" : "",
                    492:            datatype[SECOND_X_AXIS] == TIME ? " time" : "",
                    493:            datatype[SECOND_Y_AXIS] == TIME ? " time" : "");
                    494:
                    495:     if (boxwidth < 0.0)
                    496:        fputs("set boxwidth\n", fp);
                    497:     else
                    498:        fprintf(fp, "set boxwidth %g\n", boxwidth);
                    499:     if (dgrid3d)
                    500:        fprintf(fp, "set dgrid3d %d,%d, %d\n",
                    501:                dgrid3d_row_fineness,
                    502:                dgrid3d_col_fineness,
                    503:                dgrid3d_norm_value);
                    504:
                    505:     fprintf(fp, "\
                    506: set dummy %s,%s\n\
                    507: set format x \"%s\"\n\
                    508: set format y \"%s\"\n\
                    509: set format x2 \"%s\"\n\
                    510: set format y2 \"%s\"\n\
                    511: set format z \"%s\"\n\
                    512: set angles %s\n",
                    513:            dummy_var[0], dummy_var[1],
                    514:            conv_text(str, xformat),
                    515:            conv_text(str, yformat),
                    516:            conv_text(str, x2format),
                    517:            conv_text(str, y2format),
                    518:            conv_text(str, zformat),
                    519:            (angles_format == ANGLES_RADIANS) ? "radians" : "degrees");
                    520:
                    521:     if (work_grid.l_type == 0)
                    522:        fputs("set nogrid\n", fp);
                    523:     else {
                    524:        if (polar_grid_angle)   /* set angle already output */
                    525:            fprintf(fp, "set grid polar %f\n", polar_grid_angle / ang2rad);
                    526:        else
                    527:            fputs("set grid nopolar\n", fp);
                    528:        fprintf(fp, "set grid %sxtics %sytics %sztics %sx2tics %sy2tics %smxtics %smytics %smztics %smx2tics %smy2tics lt %d lw %.3f, lt %d lw %.3f\n",
                    529:                work_grid.l_type & GRID_X ? "" : "no",
                    530:                work_grid.l_type & GRID_Y ? "" : "no",
                    531:                work_grid.l_type & GRID_Z ? "" : "no",
                    532:                work_grid.l_type & GRID_X2 ? "" : "no",
                    533:                work_grid.l_type & GRID_Y2 ? "" : "no",
                    534:                work_grid.l_type & GRID_MX ? "" : "no",
                    535:                work_grid.l_type & GRID_MY ? "" : "no",
                    536:                work_grid.l_type & GRID_MZ ? "" : "no",
                    537:                work_grid.l_type & GRID_MX2 ? "" : "no",
                    538:                work_grid.l_type & GRID_MY2 ? "" : "no",
                    539:                grid_lp.l_type + 1, grid_lp.l_width,
                    540:                mgrid_lp.l_type + 1, mgrid_lp.l_width);
                    541:     }
                    542:     fprintf(fp, "set key title \"%s\"\n", conv_text(str, key_title));
                    543:     switch (key) {
                    544:     case -1:{
                    545:            fputs("set key", fp);
                    546:            switch (key_hpos) {
                    547:            case TRIGHT:
                    548:                fputs(" right", fp);
                    549:                break;
                    550:            case TLEFT:
                    551:                fputs(" left", fp);
                    552:                break;
                    553:            case TOUT:
                    554:                fputs(" out", fp);
                    555:                break;
                    556:            }
                    557:            switch (key_vpos) {
                    558:            case TTOP:
                    559:                fputs(" top", fp);
                    560:                break;
                    561:            case TBOTTOM:
                    562:                fputs(" bottom", fp);
                    563:                break;
                    564:            case TUNDER:
                    565:                fputs(" below", fp);
                    566:                break;
                    567:            }
                    568:            break;
                    569:        }
                    570:     case 0:
                    571:        fputs("set nokey\n", fp);
                    572:        break;
                    573:     case 1:
                    574:        fputs("set key ", fp);
                    575:        save_position(fp, &key_user_pos);
                    576:        break;
                    577:     }
                    578:     if (key) {
                    579:        fprintf(fp, " %s %sreverse box linetype %d linewidth %.3f samplen %g spacing %g width %g\n",
                    580:                key_just == JLEFT ? "Left" : "Right",
                    581:                key_reverse ? "" : "no",
                    582:                key_box.l_type + 1, key_box.l_width, key_swidth, key_vert_factor, key_width_fix);
                    583:     }
                    584:     fputs("set nolabel\n", fp);
                    585:     for (this_label = first_label; this_label != NULL;
                    586:         this_label = this_label->next) {
                    587:        fprintf(fp, "set label %d \"%s\" at ",
                    588:                this_label->tag,
                    589:                conv_text(str, this_label->text));
                    590:        save_position(fp, &this_label->place);
                    591:
                    592:        switch (this_label->pos) {
                    593:        case LEFT:
                    594:            fputs(" left", fp);
                    595:            break;
                    596:        case CENTRE:
                    597:            fputs(" centre", fp);
                    598:            break;
                    599:        case RIGHT:
                    600:            fputs(" right", fp);
                    601:            break;
                    602:        }
                    603:        fprintf(fp, " %srotate", this_label->rotate ? "" : "no");
                    604:        if ((this_label->font)[0] != NUL)
                    605:            fprintf(fp, " font \"%s\"", this_label->font);
                    606:        /* Entry font added by DJL */
                    607:        fputc('\n', fp);
                    608:     }
                    609:     fputs("set noarrow\n", fp);
                    610:     for (this_arrow = first_arrow; this_arrow != NULL;
                    611:         this_arrow = this_arrow->next) {
                    612:        fprintf(fp, "set arrow %d from ", this_arrow->tag);
                    613:        save_position(fp, &this_arrow->start);
                    614:        fputs(" to ", fp);
                    615:        save_position(fp, &this_arrow->end);
                    616:        fprintf(fp, " %s linetype %d linewidth %.3f\n",
                    617:                this_arrow->head ? "" : " nohead",
                    618:                this_arrow->lp_properties.l_type + 1,
                    619:                this_arrow->lp_properties.l_width);
                    620:     }
                    621:     fputs("set nolinestyle\n", fp);
                    622:     for (this_linestyle = first_linestyle; this_linestyle != NULL;
                    623:         this_linestyle = this_linestyle->next) {
                    624:        fprintf(fp, "set linestyle %d ", this_linestyle->tag);
                    625:        fprintf(fp, "linetype %d linewidth %.3f pointtype %d pointsize %.3f\n",
                    626:                this_linestyle->lp_properties.l_type + 1,
                    627:                this_linestyle->lp_properties.l_width,
                    628:                this_linestyle->lp_properties.p_type + 1,
                    629:                this_linestyle->lp_properties.p_size);
                    630:     }
                    631:     fputs("set nologscale\n", fp);
                    632:     if (is_log_x)
                    633:        fprintf(fp, "set logscale x %g\n", base_log_x);
                    634:     if (is_log_y)
                    635:        fprintf(fp, "set logscale y %g\n", base_log_y);
                    636:     if (is_log_z)
                    637:        fprintf(fp, "set logscale z %g\n", base_log_z);
                    638:     if (is_log_x2)
                    639:        fprintf(fp, "set logscale x2 %g\n", base_log_x2);
                    640:     if (is_log_y2)
                    641:        fprintf(fp, "set logscale y2 %g\n", base_log_y2);
                    642:
                    643:     fprintf(fp, "\
                    644: set offsets %g, %g, %g, %g\n\
                    645: set pointsize %g\n\
                    646: set encoding %s\n\
                    647: set %spolar\n\
                    648: set %sparametric\n\
                    649: set view %g, %g, %g, %g\n\
                    650: set samples %d, %d\n\
                    651: set isosamples %d, %d\n\
                    652: set %ssurface\n\
                    653: set %scontour",
                    654:            loff, roff, toff, boff,
                    655:            pointsize,
                    656:            encoding_names[encoding],
                    657:            (polar) ? "" : "no",
                    658:            (parametric) ? "" : "no",
                    659:            surface_rot_x, surface_rot_z, surface_scale, surface_zscale,
                    660:            samples_1, samples_2,
                    661:            iso_samples_1, iso_samples_2,
                    662:            (draw_surface) ? "" : "no",
                    663:            (draw_contour) ? "" : "no");
                    664:
                    665:     switch (draw_contour) {
                    666:     case CONTOUR_NONE:
                    667:        fputc('\n', fp);
                    668:        break;
                    669:     case CONTOUR_BASE:
                    670:        fputs(" base\n", fp);
                    671:        break;
                    672:     case CONTOUR_SRF:
                    673:        fputs(" surface\n", fp);
                    674:        break;
                    675:     case CONTOUR_BOTH:
                    676:        fputs(" both\n", fp);
                    677:        break;
                    678:     }
                    679:     if (label_contours)
                    680:        fprintf(fp, "set clabel '%s'\n", contour_format);
                    681:     else
                    682:        fputs("set noclabel\n", fp);
                    683:
                    684:     fputs("set mapping ", fp);
                    685:     switch(mapping3d) {
                    686:     case MAP3D_SPHERICAL:
                    687:        fputs("spherical\n", fp);
                    688:        break;
                    689:     case MAP3D_CYLINDRICAL:
                    690:        fputs("cylindrical\n", fp);
                    691:        break;
                    692:     case MAP3D_CARTESIAN:
                    693:     default:
                    694:        fputs("cartesian\n", fp);
                    695:        break;
                    696:     }
                    697:
                    698:     if (missing_val != NULL)
                    699:        fprintf(fp, "set missing %s\n", missing_val);
                    700:
                    701:     save_hidden3doptions(fp);
                    702:     fprintf(fp, "set cntrparam order %d\n", contour_order);
                    703:     fputs("set cntrparam ", fp);
                    704:     switch (contour_kind) {
                    705:     case CONTOUR_KIND_LINEAR:
                    706:        fputs("linear\n", fp);
                    707:        break;
                    708:     case CONTOUR_KIND_CUBIC_SPL:
                    709:        fputs("cubicspline\n", fp);
                    710:        break;
                    711:     case CONTOUR_KIND_BSPLINE:
                    712:        fputs("bspline\n", fp);
                    713:        break;
                    714:     }
                    715:     fputs("set cntrparam levels ", fp);
                    716:     switch (levels_kind) {
                    717:     case LEVELS_AUTO:
                    718:        fprintf(fp, "auto %d\n", contour_levels);
                    719:        break;
                    720:     case LEVELS_INCREMENTAL:
                    721:        fprintf(fp, "incremental %g,%g,%g\n",
                    722:                levels_list[0], levels_list[1],
                    723:                levels_list[0] + levels_list[1] * contour_levels);
                    724:        break;
                    725:     case LEVELS_DISCRETE:
                    726:        {
                    727:            int i;
                    728:            fprintf(fp, "discrete %g", levels_list[0]);
                    729:            for (i = 1; i < contour_levels; i++)
                    730:                fprintf(fp, ",%g ", levels_list[i]);
                    731:            fputc('\n', fp);
                    732:        }
                    733:     }
                    734:     fprintf(fp, "\
                    735: set cntrparam points %d\n\
                    736: set size ratio %g %g,%g\n\
                    737: set origin %g,%g\n\
                    738: set data style ",
                    739:            contour_pts,
                    740:            aspect_ratio, xsize, ysize,
                    741:            xoffset, yoffset);
                    742:
                    743:     switch (data_style) {
                    744:     case LINES:
                    745:        fputs("lines\n", fp);
                    746:        break;
                    747:     case POINTSTYLE:
                    748:        fputs("points\n", fp);
                    749:        break;
                    750:     case IMPULSES:
                    751:        fputs("impulses\n", fp);
                    752:        break;
                    753:     case LINESPOINTS:
                    754:        fputs("linespoints\n", fp);
                    755:        break;
                    756:     case DOTS:
                    757:        fputs("dots\n", fp);
                    758:        break;
                    759:     case YERRORBARS:
                    760:        fputs("yerrorbars\n", fp);
                    761:        break;
                    762:     case XERRORBARS:
                    763:        fputs("xerrorbars\n", fp);
                    764:        break;
                    765:     case XYERRORBARS:
                    766:        fputs("xyerrorbars\n", fp);
                    767:        break;
                    768:     case BOXES:
                    769:        fputs("boxes\n", fp);
                    770:        break;
                    771:     case BOXERROR:
                    772:        fputs("boxerrorbars\n", fp);
                    773:        break;
                    774:     case BOXXYERROR:
                    775:        fputs("boxxyerrorbars\n", fp);
                    776:        break;
                    777:     case STEPS:
                    778:        fputs("steps\n", fp);
                    779:        break;                  /* JG */
                    780:     case FSTEPS:
                    781:        fputs("fsteps\n", fp);
                    782:        break;                  /* HOE */
                    783:     case HISTEPS:
                    784:        fputs("histeps\n", fp);
                    785:        break;                  /* CAC */
                    786:     case VECTOR:
                    787:        fputs("vector\n", fp);
                    788:        break;
                    789:     case FINANCEBARS:
                    790:        fputs("financebars\n", fp);
                    791:        break;
                    792:     case CANDLESTICKS:
                    793:        fputs("candlesticks\n", fp);
                    794:        break;
                    795:     }
                    796:     fputs("set function style ", fp);
                    797:     switch (func_style) {
                    798:     case LINES:
                    799:        fputs("lines\n", fp);
                    800:        break;
                    801:     case POINTSTYLE:
                    802:        fputs("points\n", fp);
                    803:        break;
                    804:     case IMPULSES:
                    805:        fputs("impulses\n", fp);
                    806:        break;
                    807:     case LINESPOINTS:
                    808:        fputs("linespoints\n", fp);
                    809:        break;
                    810:     case DOTS:
                    811:        fputs("dots\n", fp);
                    812:        break;
                    813:     case YERRORBARS:
                    814:        fputs("yerrorbars\n", fp);
                    815:        break;
                    816:     case XERRORBARS:
                    817:        fputs("xerrorbars\n", fp);
                    818:        break;
                    819:     case XYERRORBARS:
                    820:        fputs("xyerrorbars\n", fp);
                    821:        break;
                    822:     case BOXXYERROR:
                    823:        fputs("boxxyerrorbars\n", fp);
                    824:        break;
                    825:     case BOXES:
                    826:        fputs("boxes\n", fp);
                    827:        break;
                    828:     case BOXERROR:
                    829:        fputs("boxerrorbars\n", fp);
                    830:        break;
                    831:     case STEPS:
                    832:        fputs("steps\n", fp);
                    833:        break;                  /* JG */
                    834:     case FSTEPS:
                    835:        fputs("fsteps\n", fp);
                    836:        break;                  /* HOE */
                    837:     case HISTEPS:
                    838:        fputs("histeps\n", fp);
                    839:        break;                  /* CAC */
                    840:     case VECTOR:
                    841:        fputs("vector\n", fp);
                    842:        break;
                    843:     case FINANCEBARS:
                    844:        fputs("financebars\n", fp);
                    845:        break;
                    846:     case CANDLESTICKS:
                    847:        fputs("candlesticks\n", fp);
                    848:        break;
                    849:     default:
                    850:         /* HBB: default case demanded by gcc, still needed ?? */
                    851:        fputs("---error!---\n", fp);
                    852:     }
                    853:
                    854:     fprintf(fp, "\
                    855: set xzeroaxis lt %d lw %.3f\n\
                    856: set x2zeroaxis lt %d lw %.3f\n\
                    857: set yzeroaxis lt %d lw %.3f\n\
                    858: set y2zeroaxis lt %d lw %.3f\n\
                    859: set tics %s\n\
                    860: set ticslevel %g\n\
                    861: set ticscale %g %g\n",
                    862:            xzeroaxis.l_type + 1, xzeroaxis.l_width,
                    863:            x2zeroaxis.l_type + 1, x2zeroaxis.l_width,
                    864:            yzeroaxis.l_type + 1, yzeroaxis.l_width,
                    865:            y2zeroaxis.l_type + 1, y2zeroaxis.l_width,
                    866:            (tic_in) ? "in" : "out",
                    867:            ticslevel,
                    868:            ticscale, miniticscale);
                    869:
                    870: #define SAVE_XYZLABEL(name,lab) { \
                    871:   fprintf(fp, "set %s \"%s\" %f,%f ", \
                    872:     name, conv_text(str,lab.text),lab.xoffset,lab.yoffset); \
                    873:   fprintf(fp, " \"%s\"\n", conv_text(str, lab.font)); \
                    874: }
                    875:
                    876:
                    877: #define SAVE_MINI(name,m,freq) switch(m&TICS_MASK) { \
                    878:  case 0: fprintf(fp, "set no%s\n", name); break; \
                    879:  case MINI_AUTO: fprintf(fp, "set %s\n",name); break; \
                    880:  case MINI_DEFAULT: fprintf(fp, "set %s default\n",name); break; \
                    881:  case MINI_USER: fprintf(fp, "set %s %f\n", name, freq); break; \
                    882: }
                    883:     SAVE_MINI("mxtics", mxtics, mxtfreq)
                    884:        SAVE_MINI("mytics", mytics, mytfreq)
                    885:        SAVE_MINI("mx2tics", mx2tics, mx2tfreq)
                    886:        SAVE_MINI("my2tics", my2tics, my2tfreq)
                    887:        save_tics(fp, xtics, FIRST_X_AXIS, &xticdef, rotate_xtics, "x");
                    888:     save_tics(fp, ytics, FIRST_Y_AXIS, &yticdef, rotate_ytics, "y");
                    889:     save_tics(fp, ztics, FIRST_Z_AXIS, &zticdef, rotate_ztics, "z");
                    890:     save_tics(fp, x2tics, SECOND_X_AXIS, &x2ticdef, rotate_x2tics, "x2");
                    891:     save_tics(fp, y2tics, SECOND_Y_AXIS, &y2ticdef, rotate_y2tics, "y2");
                    892:     SAVE_XYZLABEL("title", title);
                    893:
                    894:     fprintf(fp, "set %s \"%s\" %s %srotate %f,%f ",
                    895:            "timestamp", conv_text(str, timelabel.text),
                    896:            (timelabel_bottom ? "bottom" : "top"),
                    897:            (timelabel_rotate ? "" : "no"),
                    898:            timelabel.xoffset, timelabel.yoffset);
                    899:     fprintf(fp, " \"%s\"\n", conv_text(str, timelabel.font));
                    900:
                    901:     save_range(fp, R_AXIS, rmin, rmax, autoscale_r, "r");
                    902:     save_range(fp, T_AXIS, tmin, tmax, autoscale_t, "t");
                    903:     save_range(fp, U_AXIS, umin, umax, autoscale_u, "u");
                    904:     save_range(fp, V_AXIS, vmin, vmax, autoscale_v, "v");
                    905:
                    906:     SAVE_XYZLABEL("xlabel", xlabel);
                    907:     SAVE_XYZLABEL("x2label", x2label);
                    908:
                    909:     if (strlen(timefmt)) {
                    910:        fprintf(fp, "set timefmt \"%s\"\n", conv_text(str, timefmt));
                    911:     }
                    912:     save_range(fp, FIRST_X_AXIS, xmin, xmax, autoscale_x, "x");
                    913:     save_range(fp, SECOND_X_AXIS, x2min, x2max, autoscale_x2, "x2");
                    914:
                    915:     SAVE_XYZLABEL("ylabel", ylabel);
                    916:     SAVE_XYZLABEL("y2label", y2label);
                    917:
                    918:     save_range(fp, FIRST_Y_AXIS, ymin, ymax, autoscale_y, "y");
                    919:     save_range(fp, SECOND_Y_AXIS, y2min, y2max, autoscale_y2, "y2");
                    920:
                    921:     SAVE_XYZLABEL("zlabel", zlabel);
                    922:     save_range(fp, FIRST_Z_AXIS, zmin, zmax, autoscale_z, "z");
                    923:
                    924:     fprintf(fp, "set zero %g\n", zero);
                    925:     fprintf(fp, "set lmargin %d\nset bmargin %d\nset rmargin %d\nset tmargin %d\n",
                    926:            lmargin, bmargin, rmargin, tmargin);
                    927:
                    928:     fprintf(fp, "set locale \"%s\"\n", cur_locale);
                    929: }
                    930:
                    931: static void save_tics(fp, where, axis, tdef, rotate, text)
                    932: FILE *fp;
                    933: int where;
                    934: int axis;
                    935: struct ticdef *tdef;
                    936: TBOOLEAN rotate;
                    937: char *text;
                    938: {
                    939:     char str[MAX_LINE_LEN + 1];
                    940:
                    941:     if (where == NO_TICS) {
                    942:        fprintf(fp, "set no%stics\n", text);
                    943:        return;
                    944:     }
                    945:     fprintf(fp, "set %stics %s %smirror %srotate ", text,
                    946:            (where & TICS_MASK) == TICS_ON_AXIS ? "axis" : "border",
                    947:            (where & TICS_MIRROR) ? "" : "no", rotate ? "" : "no");
                    948:     switch (tdef->type) {
                    949:     case TIC_COMPUTED:{
                    950:            fputs("autofreq ", fp);
                    951:            break;
                    952:        }
                    953:     case TIC_MONTH:{
                    954:            fprintf(fp, "\nset %smtics", text);
                    955:            break;
                    956:        }
                    957:     case TIC_DAY:{
                    958:            fprintf(fp, "\nset %cdtics", axis);
                    959:            break;
                    960:        }
                    961:     case TIC_SERIES:
                    962:        if (datatype[axis] == TIME) {
                    963:            if (tdef->def.series.start != -VERYLARGE) {
                    964:                char fd[26];
                    965:                gstrftime(fd, 24, timefmt, (double) tdef->def.series.start);
                    966:                fprintf(fp, "\"%s\",", conv_text(str, fd));
                    967:            }
                    968:            fprintf(fp, "%g", tdef->def.series.incr);
                    969:
                    970:            if (tdef->def.series.end != VERYLARGE) {
                    971:                char td[26];
                    972:                gstrftime(td, 24, timefmt, (double) tdef->def.series.end);
                    973:                fprintf(fp, ",\"%s\"", conv_text(str, td));
                    974:            }
                    975:        } else {                /* !TIME */
                    976:
                    977:            if (tdef->def.series.start != -VERYLARGE)
                    978:                fprintf(fp, "%g,", tdef->def.series.start);
                    979:            fprintf(fp, "%g", tdef->def.series.incr);
                    980:            if (tdef->def.series.end != VERYLARGE)
                    981:                fprintf(fp, ",%g", tdef->def.series.end);
                    982:        }
                    983:
                    984:        break;
                    985:
                    986:     case TIC_USER:{
                    987:            register struct ticmark *t;
                    988:            int flag_time;
                    989:            flag_time = (datatype[axis] == TIME);
                    990:            fputs(" (", fp);
                    991:            for (t = tdef->def.user; t != NULL; t = t->next) {
                    992:                if (t->label)
                    993:                    fprintf(fp, "\"%s\" ", conv_text(str, t->label));
                    994:                if (flag_time) {
                    995:                    char td[26];
                    996:                    gstrftime(td, 24, timefmt, (double) t->position);
                    997:                    fprintf(fp, "\"%s\"", conv_text(str, td));
                    998:                } else {
                    999:                    fprintf(fp, "%g", t->position);
                   1000:                }
                   1001:                if (t->next) {
                   1002:                    fputs(", ", fp);
                   1003:                }
                   1004:            }
                   1005:            fputs(")", fp);
                   1006:            break;
                   1007:        }
                   1008:     }
                   1009:     putc('\n', fp);
                   1010: }
                   1011:
                   1012: static void save_position(fp, pos)
                   1013: FILE *fp;
                   1014: struct position *pos;
                   1015: {
                   1016:     static char *msg[] =
                   1017:     {"first_axes ", "second axes ", "graph ", "screen "};
                   1018:
                   1019:     assert(first_axes == 0 && second_axes == 1 && graph == 2 && screen == 3);
                   1020:
                   1021:     fprintf(fp, "%s%g, %s%g, %s%g",
                   1022:            pos->scalex == first_axes ? "" : msg[pos->scalex], pos->x,
                   1023:            pos->scaley == pos->scalex ? "" : msg[pos->scaley], pos->y,
                   1024:            pos->scalez == pos->scaley ? "" : msg[pos->scalez], pos->z);
                   1025: }
                   1026:
                   1027: void load_file(fp, name, can_do_args)
                   1028: FILE *fp;
                   1029: char *name;
                   1030: TBOOLEAN can_do_args;
                   1031: {
                   1032:     register int len;
                   1033:
                   1034:     int start, left;
                   1035:     int more;
                   1036:     int stop = FALSE;
                   1037:
                   1038:     lf_push(fp);               /* save state for errors and recursion */
                   1039:     do_load_arg_substitution = can_do_args;
                   1040:
                   1041:     if (fp == (FILE *) NULL) {
                   1042:        /* HBB 980311: alloc() it, to save valuable stack space: */
                   1043:        char *errbuf = gp_alloc(BUFSIZ, "load_file errorstring");
                   1044:        (void) sprintf(errbuf, "Cannot open %s file '%s'",
                   1045:                       can_do_args ? "call" : "load", name);
                   1046:        os_error(errbuf, c_token);
                   1047:        free(errbuf);
                   1048:     } else if (fp == stdin) {
                   1049:        /* DBT 10-6-98  go interactive if "-" named as load file */
                   1050:        interactive = TRUE;
                   1051:        while(!com_line())
                   1052:            ;
                   1053:     } else {
                   1054:        /* go into non-interactive mode during load */
                   1055:        /* will be undone below, or in load_file_error */
                   1056:        interactive = FALSE;
                   1057:        inline_num = 0;
                   1058:        infile_name = name;
                   1059:
                   1060:        if (can_do_args) {
                   1061:            int aix = 0;
                   1062:            while (++c_token < num_tokens && aix <= 9) {
                   1063:                if (isstring(c_token))
                   1064:                    m_quote_capture(&call_args[aix++], c_token, c_token);
                   1065:                else
                   1066:                    m_capture(&call_args[aix++], c_token, c_token);
                   1067:            }
                   1068:
                   1069: /*         A GNUPLOT "call" command can have up to _10_ arguments named "$0"
                   1070:    to "$9".  After reading the 10th argument (i.e.: "$9") the variable
                   1071:    'aix' contains the value '10' because of the 'aix++' construction
                   1072:    in '&call_args[aix++]'.  So I think the following test of 'aix'
                   1073:    should be done against '10' instead of '9'.                (JFi) */
                   1074:
                   1075: /*              if (c_token >= num_tokens && aix > 9) */
                   1076:            if (c_token >= num_tokens && aix > 10)
                   1077:                int_error("too many arguments for CALL <file>", ++c_token);
                   1078:        }
                   1079:        while (!stop) {         /* read all commands in file */
                   1080:            /* read one command */
                   1081:            left = input_line_len;
                   1082:            start = 0;
                   1083:            more = TRUE;
                   1084:
                   1085:            while (more) {
                   1086:                if (fgets(&(input_line[start]), left, fp) == (char *) NULL) {
                   1087:                    stop = TRUE;        /* EOF in file */
                   1088:                    input_line[start] = '\0';
                   1089:                    more = FALSE;
                   1090:                } else {
                   1091:                    inline_num++;
                   1092:                    len = strlen(input_line) - 1;
                   1093:                    if (input_line[len] == '\n') {      /* remove any newline */
                   1094:                        input_line[len] = '\0';
                   1095:                        /* Look, len was 1-1 = 0 before, take care here! */
                   1096:                        if (len > 0)
                   1097:                            --len;
                   1098:                        if (input_line[len] == '\r') {  /* remove any carriage return */
                   1099:                            input_line[len] = NUL;
                   1100:                            if (len > 0)
                   1101:                                --len;
                   1102:                        }
                   1103:                    }
                   1104:                     else if (len + 2 >= left) {
                   1105:                        extend_input_line();
                   1106:                        left = input_line_len - len - 1;
                   1107:                        start = len + 1;
                   1108:                        continue;       /* don't check for '\' */
                   1109:                    }
                   1110:                    if (input_line[len] == '\\') {
                   1111:                        /* line continuation */
                   1112:                        start = len;
                   1113:                        left = input_line_len - start;
                   1114:                    } else
                   1115:                        more = FALSE;
                   1116:                }
                   1117:            }
                   1118:
                   1119:            if (strlen(input_line) > 0) {
                   1120:                if (can_do_args) {
                   1121:                    register int il = 0;
                   1122:                    register char *rl;
                   1123:                    char *raw_line = rl = gp_alloc((unsigned long) strlen(input_line) + 1, "string");
                   1124:
                   1125:                    strcpy(raw_line, input_line);
                   1126:                    *input_line = '\0';
                   1127:                    while (*rl) {
                   1128:                        register int aix;
                   1129:                        if (*rl == '$'
                   1130:                            && ((aix = *(++rl)) != 0)   /* HBB 980308: quiet BCC warning */
                   1131:                            &&aix >= '0' && aix <= '9') {
                   1132:                            if (call_args[aix -= '0']) {
                   1133:                                len = strlen(call_args[aix]);
                   1134:                                while (input_line_len - il < len + 1) {
                   1135:                                    extend_input_line();
                   1136:                                }
                   1137:                                strcpy(input_line + il, call_args[aix]);
                   1138:                                il += len;
                   1139:                            }
                   1140:                        } else {
                   1141:                            /* substitute for $<n> here */
                   1142:                            if (il + 1 > input_line_len) {
                   1143:                                extend_input_line();
                   1144:                            }
                   1145:                            input_line[il++] = *rl;
                   1146:                        }
                   1147:                        rl++;
                   1148:                    }
                   1149:                    if (il + 1 > input_line_len) {
                   1150:                        extend_input_line();
                   1151:                    }
                   1152:                    input_line[il] = '\0';
                   1153:                    free(raw_line);
                   1154:                }
                   1155:                screen_ok = FALSE;      /* make sure command line is
                   1156:                                           echoed on error */
                   1157:                do_line();
                   1158:            }
                   1159:        }
                   1160:     }
                   1161:
                   1162:     /* pop state */
                   1163:     (void) lf_pop();           /* also closes file fp */
                   1164: }
                   1165:
                   1166: /* pop from load_file state stack */
                   1167: static TBOOLEAN                        /* FALSE if stack was empty */
                   1168:  lf_pop()
                   1169: {                              /* called by load_file and load_file_error */
                   1170:     LFS *lf;
                   1171:
                   1172:     if (lf_head == NULL)
                   1173:        return (FALSE);
                   1174:     else {
                   1175:        int argindex;
                   1176:        lf = lf_head;
                   1177:        if (lf->fp != (FILE *)NULL && lf->fp != stdin) {
                   1178:            /* DBT 10-6-98  do not close stdin in the case
                   1179:             * that "-" is named as a load file
                   1180:             */
                   1181:            (void) fclose(lf->fp);
                   1182:        }
                   1183:        for (argindex = 0; argindex < 10; argindex++) {
                   1184:            if (call_args[argindex]) {
                   1185:                free(call_args[argindex]);
                   1186:            }
                   1187:            call_args[argindex] = lf->call_args[argindex];
                   1188:        }
                   1189:        do_load_arg_substitution = lf->do_load_arg_substitution;
                   1190:        interactive = lf->interactive;
                   1191:        inline_num = lf->inline_num;
                   1192:        infile_name = lf->name;
                   1193:        lf_head = lf->prev;
                   1194:        free((char *) lf);
                   1195:        return (TRUE);
                   1196:     }
                   1197: }
                   1198:
                   1199: /* push onto load_file state stack */
                   1200: /* essentially, we save information needed to undo the load_file changes */
                   1201: static void lf_push(fp)                /* called by load_file */
                   1202: FILE *fp;
                   1203: {
                   1204:     LFS *lf;
                   1205:     int argindex;
                   1206:
                   1207:     lf = (LFS *) gp_alloc((unsigned long) sizeof(LFS), (char *) NULL);
                   1208:     if (lf == (LFS *) NULL) {
                   1209:        if (fp != (FILE *) NULL)
                   1210:            (void) fclose(fp);  /* it won't be otherwise */
                   1211:        int_error("not enough memory to load file", c_token);
                   1212:     }
                   1213:     lf->fp = fp;               /* save this file pointer */
                   1214:     lf->name = infile_name;    /* save current name */
                   1215:     lf->interactive = interactive;     /* save current state */
                   1216:     lf->inline_num = inline_num;       /* save current line number */
                   1217:     lf->do_load_arg_substitution = do_load_arg_substitution;
                   1218:     for (argindex = 0; argindex < 10; argindex++) {
                   1219:        lf->call_args[argindex] = call_args[argindex];
                   1220:        call_args[argindex] = NULL;     /* initially no args */
                   1221:     }
                   1222:     lf->prev = lf_head;                /* link to stack */
                   1223:     lf_head = lf;
                   1224: }
                   1225:
                   1226: /* used for reread  vsnyder@math.jpl.nasa.gov */
                   1227: FILE *lf_top()
                   1228: {
                   1229:     if (lf_head == (LFS *) NULL)
                   1230:        return ((FILE *) NULL);
                   1231:     return (lf_head->fp);
                   1232: }
                   1233:
                   1234: /* called from main */
                   1235: void load_file_error()
                   1236: {
                   1237:     /* clean up from error in load_file */
                   1238:     /* pop off everything on stack */
                   1239:     while (lf_pop());
                   1240: }
                   1241:
                   1242: /* find char c in string str; return p such that str[p]==c;
                   1243:  * if c not in str then p=strlen(str)
                   1244:  */
                   1245: int instring(str, c)
                   1246: char *str;
                   1247: int c;
                   1248: {
                   1249:     int pos = 0;
                   1250:
                   1251:     while (str != NULL && *str != NUL && c != *str) {
                   1252:        str++;
                   1253:        pos++;
                   1254:     }
                   1255:     return (pos);
                   1256: }
                   1257:
                   1258: void show_functions()
                   1259: {
                   1260:     register struct udft_entry *udf = first_udf;
                   1261:
                   1262:     fputs("\n\tUser-Defined Functions:\n", stderr);
                   1263:
                   1264:     while (udf) {
                   1265:        if (udf->definition)
                   1266:            fprintf(stderr, "\t%s\n", udf->definition);
                   1267:        else
                   1268:            fprintf(stderr, "\t%s is undefined\n", udf->udf_name);
                   1269:        udf = udf->next_udf;
                   1270:     }
                   1271: }
                   1272:
                   1273:
                   1274: void show_at()
                   1275: {
                   1276:     (void) putc('\n', stderr);
                   1277:     disp_at(temp_at(), 0);
                   1278: }
                   1279:
                   1280:
                   1281: void disp_at(curr_at, level)
                   1282: struct at_type *curr_at;
                   1283: int level;
                   1284: {
                   1285:     register int i, j;
                   1286:     register union argument *arg;
                   1287:
                   1288:     for (i = 0; i < curr_at->a_count; i++) {
                   1289:        (void) putc('\t', stderr);
                   1290:        for (j = 0; j < level; j++)
                   1291:            (void) putc(' ', stderr);   /* indent */
                   1292:
                   1293:        /* print name of instruction */
                   1294:
                   1295:        fputs(ft[(int) (curr_at->actions[i].index)].f_name, stderr);
                   1296:        arg = &(curr_at->actions[i].arg);
                   1297:
                   1298:        /* now print optional argument */
                   1299:
                   1300:        switch (curr_at->actions[i].index) {
                   1301:        case PUSH:
                   1302:            fprintf(stderr, " %s\n", arg->udv_arg->udv_name);
                   1303:            break;
                   1304:        case PUSHC:
                   1305:            (void) putc(' ', stderr);
                   1306:            disp_value(stderr, &(arg->v_arg));
                   1307:            (void) putc('\n', stderr);
                   1308:            break;
                   1309:        case PUSHD1:
                   1310:            fprintf(stderr, " %c dummy\n",
                   1311:                    arg->udf_arg->udf_name[0]);
                   1312:            break;
                   1313:        case PUSHD2:
                   1314:            fprintf(stderr, " %c dummy\n",
                   1315:                    arg->udf_arg->udf_name[1]);
                   1316:            break;
                   1317:        case CALL:
                   1318:            fprintf(stderr, " %s", arg->udf_arg->udf_name);
                   1319:            if (level < 6) {
                   1320:                if (arg->udf_arg->at) {
                   1321:                    (void) putc('\n', stderr);
                   1322:                    disp_at(arg->udf_arg->at, level + 2);       /* recurse! */
                   1323:                } else
                   1324:                    fputs(" (undefined)\n", stderr);
                   1325:            } else
                   1326:                (void) putc('\n', stderr);
                   1327:            break;
                   1328:        case CALLN:
                   1329:            fprintf(stderr, " %s", arg->udf_arg->udf_name);
                   1330:            if (level < 6) {
                   1331:                if (arg->udf_arg->at) {
                   1332:                    (void) putc('\n', stderr);
                   1333:                    disp_at(arg->udf_arg->at, level + 2);       /* recurse! */
                   1334:                } else
                   1335:                    fputs(" (undefined)\n", stderr);
                   1336:            } else
                   1337:                (void) putc('\n', stderr);
                   1338:            break;
                   1339:        case JUMP:
                   1340:        case JUMPZ:
                   1341:        case JUMPNZ:
                   1342:        case JTERN:
                   1343:            fprintf(stderr, " +%d\n", arg->j_arg);
                   1344:            break;
                   1345:        case DOLLARS:
                   1346:            fprintf(stderr, " %d\n", arg->v_arg.v.int_val);
                   1347:            break;
                   1348:        default:
                   1349:            (void) putc('\n', stderr);
                   1350:        }
                   1351:     }
                   1352: }
                   1353:
                   1354: /* find max len of keys and count keys with len > 0 */
                   1355:
                   1356: int find_maxl_keys(plots, count, kcnt)
                   1357: struct curve_points *plots;
                   1358: int count, *kcnt;
                   1359: {
                   1360:     int mlen, len, curve, cnt;
                   1361:     register struct curve_points *this_plot;
                   1362:
                   1363:     mlen = cnt = 0;
                   1364:     this_plot = plots;
                   1365:     for (curve = 0; curve < count; this_plot = this_plot->next_cp, curve++)
                   1366:        if (this_plot->title
                   1367:            && ((len = /*assign */ strlen(this_plot->title)) != 0)      /* HBB 980308: quiet BCC warning */
                   1368:            ) {
                   1369:            cnt++;
                   1370:            if (len > mlen)
                   1371:                mlen = strlen(this_plot->title);
                   1372:        }
                   1373:     if (kcnt != NULL)
                   1374:        *kcnt = cnt;
                   1375:     return (mlen);
                   1376: }
                   1377:
                   1378:
                   1379: /* calculate the number and max-width of the keys for an splot.
                   1380:  * Note that a blank line is issued after each set of contours
                   1381:  */
                   1382: int find_maxl_keys3d(plots, count, kcnt)
                   1383: struct surface_points *plots;
                   1384: int count, *kcnt;
                   1385: {
                   1386:     int mlen, len, surf, cnt;
                   1387:     struct surface_points *this_plot;
                   1388:
                   1389:     mlen = cnt = 0;
                   1390:     this_plot = plots;
                   1391:     for (surf = 0; surf < count; this_plot = this_plot->next_sp, surf++) {
                   1392:
                   1393:        /* we draw a main entry if there is one, and we are
                   1394:         * drawing either surface, or unlabelled contours
                   1395:         */
                   1396:        if (this_plot->title && *this_plot->title &&
                   1397:            (draw_surface || (draw_contour && !label_contours))) {
                   1398:            ++cnt;
                   1399:            len = strlen(this_plot->title);
                   1400:            if (len > mlen)
                   1401:                mlen = len;
                   1402:        }
                   1403:        if (draw_contour && label_contours && this_plot->contours != NULL) {
                   1404:            len = find_maxl_cntr(this_plot->contours, &cnt);
                   1405:            if (len > mlen)
                   1406:                mlen = len;
                   1407:        }
                   1408:     }
                   1409:
                   1410:     if (kcnt != NULL)
                   1411:        *kcnt = cnt;
                   1412:     return (mlen);
                   1413: }
                   1414:
                   1415: static int find_maxl_cntr(contours, count)
                   1416: struct gnuplot_contours *contours;
                   1417: int *count;
                   1418: {
                   1419:     register int cnt;
                   1420:     register int mlen, len;
                   1421:     register struct gnuplot_contours *cntrs = contours;
                   1422:
                   1423:     mlen = cnt = 0;
                   1424:     while (cntrs) {
                   1425:        if (label_contours && cntrs->isNewLevel) {
                   1426:            len = strlen(cntrs->label);
                   1427:            if (len)
                   1428:                cnt++;
                   1429:            if (len > mlen)
                   1430:                mlen = len;
                   1431:        }
                   1432:        cntrs = cntrs->next;
                   1433:     }
                   1434:     *count += cnt;
                   1435:     return (mlen);
                   1436: }
                   1437:
                   1438: static void save_range(fp, axis, min, max, autosc, text)
                   1439: FILE *fp;
                   1440: int axis;
                   1441: double min, max;
                   1442: TBOOLEAN autosc;
                   1443: char *text;
                   1444: {
                   1445:     int i;
                   1446:
                   1447:     i = axis;
                   1448:     fprintf(fp, "set %srange [ ", text);
                   1449:     if (autosc & 1) {
                   1450:        putc('*', fp);
                   1451:     } else {
                   1452:        SAVE_NUM_OR_TIME(fp, min, axis);
                   1453:     }
                   1454:     fputs(" : ", fp);
                   1455:     if (autosc & 2) {
                   1456:        putc('*', fp);
                   1457:     } else {
                   1458:        SAVE_NUM_OR_TIME(fp, max, axis);
                   1459:     }
                   1460:
                   1461:     fprintf(fp, " ] %sreverse %swriteback",
                   1462:            range_flags[axis] & RANGE_REVERSE ? "" : "no",
                   1463:            range_flags[axis] & RANGE_WRITEBACK ? "" : "no");
                   1464:
                   1465:     if (autosc) {
                   1466:        /* add current (hidden) range as comments */
                   1467:        fputs("  # (currently [", fp);
                   1468:        if (autosc & 1) {
                   1469:            SAVE_NUM_OR_TIME(fp, min, axis);
                   1470:        }
                   1471:        putc(':', fp);
                   1472:        if (autosc & 2) {
                   1473:            SAVE_NUM_OR_TIME(fp, max, axis);
                   1474:        }
                   1475:        fputs("] )", fp);
                   1476:     }
                   1477:     putc('\n', fp);
                   1478: }
                   1479:
                   1480: /* check user defined format strings for valid double conversions */
                   1481: TBOOLEAN valid_format(format)
                   1482: const char *format;
                   1483: {
                   1484:     for (;;) {
                   1485:        if (!(format = strchr(format, '%')))    /* look for format spec  */
                   1486:            return TRUE;        /* passed Test           */
                   1487:        do {                    /* scan format statement */
                   1488:            format++;
                   1489:        } while (strchr("+-#0123456789.", *format));
                   1490:
                   1491:        switch (*format) {      /* Now at format modifier */
                   1492:        case '*':               /* Ignore '*' statements */
                   1493:        case '%':               /* Char   '%' itself     */
                   1494:            format++;
                   1495:            continue;
                   1496:        case 'l':               /* Now we found it !!! */
                   1497:            if (!strchr("fFeEgG", format[1]))   /* looking for a valid format */
                   1498:                return FALSE;
                   1499:            format++;
                   1500:            break;
                   1501:        default:
                   1502:            return FALSE;
                   1503:        }
                   1504:     }
                   1505: }

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