Exemplo n.º 1
0
/* Clip the given polygon to drawing coords defined by BoundingBox.
 * This routine uses the Sutherland-Hodgman algorithm.  When calling
 * this function, you must make sure that you reserved enough
 * memory for the output polygon. out_length can be as big as
 * 2*(in_length - 1)
 */
void
clip_polygon(gpiPoint *in, gpiPoint *out, int in_length, int *out_length)
{
    int i;
    gpiPoint clip_boundary[5];
    static gpiPoint *tmp_corners = NULL;

    if (!clip_area) {
	memcpy(out, in, in_length * sizeof(gpiPoint));
	*out_length = in_length;
	return;
    }
    tmp_corners = gp_realloc(tmp_corners, 2 * in_length * sizeof(gpiPoint), "clip_polygon");

    /* vertices of the rectangular clipping window starting from
       top-left in counterclockwise direction */
    clip_boundary[0].x = clip_area->xleft;  /* top left */
    clip_boundary[0].y = clip_area->ytop;
    clip_boundary[1].x = clip_area->xleft;  /* bottom left */
    clip_boundary[1].y = clip_area->ybot;
    clip_boundary[2].x = clip_area->xright; /* bottom right */
    clip_boundary[2].y = clip_area->ybot;
    clip_boundary[3].x = clip_area->xright; /* top right */
    clip_boundary[3].y = clip_area->ytop;
    clip_boundary[4] = clip_boundary[0];

    memcpy(tmp_corners, in, in_length * sizeof(gpiPoint));
    for(i = 0; i < 4; i++) {
	clip_polygon_to_boundary(tmp_corners, out, in_length, out_length, clip_boundary+i);
	memcpy(tmp_corners, out, *out_length * sizeof(gpiPoint));
	in_length = *out_length;
    }
}
Exemplo n.º 2
0
/*
 * iso_extend() reallocates a iso_curve structure to hold "num"
 * points. This will either expand or shrink the storage.
 */
void
iso_extend(struct iso_curve *ip, int num)
{
    if (num == ip->p_max)
	return;

#if defined(DOS16) || defined(WIN16)
    /* Make sure we do not allocate more than 64k points in msdos since
       * indexing is done with 16-bit int
       * Leave some bytes for malloc maintainance.
     */
    if (num > 32700)
	int_error(NO_CARET, "Array index must be less than 32k in msdos");
#endif /* 16bit (Win)Doze */

    if (num > 0) {
	if (ip->points == NULL) {
	    ip->points = (struct coordinate GPHUGE *)
		gp_alloc(num * sizeof(struct coordinate), "iso curve points");
	} else {
	    ip->points = (struct coordinate GPHUGE *)
		gp_realloc(ip->points, num * sizeof(struct coordinate), "expanding curve points");
	}
	ip->p_max = num;
    } else {
	if (ip->points != (struct coordinate GPHUGE *) NULL)
	    free(ip->points);
	ip->points = (struct coordinate GPHUGE *) NULL;
	ip->p_max = 0;
    }
}
Exemplo n.º 3
0
/*
 * In-line data blocks are implemented as a here-document:
 * $FOO << EOD
 *  data line 1
 *  data line 2
 *  ...
 * EOD
 *
 * The data block name must begin with $ followed by a letter.
 * The string EOD is arbitrary; lines of data will be read from the input stream
 * until the leading characters on the line match the given character string.
 * No attempt is made to parse the data at the time it is read in.
 */
void
datablock_command()
{
    FILE *fin;
    char *name, *eod;
    int nlines;
    int nsize = 4;
    struct udvt_entry *datablock;
    char dataline[MAX_LINE_LEN+1];

    if (!isletter(c_token+1))
	int_error(c_token, "illegal datablock name");

    /* Create or recycle a datablock with the requested name */
    name = parse_datablock_name();
    datablock = add_udv_by_name(name);

    if (!datablock->udv_undef)
	gpfree_datablock(&datablock->udv_value);
    datablock->udv_undef = FALSE;
    datablock->udv_value.type = DATABLOCK;
    datablock->udv_value.v.data_array = NULL;

    if (!equals(c_token, "<<") || !isletter(c_token+1))
	int_error(c_token, "data block name must be followed by << EODmarker");
    c_token++;
    eod = gp_alloc(token[c_token].length +2, "datablock");
    copy_str(&eod[0], c_token, token[c_token].length + 2);
    c_token++;

    /* Read in and store data lines until EOD */
    fin = (lf_head == NULL) ? stdin : lf_head->fp;
    if (!fin)
	int_error(NO_CARET,"attempt to define data block from invalid context");
    for (nlines = 0; fgets(dataline, MAX_LINE_LEN, fin); nlines++) {
	int n;

	if (!strncmp(eod, dataline, strlen(eod)))
	    break;
	/* Allocate space for data lines plus at least 2 empty lines at the end. */
	if (nlines >= nsize-4) {
	    nsize *= 2;
	    datablock->udv_value.v.data_array =
		gp_realloc( datablock->udv_value.v.data_array,
			nsize * sizeof(char *), "datablock");
	    memset(&datablock->udv_value.v.data_array[nlines], 0,
		    (nsize - nlines) * sizeof(char *));
	}
	/* Strip trailing newline character */
	n = strlen(dataline);
	if (n > 0 && dataline[n - 1] == '\n')
	    dataline[n - 1] = NUL;
	datablock->udv_value.v.data_array[nlines] = gp_strdup(dataline);
    }
    inline_num += nlines + 1;	/* Update position in input file */

    free(eod);
    return;
}
Exemplo n.º 4
0
double *
redim_vec(double **v, int n)
{
    if (n < 1)
	*v = NULL;
    else
	*v = gp_realloc(*v, n * sizeof((*v)[0]), "vec");
    return *v;
}
Exemplo n.º 5
0
Arquivo: parse.c Projeto: Reen/gnuplot
static void
extend_at()
{
    size_t newsize = sizeof(struct at_type) + at_size * sizeof(struct at_entry);

    at = gp_realloc(at, newsize, "extend_at");
    at_size += MAX_AT_LEN;
    FPRINTF((stderr, "Extending at size to %d\n", at_size));
}
Exemplo n.º 6
0
/* append string src to dest
   re-allocates memory if necessary, (re-)determines the length of the
   destination string only if len==0
 */
size_t
strappend(char **dest, size_t *size, size_t len, const char *src)
{
    size_t destlen = (len != 0) ? len : strlen(*dest);
    size_t srclen = strlen(src);
    if (destlen + srclen + 1 > *size) {
        *size *= 2;
        *dest = (char *) gp_realloc(*dest, *size, "strappend");
    }
    memcpy(*dest + destlen, src, srclen + 1);
    return destlen + srclen;
}
Exemplo n.º 7
0
void extend_token_table()
{
    if (token_table_size == 0) {
	/* first time */
	token = (struct lexical_unit *) gp_alloc(MAX_TOKENS * sizeof(struct lexical_unit), "token table");
	token_table_size = MAX_TOKENS;
    } else {
	token = gp_realloc(token, (token_table_size + MAX_TOKENS) * sizeof(struct lexical_unit), "extend token table");
	token_table_size += MAX_TOKENS;
	FPRINTF((stderr, "extending token table to %d elements\n", token_table_size));
    }
}
Exemplo n.º 8
0
Arquivo: parse.c Projeto: Reen/gnuplot
struct at_type *
perm_at()
{
    struct at_type *at_ptr;
    size_t len;

    (void) temp_at();
    len = sizeof(struct at_type)
	+ (at->a_count - MAX_AT_LEN) * sizeof(struct at_entry);
    at_ptr = (struct at_type *) gp_realloc(at, len, "perm_at");
    at = NULL;			/* invalidate at pointer */
    return (at_ptr);
}
Exemplo n.º 9
0
/*
 * m_capture() is similar to capture(), but it mallocs storage for the
 * string.
 */
void
m_capture(char **str, int start, int end)
{
    int i, e;
    char *s;

    e = token[end].start_index + token[end].length;
    *str = gp_realloc(*str, (e - token[start].start_index + 1), "string");
    s = *str;
    for (i = token[start].start_index; i < e && gp_input_line[i] != NUL; i++)
	*s++ = gp_input_line[i];
    *s = NUL;
}
Exemplo n.º 10
0
/* support for dynamic size of input line */
void extend_input_line()
{
    if (input_line_len == 0) {
	/* first time */
	input_line = gp_alloc(MAX_LINE_LEN, "input_line");
	input_line_len = MAX_LINE_LEN;
	input_line[0] = NUL;
    } else {
	input_line = gp_realloc(input_line, input_line_len + MAX_LINE_LEN, "extend input line");
	input_line_len += MAX_LINE_LEN;
	FPRINTF((stderr, "extending input line to %d chars\n", input_line_len));
    }
}
Exemplo n.º 11
0
static void
extend_cur_line()
{
    char *new_line;

    /* extent input line length */
    new_line = gp_realloc(cur_line, line_len + MAXBUF, NULL);
    if (!new_line) {
	reset_termio();
	int_error(NO_CARET, "Can't extend readline length");
    }
    cur_line = new_line;
    line_len += MAXBUF;
    FPRINTF((stderr, "\nextending readline length to %d chars\n", line_len));
}
Exemplo n.º 12
0
/* Output time given in seconds from year 2000 into string */
void
f_strftime(union argument *arg)
{
    struct value fmt, val;
    char *fmtstr, *buffer;
    int fmtlen, buflen, length;

    (void) arg; /* Avoid compiler warnings */

    /* Retrieve parameters from top of stack */
    pop(&val);
    pop(&fmt);
    if ( fmt.type != STRING )
	int_error(NO_CARET,
		  "First parameter to strftime must be a format string");

    /* Prepare format string.
     * Make sure the resulting string not empty by adding a space.
     * Otherwise, the return value of gstrftime doesn't give enough
     * information.
     */
    fmtlen = strlen(fmt.v.string_val) + 1;
    fmtstr = gp_alloc(fmtlen + 1, "f_strftime: fmt");
    strncpy(fmtstr, fmt.v.string_val, fmtlen);
    strncat(fmtstr, " ", fmtlen);
    buflen = 80 + 2*fmtlen;
    buffer = gp_alloc(buflen, "f_strftime: buffer");

    /* Get time_str */
    length = gstrftime(buffer, buflen, fmtstr, real(&val));
    if (length == 0 || length >= buflen)
	int_error(NO_CARET, "Resulting string is too long");

    /* Remove trailing space */
    assert(buffer[length-1] == ' ');
    buffer[length-1] = NUL;
    buffer = gp_realloc(buffer, strlen(buffer)+1, "f_strftime");
    FPRINTF((stderr," strftime result = \"%s\"\n",buffer));

    gpfree_string(&val);
    gpfree_string(&fmt);
    free(fmtstr);

    push(Gstring(&val, buffer));
}
Exemplo n.º 13
0
/* retrieve path relative to gnuplot executable */
LPSTR
RelativePathToGnuplot(const char * path)
{
#ifdef UNICODE
    LPSTR ansi_dir = AnsiText(szPackageDir, encoding);
    LPSTR rel_path = (char *) gp_realloc(ansi_dir, strlen(ansi_dir) + strlen(path) + 1, "RelativePathToGnuplot");
    if (rel_path == NULL) {
	free(ansi_dir);
	return (LPSTR) path;
    }
#else
    char * rel_path = (char * ) gp_alloc(strlen(szPackageDir) + strlen(path) + 1, "RelativePathToGnuplot");
    strcpy(rel_path, szPackageDir);
#endif
    /* szPackageDir is guaranteed to have a trailing backslash */
    strcat(rel_path, path);
    return rel_path;
}
Exemplo n.º 14
0
/* expand tilde in path
 * path cannot be a static array!
 * tilde must be the first character in *pathp;
 * we may change that later
 */
void
gp_expand_tilde(char **pathp)
{
    if (!*pathp)
	int_error(NO_CARET, "Cannot expand empty path");

    if ((*pathp)[0] == '~' && (*pathp)[1] == DIRSEP1) {
	if (user_homedir) {
	    size_t n = strlen(*pathp);

	    *pathp = gp_realloc(*pathp, n + strlen(user_homedir), "tilde expansion");
	    /* include null at the end ... */
	    memmove(*pathp + strlen(user_homedir) - 1, *pathp, n + 1);
	    memcpy(*pathp, user_homedir, strlen(user_homedir));
	} else
	    int_warn(NO_CARET, "HOME not set - cannot expand tilde");
    }
}
Exemplo n.º 15
0
/*
 * m_quote_capture() is similar to m_capture(), but it removes
 * quotes from either end of the string.
 */
void
m_quote_capture(char **str, int start, int end)
{
    int i, e;
    char *s;

    e = token[end].start_index + token[end].length - 1;
    *str = gp_realloc(*str, (e - token[start].start_index + 1), "string");
    s = *str;
    for (i = token[start].start_index + 1; i < e && gp_input_line[i] != NUL; i++)
	*s++ = gp_input_line[i];
    *s = NUL;

    if (gp_input_line[token[start].start_index] == '"')
	parse_esc(*str);
    else
        parse_sq(*str);

}
Exemplo n.º 16
0
FILE *
loadpath_fopen(const char *filename, const char *mode)
{
    FILE *fp;

#if defined(PIPES)
    if (*filename == '<') {
	restrict_popen();
	if ((fp = popen(filename + 1, "r")) == (FILE *) NULL)
	    return (FILE *) 0;
    } else
#endif /* PIPES */
    if ((fp = fopen(filename, mode)) == (FILE *) NULL) {
	/* try 'loadpath' variable */
	char *fullname = NULL, *path;

	while ((path = get_loadpath()) != NULL) {
	    /* length of path, dir separator, filename, \0 */
	    fullname = gp_realloc(fullname, strlen(path) + 1 + strlen(filename) + 1, "loadpath_fopen");
	    strcpy(fullname, path);
	    PATH_CONCAT(fullname, filename);
	    if ((fp = fopen(fullname, mode)) != NULL) {
		free(fullname);
		fullname = NULL;
		/* reset loadpath internals!
		 * maybe this can be replaced by calling get_loadpath with
		 * a NULL argument and some loadpath_handler internal logic */
		while (get_loadpath());
		break;
	    }
	}

	if (fullname)
	    free(fullname);

    }

#ifdef _Windows
    if (fp != NULL)
	setmode(fileno(fp), _O_BINARY);
#endif
    return fp;
}
Exemplo n.º 17
0
/*{{{  static char *df_gets() */
static char *df_gets()
{
    int len = 0;

    /* HBB 20000526: prompt user for inline data, if in interactive mode */
    if (mixed_data_fp && interactive)
	fputs("input data ('e' ends) > ", stderr);

    if (!fgets(line, max_line_len, data_fp))
	return NULL;

    if (mixed_data_fp)
	++inline_num;

    for (;;) {
	len += strlen(line + len);

	if (len > 0 && line[len - 1] == '\n') {
	    /* we have read an entire text-file line.
	     * Strip the trailing linefeed and return
	     */
	    line[len - 1] = 0;
	    return line;
	}
	/* buffer we provided may not be full - dont grab extra
	 * memory un-necessarily. This may trap a problem with last
	 * line in file not being properly terminated - each time
	 * through a replot loop, it was doubling buffer size
	 */

	if ((max_line_len - len) < 32)
	    line = gp_realloc(line, max_line_len *= 2, "datafile line buffer");

	if (!fgets(line + len, max_line_len - len, data_fp))
	    return line;	/* unexpected end of file, but we have something to do */
    }

    /* NOTREACHED */
    return NULL;
}
Exemplo n.º 18
0
/*
 * iso_extend() reallocates a iso_curve structure to hold "num"
 * points. This will either expand or shrink the storage.
 */
void
iso_extend(struct iso_curve *ip, int num)
{
    if (num == ip->p_max)
	return;

    if (num > 0) {
	if (ip->points == NULL) {
	    ip->points = (struct coordinate GPHUGE *)
		gp_alloc(num * sizeof(struct coordinate), "iso curve points");
	} else {
	    ip->points = (struct coordinate GPHUGE *)
		gp_realloc(ip->points, num * sizeof(struct coordinate), "expanding curve points");
	}
	if (num > ip->p_max)
	    memset( &(ip->points[ip->p_max]), 0, (num - ip->p_max) * sizeof(struct coordinate));
	ip->p_max = num;
    } else {
	if (ip->points != (struct coordinate GPHUGE *) NULL)
	    free(ip->points);
	ip->points = (struct coordinate GPHUGE *) NULL;
	ip->p_max = 0;
    }
}
Exemplo n.º 19
0
void
edf_filetype_function(void)
{
    FILE *fp;
    char *header = NULL;
    int header_size = 0;
    char *p;
    int k;
    /* open (header) file */
    fp = loadpath_fopen(df_filename, "rb");
    if (!fp)
	os_error(NO_CARET, "Can't open data file \"%s\"", df_filename);
    /* read header: it is a multiple of 512 B ending by "}\n" */
    while (header_size == 0 || strncmp(&header[header_size-2],"}\n",2)) {
	int header_size_prev = header_size;
	if (header_size > 12*512) /* protection against indefinite loop */
	    os_error(NO_CARET, "Damaged EDF header of %s: not multiple of 512 B.\n", df_filename);
	header_size += 512;
	if (!header)
	    header = gp_alloc(header_size+1, "EDF header");
	else
	    header = gp_realloc(header, header_size+1, "EDF header");
	header[header_size_prev] = 0; /* protection against empty file */
	fread(header+header_size_prev, 512, 1, fp);
	header[header_size] = 0; /* end of string: protection against strstr later on */
    }
    fclose(fp);
    /* make sure there is a binary record structure for each image */
    if (df_num_bin_records < 1)
	df_add_binary_records(1-df_num_bin_records, DF_CURRENT_RECORDS); /* otherwise put here: number of images (records) from this file */
    if ((p = edf_findInHeader(header, "EDF_BinaryFileName"))) {
	int plen = strcspn(p, " ;\n");
	df_filename = gp_realloc(df_filename, plen+1, "datafile name");
	strncpy(df_filename, p, plen);
	df_filename[plen] = '\0';
	if ((p = edf_findInHeader(header, "EDF_BinaryFilePosition")))
	    df_bin_record[0].scan_skip[0] = atoi(p);
	else
	    df_bin_record[0].scan_skip[0] = 0;
    } else
	df_bin_record[0].scan_skip[0] = header_size; /* skip header */
    /* set default values */
    df_bin_record[0].scan_dir[0] = 1;
    df_bin_record[0].scan_dir[1] = -1;
    df_bin_record[0].scan_generate_coord = TRUE;
    df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
    df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
    df_extend_binary_columns(1);
    df_set_skip_before(1,0);
    df_set_skip_after(1,0);
    df_no_use_specs = 1;
    use_spec[0].column = 1;
    /* now parse the header */
    if ((p = edf_findInHeader(header, "Dim_1")))
	df_bin_record[0].scan_dim[0] = atoi(p);
    if ((p = edf_findInHeader(header, "Dim_2")))
	df_bin_record[0].scan_dim[1] = atoi(p);
    if ((p = edf_findInHeader(header, "DataType"))) {
	k = lookup_table4_nth(edf_datatype_table, p);
	if (k >= 0) { /* known EDF DataType */
	    int s = edf_datatype_table[k].sajzof; 
	    switch (edf_datatype_table[k].signum) {
		case 0: df_set_read_type(1,SIGNED_TEST(s)); break;
		case 1: df_set_read_type(1,UNSIGNED_TEST(s)); break;
		case 2: df_set_read_type(1,FLOAT_TEST(s)); break;
	    }
	}
    }
    if ((p = edf_findInHeader(header, "ByteOrder"))) {
	k = lookup_table_nth(edf_byteorder_table, p);
	if (k >= 0)
	    df_bin_file_endianess = edf_byteorder_table[k].value;
    }
    /* Origin vs center: EDF specs allows only Center, but it does not hurt if
       Origin is supported as well; however, Center rules if both specified.
    */
    if ((p = edf_findInHeader(header, "Origin_1"))) {
	df_bin_record[0].scan_cen_or_ori[0] = atof(p);
	df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN;
    }
    if ((p = edf_findInHeader(header, "Origin_2"))) {
	df_bin_record[0].scan_cen_or_ori[1] = atof(p);
	df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN;
    }
    if ((p = edf_findInHeader(header, "Center_1"))) {
	df_bin_record[0].scan_cen_or_ori[0] = atof(p);
	df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER;
    }
    if ((p = edf_findInHeader(header, "Center_2"))) {
	df_bin_record[0].scan_cen_or_ori[1] = atof(p);
	df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER;
    }
    /* now pixel sizes and raster orientation */
    if ((p = edf_findInHeader(header, "PSize_1")))
	df_bin_record[0].scan_delta[0] = atof(p);
    if ((p = edf_findInHeader(header, "PSize_2")))
	df_bin_record[0].scan_delta[1] = atof(p);
    if ((p = edf_findInHeader(header, "RasterAxes"))) {
	k = lookup_table_nth(edf_rasteraxes_table, p);
	switch (k) {
	    case EDF_RASTER_AXES_XrightYup:
		df_bin_record[0].scan_dir[0] = 1;
		df_bin_record[0].scan_dir[1] = 1;
		df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
		df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
		break;
	    default: /* also EDF_RASTER_AXES_XrightYdown */
		df_bin_record[0].scan_dir[0] = 1;
		df_bin_record[0].scan_dir[1] = -1;
		df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
		df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
	}
    }

    free(header);

}
Exemplo n.º 20
0
void
mcs_interp(struct curve_points *plot)
{
    /* These track the original (pre-sorted) data points */
    int N = plot->p_count;
    struct coordinate *p = gp_realloc(plot->points, (N+1) * sizeof(coordinate), "mcs");
    int i;

    /* These will track the resulting smoothed curve */
    struct coordinate *new_points = gp_alloc((samples_1+1) * sizeof(coordinate), "mcs");
    double sxmin = AXIS_LOG_VALUE(plot->x_axis, X_AXIS.min);
    double sxmax = AXIS_LOG_VALUE(plot->x_axis, X_AXIS.max);
    double xstart, xend, xstep;

    xstart = GPMAX(p[0].x, sxmin);
    xend = GPMIN(p[N-1].x, sxmax);
    xstep = (xend - xstart) / (samples_1 - 1);

    /* Calculate spline coefficients */
#define DX	xlow
#define SLOPE	xhigh
#define C1	ylow
#define C2	yhigh
#define C3	z

    for (i = 0; i < N-1; i++) {
	p[i].DX = p[i+1].x - p[i].x;
	p[i].SLOPE = (p[i+1].y - p[i].y) / p[i].DX;
    }
    p[N-1].SLOPE = 0;

    p[0].C1 = p[0].SLOPE;
    for (i = 0; i < N-1; i++) {
	if (p[i].SLOPE * p[i+1].SLOPE <= 0) {
	    p[i+1].C1 = 0;
	} else {
	    double sum = p[i].DX + p[i+1].DX;
	    p[i+1].C1 = (3. * sum)
		    / ((sum + p[i+1].DX) /  p[i].SLOPE + (sum + p[i].DX) /  p[i+1].SLOPE);
	}
    }
    p[N].C1 = p[N-1].SLOPE;

    for (i = 0; i < N; i++) {
	double temp = p[i].C1 + p[i+1].C1 - 2*p[i].SLOPE;
	p[i].C2 = (p[i].SLOPE - p[i].C1 -temp) / p[i].DX;
	p[i].C3 = temp / (p[i].DX * p[i].DX);
    }

    /* Use the coefficients C1, C2, C3 to interpolate over the requested range */
    for (i = 0; i < samples_1; i++) {
	double x = xstart + i * xstep;
	double y;
	TBOOLEAN exact = FALSE;

	if (x == p[N-1].x) {	/* Exact value for right-most point of original data */
	    y = p[N-1].y;
	    exact = TRUE;
	} else {
	    int low = 0;
	    int mid; 
	    int high = N-1;
	    while (low <= high) {
		mid = floor((low + high) / 2);
		if (p[mid].x < x)
		    low = mid + 1;
		else if (p[mid].x > x)
		    high = mid - 1;
		else {		/* Exact value for some point in original data */
		    y = p[mid].y;
		    exact = TRUE;
		    break;
		}
	    }
	    if (!exact) {
		int j = GPMAX(0, high);
		double diff = x - p[j].x;
		y = p[j].y + p[j].C1 * diff + p[j].C2 * diff * diff + p[j].C3 * diff * diff * diff;
	    }
	}

	/* FIXME:  Log x?  autoscale x? */
	new_points[i].x = x;
	new_points[i].type = INRANGE;
	STORE_WITH_LOG_AND_UPDATE_RANGE(new_points[i].y, y, new_points[i].type,
		plot->y_axis, plot->noautoscale, NOOP, NOOP);
    }

    /* Replace original data with the interpolated curve */
    free(p);
    plot->points = new_points;
    plot->p_count = samples_1;
    plot->p_max = samples_1 + 1;

#undef DX
#undef SLOPE
#undef C1
#undef C2
#undef C3
}
Exemplo n.º 21
0
void 
statsrequest(void)
{ 
    int i;
    int columns;
    int columnsread;
    double v[2];
    static char *file_name = NULL;

    /* Vars to hold data and results */
    long n;                /* number of records retained */
    long max_n;

    static double *data_x = NULL;
    static double *data_y = NULL;   /* values read from file */
    long invalid;          /* number of missing/invalid records */
    long blanks;           /* number of blank lines */
    long doubleblanks;     /* number of repeated blank lines */
    long out_of_range;     /* number pts rejected, because out of range */

    struct file_stats res_file;
    struct sgl_column_stats res_x, res_y;
    struct two_column_stats res_xy;
    
    float *matrix;            /* matrix data. This must be float. */
    int nc, nr;               /* matrix dimensions. */
    int index;

    /* Vars for variable handling */
    static char *prefix = NULL;       /* prefix for user-defined vars names */

    /* Vars that control output */
    TBOOLEAN do_output = TRUE;     /* Generate formatted output */ 
    
    c_token++;

    /* Parse ranges */
    AXIS_INIT2D(FIRST_X_AXIS, 0);
    AXIS_INIT2D(FIRST_Y_AXIS, 0);
    parse_range(FIRST_X_AXIS);
    parse_range(FIRST_Y_AXIS);

    /* Initialize */
    columnsread = 2;
    invalid = 0;          /* number of missing/invalid records */
    blanks = 0;           /* number of blank lines */
    doubleblanks = 0;     /* number of repeated blank lines */
    out_of_range = 0;     /* number pts rejected, because out of range */
    n = 0;                /* number of records retained */
    nr = 0;               /* Matrix dimensions */
    nc = 0;
    max_n = INITIAL_DATA_SIZE;
    
    free(data_x);
    free(data_y);
    data_x = vec(max_n);       /* start with max. value */
    data_y = vec(max_n);

    if ( !data_x || !data_y )
      int_error( NO_CARET, "Internal error: out of memory in stats" );

    n = invalid = blanks = doubleblanks = out_of_range = nr = 0;

    /* Get filename */
    free ( file_name );
    file_name = try_to_get_string();

    if ( !file_name )
	int_error(c_token, "missing filename");

    /* ===========================================================
    v923z: insertion for treating matrices 
      EAM: only handles ascii matrix with uniform grid,
           and fails to apply any input data transforms
      =========================================================== */
    if ( almost_equals(c_token, "mat$rix") ) {
	df_open(file_name, 3, NULL);
	index = df_num_bin_records - 1;
	
	/* We take these values as set by df_determine_matrix_info
	See line 1996 in datafile.c */
	nc = df_bin_record[index].scan_dim[0];
	nr = df_bin_record[index].scan_dim[1];
	n = nc * nr;
	
	matrix = (float *)df_bin_record[index].memory_data;
	
	/* Fill up a vector, so that we can use the existing code. */
	if ( !redim_vec(&data_x, n ) ) {
	    int_error( NO_CARET, 
		   "Out of memory in stats: too many datapoints (%d)?", n );
	}
	for( i=0; i < n; i++ ) {
	    data_y[i] = (double)matrix[i];  
	}
	/* We can close the file here, there is nothing else to do */
	df_close();
	/* We will invoke single column statistics for the matrix */
	columns = 1;

    } else { /* Not a matrix */
	columns = df_open(file_name, 2, NULL); /* up to 2 using specs allowed */

	if (columns < 0)
	    int_error(NO_CARET, "Can't read data file"); 

	if (columns > 2 )
	    int_error(c_token, "Need 0 to 2 using specs for stats command");

	/* If the user has set an explicit locale for numeric input, apply it
	   here so that it affects data fields read from the input file. */
	/* v923z: where exactly should this be? here or before the matrix case? 
	 * I think, we should move everything here to before trying to open the file. 
	 * There is no point in trying to read anything, if the axis is logarithmic, e.g.
	 */
	set_numeric_locale();   

	/* For all these below: we could save the state, switch off, then restore */
	if ( axis_array[FIRST_X_AXIS].log || axis_array[FIRST_Y_AXIS].log )
	    int_error( NO_CARET, "Stats command not available with logscale active");

	if ( axis_array[FIRST_X_AXIS].datatype == DT_TIMEDATE || axis_array[FIRST_Y_AXIS].datatype == DT_TIMEDATE )
	    int_error( NO_CARET, "Stats command not available in timedata mode");

	if ( polar )
	    int_error( NO_CARET, "Stats command not available in polar mode" );

	if ( parametric )
	    int_error( NO_CARET, "Stats command not available in parametric mode" );

	/* The way readline and friends work is as follows:
	 - df_open will return the number of columns requested in the using spec
	   so that "columns" will be 0, 1, or 2 (no using, using 1, using 1:2)
	 - readline always returns the same number of columns (for us: 1 or 2)
	 - using 1:2 = return two columns, skipping lines w/ bad data
	 - using 1   = return sgl column (supply zeros (0) for the second col)
	 - no using  = return two columns (first two), fail on bad data 

	 We need to know how many columns to process. If columns==1 or ==2
	 (that is, if there was a using spec), all is clear and we use the
	 value of columns. 
	 But: if columns is 0, then we need to figure out the number of cols
	 read from the return value of readline. If readline ever returns
	 1, we take that; only if it always returns 2 do we assume two cols.
	 */
  
	while( (i = df_readline(v, 2)) != DF_EOF ) {
	    columnsread = ( i > columnsread ? i : columnsread );

	    if ( n >= max_n ) {
		max_n = (max_n * 3) / 2; /* increase max_n by factor of 1.5 */
	  
		/* Some of the reallocations went bad: */
		if ( 0 || !redim_vec(&data_x, max_n) || !redim_vec(&data_y, max_n) ) {
		    df_close();
		    int_error( NO_CARET, 
		       "Out of memory in stats: too many datapoints (%d)?",
		       max_n );
		} 
	    } /* if (need to extend storage space) */

	    switch (i) {
	    case DF_MISSING:
	    case DF_UNDEFINED:
	      /* Invalids are only recognized if the syntax is like this:
		     stats "file" using ($1):($2)
		 If the syntax is simply:
		     stats "file" using 1:2
		 then df_readline simply skips invalid records (does not
		 return anything!) Status: 2009-11-02 */
	      invalid += 1;
	      continue;
	      
	    case DF_FIRST_BLANK: 
	      blanks += 1;
	      continue;

	    case DF_SECOND_BLANK:      
	      blanks += 1;
	      doubleblanks += 1;
	      continue;
	      
	    case 0:
	      int_error( NO_CARET, "bad data on line %d of file %s",
	  		df_line_number, df_filename ? df_filename : "" );
	      break;

	    case 1: /* Read single column successfully  */
	      if ( validate_data(v[0], FIRST_Y_AXIS) )  {
		data_y[n] = v[0];
		n++;
	      } else {
		out_of_range++;
	      }
	      break;

	    case 2: /* Read two columns successfully  */
	      if ( validate_data(v[0], FIRST_X_AXIS) &&
		  validate_data(v[1], FIRST_Y_AXIS) ) {
		data_x[n] = v[0];
		data_y[n] = v[1];
		n++;
	      } else {
		out_of_range++;
	      }
	      break;
	    }
	} /* end-while : done reading file */
	df_close();

	/* now resize fields to actual length: */
	redim_vec(&data_x, n);
	redim_vec(&data_y, n);

	/* figure out how many columns where really read... */
	if ( columns == 0 )
	    columns = columnsread;

    }  /* end of case when the data file is not a matrix */

    /* Now finished reading user input; return to C locale for internal use*/
    reset_numeric_locale();

    /* PKJ - TODO: similar for logscale, polar/parametric, timedata */

    /* No data! Try to explain why. */
    if ( n == 0 ) {
	if ( out_of_range > 0 )
	    int_error( NO_CARET, "All points out of range" );
	else 
	    int_error( NO_CARET, "No valid data points found in file" );
    }

    /* Parse the remainder of the command line: 0 to 2 tokens possible */
    while( !(END_OF_COMMAND) ) {
	if ( almost_equals( c_token, "out$put" ) ) {
		do_output = TRUE;
		c_token++;

	} else if ( almost_equals( c_token, "noout$put" ) ) {
		do_output = FALSE;
		c_token++;

	} else if ( almost_equals(c_token, "pre$fix") 
	       ||   equals(c_token, "name")) {
	    c_token++;
	    free ( prefix );
	    prefix = try_to_get_string();
	    if (!legal_identifier(prefix) || !strcmp ("GPVAL_", prefix))
		int_error( --c_token, "illegal prefix" );

	}  else {
	    int_error( c_token, "Expecting [no]output or prefix");
	}

    }

    /* Set defaults if not explicitly set by user */
    if (!prefix)
	prefix = gp_strdup("STATS_");
    i = strlen(prefix);
    if (prefix[i-1] != '_') {
	prefix = gp_realloc(prefix, i+2, "prefix");
	strcat(prefix,"_");
    }

    /* Do the actual analysis */
    res_file = analyze_file( n, out_of_range, invalid, blanks, doubleblanks );
    if ( columns == 1 ) {
	res_y = analyze_sgl_column( data_y, n, nr );
    }

    if ( columns == 2 ) {
	/* If there are two columns, then the data file is not a matrix */
	res_x = analyze_sgl_column( data_x, n, 0 );
	res_y = analyze_sgl_column( data_y, n, 0 );
	res_xy = analyze_two_columns( data_x, data_y, res_x, res_y, n );
    }

    /* Store results in user-accessible variables */
    /* Clear out any previous use of these variables */
    del_udv_by_name( prefix, TRUE );

    file_variables( res_file, prefix );

    if ( columns == 1 ) {
	sgl_column_variables( res_y, prefix, "" );
    }
    
    if ( columns == 2 ) {
	sgl_column_variables( res_x, prefix, "_x" );
	sgl_column_variables( res_y, prefix, "_y" );
	two_column_variables( res_xy, prefix );
    }

    /* Output */
    if ( do_output ) {
	file_output( res_file );
	if ( columns == 1 )
	    sgl_column_output( res_y, res_file.records );
	else
	    two_column_output( res_x, res_y, res_xy, res_file.records );
    }

    /* Cleanup */
      
    free(data_x);
    free(data_y);

    data_x = NULL;
    data_y = NULL;
    
    free( file_name );
    file_name = NULL;
    
    free( prefix );
    prefix = NULL;
}
Exemplo n.º 22
0
void
mcs_interp(struct curve_points *plot)
{
    /* These track the original (pre-sorted) data points */
    int N = plot->p_count;
    struct coordinate *p = gp_realloc(plot->points, (N+1) * sizeof(coordinate), "mcs");
    int i;

    /* These will track the resulting smoothed curve (>= 3X original count) */
    /* Larger number of samples gives smoother curve (no surprise!) */
    int Nsamp = (samples_1 > 2*N) ? samples_1 : 2*N;
    int Ntot = N + Nsamp;
    struct coordinate *new_points = gp_alloc((Ntot) * sizeof(coordinate), "mcs");
    double xstart = GPMAX(p[0].x, X_AXIS.min);
    double xend = GPMIN(p[N-1].x, X_AXIS.max);
    double xstep = (xend - xstart) / (Nsamp - 1);

    /* Load output x coords for sampling */
    for (i=0; i<N; i++)
	new_points[i].x = p[i].x;
    for ( ; i<Ntot; i++)
	new_points[i].x = xstart + (i-N)*xstep;
    /* Sort output x coords */
    qsort(new_points, Ntot, sizeof(struct coordinate), compare_points);
    /* Displace any collisions */
    for (i=1; i<Ntot-1; i++) {
	double delta = new_points[i].x - new_points[i-1].x;
	if (new_points[i+1].x - new_points[i].x < delta/1000.)
	    new_points[i].x -= delta/2.;
    }

    /* Calculate spline coefficients */
#define DX	xlow
#define SLOPE	xhigh
#define C1	ylow
#define C2	yhigh
#define C3	z

    for (i = 0; i < N-1; i++) {
	p[i].DX = p[i+1].x - p[i].x;
	p[i].SLOPE = (p[i+1].y - p[i].y) / p[i].DX;
    }
    p[N-1].SLOPE = 0;

    p[0].C1 = p[0].SLOPE;
    for (i = 0; i < N-1; i++) {
	if (p[i].SLOPE * p[i+1].SLOPE <= 0) {
	    p[i+1].C1 = 0;
	} else {
	    double sum = p[i].DX + p[i+1].DX;
	    p[i+1].C1 = (3. * sum)
		    / ((sum + p[i+1].DX) /  p[i].SLOPE + (sum + p[i].DX) /  p[i+1].SLOPE);
	}
    }
    p[N].C1 = p[N-1].SLOPE;

    for (i = 0; i < N; i++) {
	double temp = p[i].C1 + p[i+1].C1 - 2*p[i].SLOPE;
	p[i].C2 = (p[i].SLOPE - p[i].C1 -temp) / p[i].DX;
	p[i].C3 = temp / (p[i].DX * p[i].DX);
    }

    /* Use the coefficients C1, C2, C3 to interpolate over the requested range */
    for (i = 0; i < Ntot; i++) {
	double x = new_points[i].x;
	double y;
	TBOOLEAN exact = FALSE;

	if (x == p[N-1].x) {	/* Exact value for right-most point of original data */
	    y = p[N-1].y;
	    exact = TRUE;
	} else {
	    int low = 0;
	    int mid; 
	    int high = N-1;
	    while (low <= high) {
		mid = floor((low + high) / 2);
		if (p[mid].x < x)
		    low = mid + 1;
		else if (p[mid].x > x)
		    high = mid - 1;
		else {		/* Exact value for some point in original data */
		    y = p[mid].y;
		    exact = TRUE;
		    break;
		}
	    }
	    if (!exact) {
		int j = GPMAX(0, high);
		double diff = x - p[j].x;
		y = p[j].y + p[j].C1 * diff + p[j].C2 * diff * diff + p[j].C3 * diff * diff * diff;
	    }
	}

	xstart = X_AXIS.min;
	xend = X_AXIS.max;
	if (inrange(x, xstart, xend))
	    new_points[i].type = INRANGE;
	else
	    new_points[i].type = OUTRANGE;
	/* FIXME:  simpler test for outrange would be sufficient */
	STORE_AND_UPDATE_RANGE(new_points[i].y, y, new_points[i].type,
		plot->y_axis, plot->noautoscale, NOOP);
    }

    /* Replace original data with the interpolated curve */
    free(p);
    plot->points = new_points;
    plot->p_count = Ntot;
    plot->p_max = Ntot + 1;

#undef DX
#undef SLOPE
#undef C1
#undef C2
#undef C3
}
Exemplo n.º 23
0
/*
 * char *fontpath_handler (int, char *)
 *
 */
char *
fontpath_handler(int action, char *path)
{
    /* fontpath variable
     * the path elements are '\0' separated (!)
     * this way, reading out fontpath is very
     * easy to implement */
    static char *fontpath;
    /* index pointer, end of fontpath,
     * env section of fontpath, current limit, in that order */
    static char *p, *last, *envptr, *limit;

    if (!fontpath_init_done) {
	fontpath_init_done = TRUE;
	init_fontpath();
    }

    switch (action) {
    case ACTION_CLEAR:
	/* Clear fontpath, fall through to init */
	FPRINTF((stderr, "Clear fontpath\n"));
	free(fontpath);
	fontpath = p = last = NULL;
	/* HBB 20000726: 'limit' has to be initialized to NULL, too! */
	limit = NULL;
    case ACTION_INIT:
	/* Init fontpath from environment */
	FPRINTF((stderr, "Init fontpath from environment\n"));
	assert(fontpath == NULL);
	if (!fontpath)
	{
	    char *envlib = getenv("GNUPLOT_FONTPATH");
	    if (envlib) {
		/* get paths from environment */
		int len = strlen(envlib);
		fontpath = gp_strdup(envlib);
		/* point to end of fontpath */
		last = fontpath + len;
		/* convert all PATHSEPs to \0 */
		PATHSEP_TO_NUL(fontpath);
	    }
#if defined(HAVE_DIRENT_H) || defined(_Windows)
	    else {
		/* set hardcoded paths */
		const struct path_table *curr_fontpath = fontpath_tbl;

		while (curr_fontpath->dir) {
		    char *currdir = NULL;
		    char *envbeg = NULL;
#  if defined(PIPES)
		    char *cmdbeg = NULL;
#  endif
		    TBOOLEAN subdirs = FALSE;

		    currdir = gp_strdup( curr_fontpath->dir );

		    while ( (envbeg=strstr(currdir, "$("))
#  if defined(PIPES)
			    || (cmdbeg=strstr( currdir, "$`" ))
#  endif
			    ) {
			/* Read environment variables */
			if (envbeg) {
			    char *tmpdir = NULL;
			    char *envend = NULL, *envval = NULL;
			    unsigned int envlen;
			    envend = strchr(envbeg+2,')');
			    envend[0] = '\0';
			    envval = getenv(envbeg+2);
			    envend[0] = ')';
			    envlen = envval ? strlen(envval) : 0;
			    tmpdir = gp_alloc(strlen(currdir)+envlen
					      +envbeg-envend+1,
					      "expand fontpath");
			    strncpy(tmpdir,currdir,envbeg-currdir);
			    if (envval)
				strcpy(tmpdir+(envbeg-currdir),envval);
			    strcpy(tmpdir+(envbeg-currdir+envlen), envend+1);

			    free(currdir);
			    currdir = tmpdir;
			}
#  if defined(PIPES)
			/* Read environment variables */
			else if (cmdbeg) {
			    char *tmpdir = NULL;
			    char *envend = NULL;
			    char envval[256];
			    unsigned int envlen;
			    FILE *fcmd;
			    envend = strchr(cmdbeg+2,'`');
			    envend[0] = '\0';
			    restrict_popen();
			    fcmd = popen(cmdbeg+2,"r");
			    if (fcmd) {
				fgets(envval,255,fcmd);
				if (envval[strlen(envval)-1]=='\n')
				    envval[strlen(envval)-1]='\0';
				pclose(fcmd);
			    }
			    envend[0] = '`';
			    envlen = strlen(envval);
			    tmpdir = gp_alloc(strlen(currdir)+envlen
					      +cmdbeg-envend+1,
					      "expand fontpath");
			    strncpy(tmpdir,currdir,cmdbeg-currdir);
			    if (*envval)
				strcpy(tmpdir+(cmdbeg-currdir),envval);
			    strcpy(tmpdir+(cmdbeg-currdir+envlen), envend+1);

			    free(currdir);
			    currdir = tmpdir;
			}
#  endif
		    }

		    if ( currdir[strlen(currdir)-1] == '!' ) {
			/* search subdirectories */
			/* delete ! from directory name */
			currdir[strlen(currdir)-1] = '\0';
			subdirs = TRUE;
		    }

		    if ( existdir( currdir ) ) {
			size_t plen;
			if ( subdirs )
			    /* add ! to directory name again */
			    currdir[strlen(currdir)] = '!';
			plen = strlen(currdir);
			if (fontpath) {
			    size_t elen = strlen(fontpath);
			    fontpath = gp_realloc(fontpath,
						  elen + 1 + plen + 1,
						  "expand fontpath");
			    last = fontpath+elen;
			    *last = PATHSEP;
			    ++last;
			    *last = '\0';
			} else {
			    fontpath = gp_alloc(plen + 1,
						"expand fontpath");
			    last = fontpath;
			}

			strcpy(last, currdir );
			last += plen;
		    }
		    curr_fontpath++;
		    if (currdir) {
			free(currdir);
			currdir = NULL;
		    }
		}
		/* convert all PATHSEPs to \0 */
		if (fontpath)
		    PATHSEP_TO_NUL(fontpath);
	    }
#endif /* HAVE_DIRENT_H */

	}			/* else: already initialised; int_warn (?) */
	/* point to env portion of fontpath */
	envptr = fontpath;
	break;
    case ACTION_SET:
	/* set the fontpath */
	FPRINTF((stderr, "Set fontpath\n"));
	if (path && *path != NUL) {
	    /* length of env portion */
	    size_t elen = last - envptr;
	    size_t plen = strlen(path);
	    if (fontpath && envptr) {
		/* we are prepending a path name; because
		 * realloc() preserves only the contents up
		 * to the minimum of old and new size, we move
		 * the part to be preserved to the beginning
		 * of the string; use memmove() because strings
		 * may overlap */
		memmove(fontpath, envptr, elen + 1);
	    }
	    fontpath = gp_realloc(fontpath, elen + 1 + plen + 1, "expand fontpath");
	    /* now move env part back to the end to make space for
	     * the new path */
	    memmove(fontpath + plen + 1, fontpath, elen + 1);
	    strcpy(fontpath, path);
	    /* separate new path(s) and env path(s) */
	    fontpath[plen] = PATHSEP;
	    /* adjust pointer to env part and last */
	    envptr = &fontpath[plen+1];
	    last = envptr + elen;
	    PATHSEP_TO_NUL(fontpath);
	}			/* else: NULL = empty */
	break;
    case ACTION_SHOW:
	/* print the current, full fontpath */
	FPRINTF((stderr, "Show fontpath\n"));
	if (fontpath) {
	    fputs("\tfontpath is ", stderr);
	    PRINT_PATHLIST(fontpath, envptr);
	    if (envptr) {
		/* env part */
		fputs("\tsystem fontpath is ", stderr);
		PRINT_PATHLIST(envptr, last);
	    }
	} else
	    fputs("\tfontpath is empty\n", stderr);
	break;
    case ACTION_SAVE:
	/* we don't save the font path taken from the
	 * environment, so don't go beyond envptr when
	 * extracting the path elements
	 */
	limit = envptr;
    case ACTION_GET:
	/* subsequent calls to get_fontpath() return all
	 * elements of the fontpath until exhausted
	 */
	FPRINTF((stderr, "Get fontpath\n"));
	if (!fontpath)
	    return NULL;
	if (!p) {
	    /* init section */
	    p = fontpath;
	    if (!limit)
		limit = last;
	} else {
	    /* skip over '\0' */
	    p += strlen(p) + 1;
	}
	if (p >= limit)
	    limit = p = NULL;
	return p;
    case ACTION_NULL:
	/* just return */
    default:
	break;
    }

    /* should always be ignored - points to the
     * first path in the list */
    return fontpath;

}
Exemplo n.º 24
0
char *
locale_handler(int action, char *newlocale)
{
    struct tm tm;
    int i;

    switch(action) {
    case ACTION_CLEAR:
    case ACTION_INIT:
	free(current_locale);
#ifdef HAVE_LOCALE_H
	setlocale(LC_TIME, "");
	setlocale(LC_CTYPE, "");
	current_locale = gp_strdup(setlocale(LC_TIME,NULL));
#else
	current_locale = gp_strdup(INITIAL_LOCALE);
#endif
	break;

    case ACTION_SET:
#ifdef HAVE_LOCALE_H
	if (setlocale(LC_TIME, newlocale)) {
	    free(current_locale);
	    current_locale = gp_strdup(setlocale(LC_TIME,NULL));
	} else {
	    int_error(c_token, "Locale not available");
	}

	/* we can do a *lot* better than this ; eg use system functions
	 * where available; create values on first use, etc
	 */
	memset(&tm, 0, sizeof(struct tm));
	for (i = 0; i < 7; ++i) {
	    tm.tm_wday = i;		/* hope this enough */
	    strftime(full_day_names[i], sizeof(full_day_names[i]), "%A", &tm);
	    strftime(abbrev_day_names[i], sizeof(abbrev_day_names[i]), "%a", &tm);
	}
	for (i = 0; i < 12; ++i) {
	    tm.tm_mon = i;		/* hope this enough */
	    strftime(full_month_names[i], sizeof(full_month_names[i]), "%B", &tm);
	    strftime(abbrev_month_names[i], sizeof(abbrev_month_names[i]), "%b", &tm);
	}
#else
	current_locale = gp_realloc(current_locale, strlen(newlocale) + 1, "locale");
	strcpy(current_locale, newlocale);
#endif /* HAVE_LOCALE_H */
	break;

    case ACTION_SHOW:
#ifdef HAVE_LOCALE_H
	fprintf(stderr, "\tgnuplot LC_CTYPE   %s\n", setlocale(LC_CTYPE,NULL));
	fprintf(stderr, "\tgnuplot encoding   %s\n", encoding_names[encoding]);
	fprintf(stderr, "\tgnuplot LC_TIME    %s\n", setlocale(LC_TIME,NULL));
	fprintf(stderr, "\tgnuplot LC_NUMERIC %s\n", numeric_locale ? numeric_locale : "C");
#else
	fprintf(stderr, "\tlocale is \"%s\"\n", current_locale);
#endif
	break;
    
    case ACTION_GET:
    default:
	break;
    }

    return current_locale;
}
Exemplo n.º 25
0
/* convert a struct value to a string */
char *
value_to_str(struct value *val, TBOOLEAN need_quotes)
{
    static int i = 0;
    static char * s[4] = {NULL, NULL, NULL, NULL};
    static size_t c[4] = {0, 0, 0, 0};
    static const int minbufsize = 54;
    int j = i;

    i = (i + 1) % 4;
    if (s[j] == NULL) {
        s[j] = (char *) gp_alloc(minbufsize, "value_to_str");
        c[j] = minbufsize;
    }

    switch (val->type) {
    case INTGR:
        sprintf(s[j], "%d", val->v.int_val);
        break;
    case CMPLX:
        if (isnan(val->v.cmplx_val.real))
            sprintf(s[j], "NaN");
        else if (val->v.cmplx_val.imag != 0.0)
            sprintf(s[j], "{%s, %s}",
                    num_to_str(val->v.cmplx_val.real),
                    num_to_str(val->v.cmplx_val.imag));
        else
            return num_to_str(val->v.cmplx_val.real);
        break;
    case STRING:
        if (val->v.string_val) {
            if (!need_quotes) {
                return val->v.string_val;
            } else {
                char * cstr = conv_text(val->v.string_val);
                size_t reqsize = strlen(cstr) + 3;
                if (reqsize > c[j]) {
                    /* Don't leave c[j[ non-zero if realloc fails */
                    s[j] = (char *) gp_realloc(s[j], reqsize + 20, NULL);
                    if (s[j] != NULL) {
                        c[j] = reqsize + 20;
                    } else {
                        c[j] = 0;
                        int_error(NO_CARET, "out of memory");
                    }
                }
                sprintf(s[j], "\"%s\"", cstr);
            }
        } else {
            s[j][0] = NUL;
        }
        break;
    case DATABLOCK:
    {
        char **dataline = val->v.data_array;
        int nlines = 0;
        if (dataline != NULL) {
            while (*dataline++ != NULL)
                nlines++;
        }
        sprintf(s[j], "<%d line data block>", nlines);
        break;
    }
    default:
        int_error(NO_CARET, "unknown type in value_to_str()");
    }

    return s[j];
}
Exemplo n.º 26
0
/*
 * char *loadpath_handler (int, char *)
 *
 */
char *
loadpath_handler(int action, char *path)
{
    /* loadpath variable
     * the path elements are '\0' separated (!)
     * this way, reading out loadpath is very
     * easy to implement */
    static char *loadpath;
    /* index pointer, end of loadpath,
     * env section of loadpath, current limit, in that order */
    static char *p, *last, *envptr, *limit;
#ifdef X11
    char *appdir;
#endif

    switch (action) {
    case ACTION_CLEAR:
	/* Clear loadpath, fall through to init */
	FPRINTF((stderr, "Clear loadpath\n"));
	free(loadpath);
	loadpath = p = last = NULL;
	/* HBB 20000726: 'limit' has to be initialized to NULL, too! */
	limit = NULL;
    case ACTION_INIT:
	/* Init loadpath from environment */
	FPRINTF((stderr, "Init loadpath from environment\n"));
	assert(loadpath == NULL);
	if (!loadpath)
	{
	    char *envlib = getenv("GNUPLOT_LIB");
	    if (envlib) {
		int len = strlen(envlib);
		loadpath = gp_strdup(envlib);
		/* point to end of loadpath */
		last = loadpath + len;
		/* convert all PATHSEPs to \0 */
		PATHSEP_TO_NUL(loadpath);
	    }			/* else: NULL = empty */
	}			/* else: already initialised; int_warn (?) */
	/* point to env portion of loadpath */
	envptr = loadpath;
	break;
    case ACTION_SET:
	/* set the loadpath */
	FPRINTF((stderr, "Set loadpath\n"));
	if (path && *path != NUL) {
	    /* length of env portion */
	    size_t elen = last - envptr;
	    size_t plen = strlen(path);
	    if (loadpath && envptr) {
		/* we are prepending a path name; because
		 * realloc() preserves only the contents up
		 * to the minimum of old and new size, we move
		 * the part to be preserved to the beginning
		 * of the string; use memmove() because strings
		 * may overlap */
		memmove(loadpath, envptr, elen + 1);
	    }
	    loadpath = gp_realloc(loadpath, elen + 1 + plen + 1, "expand loadpath");
	    /* now move env part back to the end to make space for
	     * the new path */
	    memmove(loadpath + plen + 1, loadpath, elen + 1);
	    strcpy(loadpath, path);
	    /* separate new path(s) and env path(s) */
	    loadpath[plen] = PATHSEP;
	    /* adjust pointer to env part and last */
	    envptr = &loadpath[plen+1];
	    last = envptr + elen;
	    PATHSEP_TO_NUL(loadpath);
	}			/* else: NULL = empty */
	break;
    case ACTION_SHOW:
	/* print the current, full loadpath */
	FPRINTF((stderr, "Show loadpath\n"));
	if (loadpath) {
	    fputs("\tloadpath is ", stderr);
	    PRINT_PATHLIST(loadpath, envptr);
	    if (envptr) {
		/* env part */
		fputs("\tloadpath from GNUPLOT_LIB is ", stderr);
		PRINT_PATHLIST(envptr, last);
	    }
	} else
	    fputs("\tloadpath is empty\n", stderr);
#ifdef GNUPLOT_SHARE_DIR
	fprintf(stderr,"\tgnuplotrc is read from %s\n",GNUPLOT_SHARE_DIR);
#endif
#ifdef X11
	if ((appdir = getenv("XAPPLRESDIR"))) {
	    fprintf(stderr,"\tenvironmental path for X11 application defaults: \"%s\"\n",
		appdir);
	}
#ifdef XAPPLRESDIR
	else {
	    fprintf(stderr,"\tno XAPPLRESDIR found in the environment,\n");
	    fprintf(stderr,"\t    falling back to \"%s\"\n", XAPPLRESDIR);
	}
#endif
#endif
	break;
    case ACTION_SAVE:
	/* we don't save the load path taken from the
	 * environment, so don't go beyond envptr when
	 * extracting the path elements
	 */
	limit = envptr;
    case ACTION_GET:
	/* subsequent calls to get_loadpath() return all
	 * elements of the loadpath until exhausted
	 */
	FPRINTF((stderr, "Get loadpath\n"));
	if (!loadpath)
	    return NULL;
	if (!p) {
	    /* init section */
	    p = loadpath;
	    if (!limit)
		limit = last;
	} else {
	    /* skip over '\0' */
	    p += strlen(p) + 1;
	}
	if (p >= limit) 
	    limit = p = NULL;
	return p;
	break;
    case ACTION_NULL:
	/* just return */
    default:
	break;
    }

    /* should always be ignored - points to the
     * first path in the list */
    return loadpath;

}
Exemplo n.º 27
0
/*
 * Binned histogram of input values.
 *   plot FOO using N:(1) bins{=<nbins>} {binrange=[binlow:binhigh]} with boxes
 * If no binrange is given, the range is taken from the x axis range.
 * In the latter case "set xrange" may exclude some data points,
 * while "set auto x" will include all data points.
 */
void
make_bins(struct curve_points *plot, int nbins, double binlow, double binhigh)
{
    int i, binno;
    double *bin;
    double bottom, top, binwidth, range;
    struct axis *xaxis = &axis_array[plot->x_axis];
    struct axis *yaxis = &axis_array[plot->y_axis];
    double ymax = 0;
    int N = plot->p_count;

    /* Divide the range on X into the requested number of bins.
     * NB: This range is independent of the values of the points.
     */
    if (binlow == 0 && binhigh == 0) {
	bottom = xaxis->data_min;
	top = xaxis->data_max;
    } else {
	bottom = binlow;
	top = binhigh;
    }
    bottom = axis_log_value(xaxis, bottom);
    top = axis_log_value(xaxis, top);
    binwidth = (top - bottom) / (nbins - 1);
    bottom -= binwidth/2.;
    top += binwidth/2.;
    range = top - bottom;

    bin = gp_alloc(nbins*sizeof(double), "bins");
    for (i=0; i<nbins; i++)
 	bin[i] = 0;
    for (i=0; i<N; i++) {
	if (plot->points[i].type == UNDEFINED)
	    continue;
	binno = floor(nbins * (plot->points[i].x - bottom) / range);
        /* FIXME: Should outrange points be dumped in the first/last bin? */
	if (0 <= binno && binno < nbins)
	    bin[binno] += axis_de_log_value(yaxis, plot->points[i].y);
    }

    if (xaxis->autoscale & AUTOSCALE_MIN) {
	if (xaxis->min > bottom)
	    xaxis->min = bottom;
    }
    if (xaxis->autoscale & AUTOSCALE_MAX) {
	if (xaxis->max < top)
	    xaxis->max = top;
    }

    /* Replace the original data with one entry per bin.
     * new x = midpoint of bin
     * new y = number of points in the bin
     */
    plot->p_count = nbins;
    plot->points = gp_realloc( plot->points, nbins * sizeof(struct coordinate), "curve_points");
    for (i=0; i<nbins; i++) {
	double bincent = bottom + (0.5 + (double)i) * binwidth;
	plot->points[i].type = INRANGE;
	plot->points[i].x     = bincent;
	plot->points[i].xlow  = bincent - binwidth/2.;
	plot->points[i].xhigh = bincent + binwidth/2.;
	plot->points[i].y     = axis_log_value(yaxis, bin[i]);
	plot->points[i].ylow  = plot->points[i].y;
	plot->points[i].yhigh = plot->points[i].y;
	plot->points[i].z = 0;	/* FIXME: leave it alone? */
	if (inrange(axis_de_log_value(xaxis, bincent), xaxis->min, xaxis->max)) {
	    if (ymax < bin[i])
		ymax = bin[i];
	} else {
	    plot->points[i].type = OUTRANGE;
	}
	FPRINTF((stderr, "bin[%d] %g %g\n", i, plot->points[i].x, plot->points[i].y));
    }

    if (yaxis->autoscale & AUTOSCALE_MIN) {
	if (yaxis->min > 0)
	    yaxis->min = 0;
    }
    if (yaxis->autoscale & AUTOSCALE_MAX) {
	if (yaxis->max < ymax)
	    yaxis->max = ymax;
    }

    /* Clean up */
    free(bin);
}
Exemplo n.º 28
0
/* EAM July 2004  (revised to dynamic buffer July 2005)
 * There are probably an infinite number of things that can
 * go wrong if the user mis-matches arguments and format strings
 * in the call to sprintf, but I hope none will do worse than
 * result in a garbage output string.
 */
void
f_sprintf(union argument *arg)
{
    struct value a[10], *args;
    struct value num_params;
    struct value result;
    char *buffer;
    int bufsize;
    char *next_start, *outpos, tempchar;
    int next_length;
    char *prev_start;
    int prev_pos;
    int i, remaining;
    int nargs = 0;
    enum DATA_TYPES spec_type;

    /* Retrieve number of parameters from top of stack */
    pop(&num_params);
    nargs = num_params.v.int_val;
    if (nargs > 10) {	/* Fall back to slow but sure allocation */
	args = gp_alloc(sizeof(struct value)*nargs, "sprintf args");
    } else
	args = a;

    for (i=0; i<nargs; i++)
	pop(&args[i]);  /* pop next argument */

    /* Make sure we got a format string of some sort */
    if (args[nargs-1].type != STRING)
	int_error(NO_CARET,"First parameter to sprintf must be a format string");

    /* Allocate space for the output string. If this isn't */
    /* long enough we can reallocate a larger space later. */
    bufsize = 80 + strlen(args[nargs-1].v.string_val);
    buffer = gp_alloc(bufsize, "f_sprintf");

    /* Copy leading fragment of format into output buffer */
    outpos = buffer;
    next_start  = args[nargs-1].v.string_val;
    next_length = strcspn(next_start,"%");
    strncpy(outpos, next_start, next_length);

    next_start += next_length;
    outpos += next_length;

    /* Format the remaining sprintf() parameters one by one */
    prev_start = next_start;
    prev_pos = next_length;
    remaining = nargs - 1;

    /* If the user has set an explicit LC_NUMERIC locale, apply it */
    /* to sprintf calls during expression evaluation.              */
    set_numeric_locale();

    /* Each time we start this loop we are pointing to a % character */
    while (remaining-->0 && next_start[0] && next_start[1]) {
	struct value *next_param = &args[remaining];

	/* Check for %%; print as literal and don't consume a parameter */
	if (!strncmp(next_start,"%%",2)) {
	    next_start++;
	    do {
		*outpos++ = *next_start++;
	    } while(*next_start && *next_start != '%');
	    remaining++;
	    continue;
	}

	next_length = strcspn(next_start+1,"%") + 1;
	tempchar = next_start[next_length];
	next_start[next_length] = '\0';

	spec_type = sprintf_specifier(next_start);

	/* string value <-> numerical value check */
	if ( spec_type == STRING && next_param->type != STRING )
	    int_error(NO_CARET,"f_sprintf: attempt to print numeric value with string format");
	if ( spec_type != STRING && next_param->type == STRING )
	    int_error(NO_CARET,"f_sprintf: attempt to print string value with numeric format");

#ifdef HAVE_SNPRINTF
	/* Use the format to print next arg */
	switch(spec_type) {
	case INTGR:
	    snprintf(outpos,bufsize-(outpos-buffer),
		     next_start, (int)real(next_param));
	    break;
	case CMPLX:
	    snprintf(outpos,bufsize-(outpos-buffer),
		     next_start, real(next_param));
	    break;
	case STRING:
	    snprintf(outpos,bufsize-(outpos-buffer),
		next_start, next_param->v.string_val);
	    break;
	default:
	    int_error(NO_CARET,"internal error: invalid spec_type");
	}
#else
	/* FIXME - this is bad; we should dummy up an snprintf equivalent */
	switch(spec_type) {
	case INTGR:
	    sprintf(outpos, next_start, (int)real(next_param));
	    break;
	case CMPLX:
	    sprintf(outpos, next_start, real(next_param));
	    break;
	case STRING:
	    sprintf(outpos, next_start, next_param->v.string_val);
	    break;
	default:
	    int_error(NO_CARET,"internal error: invalid spec_type");
	}
#endif

	next_start[next_length] = tempchar;
	next_start += next_length;
	outpos = &buffer[strlen(buffer)];

	/* Check whether previous parameter output hit the end of the buffer */
	/* If so, reallocate a larger buffer, go back and try it again.      */
	if (strlen(buffer) >= bufsize-2) {
	    bufsize *= 2;
	    buffer = gp_realloc(buffer, bufsize, "f_sprintf");
	    next_start = prev_start;
	    outpos = buffer + prev_pos;
	    remaining++;
	    continue;
	} else {
	    prev_start = next_start;
	    prev_pos = outpos - buffer;
	}

    }

    /* Copy the trailing portion of the format, if any */
    /* We could just call snprintf(), but it doesn't check for */
    /* whether there really are more variables to handle.      */
    i = bufsize - (outpos-buffer);
    while (*next_start && --i > 0) {
	if (*next_start == '%' && *(next_start+1) == '%')
	    next_start++;
	*outpos++ = *next_start++;
    }
    *outpos = '\0';

    FPRINTF((stderr," snprintf result = \"%s\"\n",buffer));
    push(Gstring(&result, buffer));
    free(buffer);

    /* Free any strings from parameters we have now used */
    for (i=0; i<nargs; i++)
	gpfree_string(&args[i]);

    if (args != a)
	free(args);

    /* Return to C locale for internal use */
    reset_numeric_locale();

}
Exemplo n.º 29
0
char *
readline(const char *prompt)
{
    int cur_char;
    char *new_line;


    /* start with a string of MAXBUF chars */
    if (line_len != 0) {
	free(cur_line);
	line_len = 0;
    }
    cur_line = gp_alloc(MAXBUF, "readline");
    line_len = MAXBUF;

    /* set the termio so we can do our own input processing */
    set_termio();

    /* print the prompt */
    fputs(prompt, stderr);
    cur_line[0] = '\0';
    cur_pos = 0;
    max_pos = 0;
    cur_entry = NULL;

    /* get characters */
    for (;;) {

	cur_char = special_getc();

	/* Accumulate ascii (7bit) printable characters
	 * and all leading 8bit characters.
	 */
	if ((isprint(cur_char)
	      || (((cur_char & 0x80) != 0) && (cur_char != EOF)))
	    && (cur_char != 0x09) /* TAB is a printable character in some locales */
	    ) {
	    size_t i;

	    if (max_pos + 1 >= line_len) {
		extend_cur_line();
	    }
	    for (i = max_pos; i > cur_pos; i--) {
		cur_line[i] = cur_line[i - 1];
	    }
	    user_putc(cur_char);

	    cur_line[cur_pos] = cur_char;
	    cur_pos += 1;
	    max_pos += 1;
	    cur_line[max_pos] = '\0';

	    if (cur_pos < max_pos) {
		switch (encoding) {
		case S_ENC_UTF8:
		    if ((cur_char & 0xc0) == 0)
			fix_line(); /* Normal ascii character */
		    else if ((cur_char & 0xc0) == 0xc0)
			; /* start of a multibyte sequence. */
		    else if (((cur_char & 0xc0) == 0x80) &&
			 ((unsigned char)(cur_line[cur_pos-2]) >= 0xe0))
			; /* second byte of a >2 byte sequence */
		    else {
			/* Last char of multi-byte sequence */
			fix_line();
		    }
		    break;
		default:
		    fix_line();
		    break;
		}
	    }

	/* else interpret unix terminal driver characters */
#ifdef VERASE
	} else if (cur_char == term_chars[VERASE]) {	/* ^H */
	    delete_backward();
#endif /* VERASE */
#ifdef VEOF
	} else if (cur_char == term_chars[VEOF]) {	/* ^D? */
	    if (max_pos == 0) {
		reset_termio();
		return ((char *) NULL);
	    }
	    delete_forward();
#endif /* VEOF */
#ifdef VKILL
	} else if (cur_char == term_chars[VKILL]) {	/* ^U? */
	    clear_line(prompt);
#endif /* VKILL */
#ifdef VWERASE
	} else if (cur_char == term_chars[VWERASE]) {	/* ^W? */
	    delete_previous_word();
#endif /* VWERASE */
#ifdef VREPRINT
	} else if (cur_char == term_chars[VREPRINT]) {	/* ^R? */
	    putc(NEWLINE, stderr);	/* go to a fresh line */
	    redraw_line(prompt);
#endif /* VREPRINT */
#ifdef VSUSP
	} else if (cur_char == term_chars[VSUSP]) {
	    reset_termio();
	    kill(0, SIGTSTP);

	    /* process stops here */

	    set_termio();
	    /* print the prompt */
	    redraw_line(prompt);
#endif /* VSUSP */
	} else {
	    /* do normal editing commands */
	    /* some of these are also done above */
	    switch (cur_char) {
	    case EOF:
		reset_termio();
		return ((char *) NULL);
	    case 001:		/* ^A */
		while (cur_pos > 0)
		    backspace();
		break;
	    case 002:		/* ^B */
		if (cur_pos > 0)
		    backspace();
		break;
	    case 005:		/* ^E */
		while (cur_pos < max_pos) {
		    user_putc(cur_line[cur_pos]);
		    cur_pos += 1;
		}
		break;
	    case 006:		/* ^F */
		if (cur_pos < max_pos) {
		    step_forward();
		}
		break;
#if defined(HAVE_DIRENT_H) || defined(WIN32)
	    case 011:		/* ^I / TAB */
		tab_completion(TRUE); /* next tab completion */
		break;
	    case 034:		/* remapped by wtext.c or ansi_getc from Shift-Tab */
		tab_completion(FALSE); /* previous tab completion */
		break;
#endif
	    case 013:		/* ^K */
		clear_eoline(prompt);
		max_pos = cur_pos;
		break;
	    case 020:		/* ^P */
		if (history != NULL) {
		    if (cur_entry == NULL) {
			cur_entry = history;
			clear_line(prompt);
			copy_line(cur_entry->line);
		    } else if (cur_entry->prev != NULL) {
			cur_entry = cur_entry->prev;
			clear_line(prompt);
			copy_line(cur_entry->line);
		    }
		}
		break;
	    case 016:		/* ^N */
		if (cur_entry != NULL) {
		    cur_entry = cur_entry->next;
		    clear_line(prompt);
		    if (cur_entry != NULL)
			copy_line(cur_entry->line);
		    else
			cur_pos = max_pos = 0;
		}
		break;
	    case 014:		/* ^L */
	    case 022:		/* ^R */
		putc(NEWLINE, stderr);	/* go to a fresh line */
		redraw_line(prompt);
		break;
#ifndef DEL_ERASES_CURRENT_CHAR
	    case 0177:		/* DEL */
	    case 023:		/* Re-mapped from CSI~3 in ansi_getc() */
#endif
	    case 010:		/* ^H */
		delete_backward();
		break;
	    case 004:		/* ^D */
		if (max_pos == 0) {
		    reset_termio();
		    return ((char *) NULL);
		}
		/* intentionally omitting break */
#ifdef DEL_ERASES_CURRENT_CHAR
	    case 0177:		/* DEL */
	    case 023:		/* Re-mapped from CSI~3 in ansi_getc() */
#endif
		delete_forward();
		break;
	    case 025:		/* ^U */
		clear_line(prompt);
		break;
	    case 027:		/* ^W */
		delete_previous_word();
		break;
	    case '\n':		/* ^J */
	    case '\r':		/* ^M */
		cur_line[max_pos + 1] = '\0';
#ifdef OS2
		while (cur_pos < max_pos) {
		    user_putc(cur_line[cur_pos]);
		    cur_pos += 1;
		}
#endif
		putc(NEWLINE, stderr);

		/* Shrink the block down to fit the string ?
		 * if the alloc fails, we still own block at cur_line,
		 * but this shouldn't really fail.
		 */
		new_line = (char *) gp_realloc(cur_line, strlen(cur_line) + 1,
					       "line resize");
		if (new_line)
		    cur_line = new_line;
		/* else we just hang on to what we had - it's not a problem */

		line_len = 0;
		FPRINTF((stderr, "Resizing input line to %d chars\n", strlen(cur_line)));
		reset_termio();
		return (cur_line);
	    default:
		break;
	    }
	}
    }
}
Exemplo n.º 30
0
/*
 * Binned histogram of input values.
 *
 *   plot FOO using N:(1) bins{=<nbins>} {binrange=[binlow:binhigh]}
 *                        {binwidth=<width>} with boxes
 *
 * This option is EXPERIMENTAL, details may change before inclusion in a stable
 * gnuplot release.
 *
 * If no binrange is given, binlow and binhigh are taken from the x range of the data.
 * In either of these cases binlow is the midpoint x-coordinate of the first bin
 * and binhigh is the midpoint x-coordinate of the last bin.
 * Points that lie exactly on a bin boundary are assigned to the upper bin.
 * Bin assignments are not affected by "set xrange".
 * Notes:
 *    binwidth = (binhigh-binlow) / (nbins-1)
 *        xmin = binlow - binwidth/2
 *        xmax = binhigh + binwidth/2
 *    first bin holds points with (xmin =< x < xmin + binwidth)
 *    last bin holds points with (xmax-binwidth =< x < binhigh + binwidth)
 */
void
make_bins(struct curve_points *plot, int nbins,
          double binlow, double binhigh, double binwidth)
{
    int i, binno;
    double *bin;
    double bottom, top, range;
    struct axis *xaxis = &axis_array[plot->x_axis];
    struct axis *yaxis = &axis_array[plot->y_axis];
    double ymax = 0;
    int N = plot->p_count;

    /* Find the range of points to be binned */
    if (binlow != binhigh) {
	/* Explicit binrange [min:max] in the plot command */
	bottom = binlow;
	top = binhigh;
    } else {
	/* Take binrange from the data itself */
	bottom = VERYLARGE; top = -VERYLARGE;
	for (i=0; i<N; i++) {
	    if (bottom > plot->points[i].x)
		bottom = plot->points[i].x;
	    if (top < plot->points[i].x)
		top = plot->points[i].x;
	}
	if (top <= bottom)
	    int_warn(NO_CARET, "invalid bin range [%g:%g]", bottom, top);
    }

    /* If a fixed binwidth was provided, find total number of bins */
    if (binwidth > 0) {
	double temp;
	nbins = 1 + (top - bottom) / binwidth;
	temp = nbins * binwidth - (top - bottom);
	bottom -= temp/2.;
	top += temp/2.;
    }
    /* otherwise we use (N-1) intervals between midpoints of bin 1 and bin N */
    else {
	binwidth = (top - bottom) / (nbins - 1);
	bottom -= binwidth/2.;
	top += binwidth/2.;
    }
    range = top - bottom;

    FPRINTF((stderr,"make_bins: %d bins from %g to %g, binwidth %g\n",
	    nbins, bottom, top, binwidth));

    bin = gp_alloc(nbins*sizeof(double), "bins");
    for (i=0; i<nbins; i++)
 	bin[i] = 0;
    for (i=0; i<N; i++) {
	if (plot->points[i].type == UNDEFINED)
	    continue;
	binno = floor(nbins * (plot->points[i].x - bottom) / range);
	if (0 <= binno && binno < nbins)
	    bin[binno] += plot->points[i].y;
    }

    if (xaxis->autoscale & AUTOSCALE_MIN) {
	if (xaxis->min > bottom)
	    xaxis->min = bottom;
    }
    if (xaxis->autoscale & AUTOSCALE_MAX) {
	if (xaxis->max < top)
	    xaxis->max = top;
    }

    /* Replace the original data with one entry per bin.
     * new x = midpoint of bin
     * new y = number of points in the bin
     */
    plot->p_count = nbins;
    plot->points = gp_realloc( plot->points, nbins * sizeof(struct coordinate), "curve_points");
    for (i=0; i<nbins; i++) {
	double bincent = bottom + (0.5 + (double)i) * binwidth;
	plot->points[i].type = INRANGE;
	plot->points[i].x     = bincent;
	plot->points[i].xlow  = bincent - binwidth/2.;
	plot->points[i].xhigh = bincent + binwidth/2.;
	plot->points[i].y     = bin[i];
	plot->points[i].ylow  = plot->points[i].y;
	plot->points[i].yhigh = plot->points[i].y;
	plot->points[i].z = 0;	/* FIXME: leave it alone? */
	if (inrange(bincent, xaxis->min, xaxis->max)) {
	    if (ymax < bin[i])
		ymax = bin[i];
	} else {
	    plot->points[i].type = OUTRANGE;
	}
	FPRINTF((stderr, "bin[%d] %g %g\n", i, plot->points[i].x, plot->points[i].y));
    }

    if (yaxis->autoscale & AUTOSCALE_MIN) {
	if (yaxis->min > 0)
	    yaxis->min = 0;
    }
    if (yaxis->autoscale & AUTOSCALE_MAX) {
	if (yaxis->max < ymax)
	    yaxis->max = ymax;
    }

    /* Clean up */
    free(bin);
}