source: libcfa/src/iostream.cfa@ 67130fe

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 67130fe was 3c573e9, checked in by Peter A. Buhr <pabuhr@…>, 6 years ago

first draft of output manipulators and start input manipulators

  • Property mode set to 100644
File size: 27.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// iostream.c --
8//
9// Author : Peter A. Buhr
10// Created On : Wed May 27 17:56:53 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Tue Jun 4 17:32:34 2019
13// Update Count : 761
14//
15
16#include "iostream.hfa"
17
18extern "C" {
19#include <stdio.h>
20#include <stdbool.h> // true/false
21//#include <string.h> // strlen, strcmp
22extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
23extern int strcmp (const char *__s1, const char *__s2) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
24extern char *strcpy (char *__restrict __dest, const char *__restrict __src) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
25extern void *memcpy (void *__restrict __dest, const void *__restrict __src, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
26#include <float.h> // DBL_DIG, LDBL_DIG
27#include <math.h> // isfinite
28#include <complex.h> // creal, cimag
29} // extern "C"
30
31forall( dtype ostype | ostream( ostype ) ) {
32 ostype & ?|?( ostype & os, zero_t ) {
33 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
34 fmt( os, "%d", 0n );
35 return os;
36 } // ?|?
37 void ?|?( ostype & os, zero_t z ) {
38 (ostype &)(os | z); nl( os );
39 } // ?|?
40
41 ostype & ?|?( ostype & os, one_t ) {
42 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
43 fmt( os, "%d", 1n );
44 return os;
45 } // ?|?
46 void ?|?( ostype & os, one_t o ) {
47 (ostype &)(os | o); nl( os );
48 } // ?|?
49
50 ostype & ?|?( ostype & os, bool b ) {
51 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
52 fmt( os, "%s", b ? "true" : "false" );
53 return os;
54 } // ?|?
55 void ?|?( ostype & os, bool b ) {
56 (ostype &)(os | b); nl( os );
57 } // ?|?
58
59 ostype & ?|?( ostype & os, char c ) {
60 fmt( os, "%c", c );
61 if ( c == '\n' ) setNL( os, true );
62 return sepOff( os );
63 } // ?|?
64 void ?|?( ostype & os, char c ) {
65 (ostype &)(os | c); nl( os );
66 } // ?|?
67
68 ostype & ?|?( ostype & os, signed char sc ) {
69 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
70 fmt( os, "%hhd", sc );
71 return os;
72 } // ?|?
73 void ?|?( ostype & os, signed char sc ) {
74 (ostype &)(os | sc); nl( os );
75 } // ?|?
76
77 ostype & ?|?( ostype & os, unsigned char usc ) {
78 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
79 fmt( os, "%hhu", usc );
80 return os;
81 } // ?|?
82 void ?|?( ostype & os, unsigned char usc ) {
83 (ostype &)(os | usc); nl( os );
84 } // ?|?
85
86 ostype & ?|?( ostype & os, short int si ) {
87 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
88 fmt( os, "%hd", si );
89 return os;
90 } // ?|?
91 void & ?|?( ostype & os, short int si ) {
92 (ostype &)(os | si); nl( os );
93 } // ?|?
94
95 ostype & ?|?( ostype & os, unsigned short int usi ) {
96 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
97 fmt( os, "%hu", usi );
98 return os;
99 } // ?|?
100 void & ?|?( ostype & os, unsigned short int usi ) {
101 (ostype &)(os | usi); nl( os );
102 } // ?|?
103
104 ostype & ?|?( ostype & os, int i ) {
105 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
106 fmt( os, "%d", i );
107 return os;
108 } // ?|?
109 void & ?|?( ostype & os, int i ) {
110 (ostype &)(os | i); nl( os );
111 } // ?|?
112
113 ostype & ?|?( ostype & os, unsigned int ui ) {
114 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
115 fmt( os, "%u", ui );
116 return os;
117 } // ?|?
118 void & ?|?( ostype & os, unsigned int ui ) {
119 (ostype &)(os | ui); nl( os );
120 } // ?|?
121
122 ostype & ?|?( ostype & os, long int li ) {
123 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
124 fmt( os, "%ld", li );
125 return os;
126 } // ?|?
127 void & ?|?( ostype & os, long int li ) {
128 (ostype &)(os | li); nl( os );
129 } // ?|?
130
131 ostype & ?|?( ostype & os, unsigned long int uli ) {
132 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
133 fmt( os, "%lu", uli );
134 return os;
135 } // ?|?
136 void & ?|?( ostype & os, unsigned long int uli ) {
137 (ostype &)(os | uli); nl( os );
138 } // ?|?
139
140 ostype & ?|?( ostype & os, long long int lli ) {
141 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
142 fmt( os, "%lld", lli );
143 return os;
144 } // ?|?
145 void & ?|?( ostype & os, long long int lli ) {
146 (ostype &)(os | lli); nl( os );
147 } // ?|?
148
149 ostype & ?|?( ostype & os, unsigned long long int ulli ) {
150 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
151 fmt( os, "%llu", ulli );
152 return os;
153 } // ?|?
154 void & ?|?( ostype & os, unsigned long long int ulli ) {
155 (ostype &)(os | ulli); nl( os );
156 } // ?|?
157
158 #define PrintWithDP( os, format, val, ... ) \
159 { \
160 enum { size = 48 }; \
161 char buf[size]; \
162 int len = snprintf( buf, size, format, ##__VA_ARGS__, val ); \
163 fmt( os, "%s", buf ); \
164 if ( isfinite( val ) ) { /* if number, always print decimal point */ \
165 for ( int i = 0;; i += 1 ) { \
166 if ( i == len ) { fmt( os, "." ); break; } \
167 if ( buf[i] == '.' ) break; \
168 } /* for */ \
169 } /* if */ \
170 }
171
172 ostype & ?|?( ostype & os, float f ) {
173 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
174 PrintWithDP( os, "%g", f );
175 return os;
176 } // ?|?
177 void & ?|?( ostype & os, float f ) {
178 (ostype &)(os | f); nl( os );
179 } // ?|?
180
181 ostype & ?|?( ostype & os, double d ) {
182 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
183 PrintWithDP( os, "%.*lg", d, DBL_DIG );
184 return os;
185 } // ?|?
186 void & ?|?( ostype & os, double d ) {
187 (ostype &)(os | d); nl( os );
188 } // ?|?
189
190 ostype & ?|?( ostype & os, long double ld ) {
191 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
192 PrintWithDP( os, "%.*Lg", ld, LDBL_DIG );
193 return os;
194 } // ?|?
195 void & ?|?( ostype & os, long double ld ) {
196 (ostype &)(os | ld); nl( os );
197 } // ?|?
198
199 ostype & ?|?( ostype & os, float _Complex fc ) {
200 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
201// os | crealf( fc ) | nonl;
202 PrintWithDP( os, "%g", crealf( fc ) );
203 PrintWithDP( os, "%+g", cimagf( fc ) );
204 fmt( os, "i" );
205 return os;
206 } // ?|?
207 void & ?|?( ostype & os, float _Complex fc ) {
208 (ostype &)(os | fc); nl( os );
209 } // ?|?
210
211 ostype & ?|?( ostype & os, double _Complex dc ) {
212 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
213// os | creal( dc ) | nonl;
214 PrintWithDP( os, "%.*lg", creal( dc ), DBL_DIG );
215 PrintWithDP( os, "%+.*lg", cimag( dc ), DBL_DIG );
216 fmt( os, "i" );
217 return os;
218 } // ?|?
219 void & ?|?( ostype & os, double _Complex dc ) {
220 (ostype &)(os | dc); nl( os );
221 } // ?|?
222
223 ostype & ?|?( ostype & os, long double _Complex ldc ) {
224 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
225// os | creall( ldc ) || nonl;
226 PrintWithDP( os, "%.*Lg", creall( ldc ), LDBL_DIG );
227 PrintWithDP( os, "%+.*Lg", cimagl( ldc ), LDBL_DIG );
228 fmt( os, "i" );
229 return os;
230 } // ?|?
231 void & ?|?( ostype & os, long double _Complex ldc ) {
232 (ostype &)(os | ldc); nl( os );
233 } // ?|?
234
235 ostype & ?|?( ostype & os, const char * str ) {
236 enum { Open = 1, Close, OpenClose };
237 static const unsigned char mask[256] @= {
238 // opening delimiters, no space after
239 ['('] : Open, ['['] : Open, ['{'] : Open,
240 ['='] : Open, ['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open,
241 [(unsigned char)'¡'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open,
242 // closing delimiters, no space before
243 [','] : Close, ['.'] : Close, [';'] : Close, ['!'] : Close, ['?'] : Close,
244 ['%'] : Close, [(unsigned char)'¢'] : Close, [(unsigned char)'»'] : Close,
245 [')'] : Close, [']'] : Close, ['}'] : Close,
246 // opening-closing delimiters, no space before or after
247 ['\''] : OpenClose, ['`'] : OpenClose, ['"'] : OpenClose, [':'] : OpenClose,
248 [' '] : OpenClose, ['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace
249 }; // mask
250
251 if ( str[0] == '\0' ) { sepOff( os ); return os; } // null string => no separator
252
253 // first character IS NOT spacing or closing punctuation => add left separator
254 unsigned char ch = str[0]; // must make unsigned
255 if ( sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) {
256 fmt( os, "%s", sepGetCur( os ) );
257 } // if
258
259 // if string starts line, must reset to determine open state because separator is off
260 sepReset( os ); // reset separator
261
262 // last character IS spacing or opening punctuation => turn off separator for next item
263 size_t len = strlen( str );
264 ch = str[len - 1]; // must make unsigned
265 if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
266 sepOn( os );
267 } else {
268 sepOff( os );
269 } // if
270 if ( ch == '\n' ) setNL( os, true ); // check *AFTER* sepPrt call above as it resets NL flag
271 return write( os, str, len );
272 } // ?|?
273 void ?|?( ostype & os, const char * str ) {
274 (ostype &)(os | str); nl( os );
275 } // ?|?
276
277// ostype & ?|?( ostype & os, const char16_t * str ) {
278// if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
279// fmt( os, "%ls", str );
280// return os;
281// } // ?|?
282
283// #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
284// ostype & ?|?( ostype & os, const char32_t * str ) {
285// if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
286// fmt( os, "%ls", str );
287// return os;
288// } // ?|?
289// #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
290
291// ostype & ?|?( ostype & os, const wchar_t * str ) {
292// if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
293// fmt( os, "%ls", str );
294// return os;
295// } // ?|?
296
297 ostype & ?|?( ostype & os, const void * p ) {
298 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
299 fmt( os, "%p", p );
300 return os;
301 } // ?|?
302 void ?|?( ostype & os, const void * p ) {
303 (ostype &)(os | p); nl( os );
304 } // ?|?
305
306 // manipulators
307 ostype & ?|?( ostype & os, ostype & (* manip)( ostype & ) ) {
308 (ostype &)(manip( os ));
309 return os;
310 } // ?|?
311 void ?|?( ostype & os, ostype & (* manip)( ostype & ) ) {
312 (ostype &)(manip( os ));
313 if ( getPrt( os ) ) nl( os ); // something printed ?
314 setPrt( os, false ); // turn off
315 } // ?|?
316
317 ostype & sep( ostype & os ) {
318 return (ostype &)(os | sepGet( os ));
319 } // sep
320
321 ostype & sepTuple( ostype & os ) {
322 return os | sepGetTuple( os );
323 } // sepTuple
324
325 ostype & nl( ostype & os ) {
326 (ostype &)(os | '\n');
327 setPrt( os, false ); // turn off
328 setNL( os, true );
329 flush( os );
330 return sepOff( os ); // prepare for next line
331 } // nl
332
333 void nl( ostype & os ) {
334 if ( getANL( os ) ) (ostype &)(nl( os )); // implementation only
335 else setPrt( os, false ); // turn off
336 } // nl
337
338 ostype & nonl( ostype & os ) {
339 setPrt( os, false ); // turn off
340 return os;
341 } // nonl
342
343 ostype & sepOn( ostype & os ) {
344 sepOn( os ); // call void returning
345 return os;
346 } // sepOn
347
348 ostype & sepOff( ostype & os ) {
349 sepOff( os ); // call void returning
350 return os;
351 } // sepOff
352
353 ostype & sepEnable( ostype & os ) {
354 sepEnable( os ); // call void returning
355 return os;
356 } // sepEnable
357
358 ostype & sepDisable( ostype & os ) {
359 sepDisable( os ); // call void returning
360 return os;
361 } // sepDisable
362
363 ostype & nlOn( ostype & os ) {
364 nlOn( os ); // call void returning
365 return os;
366 } // nlOn
367
368 ostype & nlOff( ostype & os ) {
369 nlOff( os ); // call void returning
370 return os;
371 } // nlOff
372} // distribution
373
374// tuples
375forall( dtype ostype, otype T, ttype Params | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } ) {
376 ostype & ?|?( ostype & os, T arg, Params rest ) {
377 (ostype &)(os | arg); // print first argument
378 sepSetCur( os, sepGetTuple( os ) ); // switch to tuple separator
379 (ostype &)(os | rest); // print remaining arguments
380 sepSetCur( os, sepGet( os ) ); // switch to regular separator
381 return os;
382 } // ?|?
383 void ?|?( ostype & os, T arg, Params rest ) {
384 // (ostype &)(?|?( os, arg, rest )); nl( os );
385 (ostype &)(os | arg); // print first argument
386 sepSetCur( os, sepGetTuple( os ) ); // switch to tuple separator
387 (ostype &)(os | rest); // print remaining arguments
388 sepSetCur( os, sepGet( os ) ); // switch to regular separator
389 nl( os );
390 } // ?|?
391} // distribution
392
393
394//*********************************** Integral ***********************************
395
396static const char * shortbin[] = { "0", "1", "10", "11", "100", "101", "110", "111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };
397static const char * longbin[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };
398
399// Default prefix for non-decimal prints is 0b, 0, 0x.
400#define IntegralFMTImpl( T, CODE, IFMTNP, IFMTP ) \
401forall( dtype ostype | ostream( ostype ) ) { \
402 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
403 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); \
404\
405 if ( f.base == 'b' || f.base == 'B' ) { /* bespoke binary format */ \
406 int bits; \
407 if ( f.val == (T){0} ) bits = 1; /* force at least one bit to print */ \
408 else bits = sizeof(long long int) * 8 - __builtin_clzll( f.val ); /* position of most significant bit */ \
409 bits = bits > sizeof(f.val) * 8 ? sizeof(f.val) * 8 : bits; \
410 int spaces = f.wd - bits; /* can be negative */ \
411 if ( ! f.flags.nobsdp ) { spaces -= 2; } /* base prefix takes space */ \
412 /* printf( "%d %d\n", bits, spaces ); */ \
413 if ( ! f.flags.left ) { /* right justified ? */ \
414 /* Note, base prefix then zero padding or spacing then prefix. */ \
415 if ( f.flags.pad0 || f.flags.pc ) { \
416 if ( ! f.flags.nobsdp ) { fmt( os, "0%c", f.base ); } \
417 if ( f.flags.pc ) spaces = f.pc - bits; \
418 if ( spaces > 0 ) fmt( os, "%0*d", spaces, 0 ); /* zero pad */ \
419 } else { \
420 if ( spaces > 0 ) fmt( os, "%*s", spaces, " " ); /* space pad */ \
421 if ( ! f.flags.nobsdp ) { fmt( os, "0%c", f.base ); } \
422 } /* if */ \
423 } else if ( ! f.flags.nobsdp ) { \
424 fmt( os, "0%c", f.base ); \
425 } /* if */ \
426 int shift = (bits - 1) / 4 * 4; /* floor( bits - 1, 4 ) */ \
427 typeof( f.val ) temp = f.val; \
428 fmt( os, "%s", shortbin[(temp >> shift) & 0xf] ); \
429 for () { \
430 shift -= 4; \
431 if ( shift < 0 ) break; \
432 temp = f.val; \
433 fmt( os, "%s", longbin[(temp >> shift) & 0xf] ); \
434 } /* for */ \
435 if ( f.flags.left && spaces > 0 ) fmt( os, "%*s", spaces, " " ); \
436 return os; \
437 } /* if */ \
438\
439 char fmtstr[sizeof(IFMTP)]; /* sizeof includes '\0' */ \
440 if ( ! f.flags.pc ) memcpy( &fmtstr, IFMTNP, sizeof(IFMTNP) ); \
441 else memcpy( &fmtstr, IFMTP, sizeof(IFMTP) ); \
442 int star = 4; /* position before first '*' */ \
443\
444 /* Insert flags into spaces before '*', from right to left. */ \
445 if ( ! f.flags.nobsdp ) { fmtstr[star] = '#'; star -= 1; } \
446 if ( f.flags.left ) { fmtstr[star] = '-'; star -= 1; } \
447 if ( f.flags.sign && f.base == CODE ) { fmtstr[star] = '+'; star -= 1; } \
448 if ( f.flags.pad0 && ! f.flags.pc ) { fmtstr[star] = '0'; star -= 1; } \
449 fmtstr[star] = '%'; \
450\
451 if ( ! f.flags.pc ) { /* no precision */ \
452 /* printf( "%s\n", &fmtstr[star] ); */ \
453 fmtstr[sizeof(IFMTNP)-2] = f.base; /* sizeof includes '\0' */ \
454 fmt( os, &fmtstr[star], f.wd, f.val ); \
455 } else { /* precision */ \
456 fmtstr[sizeof(IFMTP)-2] = f.base; /* sizeof includes '\0' */ \
457 /* printf( "%s\n", &fmtstr[star] ); */ \
458 fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); \
459 } /* if */ \
460 return os; \
461 } /* ?|? */ \
462 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); nl( os ); } \
463} // distribution
464
465IntegralFMTImpl( signed char, 'd', "% *hh ", "% *.*hh " )
466IntegralFMTImpl( unsigned char, 'u', "% *hh ", "% *.*hh " )
467IntegralFMTImpl( signed short int, 'd', "% *h ", "% *.*h " )
468IntegralFMTImpl( unsigned short int, 'u', "% *h ", "% *.*h " )
469IntegralFMTImpl( signed int, 'd', "% * ", "% *.* " )
470IntegralFMTImpl( unsigned int, 'u', "% * ", "% *.* " )
471IntegralFMTImpl( signed long int, 'd', "% *l ", "% *.*l " )
472IntegralFMTImpl( unsigned long int, 'u', "% *l ", "% *.*l " )
473IntegralFMTImpl( signed long long int, 'd', "% *ll ", "% *.*ll " )
474IntegralFMTImpl( unsigned long long int, 'u', "% *ll ", "% *.*ll " )
475
476//*********************************** Floating Point ***********************************
477
478#define PrintWithDP2( os, format, val, ... ) \
479 { \
480 enum { size = 48 }; \
481 char buf[size]; \
482 int bufbeg = 0, i, len = snprintf( buf, size, format, ##__VA_ARGS__, val ); \
483 if ( isfinite( val ) && (f.base != 'g' || f.pc != 0) ) { /* if number, print decimal point */ \
484 for ( i = 0; i < len && buf[i] != '.' && buf[i] != 'e' && buf[i] != 'E'; i += 1 ); /* decimal point or scientific ? */ \
485 if ( i == len && ! f.flags.nobsdp ) { \
486 if ( ! f.flags.left ) { \
487 buf[i] = '.'; buf[i + 1] = '\0'; \
488 if ( buf[0] == ' ' ) bufbeg = 1; /* decimal point within width */ \
489 } else { \
490 for ( i = 0; i < len && buf[i] != ' '; i += 1 ); /* trailing blank ? */ \
491 buf[i] = '.'; \
492 if ( i == len ) buf[i + 1] = '\0'; \
493 } /* if */ \
494 } /* if */ \
495 } /* if */ \
496 fmt( os, "%s", &buf[bufbeg] ); \
497 }
498
499#define FloatingPointFMTImpl( T, DFMTNP, DFMTP ) \
500forall( dtype ostype | ostream( ostype ) ) { \
501 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
502 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); \
503 char fmtstr[sizeof(DFMTP)]; /* sizeof includes '\0' */ \
504 if ( ! f.flags.pc ) memcpy( &fmtstr, DFMTNP, sizeof(DFMTNP) ); \
505 else memcpy( &fmtstr, DFMTP, sizeof(DFMTP) ); \
506 int star = 4; /* position before first '*' */ \
507\
508 /* Insert flags into spaces before '*', from right to left. */ \
509 if ( f.flags.left ) { fmtstr[star] = '-'; star -= 1; } \
510 if ( f.flags.sign ) { fmtstr[star] = '+'; star -= 1; } \
511 if ( f.flags.pad0 ) { fmtstr[star] = '0'; star -= 1; } \
512 fmtstr[star] = '%'; \
513\
514 if ( ! f.flags.pc ) { /* no precision */ \
515 fmtstr[sizeof(DFMTNP)-2] = f.base; /* sizeof includes '\0' */ \
516 /* printf( "%g %d %s\n", f.val, f.wd, &fmtstr[star]); */ \
517 PrintWithDP2( os, &fmtstr[star], f.val, f.wd ) \
518 } else { /* precision */ \
519 fmtstr[sizeof(DFMTP)-2] = f.base; /* sizeof includes '\0' */ \
520 /* printf( "%g %d %d %s\n", f.val, f.wd, f.pc, &fmtstr[star] ); */ \
521 PrintWithDP2( os, &fmtstr[star], f.val, f.wd, f.pc ) \
522 } /* if */ \
523 return os; \
524 } /* ?|? */ \
525 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); nl( os ); } \
526} // distribution
527
528FloatingPointFMTImpl( double, "% * ", "% *.* " )
529FloatingPointFMTImpl( long double, "% *L ", "% *.*L " )
530
531//*********************************** Character ***********************************
532
533forall( dtype ostype | ostream( ostype ) ) {
534 ostype & ?|?( ostype & os, _Ostream_Manip(char) f ) {
535 if ( f.base != 'c' ) { // bespoke binary/octal/hex format
536 _Ostream_Manip(unsigned char) fmtuc @= { f.val, f.wd, f.pc, f.base, {'\0'} };
537 fmtuc.flags.pc = f.flags.pc;
538 fmtuc.flags.nobsdp = f.flags.nobsdp;
539// os | fmtuc | nonl;
540 (ostype &)(os | fmtuc);
541 return os;
542 } // if
543
544 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
545
546 #define CFMTNP "% * "
547 char fmtstr[sizeof(CFMTNP)]; // sizeof includes '\0'
548 memcpy( &fmtstr, CFMTNP, sizeof(CFMTNP) );
549 int star = 1; // position before first '*'
550
551 // Insert flags into spaces before '*', from right to left.
552 if ( f.flags.left ) { fmtstr[star] = '-'; star -= 1; }
553 fmtstr[star] = '%';
554
555 fmtstr[sizeof(CFMTNP)-2] = f.base; // sizeof includes '\0'
556 // printf( "%d %s\n", f.wd, &fmtstr[star] );
557 fmt( os, &fmtstr[star], f.wd, f.val );
558 return os;
559 } // ?|?
560 void ?|?( ostype & os, _Ostream_Manip(char) f ) { (ostype &)(os | f); nl( os ); }
561} // distribution
562
563//*********************************** C String ***********************************
564
565forall( dtype ostype | ostream( ostype ) ) {
566 ostype & ?|?( ostype & os, _Ostream_Manip(const char *) f ) {
567 if ( ! f.val ) return os; // null pointer ?
568
569 if ( f.base != 's' ) { // bespoke binary/octal/hex format
570 _Ostream_Manip(unsigned char) fmtuc @= { 0, f.wd, f.pc, f.base, {'\0'} };
571 fmtuc.flags.pc = f.flags.pc;
572 fmtuc.flags.nobsdp = f.flags.nobsdp;
573 for ( unsigned int i = 0; f.val[i] != '\0'; i += 1 ) {
574 fmtuc.val = f.val[i];
575// os | fmtuc | nonl;
576 (ostype &)(os | fmtuc);
577 } // for
578 return os;
579 } // if
580
581 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
582
583 #define SFMTNP "% * "
584 #define SFMTP "% *.* "
585 char fmtstr[sizeof(SFMTP)]; // sizeof includes '\0'
586 if ( ! f.flags.pc ) memcpy( &fmtstr, SFMTNP, sizeof(SFMTNP) );
587 else memcpy( &fmtstr, SFMTP, sizeof(SFMTP) );
588 int star = 1; // position before first '*'
589
590 // Insert flags into spaces before '*', from right to left.
591 if ( f.flags.left ) { fmtstr[star] = '-'; star -= 1; }
592 fmtstr[star] = '%';
593
594 if ( ! f.flags.pc ) { // no precision
595 // printf( "%d %s\n", f.wd, &fmtstr[star] );
596 fmtstr[sizeof(SFMTNP)-2] = f.base; // sizeof includes '\0'
597 fmt( os, &fmtstr[star], f.wd, f.val );
598 } else { // precision
599 fmtstr[sizeof(SFMTP)-2] = f.base; // sizeof includes '\0'
600 // printf( "%d %d %s\n", f.wd, f.pc, &fmtstr[star] );
601 fmt( os, &fmtstr[star], f.wd, f.pc, f.val );
602 } // if
603 return os;
604 } // ?|?
605 void ?|?( ostype & os, _Ostream_Manip(const char *) f ) { (ostype &)(os | f); nl( os ); }
606} // distribution
607
608//---------------------------------------
609
610// writes the range [begin, end) to the given stream
611forall( dtype ostype, otype elt_type | writeable( elt_type, ostype ), otype iterator_type | iterator( iterator_type, elt_type ) ) {
612 void write( iterator_type begin, iterator_type end, ostype & os ) {
613 void print( elt_type i ) { os | i; }
614 for_each( begin, end, print );
615 } // ?|?
616
617 void write_reverse( iterator_type begin, iterator_type end, ostype & os ) {
618 void print( elt_type i ) { os | i; }
619 for_each_reverse( begin, end, print );
620 } // ?|?
621} // distribution
622
623
624//*********************************** Istream ***********************************
625
626
627forall( dtype istype | istream( istype ) ) {
628 istype & ?|?( istype & is, bool & b ) {
629 char val[6];
630 fmt( is, "%5s", val );
631 if ( strcmp( val, "true" ) == 0 ) b = true;
632 else if ( strcmp( val, "false" ) == 0 ) b = false;
633 else {
634 fprintf( stderr, "invalid Boolean constant\n" );
635 abort();
636 } // if
637 return is;
638 } // ?|?
639
640 istype & ?|?( istype & is, char & c ) {
641 char temp;
642 for () {
643 fmt( is, "%c", &temp ); // must pass pointer through varg to fmt
644 // do not overwrite parameter with newline unless appropriate
645 if ( temp != '\n' || getANL( is ) ) { c = temp; break; }
646 if ( eof( is ) ) break;
647 } // for
648 return is;
649 } // ?|?
650
651 istype & ?|?( istype & is, signed char & sc ) {
652 fmt( is, "%hhi", &sc );
653 return is;
654 } // ?|?
655
656 istype & ?|?( istype & is, unsigned char & usc ) {
657 fmt( is, "%hhi", &usc );
658 return is;
659 } // ?|?
660
661 istype & ?|?( istype & is, short int & si ) {
662 fmt( is, "%hi", &si );
663 return is;
664 } // ?|?
665
666 istype & ?|?( istype & is, unsigned short int & usi ) {
667 fmt( is, "%hi", &usi );
668 return is;
669 } // ?|?
670
671 istype & ?|?( istype & is, int & i ) {
672 fmt( is, "%i", &i );
673 return is;
674 } // ?|?
675
676 istype & ?|?( istype & is, unsigned int & ui ) {
677 fmt( is, "%i", &ui );
678 return is;
679 } // ?|?
680
681 istype & ?|?( istype & is, long int & li ) {
682 fmt( is, "%li", &li );
683 return is;
684 } // ?|?
685
686 istype & ?|?( istype & is, unsigned long int & ulli ) {
687 fmt( is, "%li", &ulli );
688 return is;
689 } // ?|?
690
691 istype & ?|?( istype & is, long long int & lli ) {
692 fmt( is, "%lli", &lli );
693 return is;
694 } // ?|?
695
696 istype & ?|?( istype & is, unsigned long long int & ulli ) {
697 fmt( is, "%lli", &ulli );
698 return is;
699 } // ?|?
700
701
702 istype & ?|?( istype & is, float & f ) {
703 fmt( is, "%f", &f );
704 return is;
705 } // ?|?
706
707 istype & ?|?( istype & is, double & d ) {
708 fmt( is, "%lf", &d );
709 return is;
710 } // ?|?
711
712 istype & ?|?( istype & is, long double & ld ) {
713 fmt( is, "%Lf", &ld );
714 return is;
715 } // ?|?
716
717
718 istype & ?|?( istype & is, float _Complex & fc ) {
719 float re, im;
720 fmt( is, "%f%fi", &re, &im );
721 fc = re + im * _Complex_I;
722 return is;
723 } // ?|?
724
725 istype & ?|?( istype & is, double _Complex & dc ) {
726 double re, im;
727 fmt( is, "%lf%lfi", &re, &im );
728 dc = re + im * _Complex_I;
729 return is;
730 } // ?|?
731
732 istype & ?|?( istype & is, long double _Complex & ldc ) {
733 long double re, im;
734 fmt( is, "%Lf%Lfi", &re, &im );
735 ldc = re + im * _Complex_I;
736 return is;
737 } // ?|?
738
739 // manipulators
740 istype & ?|?( istype & is, istype & (* manip)( istype & ) ) {
741 return manip( is );
742 } // ?|?
743
744 istype & nl( istype & is ) {
745 fmt( is, "%*[^\n]" ); // ignore characters to newline
746 return is;
747 } // nl
748
749 istype & nlOn( istype & is ) {
750 nlOn( is ); // call void returning
751 return is;
752 } // nlOn
753
754 istype & nlOff( istype & is ) {
755 nlOff( is ); // call void returning
756 return is;
757 } // nlOff
758} // distribution
759
760_Istream_cstrUC cstr( char * str ) { return (_Istream_cstrUC){ str }; }
761forall( dtype istype | istream( istype ) )
762istype & ?|?( istype & is, _Istream_cstrUC cstr ) {
763 fmt( is, "%s", cstr.s );
764 return is;
765} // cstr
766
767_Istream_cstrC cstr( char * str, int size ) { return (_Istream_cstrC){ str, size }; }
768forall( dtype istype | istream( istype ) )
769istype & ?|?( istype & is, _Istream_cstrC cstr ) {
770 char buf[16];
771 sprintf( buf, "%%%ds", cstr.size );
772 fmt( is, buf, cstr.s );
773 return is;
774} // cstr
775
776#if 0
777forall( dtype istype | istream( istype ) )
778istype & ?|?( istype & is, _Istream_skip skip ) {
779 fmt( is, skip.s, "" ); // no input arguments
780 return is;
781} // skip
782
783forall( dtype istype | istream( istype ) )
784istype & ?|?( istype & is, _Istream_incl incl ) {
785 size_t len = strlen( incl.scanset ) + 4; // extras: "%[]\0"
786 char fmtstr[len];
787 fmtstr[0] = '%'; fmtstr[1] = '[';
788 strcpy( &fmtstr[2], incl.scanset ); // after '[', copy includes '\0'
789 fmtstr[len - 2] = ']'; fmtstr[len - 1] = '\0';
790 fmt( is, fmtstr, incl.s );
791 return is;
792} // incl
793
794forall( dtype istype | istream( istype ) )
795istype & ?|?( istype & is, _Istream_excl excl ) {
796 size_t len = strlen( excl.scanset );
797 char fmtstr[len+5];
798 fmtstr[0] = '%'; fmtstr[1] = '['; fmtstr[2] = '^';
799 strcpy( &fmtstr[3], excl.scanset ); // after '^', copy includes '\0'
800 fmtstr[len - 2] = ']'; fmtstr[len - 1] = '\0';
801 fmt( is, fmtstr, excl.s );
802 return is;
803} // excl
804
805forall( dtype istype | istream( istype ) )
806istype & ?|?( istype & is, _Istream_cstr cstr ) {
807 fmt( is, "%s", cstr.s );
808 return is;
809} // cstr
810
811_Istream_cstrW cstr( char * s, int size ) { return (_Istream_cstrW){ s, size }; }
812forall( dtype istype | istream( istype ) )
813istype & ?|?( istype & is, _Istream_cstrW cstr ) {
814 enum { size = 16 };
815 char fmtstr[size];
816 sprintf( fmtstr, "%%%ds", cstr.size );
817 fmt( is, fmtstr, cstr.s );
818 return is;
819} // cstr
820
821forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, _Istream_Cstr ) {
822
823}
824
825//*********************************** Manipulators ***********************************
826
827#define InputFMTImpl( T, CODE ) \
828forall( dtype istype | istream( istype ) ) \
829istype & ?|?( istype & is, _Istream_Manip(T) f ) { \
830 enum { size = 16 }; \
831 char fmtstr[size]; \
832 if ( f.wd == -1 ) { \
833 snprintf( fmtstr, size, "%%%s%s", f.ignore ? "*" : "", CODE ); \
834 } else { \
835 snprintf( fmtstr, size, "%%%s%d%s", f.ignore ? "*" : "", f.wd, CODE ); \
836 } /* if */ \
837 /* printf( "%d %s %p\n", f.wd, fmtstr, &f.val ); */ \
838 fmt( is, fmtstr, &f.val ); \
839 return is; \
840} /* ?|? */
841
842InputFMTImpl( char, "c" )
843InputFMTImpl( signed char, "hhi" )
844InputFMTImpl( unsigned char, "hhi" )
845InputFMTImpl( signed short int, "hi" )
846InputFMTImpl( unsigned short int, "hi" )
847InputFMTImpl( signed int, "i" )
848InputFMTImpl( unsigned int, "i" )
849InputFMTImpl( signed long int, "li" )
850InputFMTImpl( unsigned long int, "li" )
851InputFMTImpl( signed long long int, "lli" )
852InputFMTImpl( unsigned long long int, "lli" )
853
854InputFMTImpl( float, "f" )
855InputFMTImpl( double, "lf" )
856InputFMTImpl( long double, "Lf" )
857
858InputFMTImpl( float _Complex, "ff" )
859InputFMTImpl( double _Complex, "lf" )
860InputFMTImpl( long double _Complex, "Lf" )
861#endif // 0
862
863// Local Variables: //
864// tab-width: 4 //
865// compile-command: "cfa iostream.cfa" //
866// End: //
Note: See TracBrowser for help on using the repository browser.