Using version 5.0.3 on windows (gp503-win64-mingw.zip, using wgnuplot.exe), it seems that the ability to recall a history command by number does not quite work when the history stack is full.
To demonstrate this, run the following commands
set history size 4 plot [1:2][1:4] 1 plot [1:2][1:4] 2 plot [1:2][1:4] 3 history
This will set the history stack to 4 and then preceed to fill it up. The result of that final command is to print the current history stack which looks like
1 plot [1:2][1:4] 1 2 plot [1:2][1:4] 2 3 plot [1:2][1:4] 3 4 history
Now, issuing the command history !2
should repeat the plot command that draws a line at y=2. Instead we get the line at y=3. It seems that when the history stack is full, the new command is first added to the stack pushing all the previous entries back by one, and then the command is recalled by number. This means that the command for y=2 is now at item 1 and the command for y=3 is now at item 2, so the wrong command is recalled.
This does not occur when the history stack is not full. For example, run the following commands (first setting a smaller size and then a larger one in order to flush the stack to a known state)
set history size 4 plot [1:2][1:4] 1 plot [1:2][1:4] 2 plot [1:2][1:4] 3 set history size 8 history
This will give us a history stack holding up to 8 items and with the following populated
1 plot [1:2][1:4] 1 2 plot [1:2][1:4] 2 3 plot [1:2][1:4] 3 4 set history size 8 5 history
In this case, history !2
draws the line at y=2 as expected. Thus the off by one behavior only occurs when the history stack is full.
Additionally, while playing with the history size in order to come up with a good example to demonstrate this, I have had gnuplot (using the wgnuplot.exe executable) crash a couple of times on me with a few variations of set history size <number>
and set history <number>
. Unfortunately, I have been unable to come up with a test case that reliably causes this crash, so I'm not sure if the cause can be easily determined.
Again, this only occurs when the history stack is full. If there is room open in it, nothing like this occurs. Looking at the source code, it looks like different systems may implement the history mechanism differently, so it is also possible that this does not occur on all systems.
Diff:
A related issue occurs because the item number 1 gets pushed off the history stack.
Run
This populates the history stack and prints
Now, the command
history !"a=1"
results in the message not in history, because item 1 was pushed off the history stack by this command referencing it before it could be ran.Running
history !1
works without an error, but actually grabs item 2 as previously described.Last edit: Matthew Halverson 2016-03-25
I've been trying to think of how this issue could be fixed and although I can think of three possible approaches, all of them introduce new issues. It may be that effectively referencing an item in a full history stack by number (or by string in the case of the first item) is simply untenable.
Approach 1
Changing the order of the processing so the command is ran before putting it on the history stack (it seems that the opposisite is currently done) could work. Then a command like
history !2
will correctly grab item 2 on the stack instead of item 3 like it does now.The problem is that when I type
history
to see the history stack, it would be printed and then this command would be added. This means that when I want to access the item which said it was item 2, it would now be item 1. Thus pretty much the same problem occurs, but the mistake is moved to the printed results instead of the command referencing command. It may be that this can be fixed by the history detecting if it is full and subtracting one from every number if it is. Then the command that said it was number 2 could be accessed as number 2. This means that item 1 (which would now say it is item 0) would have to be skipped (it will end up pushed off the stack before I can access it anyways) and the stack would always show one empty slot (in our example of 4 items we would list an item 1 [really 2], item 2 [really 3], and item 3 [really 4]). This would also allow me to access item 1 (as printed) because it does not get pushed off the stack before it is accessed. This means thathistory !"some string"
would work with the first item as well.Approach 2
It may be possible to have the referencing process determine if the stack is full and subtract one from it in that case. Thus when I run
history !2
on a full stack it actually grabs item 1 (which would have been item 2 before this command was added to the stack) but if the stack is not full then it would grab item 2. For this to work, we must be able to determine if the stack was full before the new command was added (which would shift all the numbers) or if the new command was the one that filled it up (which would not shift the numbers this time, but the next command would).Here we have the problem with item 1 being unaccessible because it gets pushed off the stack. Thus the command
history !1
would be meaningless.Approach 3
It may be possible to increase the size of the stack by one if it is full before running the new command and then adjust back. Thus if we have a stack size of 4 and it is full, running a new command would increase the size to 5, run the new command, and then adjust it back to 4.
This is probably too difficult to implement, and I think has the same problems as approach 1 when printing the current history stack.
Last edit: Matthew Halverson 2016-03-25
Diff:
Another possibility: do not add
history
commands to the history.Actually that is probably best (why did I come up with so complicated solutions, when this is obvious in hindsight?).
One possible problem with that, however. When I type
history !2
it doesn't addhistory !2
to the history. Instead it adds what that resolves to (and actually violates the suppress duplicates option too), so there may be some more checking needed with that (I don't know if the add method sees the history command or what the history command resolves to). But, if we avoid adding whatever that resolves to into the history, that would completely solve the problem.That might not be as trivial as I first thought. The new input is added to the history immediately before parsing. While that could be changed with a little effort, it is also not clear to me what to do if there are more commands than just a single
history
on the command line. Any thoughts?The attached patch tests for the first command on the line being
history
. If that's the case, the line is not appended to the history.Hi Bastian.
I'd like to see this patch applied. But first he handling of leading blank space needs a fix. I think the tests for NUL and blank need to test line[start+i] rather than line[i] but I'm not sure that is the complete fix.
Fixed and applied to CVS for 5.1. Should it also go to 5.0?
Wait a minute. Going back to your original description...
"set history size 4" actually does something visible on your gnuplot?
For me it has no immediate effect whatsover. It only changes how many lines will be saved to a file when you exit the program. That matches what the documentation says.
So I don't understand what problem you are seeing. Are you just saying that the numbers saved to a file do not necessarily match the numbers you saw in a previous session? IMHO that's not a bug. There is no guarantee that item #23 bears any relationship to what it was in a session from a month ago.
On the windows version (with both wgnuplot.exe and gnuplot.exe) it limits how many items are in the history stack entirely (in the current session), so yes it does something visible.
For example,
results in
keeping only the last 3 items. Continuing to run commands and then running
history
will never show more than 3 items with that setting. Thus it effects the number of items available in the current session, and not just the number saved when you exit.I don't expect the numbers to match between sessions, but they should match within the current session. I thought that this behavior was correct, but now that I look at the description again, and based on what you are saying, this is the real bug.
From what you are saying, and looking at the documentation again, there is a bug, but not necessarily the one I originally described (although that arises as a consequence). This is effecting the current season, when its effect should only arise upon exiting. That is causing the bug I described as this limit is being hard enforced in the current session. If it was only effecting what was saved upon exiting (as it is supposed to), it would fix this behavior.
Note that the setting only has an effect upon issuing a new command besides history, however. For example, if I do
with a history containing many more than 4 items, I will see many more than 4 items listed. But if I then do
I will now only see 4 items listed. Again, the size is cut down within the current session, but it only takes effect if a command other than
history
is ran. I don't know if this will be helpful in tracking down where the problem is or not.Last edit: Matthew Halverson 2016-03-30
Weird. I was not aware that "history" acted so differently on different platforms.
This is not a part of the program I have ever looked at.
I do see that some of the code checks for
#if defined(HAVE_LIBREADLINE) && defined(GNUPLOT_HISTORY)
Are you using libreadline? What is the first line of compile options reported by "show version long"?
I am using the precompiled windows binaries (I have only had marginal luck compiling from source under windows).
On wgnuplot.exe, show version long produces
and on gnuplot.exe, it produces the same except for the MENUNAME line near the bottom is not present.
If I am reading those correctly, it doesn't use libreadline on windows.
Last edit: Matthew Halverson 2016-03-30
Ugh. I've just built a copy configure --with-readline=builtin and indeed history is rather broken. The history numbering changes on every command, which makes it pretty much useless. As I say, I have not looked at this part of the program before so I am not familiar with the code, but it looks like some significant revision is needed to make it match the readline-based version and behave as documented.
If nothing else, it looks to me that the entire block of code starting at line 98 in history.c is counter-productive and should be removed. It renumbers the history on every command, which is crazy.
So...
Work-around: Always use "set history -1"
Seems like I am resposible for that piece of code. Actually that was one of my first contributions like 11 years back... The rationale of it was to limit the in-memory size of the history. But the commit comment didn't even say so.
I think that this can be removed more completely. Patch is attached.
Please go ahead and apply that cleanup to both 5.0 and 5.1
I think I have encountered unexpected loss of a previous command after the "don't save history commands" change but I have not been able to reproduce it on demand. It seems that sometimes the very last command in a session is not saved. But as I say I can't reliably reproduce this.
A regression caused this bug to reappear, but now it's fixed again.