|
Packit |
0986c0 |
/*
|
|
Packit |
0986c0 |
* $Id: datablock.c,v 1.8.2.1 2017/06/05 20:40:28 sfeam Exp $
|
|
Packit |
0986c0 |
*/
|
|
Packit |
0986c0 |
/* GNUPLOT - datablock.c */
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/*[
|
|
Packit |
0986c0 |
* Copyright Ethan A Merritt 2012
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* Gnuplot license:
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* Permission to use, copy, and distribute this software and its
|
|
Packit |
0986c0 |
* documentation for any purpose with or without fee is hereby granted,
|
|
Packit |
0986c0 |
* provided that the above copyright notice appear in all copies and
|
|
Packit |
0986c0 |
* that both that copyright notice and this permission notice appear
|
|
Packit |
0986c0 |
* in supporting documentation.
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* Permission to modify the software is granted, but not the right to
|
|
Packit |
0986c0 |
* distribute the complete modified source code. Modifications are to
|
|
Packit |
0986c0 |
* be distributed as patches to the released version. Permission to
|
|
Packit |
0986c0 |
* distribute binaries produced by compiling modified sources is granted,
|
|
Packit |
0986c0 |
* provided you
|
|
Packit |
0986c0 |
* 1. distribute the corresponding source modifications from the
|
|
Packit |
0986c0 |
* released version in the form of a patch file along with the binaries,
|
|
Packit |
0986c0 |
* 2. add special version identification to distinguish your version
|
|
Packit |
0986c0 |
* in addition to the base release version number,
|
|
Packit |
0986c0 |
* 3. provide your name and address as the primary contact for the
|
|
Packit |
0986c0 |
* support of your modified version, and
|
|
Packit |
0986c0 |
* 4. retain our contact information in regard to use of the base
|
|
Packit |
0986c0 |
* software.
|
|
Packit |
0986c0 |
* Permission to distribute the released version of the source code along
|
|
Packit |
0986c0 |
* with corresponding source modifications in the form of a patch file is
|
|
Packit |
0986c0 |
* granted with same provisions 2 through 4 for binary distributions.
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* This software is provided "as is" without express or implied warranty
|
|
Packit |
0986c0 |
* to the extent permitted by applicable law.
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* Alternative license:
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* As an alternative to distributing code in this file under the gnuplot license,
|
|
Packit |
0986c0 |
* you may instead comply with the terms below. In this case, redistribution and
|
|
Packit |
0986c0 |
* use in source and binary forms, with or without modification, are permitted
|
|
Packit |
0986c0 |
* provided that the following conditions are met:
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* Redistributions of source code must retain the above copyright notice, this
|
|
Packit |
0986c0 |
* list of conditions and the following disclaimer. Redistributions in binary
|
|
Packit |
0986c0 |
* form must reproduce the above copyright notice, this list of conditions and
|
|
Packit |
0986c0 |
* the following disclaimer in the documentation and/or other materials provided
|
|
Packit |
0986c0 |
* with the distribution.
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
0986c0 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
0986c0 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
0986c0 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
Packit |
0986c0 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
0986c0 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
0986c0 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
0986c0 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
0986c0 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
0986c0 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
0986c0 |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
]*/
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
#include "gp_types.h"
|
|
Packit |
0986c0 |
#include "alloc.h"
|
|
Packit |
0986c0 |
#include "command.h"
|
|
Packit |
0986c0 |
#include "datablock.h"
|
|
Packit |
0986c0 |
#include "datafile.h"
|
|
Packit |
0986c0 |
#include "eval.h"
|
|
Packit |
0986c0 |
#include "misc.h"
|
|
Packit |
0986c0 |
#include "util.h"
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
static int enlarge_datablock(struct value *datablock_value, int extra);
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/*
|
|
Packit |
0986c0 |
* In-line data blocks are implemented as a here-document:
|
|
Packit |
0986c0 |
* $FOO << EOD
|
|
Packit |
0986c0 |
* data line 1
|
|
Packit |
0986c0 |
* data line 2
|
|
Packit |
0986c0 |
* ...
|
|
Packit |
0986c0 |
* EOD
|
|
Packit |
0986c0 |
*
|
|
Packit |
0986c0 |
* The data block name must begin with $ followed by a letter.
|
|
Packit |
0986c0 |
* The string EOD is arbitrary; lines of data will be read from the input stream
|
|
Packit |
0986c0 |
* until the leading characters on the line match the given character string.
|
|
Packit |
0986c0 |
* No attempt is made to parse the data at the time it is read in.
|
|
Packit |
0986c0 |
*/
|
|
Packit |
0986c0 |
void
|
|
Packit |
0986c0 |
datablock_command()
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
FILE *fin;
|
|
Packit |
0986c0 |
char *name, *eod;
|
|
Packit |
0986c0 |
int nlines;
|
|
Packit |
0986c0 |
int nsize = 4;
|
|
Packit |
0986c0 |
struct udvt_entry *datablock;
|
|
Packit |
0986c0 |
char *dataline = NULL;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
if (!isletter(c_token+1))
|
|
Packit |
0986c0 |
int_error(c_token, "illegal datablock name");
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* Create or recycle a datablock with the requested name */
|
|
Packit |
0986c0 |
name = parse_datablock_name();
|
|
Packit |
0986c0 |
datablock = add_udv_by_name(name);
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
if (!equals(c_token, "<<") || !isletter(c_token+1))
|
|
Packit |
0986c0 |
int_error(c_token, "data block name must be followed by << EODmarker");
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
if (datablock->udv_value.type != NOTDEFINED)
|
|
Packit |
0986c0 |
gpfree_datablock(&datablock->udv_value);
|
|
Packit |
0986c0 |
datablock->udv_value.type = DATABLOCK;
|
|
Packit |
0986c0 |
datablock->udv_value.v.data_array = NULL;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
c_token++;
|
|
Packit |
0986c0 |
eod = (char *) gp_alloc(token[c_token].length +2, "datablock");
|
|
Packit |
0986c0 |
copy_str(&eod[0], c_token, token[c_token].length + 2);
|
|
Packit |
0986c0 |
c_token++;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* Read in and store data lines until EOD */
|
|
Packit |
0986c0 |
fin = (lf_head == NULL) ? stdin : lf_head->fp;
|
|
Packit |
0986c0 |
if (!fin)
|
|
Packit |
0986c0 |
int_error(NO_CARET,"attempt to define data block from invalid context");
|
|
Packit |
0986c0 |
for (nlines = 0; (dataline = df_fgets(fin)); nlines++) {
|
|
Packit |
0986c0 |
int n;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
if (!strncmp(eod, dataline, strlen(eod)))
|
|
Packit |
0986c0 |
break;
|
|
Packit |
0986c0 |
/* Allocate space for data lines plus at least 2 empty lines at the end. */
|
|
Packit |
0986c0 |
if (nlines >= nsize-4) {
|
|
Packit |
0986c0 |
nsize *= 2;
|
|
Packit |
0986c0 |
datablock->udv_value.v.data_array =
|
|
Packit |
0986c0 |
(char **) gp_realloc(datablock->udv_value.v.data_array,
|
|
Packit |
0986c0 |
nsize * sizeof(char *), "datablock");
|
|
Packit |
0986c0 |
memset(&datablock->udv_value.v.data_array[nlines], 0,
|
|
Packit |
0986c0 |
(nsize - nlines) * sizeof(char *));
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
/* Strip trailing newline character */
|
|
Packit |
0986c0 |
n = strlen(dataline);
|
|
Packit |
0986c0 |
if (n > 0 && dataline[n - 1] == '\n')
|
|
Packit |
0986c0 |
dataline[n - 1] = NUL;
|
|
Packit |
0986c0 |
datablock->udv_value.v.data_array[nlines] = gp_strdup(dataline);
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
inline_num += nlines + 1; /* Update position in input file */
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* make sure that we can safely add lines to this datablock later on */
|
|
Packit |
0986c0 |
enlarge_datablock(&datablock->udv_value, 0);
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
free(eod);
|
|
Packit |
0986c0 |
return;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
char *
|
|
Packit |
0986c0 |
parse_datablock_name()
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
/* Datablock names begin with $, but the scanner puts */
|
|
Packit |
0986c0 |
/* the $ in a separate token. Merge it with the next. */
|
|
Packit |
0986c0 |
/* Caller must _not_ free the string that is returned. */
|
|
Packit |
0986c0 |
static char *name = NULL;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
free(name);
|
|
Packit |
0986c0 |
c_token++;
|
|
Packit |
0986c0 |
name = (char *) gp_alloc(token[c_token].length + 2, "datablock");
|
|
Packit |
0986c0 |
name[0] = '$';
|
|
Packit |
0986c0 |
copy_str(&name[1], c_token, token[c_token].length + 2);
|
|
Packit |
0986c0 |
c_token++;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
return name;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
char **
|
|
Packit |
0986c0 |
get_datablock(char *name)
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
struct udvt_entry *datablock;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
datablock = get_udv_by_name(name);
|
|
Packit |
0986c0 |
if (!datablock || datablock->udv_value.type == NOTDEFINED
|
|
Packit |
0986c0 |
|| datablock->udv_value.v.data_array == NULL)
|
|
Packit |
0986c0 |
int_error(NO_CARET,"no datablock named %s",name);
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
return datablock->udv_value.v.data_array;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
void
|
|
Packit |
0986c0 |
gpfree_datablock(struct value *datablock_value)
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
int i;
|
|
Packit |
0986c0 |
char **stored_data = datablock_value->v.data_array;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
if (datablock_value->type != DATABLOCK)
|
|
Packit |
0986c0 |
return;
|
|
Packit |
0986c0 |
if (stored_data)
|
|
Packit |
0986c0 |
for (i=0; stored_data[i] != NULL; i++)
|
|
Packit |
0986c0 |
free(stored_data[i]);
|
|
Packit |
0986c0 |
free(stored_data);
|
|
Packit |
0986c0 |
datablock_value->v.data_array = NULL;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* count number of lines in a datablock */
|
|
Packit |
0986c0 |
int
|
|
Packit |
0986c0 |
datablock_size(struct value *datablock_value)
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
char **dataline;
|
|
Packit |
0986c0 |
int nlines = 0;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
dataline = datablock_value->v.data_array;
|
|
Packit |
0986c0 |
if (dataline) {
|
|
Packit |
0986c0 |
while (*dataline++)
|
|
Packit |
0986c0 |
nlines++;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
return nlines;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* resize or allocate a datablock; allocate memory in chuncks */
|
|
Packit |
0986c0 |
static int
|
|
Packit |
0986c0 |
enlarge_datablock(struct value *datablock_value, int extra)
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
int osize, nsize;
|
|
Packit |
0986c0 |
const int blocksize = 512;
|
|
Packit |
0986c0 |
int nlines = datablock_size(datablock_value);
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* reserve space in multiples of blocksize */
|
|
Packit |
0986c0 |
osize = ((nlines+1 + blocksize-1) / blocksize) * blocksize;
|
|
Packit |
0986c0 |
nsize = ((nlines+1 + extra + blocksize-1) / blocksize) * blocksize;
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* only resize if necessary */
|
|
Packit |
0986c0 |
if ((osize != nsize) || (extra == 0) || (nlines == 0)) {
|
|
Packit |
0986c0 |
datablock_value->v.data_array =
|
|
Packit |
0986c0 |
(char **) gp_realloc(datablock_value->v.data_array, nsize * sizeof(char *), "resize_datablock");
|
|
Packit |
0986c0 |
datablock_value->v.data_array[nlines] = NULL;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
return nlines;
|
|
Packit |
0986c0 |
}
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
|
|
Packit |
0986c0 |
/* append a single line to a datablock */
|
|
Packit |
0986c0 |
void
|
|
Packit |
0986c0 |
append_to_datablock(struct value *datablock_value, const char *line)
|
|
Packit |
0986c0 |
{
|
|
Packit |
0986c0 |
int nlines = enlarge_datablock(datablock_value, 1);
|
|
Packit |
0986c0 |
datablock_value->v.data_array[nlines] = (char *) line;
|
|
Packit |
0986c0 |
datablock_value->v.data_array[nlines + 1] = NULL;
|
|
Packit |
0986c0 |
}
|