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

1.1       maekawa     1: #ifndef lint
1.1.1.3 ! ohara       2: static char *RCSid = "$Id: misc.c,v 1.15.2.5 2002/04/21 13:52:55 broeker Exp $";
1.1       maekawa     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 {\
1.1.1.2   maekawa    71:   fprintf(fp,"%#g",x);\
1.1       maekawa    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:
1.1.1.3 ! ohara     103:     cp = (struct curve_points *) gp_alloc(sizeof(struct curve_points), "curve");
1.1       maekawa   104:     cp->p_max = (num >= 0 ? num : 0);
                    105:
                    106:     if (num > 0) {
                    107:        cp->points = (struct coordinate GPHUGE *)
1.1.1.3 ! ohara     108:            gp_alloc(num * sizeof(struct coordinate), "curve points");
1.1       maekawa   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 *)
1.1.1.3 ! ohara     141:                gp_alloc(num * sizeof(struct coordinate), "curve points");
1.1       maekawa   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;
1.1.1.3 ! ohara     181:     ip = (struct iso_curve *) gp_alloc(sizeof(struct iso_curve), "iso curve");
1.1       maekawa   182:     ip->p_max = (num >= 0 ? num : 0);
                    183:     if (num > 0) {
                    184:        ip->points = (struct coordinate GPHUGE *)
1.1.1.3 ! ohara     185:            gp_alloc(num * sizeof(struct coordinate), "iso curve points");
1.1       maekawa   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 *)
1.1.1.3 ! ohara     215:                gp_alloc(num * sizeof(struct coordinate), "iso curve points");
1.1       maekawa   216:        } else {
                    217:            ip->points = (struct coordinate GPHUGE *)
1.1.1.3 ! ohara     218:                gp_realloc(ip->points, num * sizeof(struct coordinate), "expanding curve points");
1.1       maekawa   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:
1.1.1.3 ! ohara     255:     sp = (struct surface_points *) gp_alloc(sizeof(struct surface_points), "surface");
1.1       maekawa   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;
1.1.1.2   maekawa   452:     char str[MAX_LINE_LEN+1];
1.1       maekawa   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:
1.1.1.2   maekawa   505:     fprintf(fp, "set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
                    506:     fprintf(fp, "set format x \"%s\"\n", conv_text(str, xformat));
                    507:     fprintf(fp, "set format y \"%s\"\n", conv_text(str, yformat));
                    508:     fprintf(fp, "set format x2 \"%s\"\n", conv_text(str, x2format));
                    509:     fprintf(fp, "set format y2 \"%s\"\n", conv_text(str, y2format));
                    510:     fprintf(fp, "set format z \"%s\"\n", conv_text(str, zformat));
                    511:     fprintf(fp, "set angles %s\n",
1.1       maekawa   512:            (angles_format == ANGLES_RADIANS) ? "radians" : "degrees");
                    513:
                    514:     if (work_grid.l_type == 0)
                    515:        fputs("set nogrid\n", fp);
                    516:     else {
                    517:        if (polar_grid_angle)   /* set angle already output */
                    518:            fprintf(fp, "set grid polar %f\n", polar_grid_angle / ang2rad);
                    519:        else
                    520:            fputs("set grid nopolar\n", fp);
                    521:        fprintf(fp, "set grid %sxtics %sytics %sztics %sx2tics %sy2tics %smxtics %smytics %smztics %smx2tics %smy2tics lt %d lw %.3f, lt %d lw %.3f\n",
                    522:                work_grid.l_type & GRID_X ? "" : "no",
                    523:                work_grid.l_type & GRID_Y ? "" : "no",
                    524:                work_grid.l_type & GRID_Z ? "" : "no",
                    525:                work_grid.l_type & GRID_X2 ? "" : "no",
                    526:                work_grid.l_type & GRID_Y2 ? "" : "no",
                    527:                work_grid.l_type & GRID_MX ? "" : "no",
                    528:                work_grid.l_type & GRID_MY ? "" : "no",
                    529:                work_grid.l_type & GRID_MZ ? "" : "no",
                    530:                work_grid.l_type & GRID_MX2 ? "" : "no",
                    531:                work_grid.l_type & GRID_MY2 ? "" : "no",
                    532:                grid_lp.l_type + 1, grid_lp.l_width,
                    533:                mgrid_lp.l_type + 1, mgrid_lp.l_width);
                    534:     }
                    535:     fprintf(fp, "set key title \"%s\"\n", conv_text(str, key_title));
                    536:     switch (key) {
                    537:     case -1:{
                    538:            fputs("set key", fp);
                    539:            switch (key_hpos) {
                    540:            case TRIGHT:
                    541:                fputs(" right", fp);
                    542:                break;
                    543:            case TLEFT:
                    544:                fputs(" left", fp);
                    545:                break;
                    546:            case TOUT:
                    547:                fputs(" out", fp);
                    548:                break;
                    549:            }
                    550:            switch (key_vpos) {
                    551:            case TTOP:
                    552:                fputs(" top", fp);
                    553:                break;
                    554:            case TBOTTOM:
                    555:                fputs(" bottom", fp);
                    556:                break;
                    557:            case TUNDER:
                    558:                fputs(" below", fp);
                    559:                break;
                    560:            }
                    561:            break;
                    562:        }
                    563:     case 0:
                    564:        fputs("set nokey\n", fp);
                    565:        break;
                    566:     case 1:
                    567:        fputs("set key ", fp);
                    568:        save_position(fp, &key_user_pos);
                    569:        break;
                    570:     }
                    571:     if (key) {
                    572:        fprintf(fp, " %s %sreverse box linetype %d linewidth %.3f samplen %g spacing %g width %g\n",
                    573:                key_just == JLEFT ? "Left" : "Right",
                    574:                key_reverse ? "" : "no",
                    575:                key_box.l_type + 1, key_box.l_width, key_swidth, key_vert_factor, key_width_fix);
                    576:     }
                    577:     fputs("set nolabel\n", fp);
                    578:     for (this_label = first_label; this_label != NULL;
                    579:         this_label = this_label->next) {
                    580:        fprintf(fp, "set label %d \"%s\" at ",
                    581:                this_label->tag,
                    582:                conv_text(str, this_label->text));
                    583:        save_position(fp, &this_label->place);
                    584:
                    585:        switch (this_label->pos) {
                    586:        case LEFT:
                    587:            fputs(" left", fp);
                    588:            break;
                    589:        case CENTRE:
                    590:            fputs(" centre", fp);
                    591:            break;
                    592:        case RIGHT:
                    593:            fputs(" right", fp);
                    594:            break;
                    595:        }
                    596:        fprintf(fp, " %srotate", this_label->rotate ? "" : "no");
                    597:        if ((this_label->font)[0] != NUL)
                    598:            fprintf(fp, " font \"%s\"", this_label->font);
                    599:        /* Entry font added by DJL */
                    600:        fputc('\n', fp);
                    601:     }
                    602:     fputs("set noarrow\n", fp);
                    603:     for (this_arrow = first_arrow; this_arrow != NULL;
                    604:         this_arrow = this_arrow->next) {
                    605:        fprintf(fp, "set arrow %d from ", this_arrow->tag);
                    606:        save_position(fp, &this_arrow->start);
                    607:        fputs(" to ", fp);
                    608:        save_position(fp, &this_arrow->end);
                    609:        fprintf(fp, " %s linetype %d linewidth %.3f\n",
                    610:                this_arrow->head ? "" : " nohead",
                    611:                this_arrow->lp_properties.l_type + 1,
                    612:                this_arrow->lp_properties.l_width);
                    613:     }
                    614:     fputs("set nolinestyle\n", fp);
                    615:     for (this_linestyle = first_linestyle; this_linestyle != NULL;
                    616:         this_linestyle = this_linestyle->next) {
                    617:        fprintf(fp, "set linestyle %d ", this_linestyle->tag);
                    618:        fprintf(fp, "linetype %d linewidth %.3f pointtype %d pointsize %.3f\n",
                    619:                this_linestyle->lp_properties.l_type + 1,
                    620:                this_linestyle->lp_properties.l_width,
                    621:                this_linestyle->lp_properties.p_type + 1,
                    622:                this_linestyle->lp_properties.p_size);
                    623:     }
                    624:     fputs("set nologscale\n", fp);
                    625:     if (is_log_x)
                    626:        fprintf(fp, "set logscale x %g\n", base_log_x);
                    627:     if (is_log_y)
                    628:        fprintf(fp, "set logscale y %g\n", base_log_y);
                    629:     if (is_log_z)
                    630:        fprintf(fp, "set logscale z %g\n", base_log_z);
                    631:     if (is_log_x2)
                    632:        fprintf(fp, "set logscale x2 %g\n", base_log_x2);
                    633:     if (is_log_y2)
                    634:        fprintf(fp, "set logscale y2 %g\n", base_log_y2);
                    635:
                    636:     fprintf(fp, "\
                    637: set offsets %g, %g, %g, %g\n\
                    638: set pointsize %g\n\
                    639: set encoding %s\n\
                    640: set %spolar\n\
                    641: set %sparametric\n\
                    642: set view %g, %g, %g, %g\n\
                    643: set samples %d, %d\n\
                    644: set isosamples %d, %d\n\
                    645: set %ssurface\n\
                    646: set %scontour",
                    647:            loff, roff, toff, boff,
                    648:            pointsize,
                    649:            encoding_names[encoding],
                    650:            (polar) ? "" : "no",
                    651:            (parametric) ? "" : "no",
                    652:            surface_rot_x, surface_rot_z, surface_scale, surface_zscale,
                    653:            samples_1, samples_2,
                    654:            iso_samples_1, iso_samples_2,
                    655:            (draw_surface) ? "" : "no",
                    656:            (draw_contour) ? "" : "no");
                    657:
                    658:     switch (draw_contour) {
                    659:     case CONTOUR_NONE:
                    660:        fputc('\n', fp);
                    661:        break;
                    662:     case CONTOUR_BASE:
                    663:        fputs(" base\n", fp);
                    664:        break;
                    665:     case CONTOUR_SRF:
                    666:        fputs(" surface\n", fp);
                    667:        break;
                    668:     case CONTOUR_BOTH:
                    669:        fputs(" both\n", fp);
                    670:        break;
                    671:     }
                    672:     if (label_contours)
                    673:        fprintf(fp, "set clabel '%s'\n", contour_format);
                    674:     else
                    675:        fputs("set noclabel\n", fp);
                    676:
                    677:     fputs("set mapping ", fp);
                    678:     switch(mapping3d) {
                    679:     case MAP3D_SPHERICAL:
                    680:        fputs("spherical\n", fp);
                    681:        break;
                    682:     case MAP3D_CYLINDRICAL:
                    683:        fputs("cylindrical\n", fp);
                    684:        break;
                    685:     case MAP3D_CARTESIAN:
                    686:     default:
                    687:        fputs("cartesian\n", fp);
                    688:        break;
                    689:     }
                    690:
                    691:     if (missing_val != NULL)
1.1.1.3 ! ohara     692:        fprintf(fp, "set missing '%s'\n", missing_val);
1.1       maekawa   693:
                    694:     save_hidden3doptions(fp);
                    695:     fprintf(fp, "set cntrparam order %d\n", contour_order);
                    696:     fputs("set cntrparam ", fp);
                    697:     switch (contour_kind) {
                    698:     case CONTOUR_KIND_LINEAR:
                    699:        fputs("linear\n", fp);
                    700:        break;
                    701:     case CONTOUR_KIND_CUBIC_SPL:
                    702:        fputs("cubicspline\n", fp);
                    703:        break;
                    704:     case CONTOUR_KIND_BSPLINE:
                    705:        fputs("bspline\n", fp);
                    706:        break;
                    707:     }
                    708:     fputs("set cntrparam levels ", fp);
                    709:     switch (levels_kind) {
                    710:     case LEVELS_AUTO:
                    711:        fprintf(fp, "auto %d\n", contour_levels);
                    712:        break;
                    713:     case LEVELS_INCREMENTAL:
                    714:        fprintf(fp, "incremental %g,%g,%g\n",
                    715:                levels_list[0], levels_list[1],
                    716:                levels_list[0] + levels_list[1] * contour_levels);
                    717:        break;
                    718:     case LEVELS_DISCRETE:
                    719:        {
                    720:            int i;
                    721:            fprintf(fp, "discrete %g", levels_list[0]);
                    722:            for (i = 1; i < contour_levels; i++)
                    723:                fprintf(fp, ",%g ", levels_list[i]);
                    724:            fputc('\n', fp);
                    725:        }
                    726:     }
                    727:     fprintf(fp, "\
                    728: set cntrparam points %d\n\
                    729: set size ratio %g %g,%g\n\
                    730: set origin %g,%g\n\
                    731: set data style ",
                    732:            contour_pts,
                    733:            aspect_ratio, xsize, ysize,
                    734:            xoffset, yoffset);
                    735:
                    736:     switch (data_style) {
                    737:     case LINES:
                    738:        fputs("lines\n", fp);
                    739:        break;
                    740:     case POINTSTYLE:
                    741:        fputs("points\n", fp);
                    742:        break;
                    743:     case IMPULSES:
                    744:        fputs("impulses\n", fp);
                    745:        break;
                    746:     case LINESPOINTS:
                    747:        fputs("linespoints\n", fp);
                    748:        break;
                    749:     case DOTS:
                    750:        fputs("dots\n", fp);
                    751:        break;
                    752:     case YERRORBARS:
                    753:        fputs("yerrorbars\n", fp);
                    754:        break;
                    755:     case XERRORBARS:
                    756:        fputs("xerrorbars\n", fp);
                    757:        break;
                    758:     case XYERRORBARS:
                    759:        fputs("xyerrorbars\n", fp);
                    760:        break;
                    761:     case BOXES:
                    762:        fputs("boxes\n", fp);
                    763:        break;
                    764:     case BOXERROR:
                    765:        fputs("boxerrorbars\n", fp);
                    766:        break;
                    767:     case BOXXYERROR:
                    768:        fputs("boxxyerrorbars\n", fp);
                    769:        break;
                    770:     case STEPS:
                    771:        fputs("steps\n", fp);
                    772:        break;                  /* JG */
                    773:     case FSTEPS:
                    774:        fputs("fsteps\n", fp);
                    775:        break;                  /* HOE */
                    776:     case HISTEPS:
                    777:        fputs("histeps\n", fp);
                    778:        break;                  /* CAC */
                    779:     case VECTOR:
                    780:        fputs("vector\n", fp);
                    781:        break;
                    782:     case FINANCEBARS:
                    783:        fputs("financebars\n", fp);
                    784:        break;
                    785:     case CANDLESTICKS:
                    786:        fputs("candlesticks\n", fp);
                    787:        break;
                    788:     }
                    789:     fputs("set function style ", fp);
                    790:     switch (func_style) {
                    791:     case LINES:
                    792:        fputs("lines\n", fp);
                    793:        break;
                    794:     case POINTSTYLE:
                    795:        fputs("points\n", fp);
                    796:        break;
                    797:     case IMPULSES:
                    798:        fputs("impulses\n", fp);
                    799:        break;
                    800:     case LINESPOINTS:
                    801:        fputs("linespoints\n", fp);
                    802:        break;
                    803:     case DOTS:
                    804:        fputs("dots\n", fp);
                    805:        break;
                    806:     case YERRORBARS:
                    807:        fputs("yerrorbars\n", fp);
                    808:        break;
                    809:     case XERRORBARS:
                    810:        fputs("xerrorbars\n", fp);
                    811:        break;
                    812:     case XYERRORBARS:
                    813:        fputs("xyerrorbars\n", fp);
                    814:        break;
                    815:     case BOXXYERROR:
                    816:        fputs("boxxyerrorbars\n", fp);
                    817:        break;
                    818:     case BOXES:
                    819:        fputs("boxes\n", fp);
                    820:        break;
                    821:     case BOXERROR:
                    822:        fputs("boxerrorbars\n", fp);
                    823:        break;
                    824:     case STEPS:
                    825:        fputs("steps\n", fp);
                    826:        break;                  /* JG */
                    827:     case FSTEPS:
                    828:        fputs("fsteps\n", fp);
                    829:        break;                  /* HOE */
                    830:     case HISTEPS:
                    831:        fputs("histeps\n", fp);
                    832:        break;                  /* CAC */
                    833:     case VECTOR:
                    834:        fputs("vector\n", fp);
                    835:        break;
                    836:     case FINANCEBARS:
                    837:        fputs("financebars\n", fp);
                    838:        break;
                    839:     case CANDLESTICKS:
                    840:        fputs("candlesticks\n", fp);
                    841:        break;
                    842:     default:
                    843:         /* HBB: default case demanded by gcc, still needed ?? */
                    844:        fputs("---error!---\n", fp);
                    845:     }
                    846:
                    847:     fprintf(fp, "\
                    848: set xzeroaxis lt %d lw %.3f\n\
                    849: set x2zeroaxis lt %d lw %.3f\n\
                    850: set yzeroaxis lt %d lw %.3f\n\
                    851: set y2zeroaxis lt %d lw %.3f\n\
                    852: set tics %s\n\
                    853: set ticslevel %g\n\
                    854: set ticscale %g %g\n",
                    855:            xzeroaxis.l_type + 1, xzeroaxis.l_width,
                    856:            x2zeroaxis.l_type + 1, x2zeroaxis.l_width,
                    857:            yzeroaxis.l_type + 1, yzeroaxis.l_width,
                    858:            y2zeroaxis.l_type + 1, y2zeroaxis.l_width,
                    859:            (tic_in) ? "in" : "out",
                    860:            ticslevel,
                    861:            ticscale, miniticscale);
                    862:
                    863: #define SAVE_XYZLABEL(name,lab) { \
                    864:   fprintf(fp, "set %s \"%s\" %f,%f ", \
                    865:     name, conv_text(str,lab.text),lab.xoffset,lab.yoffset); \
                    866:   fprintf(fp, " \"%s\"\n", conv_text(str, lab.font)); \
                    867: }
                    868:
                    869:
                    870: #define SAVE_MINI(name,m,freq) switch(m&TICS_MASK) { \
                    871:  case 0: fprintf(fp, "set no%s\n", name); break; \
                    872:  case MINI_AUTO: fprintf(fp, "set %s\n",name); break; \
                    873:  case MINI_DEFAULT: fprintf(fp, "set %s default\n",name); break; \
                    874:  case MINI_USER: fprintf(fp, "set %s %f\n", name, freq); break; \
                    875: }
                    876:     SAVE_MINI("mxtics", mxtics, mxtfreq)
                    877:        SAVE_MINI("mytics", mytics, mytfreq)
                    878:        SAVE_MINI("mx2tics", mx2tics, mx2tfreq)
                    879:        SAVE_MINI("my2tics", my2tics, my2tfreq)
                    880:        save_tics(fp, xtics, FIRST_X_AXIS, &xticdef, rotate_xtics, "x");
                    881:     save_tics(fp, ytics, FIRST_Y_AXIS, &yticdef, rotate_ytics, "y");
                    882:     save_tics(fp, ztics, FIRST_Z_AXIS, &zticdef, rotate_ztics, "z");
                    883:     save_tics(fp, x2tics, SECOND_X_AXIS, &x2ticdef, rotate_x2tics, "x2");
                    884:     save_tics(fp, y2tics, SECOND_Y_AXIS, &y2ticdef, rotate_y2tics, "y2");
                    885:     SAVE_XYZLABEL("title", title);
                    886:
                    887:     fprintf(fp, "set %s \"%s\" %s %srotate %f,%f ",
                    888:            "timestamp", conv_text(str, timelabel.text),
                    889:            (timelabel_bottom ? "bottom" : "top"),
                    890:            (timelabel_rotate ? "" : "no"),
                    891:            timelabel.xoffset, timelabel.yoffset);
                    892:     fprintf(fp, " \"%s\"\n", conv_text(str, timelabel.font));
                    893:
                    894:     save_range(fp, R_AXIS, rmin, rmax, autoscale_r, "r");
                    895:     save_range(fp, T_AXIS, tmin, tmax, autoscale_t, "t");
                    896:     save_range(fp, U_AXIS, umin, umax, autoscale_u, "u");
                    897:     save_range(fp, V_AXIS, vmin, vmax, autoscale_v, "v");
                    898:
                    899:     SAVE_XYZLABEL("xlabel", xlabel);
                    900:     SAVE_XYZLABEL("x2label", x2label);
                    901:
                    902:     if (strlen(timefmt)) {
                    903:        fprintf(fp, "set timefmt \"%s\"\n", conv_text(str, timefmt));
                    904:     }
                    905:     save_range(fp, FIRST_X_AXIS, xmin, xmax, autoscale_x, "x");
                    906:     save_range(fp, SECOND_X_AXIS, x2min, x2max, autoscale_x2, "x2");
                    907:
                    908:     SAVE_XYZLABEL("ylabel", ylabel);
                    909:     SAVE_XYZLABEL("y2label", y2label);
                    910:
                    911:     save_range(fp, FIRST_Y_AXIS, ymin, ymax, autoscale_y, "y");
                    912:     save_range(fp, SECOND_Y_AXIS, y2min, y2max, autoscale_y2, "y2");
                    913:
                    914:     SAVE_XYZLABEL("zlabel", zlabel);
                    915:     save_range(fp, FIRST_Z_AXIS, zmin, zmax, autoscale_z, "z");
                    916:
                    917:     fprintf(fp, "set zero %g\n", zero);
                    918:     fprintf(fp, "set lmargin %d\nset bmargin %d\nset rmargin %d\nset tmargin %d\n",
                    919:            lmargin, bmargin, rmargin, tmargin);
                    920:
                    921:     fprintf(fp, "set locale \"%s\"\n", cur_locale);
                    922: }
                    923:
                    924: static void save_tics(fp, where, axis, tdef, rotate, text)
                    925: FILE *fp;
                    926: int where;
                    927: int axis;
                    928: struct ticdef *tdef;
                    929: TBOOLEAN rotate;
                    930: char *text;
                    931: {
                    932:     char str[MAX_LINE_LEN + 1];
                    933:
                    934:     if (where == NO_TICS) {
                    935:        fprintf(fp, "set no%stics\n", text);
                    936:        return;
                    937:     }
                    938:     fprintf(fp, "set %stics %s %smirror %srotate ", text,
                    939:            (where & TICS_MASK) == TICS_ON_AXIS ? "axis" : "border",
                    940:            (where & TICS_MIRROR) ? "" : "no", rotate ? "" : "no");
                    941:     switch (tdef->type) {
                    942:     case TIC_COMPUTED:{
                    943:            fputs("autofreq ", fp);
                    944:            break;
                    945:        }
                    946:     case TIC_MONTH:{
                    947:            fprintf(fp, "\nset %smtics", text);
                    948:            break;
                    949:        }
                    950:     case TIC_DAY:{
                    951:            fprintf(fp, "\nset %cdtics", axis);
                    952:            break;
                    953:        }
                    954:     case TIC_SERIES:
                    955:        if (datatype[axis] == TIME) {
                    956:            if (tdef->def.series.start != -VERYLARGE) {
                    957:                char fd[26];
                    958:                gstrftime(fd, 24, timefmt, (double) tdef->def.series.start);
                    959:                fprintf(fp, "\"%s\",", conv_text(str, fd));
                    960:            }
                    961:            fprintf(fp, "%g", tdef->def.series.incr);
                    962:
                    963:            if (tdef->def.series.end != VERYLARGE) {
                    964:                char td[26];
                    965:                gstrftime(td, 24, timefmt, (double) tdef->def.series.end);
                    966:                fprintf(fp, ",\"%s\"", conv_text(str, td));
                    967:            }
                    968:        } else {                /* !TIME */
                    969:
                    970:            if (tdef->def.series.start != -VERYLARGE)
                    971:                fprintf(fp, "%g,", tdef->def.series.start);
                    972:            fprintf(fp, "%g", tdef->def.series.incr);
                    973:            if (tdef->def.series.end != VERYLARGE)
                    974:                fprintf(fp, ",%g", tdef->def.series.end);
                    975:        }
                    976:
                    977:        break;
                    978:
                    979:     case TIC_USER:{
                    980:            register struct ticmark *t;
                    981:            int flag_time;
                    982:            flag_time = (datatype[axis] == TIME);
                    983:            fputs(" (", fp);
                    984:            for (t = tdef->def.user; t != NULL; t = t->next) {
                    985:                if (t->label)
                    986:                    fprintf(fp, "\"%s\" ", conv_text(str, t->label));
                    987:                if (flag_time) {
                    988:                    char td[26];
                    989:                    gstrftime(td, 24, timefmt, (double) t->position);
                    990:                    fprintf(fp, "\"%s\"", conv_text(str, td));
                    991:                } else {
                    992:                    fprintf(fp, "%g", t->position);
                    993:                }
                    994:                if (t->next) {
                    995:                    fputs(", ", fp);
                    996:                }
                    997:            }
                    998:            fputs(")", fp);
                    999:            break;
                   1000:        }
                   1001:     }
                   1002:     putc('\n', fp);
                   1003: }
                   1004:
                   1005: static void save_position(fp, pos)
                   1006: FILE *fp;
                   1007: struct position *pos;
                   1008: {
                   1009:     static char *msg[] =
1.1.1.3 ! ohara    1010:     {"first ", "second ", "graph ", "screen "};
1.1       maekawa  1011:
                   1012:     assert(first_axes == 0 && second_axes == 1 && graph == 2 && screen == 3);
                   1013:
                   1014:     fprintf(fp, "%s%g, %s%g, %s%g",
                   1015:            pos->scalex == first_axes ? "" : msg[pos->scalex], pos->x,
                   1016:            pos->scaley == pos->scalex ? "" : msg[pos->scaley], pos->y,
                   1017:            pos->scalez == pos->scaley ? "" : msg[pos->scalez], pos->z);
                   1018: }
                   1019:
                   1020: void load_file(fp, name, can_do_args)
                   1021: FILE *fp;
                   1022: char *name;
                   1023: TBOOLEAN can_do_args;
                   1024: {
                   1025:     register int len;
                   1026:
                   1027:     int start, left;
                   1028:     int more;
                   1029:     int stop = FALSE;
                   1030:
                   1031:     lf_push(fp);               /* save state for errors and recursion */
                   1032:     do_load_arg_substitution = can_do_args;
                   1033:
                   1034:     if (fp == (FILE *) NULL) {
                   1035:        /* HBB 980311: alloc() it, to save valuable stack space: */
                   1036:        char *errbuf = gp_alloc(BUFSIZ, "load_file errorstring");
                   1037:        (void) sprintf(errbuf, "Cannot open %s file '%s'",
                   1038:                       can_do_args ? "call" : "load", name);
                   1039:        os_error(errbuf, c_token);
                   1040:        free(errbuf);
                   1041:     } else if (fp == stdin) {
                   1042:        /* DBT 10-6-98  go interactive if "-" named as load file */
                   1043:        interactive = TRUE;
                   1044:        while(!com_line())
                   1045:            ;
                   1046:     } else {
                   1047:        /* go into non-interactive mode during load */
                   1048:        /* will be undone below, or in load_file_error */
                   1049:        interactive = FALSE;
                   1050:        inline_num = 0;
                   1051:        infile_name = name;
                   1052:
                   1053:        if (can_do_args) {
                   1054:            int aix = 0;
                   1055:            while (++c_token < num_tokens && aix <= 9) {
                   1056:                if (isstring(c_token))
                   1057:                    m_quote_capture(&call_args[aix++], c_token, c_token);
                   1058:                else
                   1059:                    m_capture(&call_args[aix++], c_token, c_token);
                   1060:            }
                   1061:
                   1062: /*         A GNUPLOT "call" command can have up to _10_ arguments named "$0"
                   1063:    to "$9".  After reading the 10th argument (i.e.: "$9") the variable
                   1064:    'aix' contains the value '10' because of the 'aix++' construction
                   1065:    in '&call_args[aix++]'.  So I think the following test of 'aix'
                   1066:    should be done against '10' instead of '9'.                (JFi) */
                   1067:
                   1068: /*              if (c_token >= num_tokens && aix > 9) */
                   1069:            if (c_token >= num_tokens && aix > 10)
                   1070:                int_error("too many arguments for CALL <file>", ++c_token);
                   1071:        }
                   1072:        while (!stop) {         /* read all commands in file */
                   1073:            /* read one command */
                   1074:            left = input_line_len;
                   1075:            start = 0;
                   1076:            more = TRUE;
                   1077:
                   1078:            while (more) {
                   1079:                if (fgets(&(input_line[start]), left, fp) == (char *) NULL) {
                   1080:                    stop = TRUE;        /* EOF in file */
                   1081:                    input_line[start] = '\0';
                   1082:                    more = FALSE;
                   1083:                } else {
                   1084:                    inline_num++;
                   1085:                    len = strlen(input_line) - 1;
                   1086:                    if (input_line[len] == '\n') {      /* remove any newline */
                   1087:                        input_line[len] = '\0';
                   1088:                        /* Look, len was 1-1 = 0 before, take care here! */
                   1089:                        if (len > 0)
                   1090:                            --len;
                   1091:                        if (input_line[len] == '\r') {  /* remove any carriage return */
                   1092:                            input_line[len] = NUL;
                   1093:                            if (len > 0)
                   1094:                                --len;
                   1095:                        }
                   1096:                    }
                   1097:                     else if (len + 2 >= left) {
                   1098:                        extend_input_line();
                   1099:                        left = input_line_len - len - 1;
                   1100:                        start = len + 1;
                   1101:                        continue;       /* don't check for '\' */
                   1102:                    }
                   1103:                    if (input_line[len] == '\\') {
                   1104:                        /* line continuation */
                   1105:                        start = len;
                   1106:                        left = input_line_len - start;
                   1107:                    } else
                   1108:                        more = FALSE;
                   1109:                }
                   1110:            }
                   1111:
                   1112:            if (strlen(input_line) > 0) {
                   1113:                if (can_do_args) {
                   1114:                    register int il = 0;
                   1115:                    register char *rl;
1.1.1.3 ! ohara    1116:                    char *raw_line = gp_strdup(input_line);
1.1       maekawa  1117:
1.1.1.3 ! ohara    1118:                    rl = raw_line;
1.1       maekawa  1119:                    *input_line = '\0';
                   1120:                    while (*rl) {
                   1121:                        register int aix;
                   1122:                        if (*rl == '$'
                   1123:                            && ((aix = *(++rl)) != 0)   /* HBB 980308: quiet BCC warning */
                   1124:                            &&aix >= '0' && aix <= '9') {
                   1125:                            if (call_args[aix -= '0']) {
                   1126:                                len = strlen(call_args[aix]);
                   1127:                                while (input_line_len - il < len + 1) {
                   1128:                                    extend_input_line();
                   1129:                                }
                   1130:                                strcpy(input_line + il, call_args[aix]);
                   1131:                                il += len;
                   1132:                            }
                   1133:                        } else {
                   1134:                            /* substitute for $<n> here */
                   1135:                            if (il + 1 > input_line_len) {
                   1136:                                extend_input_line();
                   1137:                            }
                   1138:                            input_line[il++] = *rl;
                   1139:                        }
                   1140:                        rl++;
                   1141:                    }
                   1142:                    if (il + 1 > input_line_len) {
                   1143:                        extend_input_line();
                   1144:                    }
                   1145:                    input_line[il] = '\0';
                   1146:                    free(raw_line);
                   1147:                }
                   1148:                screen_ok = FALSE;      /* make sure command line is
                   1149:                                           echoed on error */
1.1.1.2   maekawa  1150:                if (do_line())
                   1151:                    stop = TRUE;
1.1       maekawa  1152:            }
                   1153:        }
                   1154:     }
                   1155:
                   1156:     /* pop state */
                   1157:     (void) lf_pop();           /* also closes file fp */
                   1158: }
                   1159:
                   1160: /* pop from load_file state stack */
                   1161: static TBOOLEAN                        /* FALSE if stack was empty */
                   1162:  lf_pop()
                   1163: {                              /* called by load_file and load_file_error */
                   1164:     LFS *lf;
                   1165:
                   1166:     if (lf_head == NULL)
                   1167:        return (FALSE);
                   1168:     else {
                   1169:        int argindex;
                   1170:        lf = lf_head;
                   1171:        if (lf->fp != (FILE *)NULL && lf->fp != stdin) {
                   1172:            /* DBT 10-6-98  do not close stdin in the case
                   1173:             * that "-" is named as a load file
                   1174:             */
                   1175:            (void) fclose(lf->fp);
                   1176:        }
                   1177:        for (argindex = 0; argindex < 10; argindex++) {
                   1178:            if (call_args[argindex]) {
                   1179:                free(call_args[argindex]);
                   1180:            }
                   1181:            call_args[argindex] = lf->call_args[argindex];
                   1182:        }
                   1183:        do_load_arg_substitution = lf->do_load_arg_substitution;
                   1184:        interactive = lf->interactive;
                   1185:        inline_num = lf->inline_num;
                   1186:        infile_name = lf->name;
                   1187:        lf_head = lf->prev;
                   1188:        free((char *) lf);
                   1189:        return (TRUE);
                   1190:     }
                   1191: }
                   1192:
                   1193: /* push onto load_file state stack */
                   1194: /* essentially, we save information needed to undo the load_file changes */
                   1195: static void lf_push(fp)                /* called by load_file */
                   1196: FILE *fp;
                   1197: {
                   1198:     LFS *lf;
                   1199:     int argindex;
                   1200:
1.1.1.3 ! ohara    1201:     lf = (LFS *) gp_alloc(sizeof(LFS), (char *) NULL);
1.1       maekawa  1202:     if (lf == (LFS *) NULL) {
                   1203:        if (fp != (FILE *) NULL)
                   1204:            (void) fclose(fp);  /* it won't be otherwise */
                   1205:        int_error("not enough memory to load file", c_token);
                   1206:     }
                   1207:     lf->fp = fp;               /* save this file pointer */
                   1208:     lf->name = infile_name;    /* save current name */
                   1209:     lf->interactive = interactive;     /* save current state */
                   1210:     lf->inline_num = inline_num;       /* save current line number */
                   1211:     lf->do_load_arg_substitution = do_load_arg_substitution;
                   1212:     for (argindex = 0; argindex < 10; argindex++) {
                   1213:        lf->call_args[argindex] = call_args[argindex];
                   1214:        call_args[argindex] = NULL;     /* initially no args */
                   1215:     }
                   1216:     lf->prev = lf_head;                /* link to stack */
                   1217:     lf_head = lf;
                   1218: }
                   1219:
                   1220: /* used for reread  vsnyder@math.jpl.nasa.gov */
                   1221: FILE *lf_top()
                   1222: {
                   1223:     if (lf_head == (LFS *) NULL)
                   1224:        return ((FILE *) NULL);
                   1225:     return (lf_head->fp);
                   1226: }
                   1227:
                   1228: /* called from main */
                   1229: void load_file_error()
                   1230: {
                   1231:     /* clean up from error in load_file */
                   1232:     /* pop off everything on stack */
                   1233:     while (lf_pop());
                   1234: }
                   1235:
                   1236: /* find char c in string str; return p such that str[p]==c;
                   1237:  * if c not in str then p=strlen(str)
                   1238:  */
                   1239: int instring(str, c)
                   1240: char *str;
                   1241: int c;
                   1242: {
                   1243:     int pos = 0;
                   1244:
                   1245:     while (str != NULL && *str != NUL && c != *str) {
                   1246:        str++;
                   1247:        pos++;
                   1248:     }
                   1249:     return (pos);
                   1250: }
                   1251:
                   1252: void show_functions()
                   1253: {
                   1254:     register struct udft_entry *udf = first_udf;
                   1255:
                   1256:     fputs("\n\tUser-Defined Functions:\n", stderr);
                   1257:
                   1258:     while (udf) {
                   1259:        if (udf->definition)
                   1260:            fprintf(stderr, "\t%s\n", udf->definition);
                   1261:        else
                   1262:            fprintf(stderr, "\t%s is undefined\n", udf->udf_name);
                   1263:        udf = udf->next_udf;
                   1264:     }
                   1265: }
                   1266:
                   1267:
                   1268: void show_at()
                   1269: {
                   1270:     (void) putc('\n', stderr);
                   1271:     disp_at(temp_at(), 0);
                   1272: }
                   1273:
                   1274:
                   1275: void disp_at(curr_at, level)
                   1276: struct at_type *curr_at;
                   1277: int level;
                   1278: {
                   1279:     register int i, j;
                   1280:     register union argument *arg;
                   1281:
                   1282:     for (i = 0; i < curr_at->a_count; i++) {
                   1283:        (void) putc('\t', stderr);
                   1284:        for (j = 0; j < level; j++)
                   1285:            (void) putc(' ', stderr);   /* indent */
                   1286:
                   1287:        /* print name of instruction */
                   1288:
                   1289:        fputs(ft[(int) (curr_at->actions[i].index)].f_name, stderr);
                   1290:        arg = &(curr_at->actions[i].arg);
                   1291:
                   1292:        /* now print optional argument */
                   1293:
                   1294:        switch (curr_at->actions[i].index) {
                   1295:        case PUSH:
                   1296:            fprintf(stderr, " %s\n", arg->udv_arg->udv_name);
                   1297:            break;
                   1298:        case PUSHC:
                   1299:            (void) putc(' ', stderr);
                   1300:            disp_value(stderr, &(arg->v_arg));
                   1301:            (void) putc('\n', stderr);
                   1302:            break;
                   1303:        case PUSHD1:
                   1304:            fprintf(stderr, " %c dummy\n",
                   1305:                    arg->udf_arg->udf_name[0]);
                   1306:            break;
                   1307:        case PUSHD2:
                   1308:            fprintf(stderr, " %c dummy\n",
                   1309:                    arg->udf_arg->udf_name[1]);
                   1310:            break;
                   1311:        case CALL:
                   1312:            fprintf(stderr, " %s", arg->udf_arg->udf_name);
                   1313:            if (level < 6) {
                   1314:                if (arg->udf_arg->at) {
                   1315:                    (void) putc('\n', stderr);
                   1316:                    disp_at(arg->udf_arg->at, level + 2);       /* recurse! */
                   1317:                } else
                   1318:                    fputs(" (undefined)\n", stderr);
                   1319:            } else
                   1320:                (void) putc('\n', stderr);
                   1321:            break;
                   1322:        case CALLN:
                   1323:            fprintf(stderr, " %s", arg->udf_arg->udf_name);
                   1324:            if (level < 6) {
                   1325:                if (arg->udf_arg->at) {
                   1326:                    (void) putc('\n', stderr);
                   1327:                    disp_at(arg->udf_arg->at, level + 2);       /* recurse! */
                   1328:                } else
                   1329:                    fputs(" (undefined)\n", stderr);
                   1330:            } else
                   1331:                (void) putc('\n', stderr);
                   1332:            break;
                   1333:        case JUMP:
                   1334:        case JUMPZ:
                   1335:        case JUMPNZ:
                   1336:        case JTERN:
                   1337:            fprintf(stderr, " +%d\n", arg->j_arg);
                   1338:            break;
                   1339:        case DOLLARS:
                   1340:            fprintf(stderr, " %d\n", arg->v_arg.v.int_val);
                   1341:            break;
                   1342:        default:
                   1343:            (void) putc('\n', stderr);
                   1344:        }
                   1345:     }
                   1346: }
                   1347:
                   1348: /* find max len of keys and count keys with len > 0 */
                   1349:
                   1350: int find_maxl_keys(plots, count, kcnt)
                   1351: struct curve_points *plots;
                   1352: int count, *kcnt;
                   1353: {
                   1354:     int mlen, len, curve, cnt;
                   1355:     register struct curve_points *this_plot;
                   1356:
                   1357:     mlen = cnt = 0;
                   1358:     this_plot = plots;
                   1359:     for (curve = 0; curve < count; this_plot = this_plot->next_cp, curve++)
                   1360:        if (this_plot->title
                   1361:            && ((len = /*assign */ strlen(this_plot->title)) != 0)      /* HBB 980308: quiet BCC warning */
                   1362:            ) {
                   1363:            cnt++;
                   1364:            if (len > mlen)
                   1365:                mlen = strlen(this_plot->title);
                   1366:        }
                   1367:     if (kcnt != NULL)
                   1368:        *kcnt = cnt;
                   1369:     return (mlen);
                   1370: }
                   1371:
                   1372:
                   1373: /* calculate the number and max-width of the keys for an splot.
                   1374:  * Note that a blank line is issued after each set of contours
                   1375:  */
                   1376: int find_maxl_keys3d(plots, count, kcnt)
                   1377: struct surface_points *plots;
                   1378: int count, *kcnt;
                   1379: {
                   1380:     int mlen, len, surf, cnt;
                   1381:     struct surface_points *this_plot;
                   1382:
                   1383:     mlen = cnt = 0;
                   1384:     this_plot = plots;
                   1385:     for (surf = 0; surf < count; this_plot = this_plot->next_sp, surf++) {
                   1386:
                   1387:        /* we draw a main entry if there is one, and we are
                   1388:         * drawing either surface, or unlabelled contours
                   1389:         */
                   1390:        if (this_plot->title && *this_plot->title &&
                   1391:            (draw_surface || (draw_contour && !label_contours))) {
                   1392:            ++cnt;
                   1393:            len = strlen(this_plot->title);
                   1394:            if (len > mlen)
                   1395:                mlen = len;
                   1396:        }
                   1397:        if (draw_contour && label_contours && this_plot->contours != NULL) {
                   1398:            len = find_maxl_cntr(this_plot->contours, &cnt);
                   1399:            if (len > mlen)
                   1400:                mlen = len;
                   1401:        }
                   1402:     }
                   1403:
                   1404:     if (kcnt != NULL)
                   1405:        *kcnt = cnt;
                   1406:     return (mlen);
                   1407: }
                   1408:
                   1409: static int find_maxl_cntr(contours, count)
                   1410: struct gnuplot_contours *contours;
                   1411: int *count;
                   1412: {
                   1413:     register int cnt;
                   1414:     register int mlen, len;
                   1415:     register struct gnuplot_contours *cntrs = contours;
                   1416:
                   1417:     mlen = cnt = 0;
                   1418:     while (cntrs) {
                   1419:        if (label_contours && cntrs->isNewLevel) {
                   1420:            len = strlen(cntrs->label);
                   1421:            if (len)
                   1422:                cnt++;
                   1423:            if (len > mlen)
                   1424:                mlen = len;
                   1425:        }
                   1426:        cntrs = cntrs->next;
                   1427:     }
                   1428:     *count += cnt;
                   1429:     return (mlen);
                   1430: }
                   1431:
                   1432: static void save_range(fp, axis, min, max, autosc, text)
                   1433: FILE *fp;
                   1434: int axis;
                   1435: double min, max;
                   1436: TBOOLEAN autosc;
                   1437: char *text;
                   1438: {
                   1439:     int i;
                   1440:
                   1441:     i = axis;
                   1442:     fprintf(fp, "set %srange [ ", text);
                   1443:     if (autosc & 1) {
                   1444:        putc('*', fp);
                   1445:     } else {
                   1446:        SAVE_NUM_OR_TIME(fp, min, axis);
                   1447:     }
                   1448:     fputs(" : ", fp);
                   1449:     if (autosc & 2) {
                   1450:        putc('*', fp);
                   1451:     } else {
                   1452:        SAVE_NUM_OR_TIME(fp, max, axis);
                   1453:     }
                   1454:
                   1455:     fprintf(fp, " ] %sreverse %swriteback",
                   1456:            range_flags[axis] & RANGE_REVERSE ? "" : "no",
                   1457:            range_flags[axis] & RANGE_WRITEBACK ? "" : "no");
                   1458:
                   1459:     if (autosc) {
                   1460:        /* add current (hidden) range as comments */
                   1461:        fputs("  # (currently [", fp);
                   1462:        if (autosc & 1) {
                   1463:            SAVE_NUM_OR_TIME(fp, min, axis);
                   1464:        }
                   1465:        putc(':', fp);
                   1466:        if (autosc & 2) {
                   1467:            SAVE_NUM_OR_TIME(fp, max, axis);
                   1468:        }
                   1469:        fputs("] )", fp);
                   1470:     }
                   1471:     putc('\n', fp);
                   1472: }
                   1473:
                   1474: /* check user defined format strings for valid double conversions */
                   1475: TBOOLEAN valid_format(format)
                   1476: const char *format;
                   1477: {
                   1478:     for (;;) {
                   1479:        if (!(format = strchr(format, '%')))    /* look for format spec  */
                   1480:            return TRUE;        /* passed Test           */
                   1481:        do {                    /* scan format statement */
                   1482:            format++;
                   1483:        } while (strchr("+-#0123456789.", *format));
                   1484:
                   1485:        switch (*format) {      /* Now at format modifier */
                   1486:        case '*':               /* Ignore '*' statements */
                   1487:        case '%':               /* Char   '%' itself     */
                   1488:            format++;
                   1489:            continue;
                   1490:        case 'l':               /* Now we found it !!! */
                   1491:            if (!strchr("fFeEgG", format[1]))   /* looking for a valid format */
                   1492:                return FALSE;
                   1493:            format++;
                   1494:            break;
                   1495:        default:
                   1496:            return FALSE;
                   1497:        }
                   1498:     }
                   1499: }

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