It appears to not be possible to plot a binary array of size 0 which is piped in through stdin. For example:
plot '-' binary format='' record=(0)
plot x*x
What I would expect is that the first line generates an empty plot (no data points) and the second line plots a parabola. What happens instead is that the first line gobbles up the rest of the script, interpreting it as binary data. This would be expected behavior if the binary size was specified negative. To quote the docs for binary array:
A negative number indicates that data should be read until the end of file.
But 0 is not a negative number, so the gobbling up of the rest of the file should not happen.
Here is why I care about this: I have a program which plots binary data whose length is only known at runtime. Sometimes the length is zero, and I would like a consistent way to handle such a situation. Specifically, it would be nice if
printf("plot '-' binary format='%double' record=(%d)\n", length);
fwrite(buf, sizeof(double), length, stdout);
would work even when length is zero.
So far as I can see, even if the code trapped record=(0), the result would be an error exit:
gnuplot> plot '-' binary format='' record=(0)
warning: Skipping data file with no valid points
^
x range is invalid
So that wouldn't actually help you.
Why can't you just test the record length before trying to plot?
if (length > 0) {
printf("plot ....", length)
fwrite(buf, ...)
}
The reason I can't trap this condition and just not plot is that I am maintainer of a C++ to gnuplot interface (gnuplot-iostream). The
printf("plot...(or equivalent) call is done by the user and happens before the array is passed to my library.By the time I get the array, my only option would be to throw an exception. Surely this will get the point across to the user that they must deal with this condition themselves. But proceeding as normal with gnuplot printing its "warning: Skipping data file with no valid points" would be more gentle. This way my library would exhibit the same behavior as gnuplot itself: proceeding with warning when there are no points rather than aborting.
But in any case, if gnuplot's behavior in this situation is not changed then at least the documentation should be fixed (i.e. to "a non-positive number indicates...").
In the case that there are 0 data records, does the client program write an EOF into the output stream? From the command line
gnuplot> plot '-' binary format='' record=(0)
terminates cleanly on ^D.
The attached patch will reject the record=(0) line, which may or may not be the best way to handle this. At first look I don't see where to trap this condition later in the code.
Ethan: how does one send EOF through a stream? Everyone on the Internet says it's not possible but clearly it is since my terminal can send EOF to gnuplot when I hit ^D (as you describe). Note that just sending ^D is not enough; since this is a binary stream, ^D is just another character. SIGPIPE doesn't seem to work... Maybe someone on StackExchange knows.
I think I can come up with a proper patch this weekend. I looked through the code a bit already and can probably work out where it would go, if people think the behavior I describe is desirable.
Yeah, I realized after I sent that it might not be possible to "send EOF"; that would normally correspond to closing the pipe. If gnuplot's input code does not handle a closed pipe properly, that's a bug in its own right. But you probably don't want to close the pipe, right? Because you want to continue to send commands through it.
I would be happy to look at a patch, but I'm not sure I have a handle on all the possible cases that would have to be tested. For example, a single column array can be described by record=(N,0). Is it legal to describe a single-row array using record=(0,N)? I don't know whether it is or isn't. The code that handles binary files has always been nearly opaque to me.
[.... checks ....]
Apparently not, as
plot '-' binary format='' record=(0,1)
causes a segfault.
As to the desired behavior in this case. It seems to me that plotting from an ascii file that contains no data throws an error. So why wouldn't the same thing be expected from a binary file?