1 /* This file is part of the GNU plotutils package. Copyright (C) 1995,
2 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
3
4 The GNU plotutils package is free software. You may redistribute it
5 and/or modify it under the terms of the GNU General Public License as
6 published by the Free Software foundation; either version 2, or (at your
7 option) any later version.
8
9 The GNU plotutils package is distributed in the hope that it will be
10 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with the GNU plotutils package; see the file COPYING. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
17 Boston, MA 02110-1301, USA. */
18
19 /* This file contains the internal _pl_m_emit_integer, _pl_m_emit_float,
20 _pl_m_emit_op_code, and _pl_m_emit_string routines, which are used by
21 MetaPlotters. They take into account the desired format (binary
22 metafile format or ascii [human-readable] metafile format.
23
24 In the unnumbered versions of libplot prior to version 0.0 (which was
25 released as part of plotutils-2.0, in 1/98), we assumed that in binary
26 metafile format, two bytes sufficed to represent any integer. This was
27 the convention used in traditional plot(5) format, and can be traced to
28 the PDP-11. Unfortunately it confined us to the range -0x10000..0x7fff
29 (assuming two's complement). Actually, the parsing in our `plot'
30 utility always treated the arguments to pencolor(), fillcolor(), and
31 filltype() specially. An argument of any of those functions was treated
32 as an unsigned integer, so it could be in the range 0..0xffff.
33
34 In version 0.0 of libplot, we switched in binary metafile format to
35 representing integers as machine integers. The parsing of metafiles by
36 `plot' now takes this into account. `plot' has command-line options for
37 backward compatibility with plot(5) format.
38
39 Our representation for floating-point numbers in binary metafiles is
40 simply the machine representation for single-precision floating point.
41 plot(5) format did not support floating point arguments, so there are no
42 concerns over backward compatibility. */
43
44 #include "sys-defines.h"
45 #include "extern.h"
46
47 /* emit one unsigned character, passed as an int */
48 void
_pl_m_emit_op_code(R___ (Plotter * _plotter)int c)49 _pl_m_emit_op_code (R___(Plotter *_plotter) int c)
50 {
51 if (_plotter->data->outfp)
52 putc (c, _plotter->data->outfp);
53 #ifdef LIBPLOTTER
54 else if (_plotter->data->outstream)
55 _plotter->data->outstream->put ((unsigned char)c);
56 #endif
57 }
58
59 void
_pl_m_emit_integer(R___ (Plotter * _plotter)int x)60 _pl_m_emit_integer (R___(Plotter *_plotter) int x)
61 {
62 if (_plotter->data->outfp)
63 {
64 if (_plotter->meta_portable_output)
65 fprintf (_plotter->data->outfp, " %d", x);
66 else
67 fwrite ((void *) &x, sizeof(int), 1, _plotter->data->outfp);
68 }
69 #ifdef LIBPLOTTER
70 else if (_plotter->data->outstream)
71 {
72 if (_plotter->meta_portable_output)
73 (*(_plotter->data->outstream)) << ' ' << x;
74 else
75 _plotter->data->outstream->write((char *)&x, sizeof(int));
76 }
77 #endif
78 }
79
80 void
_pl_m_emit_float(R___ (Plotter * _plotter)double x)81 _pl_m_emit_float (R___(Plotter *_plotter) double x)
82 {
83 if (_plotter->data->outfp)
84 {
85 if (_plotter->meta_portable_output)
86 {
87 /* treat equality with zero specially, since some printf's print
88 negative zero differently from positive zero, and that may
89 prevent regression tests from working properly */
90 fprintf (_plotter->data->outfp, x == 0.0 ? " 0" : " %g", x);
91 }
92 else
93 {
94 float f;
95
96 f = FROUND(x);
97 fwrite ((void *) &f, sizeof(float), 1, _plotter->data->outfp);
98 }
99 }
100 #ifdef LIBPLOTTER
101 else if (_plotter->data->outstream)
102 {
103 if (_plotter->meta_portable_output)
104 (*(_plotter->data->outstream)) << ' ' << x;
105 else
106 {
107 float f;
108
109 f = FROUND(x);
110 _plotter->data->outstream->write((char *)&f, sizeof(float));
111 }
112 }
113 #endif
114 }
115
116 void
_pl_m_emit_string(R___ (Plotter * _plotter)const char * s)117 _pl_m_emit_string (R___(Plotter *_plotter) const char *s)
118 {
119 bool has_newline;
120 char *t = NULL; /* keep compiler happy */
121 char *nl;
122 const char *u;
123
124 /* null pointer handled specially */
125 if (s == NULL)
126 s = "(null)";
127
128 if (strchr (s, '\n'))
129 /* don't grok arg strings containing newlines; truncate at first
130 newline if any */
131 {
132 has_newline = true;
133 t = (char *)_pl_xmalloc (strlen (s) + 1);
134 strcpy (t, s);
135 nl = strchr (t, '\n');
136 *nl = '\0';
137 u = t;
138 }
139 else
140 {
141 has_newline = false;
142 u = s;
143 }
144
145 /* emit string, with appended newline if output format is binary (old
146 plot(3) convention, which makes sense only if there can be at most one
147 string among the command arguments, and it's positioned last) */
148 if (_plotter->data->outfp)
149 {
150 fputs (u, _plotter->data->outfp);
151 if (_plotter->meta_portable_output == false)
152 putc ('\n', _plotter->data->outfp);
153 }
154 #ifdef LIBPLOTTER
155 else if (_plotter->data->outstream)
156 {
157 (*(_plotter->data->outstream)) << u;
158 if (_plotter->meta_portable_output == false)
159 (*(_plotter->data->outstream)) << '\n';
160 }
161 #endif
162
163 if (has_newline)
164 free (t);
165 }
166
167 /* End a directive that was begun by invoking _pl_m_emit_op_code() (q.v.). In
168 portable format, the terminator is a newline; in binary format, there is
169 no terminator. */
170 void
_pl_m_emit_terminator(S___ (Plotter * _plotter))171 _pl_m_emit_terminator (S___(Plotter *_plotter))
172 {
173 if (_plotter->meta_portable_output)
174 {
175 if (_plotter->data->outfp)
176 putc ('\n', _plotter->data->outfp);
177 #ifdef LIBPLOTTER
178 else if (_plotter->data->outstream)
179 (*(_plotter->data->outstream)) << '\n';
180 #endif
181 }
182 }
183