Ignore:
Timestamp:
Jun 4, 2019, 6:34:15 PM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
9be45a2
Parents:
0161ddf
Message:

first draft of output manipulators and start input manipulators

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/iostream.cfa

    r0161ddf r3c573e9  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 21 13:01:26 2019
    13 // Update Count     : 674
     12// Last Modified On : Tue Jun  4 17:32:34 2019
     13// Update Count     : 761
    1414//
    1515
     
    2020#include <stdbool.h>                                                                    // true/false
    2121//#include <string.h>                                                                   // strlen, strcmp
     22extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
    2223extern int strcmp (const char *__s1, const char *__s2) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
    23 extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
     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)));
    2426#include <float.h>                                                                              // DBL_DIG, LDBL_DIG
    2527#include <math.h>                                                                               // isfinite
    2628#include <complex.h>                                                                    // creal, cimag
    27 }
     29} // extern "C"
    2830
    2931forall( dtype ostype | ostream( ostype ) ) {
     
    198200                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    199201//              os | crealf( fc ) | nonl;
    200                 float f = crealf( fc );
    201                 PrintWithDP( os, "%g", f );
    202                 f = cimagf( fc );
    203                 PrintWithDP( os, "%+g", f );
     202                PrintWithDP( os, "%g", crealf( fc ) );
     203                PrintWithDP( os, "%+g", cimagf( fc ) );
    204204                fmt( os, "i" );
    205205                return os;
     
    212212                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    213213//              os | creal( dc ) | nonl;
    214                 double d = creal( dc );
    215                 PrintWithDP( os, "%.*lg", d, DBL_DIG );
    216                 d = cimag( dc );
    217                 PrintWithDP( os, "%+.*lg", d, DBL_DIG );
     214                PrintWithDP( os, "%.*lg", creal( dc ), DBL_DIG );
     215                PrintWithDP( os, "%+.*lg", cimag( dc ), DBL_DIG );
    218216                fmt( os, "i" );
    219217                return os;
     
    226224                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    227225//              os | creall( ldc ) || nonl;
    228                 long double ld = creall( ldc );
    229                 PrintWithDP( os, "%.*Lg", ld, LDBL_DIG );
    230                 ld = cimagl( ldc );
    231                 PrintWithDP( os, "%+.*Lg", ld, LDBL_DIG );
     226                PrintWithDP( os, "%.*Lg", creall( ldc ), LDBL_DIG );
     227                PrintWithDP( os, "%+.*Lg", cimagl( ldc ), LDBL_DIG );
    232228                fmt( os, "i" );
    233229                return os;
     
    395391} // distribution
    396392
     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
    397608//---------------------------------------
    398609
     
    410621} // distribution
    411622
    412 //---------------------------------------
     623
     624//*********************************** Istream ***********************************
     625
    413626
    414627forall( dtype istype | istream( istype ) ) {
     
    437650
    438651        istype & ?|?( istype & is, signed char & sc ) {
    439                 fmt( is, "%hhd", &sc );
     652                fmt( is, "%hhi", &sc );
    440653                return is;
    441654        } // ?|?
    442655
    443656        istype & ?|?( istype & is, unsigned char & usc ) {
    444                 fmt( is, "%hhu", &usc );
     657                fmt( is, "%hhi", &usc );
    445658                return is;
    446659        } // ?|?
    447660
    448661        istype & ?|?( istype & is, short int & si ) {
    449                 fmt( is, "%hd", &si );
     662                fmt( is, "%hi", &si );
    450663                return is;
    451664        } // ?|?
    452665
    453666        istype & ?|?( istype & is, unsigned short int & usi ) {
    454                 fmt( is, "%hu", &usi );
     667                fmt( is, "%hi", &usi );
    455668                return is;
    456669        } // ?|?
    457670
    458671        istype & ?|?( istype & is, int & i ) {
    459                 fmt( is, "%d", &i );
     672                fmt( is, "%i", &i );
    460673                return is;
    461674        } // ?|?
    462675
    463676        istype & ?|?( istype & is, unsigned int & ui ) {
    464                 fmt( is, "%u", &ui );
     677                fmt( is, "%i", &ui );
    465678                return is;
    466679        } // ?|?
    467680
    468681        istype & ?|?( istype & is, long int & li ) {
    469                 fmt( is, "%ld", &li );
     682                fmt( is, "%li", &li );
    470683                return is;
    471684        } // ?|?
    472685
    473686        istype & ?|?( istype & is, unsigned long int & ulli ) {
    474                 fmt( is, "%lu", &ulli );
     687                fmt( is, "%li", &ulli );
    475688                return is;
    476689        } // ?|?
    477690
    478691        istype & ?|?( istype & is, long long int & lli ) {
    479                 fmt( is, "%lld", &lli );
     692                fmt( is, "%lli", &lli );
    480693                return is;
    481694        } // ?|?
    482695
    483696        istype & ?|?( istype & is, unsigned long long int & ulli ) {
    484                 fmt( is, "%llu", &ulli );
     697                fmt( is, "%lli", &ulli );
    485698                return is;
    486699        } // ?|?
     
    505718        istype & ?|?( istype & is, float _Complex & fc ) {
    506719                float re, im;
    507                 fmt( is, "%g%gi", &re, &im );
     720                fmt( is, "%f%fi", &re, &im );
    508721                fc = re + im * _Complex_I;
    509722                return is;
     
    561774} // cstr
    562775
     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
    563863// Local Variables: //
    564864// tab-width: 4 //
Note: See TracChangeset for help on using the changeset viewer.