1 /*$Id: io_out.cc,v 26.137 2010/04/10 02:37:33 al Exp $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * output text to files, devices, or whatever
23 * m???? = multiple output to a bunch of io devices.
24 * with character count (so tab will work)
25 * Will start a new line first if the entire output will not fit.
26 * so wrap will not break a word or number.
27 * Where is a bit mask of places to send the output.
28 * A possible portability problem exists with the handle numbers.
29 * It assumes they start at 0, and count up, and that there are no more than
30 * the number of bits in an integer (MAXHANDLE).
31 * but I have yet to find a system that did not meet this form.
33 //testing=script,sparse 2006.07.17
35 /*--------------------------------------------------------------------------*/
36 const char* octal(int x
);
37 // OMSTREAM & OMSTREAM::tab(int count)
38 // OMSTREAM & OMSTREAM::form(const char*,...);
39 // OMSTREAM & OMSTREAM::operator<<(const char *str)
40 // OMSTREAM & OMSTREAM::operator<<(char chr)
41 /*--------------------------------------------------------------------------*/
42 FILE* OMSTREAM::_stream
[MAXHANDLE
+1];
43 unsigned OMSTREAM::_cpos
[MAXHANDLE
+1]; /* character counter */
44 /*--------------------------------------------------------------------------*/
45 /* octal: make octal string for an int
47 const char* octal(int x
)
49 static char s
[sizeof(int)*3+1];
53 /*--------------------------------------------------------------------------*/
54 /* mtab: tab to column "count" on output devices "where"
55 * by outputting spaces.
56 * If already beyond, start new line, then tab to column.
58 OMSTREAM
& OMSTREAM::tab(unsigned count
)
60 for (int ii
=0, mm
=1; ii
<=MAXHANDLE
; ++ii
, mm
<<=1) {
62 OMSTREAM
this_file(_mask
& mm
);
63 if (_cpos
[ii
] > count
) {
67 while (_cpos
[ii
]<count
) {
75 /*--------------------------------------------------------------------------*/
76 /* mprintf: multiple printf
77 * printf to "m" style files.
79 OMSTREAM
& OMSTREAM::form(const char *fmt
, ...)
81 char buffer
[BIGBUFLEN
];
84 va_start(arg_ptr
,fmt
);
85 vsprintf(buffer
,fmt
,arg_ptr
);
91 /*--------------------------------------------------------------------------*/
92 /* mputs: multiple puts.
93 * puts to "m" style files.
95 * starts new line, prefixes it with + if it would exceed width
96 * width is handled separately for each file to support different widths
97 * (which are not currently handled by .options)
98 * and it is possible that current contents of lines may be different
100 OMSTREAM
& OMSTREAM::operator<<(const char *str
)
107 error(bDANGER
, "internal error: out to stdin\n");
111 bool newline
= false; /* true if any destination is at beginning of line */
112 size_t sl
= strlen(str
);
114 /* kluge: If a string ends with certain characters,
115 * require some extra space following it, possibly forcing to next line.
116 * Why? to avoid a line break between '=' and its argument.
119 }else if (strchr("@", str
[sl
-1])) {
121 }else if (strchr("=", str
[sl
-1])) {
123 }else if (strchr("(", str
[sl
-1])) {
128 /* auto line break, with a '+' to continue. */
129 for (int ii
=0, mm
=1; ii
<=MAXHANDLE
; ++ii
, mm
<<=1) {
131 && (sl
+_cpos
[ii
]) >= OPT::outwidth
133 OMSTREAM
this_file(_mask
& mm
);
134 this_file
<< '\n' << '+';
136 } /* see if it fits .... */
137 if (_cpos
[ii
]==0) { /* if not, next line */
143 if (cipher() && newline
) {untested();
148 while (*str
&& (str
[1] || *str
!= '@')) {
153 /*--------------------------------------------------------------------------*/
154 /* mputc: multiple putc
157 * crunch spaces, if selected
158 * encripts, if selected
159 * keeps track of character count
161 OMSTREAM
& OMSTREAM::operator<<(char chr
)
166 error(bDANGER
, "internal error: out to stdin\n");
170 static int old
= '\0';
171 static int cchr
= 'w'; /* starting encryption seed */
172 /* arbitrary printable character */
174 if (chr
=='\t') {itested();
181 bool suppress
= (pack() && old
==' ' && chr
==' ');
183 if (cipher() && !suppress
&& isprint(chr
)) {untested();
184 cchr
+= static_cast<int>(chr
);
185 while (!isascii(cchr
) || !isprint(cchr
)) {untested();
188 chr
= static_cast<char>(cchr
);
192 for (int ii
=0, mm
=1; ii
<=MAXHANDLE
; ++ii
, mm
<<=1) {
195 if (chr
=='\b') {untested();
206 }else if (chr
=='\r') {itested();
207 if (_cpos
[ii
] == 0) {untested();
216 fputc(chr
,_stream
[ii
]);
224 /*--------------------------------------------------------------------------*/
225 /*--------------------------------------------------------------------------*/
226 // vim:ts=8:sw=2:noet: