1########################################################################
2##
3## Copyright (C) 2009-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn {} {@var{value} =} __gnuplot_get_var__ (@var{h}, @var{gp_var_name}, @var{fmt})
28## Undocumented internal function.
29## @end deftypefn
30
31function gp_var_value = __gnuplot_get_var__ (h, gp_var_name, fmt = "")
32
33  if (numel (h) == 1 && isfigure (h))
34    if (isempty (get (h, "__plot_stream__")))
35      ostream = __gnuplot_open_stream__ (2, h);
36    else
37      ostream = get (h, "__plot_stream__");
38    endif
39  else
40    ostream = h;
41  endif
42  if (numel (ostream) < 1)
43    error ("__gnuplot_get_var__: stream to gnuplot not open");
44  elseif (ispc ())
45    if (numel (ostream) == 1)
46      error ("__gnuplot_get_var__: Need mkfifo that is not implemented under Windows");
47    endif
48    use_mkfifo = false;
49    istream = ostream(2);
50    ostream = ostream(1);
51  else
52    use_mkfifo = true;
53    ostream = ostream(1);
54  endif
55
56  if (use_mkfifo)
57    gpin_name = tempname ();
58
59    [err, msg] = mkfifo (gpin_name, 600);
60
61    if (err)
62      error ("__gnuplot_get_var__: Can not make FIFO (%s)", msg);
63    endif
64  endif
65
66  gp_var_name = strtrim (gp_var_name);
67  n = min (strfind (gp_var_name, " "), strfind (gp_var_name, ",")) - 1;
68  if (isempty (n))
69    n = numel (gp_var_name);
70  endif
71
72  unwind_protect
73
74    ## Notes: Variables may be undefined if user closes gnuplot by "q"
75    ## or Alt-F4.  Further, this abrupt close also requires the leading
76    ## "\n" on the next line.
77    if (use_mkfifo)
78      fprintf (ostream, ["\n" 'set print "%s";' "\n"], gpin_name);
79      fflush (ostream);
80      [gpin, err] = fopen (gpin_name, "r");
81      if (err)
82        ## Try a second time, and then give an error.
83        [gpin, err] = fopen (gpin_name, "r");
84      endif
85      if (err)
86        error ("__gnuplot_get_var__: can not open FIFO");
87      endif
88      gp_cmd = sprintf (["\n" 'if (exists("%s")) print %s; else print NaN' "\n"],
89                        gp_var_name(1:n), gp_var_name);
90      fputs (ostream, gp_cmd);
91
92      ## Close output file, to force it to be flushed
93      fputs (ostream, "set print;\n");
94      fflush (ostream);
95
96      ## Now read from fifo.
97      reading = true;
98      str = {};
99      while (reading)
100        str{end+1} = fgets (gpin);
101        if (isnumeric (str{end}) && (str{end} == -1))
102          reading = false;
103          str = str(1:(end-1));
104        endif
105      endwhile
106      str = strcat (str{:});
107      fclose (gpin);
108    else
109      ## Direct gnuplot to print to <STDOUT>
110      fprintf (ostream, ['set print "-";' "\n"]);
111      fflush (ostream);
112      gp_cmd = sprintf (["\n" 'if (exists("%s")) print "OCTAVE: ", %s, ' ...
113                        '" :END_OCTAVE"; else print NaN' "\n"],
114                        gp_var_name(1:n), gp_var_name);
115      fputs (ostream, gp_cmd);
116      fflush (ostream);
117      ## Direct gnuplot to print to <STDERR>
118      fputs (ostream, "set print;\n");
119      fflush (ostream);
120
121      str = "";
122      t_start = tic ();
123      while (toc (t_start) < 10)
124        str = [str, fread(istream, "*char")'];
125        if (! isempty (str))
126          re_str = regexp (str, "OCTAVE: (.*) :END_OCTAVE", "tokens");
127          if (! isempty (re_str))
128            str = re_str{end}{1};
129            break;
130          endif
131        endif
132        fclear (istream);
133      endwhile
134    endif
135
136    ## Strip out EOLs and the continuation character "|"
137    str(str=="\n" | str=="\r") = "";
138    n_continue = strfind (str, " \\ ");
139    if (! isempty (n_continue))
140      str(n_continue+1) = "";
141    endif
142
143    if (isempty (fmt))
144      gp_var_value = strtrim (str);
145    else
146      gp_var_value = sscanf (str, fmt);
147    endif
148
149  unwind_protect_cleanup
150    if (use_mkfifo)
151      unlink (gpin_name);
152    endif
153  end_unwind_protect
154
155endfunction
156