home *** CD-ROM | disk | FTP | other *** search
- /* plot, a set of unix plot utilities.
- Copyright (C) 1989 Free Software Foundation, Inc.
-
- Plot is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY. No author or distributor accepts responsibility to
- anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing.
- Refer to the GNU General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute plot,
- but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with plot so you can know your rights and responsibilities. It
- should be in a file named COPYING. Among other things, the copyright
- notice and this notice must be preserved on all copies. */
-
- /* This file is the main routine for graph. */
-
- #include "getopt.h"
- #include "sys-defines.h"
- #include "libplot.h"
- #include "extern.h"
- #include "../COPYING"
-
- #define ARG_NONE 0
- #define ARG_REQUIRED 1
- #define ARG_OPTIONAL 2
-
- struct option long_options[] =
- {
- {"auto-abscissa", ARG_OPTIONAL, NULL, 'a'},
- {"bottom-move-margin", ARG_REQUIRED, NULL, 'u'},
- {"break-non-monotone", ARG_NONE, NULL, 'M'},
- {"break-on-labels", ARG_NONE, NULL, 'b'},
- {"data-format", ARG_REQUIRED, NULL, 'd'},
- {"dont-round-to-next-tick", ARG_NONE, NULL, 'R'},
- {"fontsize", ARG_REQUIRED, NULL, 'f'},
- {"grid", ARG_REQUIRED, NULL, 'g'},
- {"height-plot", ARG_REQUIRED, NULL, 'h'},
- {"help", ARG_NONE, NULL, 'H'},
- {"linestyle", ARG_REQUIRED, NULL, 'm'},
- {"log-axis", ARG_REQUIRED, NULL, 'l'},
- {"no-label", ARG_REQUIRED, NULL, 'N'},
- {"point-label", ARG_NONE, NULL, 'c'},
- {"right-margin-posn", ARG_REQUIRED, NULL, 'r'},
- {"save-screen", ARG_NONE, NULL, 's'},
- {"symbol", ARG_OPTIONAL, NULL, 'S'},
- {"ticksize", ARG_NONE, NULL, 'T'},
- {"toptitle", ARG_REQUIRED, NULL, 'L'},
- {"transpose", ARG_REQUIRED, NULL, 't'},
- {"version", ARG_NONE, NULL, 'v'},
- {"width-plot", ARG_REQUIRED, NULL, 'w'},
- {"xlimits", ARG_OPTIONAL, NULL, 'x'},
- {"xtitle", ARG_REQUIRED, NULL, 'X'},
- {"ylimits", ARG_OPTIONAL, NULL, 'y'},
- {"ytitle", ARG_REQUIRED, NULL, 'Y'},
- /* Long options with no equivalent short option alias */
- {"debug", ARG_NONE, NULL, 'd' << 8},
- {"fontname", ARG_REQUIRED, NULL, 'f' << 8},
- {"margin", ARG_REQUIRED, NULL, 'm' << 8},
- {"copying", ARG_NONE, NULL, 'c' << 8},
- {"warranty", ARG_NONE, NULL, 'w' << 8},
- {"high-byte-first", ARG_NONE, NULL, 'H' << 8},
- {"low-byte-first", ARG_NONE, NULL, 'L' << 8},
- {NULL, 0, 0, 0}
- };
-
- const char *progname; /* Program name */
-
- VOIDPTR *
- do_malloc (length)
- int length;
- {
- VOIDPTR *p;
- p = (VOIDPTR *) malloc (length);
-
- if (p <= (VOIDPTR *) NULL)
- {
- perror ("malloc failed");
- exit (-1);
- }
- return p;
- }
-
-
- VOIDPTR *
- do_realloc (p, length)
- VOIDPTR *p;
- int length;
- {
- p = (VOIDPTR *) realloc (p, length);
-
- if (p <= (VOIDPTR *) NULL)
- {
- perror ("realloc failed");
- exit (-1);
- }
- return p;
- }
-
-
- void
- usage ()
- {
- int i;
- fprintf (stderr, "usage: %s", progname);
- for (i=0; long_options[i].name; i++)
- {
- fprintf (stderr, " [+%s", long_options[i].name);
- if (isprint (long_options[i].val))
- fprintf (stderr, "|-%c", long_options[i].val);
- if (long_options[i].has_arg == ARG_REQUIRED)
- fprintf (stderr, " arg]");
- else
- fprintf (stderr, "]");
- }
- fprintf (stderr, "\n");
- }
-
- void
- display_version ()
- {
- (void) fprintf (stderr, "\
- graph version %s, Copyright (C) 1989 Free Software Foundation, Inc.\n\
- graph comes with ABSOLUTELY NO WARRANTY; type `graph +warranty' for\n\
- details. This is free software, and you are welcome to redistribute it.\n\
- Type `graph +copying' to view the copying conditions.\n\n", VERS);
- }
-
- int
- main (argc, argv)
- int argc;
- char *argv[];
- {
- int i;
- int option;
- int opt_index;
- int errcnt = 0; /* errors encountered */
- int show_version = 0; /* remember to show version message */
- int show_usage = 0; /* remember whether to output usage message. */
- int show_copying = 0; /* remember to show copying conditions */
- int opened = 0; /* nonzero if we have opened named input file */
- int debug = 0; /* debug option flag */
- int break_flag = 0; /* non-zero means break lines after labels. */
- int m_break_flag = 0; /* non-zero means break when x decreases. */
- int linemode_index = 0; /* the line style for curves */
- int log_axis = 0; /* no log axes by default */
- int omit_labels = 0; /* label both axes by default */
- int transpose_axes = 0; /* nonzero means -x applies to y axis. */
- data_type data_spec = ASCII_DATA; /* by default we read ascii data */
- grid_type grid_spec = FULL_GRID; /* by default we plot a full grid */
- int symbol_index = -1; /* 0=none, 1=plus, 2=cross, 3=star */
- double symbol_size = .01; /* fractional size of the symbols */
- double tick_size = .02; /* fractional size of the tick marks */
- int default_fontsize = -1; /* size in printers points for text.
- -1 means use the default. */
- point_struct *p; /* an array of points */
- int points_length; /* the size of the points array */
- int no_of_points = 0; /* the number of points in the array */
- int save_screen = 0; /* save the screen == do not erase */
- int auto_abscissa = 0; /* flag to turn on automatic generation
- of abscissa */
- int round_to_next_tick = 1; /* flag to specify rounding the limits
- to the next tick mark */
- double x_start = 0.; /* start and increment of auto abscissa */
- double delta_x = 1.;
- double margin_below = .1; /* fractional margin below the plot */
- double margin_left = .1; /* fractional margin left of the plot */
- double plot_height = .8; /* fractional height of the plot */
- double plot_width = .8; /* fractional width of the plot */
- char *point_label = 0; /* label for each point, 0 means no label. */
- char *x_label = 0; /* label for the x axis, 0 means no label. */
- char *y_label = 0; /* label for the y axis, 0 means no label. */
- char *top_label = 0; /* label above the plot, 0 means no label. */
- double margin = 0.; /* fractional margin between data and box */
-
- /* flags to indicate which limits the user has specified */
- int spec_min_x = 0, spec_min_y = 0, spec_max_x = 0, spec_max_y = 0;
- int spec_spacing_x = 0, spec_spacing_y = 0;
- /* user specified limits on the axes */
- double user_min_x = 0., user_min_y = 0., user_max_x = 0., user_max_y = 0.;
- double user_spacing_x = 0., user_spacing_y = 0.;
- double min_x, min_y, max_x, max_y;
-
- progname = strrchr (argv[0], '/');
- if (progname == NULL)
- progname = argv[0];
- else
- progname++;
-
- points_length = 4096;
- p = (point_struct *) do_malloc (points_length * sizeof (point_struct));
-
- errcnt = 0;
-
- while ((option = getopt_long (argc, argv, "-N:M::VbsvRL:T:c:X:Y:d:f:g:h:l:m:r:u:w:x::y::S::a::",
- long_options, &opt_index)) != EOF)
- {
- if (option == 0)
- option = long_options[opt_index].val;
-
- switch (option)
- {
- case 'a': /* Auto-abscissa */
- auto_abscissa = 1;
- if (optind >= argc)
- break;
- if (sscanf (argv [optind], "%lf", &delta_x) <= 0)
- break;
- optind++; /* tell getopt we recognized delta_x */
- if (delta_x == 0.)
- {
- auto_abscissa = 0; /* reset abscissa option to the default */
- delta_x = 1.;
- x_start = 0.;
- }
- if (optind >= argc)
- break;
- if (sscanf (argv [optind], "%lf", &x_start) <= 0)
- break;
- optind++; /* tell getopt we recognized x_start */
- break;
-
- case 'b': /* Break-on-labels */
- break_flag = 1;
- break;
- case 'M': /* Break-non-monotone */
- m_break_flag = 1; /* same line style for each curve */
- if (optind >= argc) /* optind is the index of the optional arg */
- break;
- if (strcmp ("m", argv[optind]) == 0)
- {
- m_break_flag = 2; /* switch line style when breaking lines */
- optind++; /* tell getopt we recognized the optional arg */
- }
- break;
- case 'f': /* Fontsize */
- if (isdigit(*optarg))
- default_fontsize = atoi (optarg);
- else
- {
- fprintf (stderr,
- "%s: Error: fontsize must be an integer. Was `%s'.\n",
- progname, optarg);
- errcnt++;
- }
- break;
- case 'g': /* Grid-style */
- switch (*optarg)
- {
- case '0':
- grid_spec = NO_GRID;
- break;
- case '1':
- grid_spec = FULL_GRID;
- break;
- case '2':
- grid_spec = TICKS_ALL_AROUND;
- break;
- case '3':
- grid_spec = TICKS_LEFT_AND_BELOW;
- break;
- case '4':
- grid_spec = AXES_AT_ORIGIN;
- break;
- default:
- fprintf (stderr,
- "%s: Unrecognized grid option `%s' ignored.\n",
- progname, argv[i]);
- errcnt++;
- }
- break;
- case 'd': /* Data-format */
- switch (*optarg)
- {
- case 'a':
- case 'A':
- data_spec = ASCII_DATA;
- break;
- case 'i':
- case 'I':
- data_spec = INT_DATA;
- break;
- case 's':
- case 'S':
- data_spec = SHORT_INT_DATA;
- break;
- case 'f':
- case 'F':
- data_spec = FLOAT_DATA;
- break;
- case 'd':
- case 'D':
- data_spec = DOUBLE_DATA;
- break;
- default:
- fprintf (stderr,
- "%s: Unrecognized data option `%s' ignored.\n",
- progname, argv[i]);
- errcnt++;
- }
- break;
- case 'm': /* Line-style */
- if (isdigit(*optarg) || (*optarg == '-'))
- linemode_index = atoi (optarg);
- else
- {
- fprintf (stderr,
- "%s: Error: line style must be an integer. Was `%s'.\n",
- progname, optarg);
- errcnt++;
- }
- break;
- case 'S': /* Symbol */
- symbol_index = 1; /* symbol # 1 is the default! */
-
- if (optind >= argc)
- break;
- if (sscanf (argv [optind], "%d", &symbol_index) <= 0)
- break;
- optind++; /* tell getopt we recognized symbol_index */
-
- if (optind >= argc)
- break;
- if (sscanf (argv [optind], "%lf", &symbol_size) <= 0)
- break;
- spec_min_x++;
- optind++; /* tell getopt we recognized symbol_size */
- break;
-
- case 'H': /* Help */
- show_usage++;
- show_version++;
- break;
- case 'v': /* Version */
- case 'V':
- show_version++;
- break;
- case 'T': /* Ticksize */
- tick_size = atof (optarg);
- break;
- case 'L': /* Top-title */
- top_label = do_malloc (strlen (optarg) + 1);
- strcpy (top_label, optarg);
- break;
- case 'l':
- switch (*optarg)
- {
- case 'x':
- case 'X':
- log_axis |= transpose_axes ? Y_AXIS : X_AXIS;
- break;
- case 'y':
- case 'Y':
- log_axis |= transpose_axes ? X_AXIS : Y_AXIS;
- break;
- default:
- (void) fprintf (stderr, "%s: ignoring unknown log axis type `%s'\n", progname, optarg);
- break;
- }
- break;
- case 'N': /* omit labels on the specified axis */
- switch (*optarg)
- {
- case 'x':
- case 'X':
- omit_labels |= transpose_axes ? Y_AXIS : X_AXIS;
- break;
- case 'y':
- case 'Y':
- omit_labels |= transpose_axes ? X_AXIS : Y_AXIS;
- break;
- default:
- (void) fprintf (stderr, "%s: ignoring unrecognized axis specification `%s'\n", progname, optarg);
- break;
- }
- switch (optarg[1])
- {
- case '\0':
- break;
- case 'x':
- case 'X':
- log_axis |= X_AXIS;
- break;
- case 'y':
- case 'Y':
- log_axis |= Y_AXIS;
- break;
- default:
- (void) fprintf (stderr, "%s: ignoring unknown log axis type `%s'\n", progname, optarg);
- break;
- }
- break;
- case 'c': /* point label */
- point_label = do_malloc (strlen (optarg) + 1);
- strcpy (point_label, optarg);
- break;
- case 'X': /* Xtitle */
- if (transpose_axes) goto Ytitle;
- Xtitle:
- x_label = do_malloc (strlen (optarg) + 1);
- strcpy (x_label, optarg);
- break;
- case 'Y': /* Ytitle */
- if (transpose_axes) goto Xtitle;
- Ytitle:
- y_label = do_malloc (strlen (optarg) + 1);
- strcpy (y_label, optarg);
- break;
- case 'u': /* bottom-margin-posn */
- margin_below = atof (optarg);
- break;
- case 'r': /* right-margin-posn */
- margin_left = atof (optarg);
- break;
- case 'R': /* round limits to the next tick mark */
- round_to_next_tick = 0;
- break;
- case 'w': /* width-plot */
- plot_width = atof (optarg);
- break;
- case 'h': /* height-plot */
- plot_height = atof (optarg);
- break;
- case 'x': /* xlimits */
- if (transpose_axes) goto ylimits;
- xlimits:
- if (optind >= argc) /* optind is the index of the optional arg */
- break;
- if (strcmp ("l", argv[optind]) == 0)
- {
- log_axis |= X_AXIS;
- optind++; /* tell getopt we recognized log axis arg */
- }
- if (optind >= argc)
- break;
- /* parse minimum x argument */
- if (sscanf (argv [optind], "%lf", &user_min_x) <= 0)
- break;
- spec_min_x++;
- optind++; /* tell getopt we recognized user_min_x */
- if (optind >= argc)
- break;
- /* parse maximum x argument */
- if (sscanf (argv [optind], "%lf", &user_max_x) <= 0)
- break;
- spec_max_x++;
- optind++; /* tell getopt we recognized user_max_x */
- if (optind >= argc)
- break;
- /* parse x tick spacing argument */
- if (sscanf (argv [optind], "%lf", &user_spacing_x) <= 0)
- break;
- spec_spacing_x++;
- optind++; /* tell getopt we recognized user_spacing_x */
- break;
-
- case 'y':
- if (transpose_axes) goto xlimits;
- ylimits:
- if (optind >= argc) /* optind is the index of the optional arg */
- break;
- if (strcmp ("l", argv[optind]) == 0)
- {
- log_axis |= Y_AXIS;
- optind++; /* tell getopt we recognized log axis arg */
- }
- if (optind >= argc)
- break;
- /* parse minimum y argument */
- if (sscanf (argv [optind], "%lf", &user_min_y) <= 0)
- break;
- spec_min_y++;
- optind++; /* tell getopt we recognized user_min_y */
- if (optind >= argc)
- break;
- /* parse maximum y argument */
- if (sscanf (argv [optind], "%lf", &user_max_y) <= 0)
- break;
- spec_max_y++;
- optind++; /* tell getopt we recognized user_max_y */
- if (optind >= argc)
- break;
- /* parse y tick spacing argument */
- if (sscanf (argv [optind], "%lf", &user_spacing_y) <= 0)
- break;
- spec_spacing_y++;
- optind++; /* tell getopt we recognized user_spacing_y */
- break;
-
- case 's':
- save_screen = 1;
- break;
- case 't':
- transpose_axes = 1;
- break;
- /*---------------- Long options below here ----------------*/
- case 'd' << 8: /* debug */
- debug = 1;
- break;
- case 'f' << 8: /* fontname */
- (void) fontname (optarg);
- break;
- case 'm' << 8: /* margin */
- margin = atof (optarg);
- break;
- case 'w' << 8: /* warranty */
- case 'c' << 8: /* copying */
- show_copying = 1;
- break;
- case 'H' << 8: /* output byte order */
- output_high_byte_first = 1;
- break;
- case 'L' << 8: /* output byte order */
- output_high_byte_first = -1;
- break;
- default:
- errcnt++;
- break;
- case 1:
- {
- FILE *data_file;
-
- if (strcmp (optarg, "-") == 0)
- data_file = stdin;
- else
- {
- data_file = fopen (optarg, "r");
- if (data_file == NULL)
- {
- (void) fprintf (stderr, "%s: ignoring nonexistent or inaccessible file `%s'\n",
- progname, optarg);
- continue;
- }
- }
- opened++;
- read_file (data_file, &p, &points_length, &no_of_points,
- auto_abscissa, x_start, delta_x, data_spec,
- symbol_index, transpose_axes, point_label,
- linemode_index, m_break_flag);
-
- if (data_file != stdin) /* Don't close stdin */
- fclose (data_file);
- }
- break;
- } /* endswitch */
- } /* endwhile */
-
-
- if (show_version)
- display_version ();
-
- if ((show_usage > 0) || (errcnt > 0))
- usage ();
-
- if (show_copying)
- {
- int k;
- for (k = 0; *copy_notice[k] != '\0'; k++)
- fputs (copy_notice[k], stderr);
- }
-
- if (errcnt > 0)
- exit (1);
-
- if (show_copying || show_usage)
- exit (0);
-
- /* Let's read in the named data files on the command line, if any.
- Read stdin if no files are given */
-
- if (optind < argc)
- {
- for (; optind < argc; optind++)
- {
- FILE *data_file;
-
- if (strcmp (argv[optind], "-") == 0)
- data_file = stdin;
- else
- {
- data_file = fopen (argv[optind], "r");
- if (data_file == NULL)
- {
- (void) fprintf (stderr, "%s: ignoring nonexistent or inaccessible file `%s'\n",
- progname, argv[optind]);
- continue;
- }
- }
- opened++;
- read_file (data_file, &p, &points_length, &no_of_points,
- auto_abscissa, x_start, delta_x, data_spec, symbol_index,
- transpose_axes, point_label, linemode_index, m_break_flag);
-
- if (data_file != stdin) /* Don't close stdin */
- fclose (data_file);
- }
- } /* endfor */
-
- if (!opened)
- /* Read stdin if no files were named on the command line. */
- read_file (stdin, &p, &points_length, &no_of_points, auto_abscissa,
- x_start, delta_x, data_spec, symbol_index, transpose_axes,
- point_label, linemode_index, m_break_flag);
-
- /* if the user doesn't specify all the limits, we compute them. */
- if (!spec_min_x || !spec_min_y)
- array_min (p, no_of_points, &min_x, &min_y);
- if (!spec_max_x || !spec_max_y)
- array_max (p, no_of_points, &max_x, &max_y);
- if (min_x == max_x)
- {
- min_x -= 1.;
- max_x += 1.;
- }
- if (min_y == max_y)
- {
- min_y -= 1.;
- max_y += 1.;
- }
-
- if (debug)
- {
- int j;
-
- fprintf (stderr, "%d elements read.\n", no_of_points);
- for (j = 0; j < no_of_points; j++)
- {
- fprintf (stderr, "%g %g", p[j].x, p[j].y);
- if (p[j].string)
- fprintf (stderr, " \"%s\"", p[j].string);
- if (p[j].symbol >= 0)
- fprintf (stderr, " symbol %d", p[j].symbol);
- if (p[j].linemode == 0)
- putc ('\n', stderr);
- else
- fprintf (stderr, " linemode %d\n", p[j].linemode);
- }
-
- fprintf (stderr, "x min: %g max: %g\n", min_x, max_x);
- fprintf (stderr, "y min: %g max: %g\n", min_y, max_y);
- if (no_of_points == 0)
- fprintf (stderr, "Warning: no data read from input.\n");
- fflush (stderr);
- }
- if (!save_screen)
- erase ();
-
- if ( ((margin_below<=0.) && !x_label)
- || ((margin_left<=0.) && !y_label)
- || ((margin_below+plot_height>=1.) && !top_label))
- fprintf (stderr, "Warning: one of the margins is too narrow for a label.\n");
-
- /* If abscissal or ordinate values increase from left to right or
- bottom ot top respectively, spacing is positive, otherwise negative.
- Abort if the user specifies an inconsistent spacing. */
- if ( spec_spacing_x
- && ((user_max_x - user_min_x) * user_spacing_x <= 0.))
- {
- fprintf (stderr, "Error: x spacing must be the same sign as xmax-xmin.\n");
- exit (-1);
- }
- if ( spec_spacing_y
- && ((user_max_y - user_min_y) * user_spacing_y <= 0.))
- {
- fprintf (stderr, "Error: y spacing must be the same sign as ymax-ymin.\n");
- exit (-1);
- }
-
-
- write_plot (stdout, p, no_of_points,
- spec_min_x ? user_min_x : min_x,
- spec_max_x ? user_max_x : max_x,
- spec_spacing_x ? user_spacing_x : 0.,
- spec_min_y ? user_min_y : min_y,
- spec_max_y ? user_max_y : max_y,
- spec_spacing_y ? user_spacing_y : 0.,
- plot_width, plot_height, margin_below, margin_left,
- symbol_size, tick_size, grid_spec,
- x_label, y_label, top_label, margin, log_axis,
- break_flag, round_to_next_tick, default_fontsize,
- omit_labels);
- return 0;
- }
-