#include "enum.hfa" #include "fstream.hfa" #include #pragma GCC visibility push(default) forall( E | Serial( E ) ) { E fromInt( unsigned i ) { E upper = upperBound(); E lower = lowerBound(); // It is okay to overflow as overflow will be theoretically caught by the other bound if ( i < fromInstance( lower ) || i > fromInstance( upper ) ) abort( "call to fromInt has index %d outside enumeration range %d-%d", i, fromInstance( lower ), fromInstance( upper ) ); return fromInt_unsafe( i ); } E succ( E e ) { E upper = upperBound(); if ( fromInstance( e ) >= fromInstance( upper ) ) abort( "call to succ() exceeds enumeration upper bound of %d", fromInstance( upper ) ); return succ_unsafe(e); } E pred( E e ) { E lower = lowerBound(); if ( fromInstance(e) <= fromInstance(lower ) ) abort( "call to pred() exceeds enumeration lower bound of %d", fromInstance( lower ) ); return pred_unsafe(e); } int Countof( __attribute__((unused)) E e ) { E upper = upperBound(); E lower = lowerBound(); return fromInstance( upper ) + fromInstance( lower ) + 1; } } forall( istype & | istream( istype ), E | CfaEnum( E ) | Serial( E ) ) istype & ?|?( istype & is, E & e ) { // fprintf( stderr, "here0\n" ); if ( eof( is ) ) throwResume ExceptionInst( missing_data ); // Match longest input enumerator string to enumerator labels, where enumerator names are unique. int N = countof( E ), lnths[N], max = 0; // printf( "N %d\n", N ); int r = 0; // for ( s; E : r; 0~@ ) { for ( s; E ) { // scan string rows gathering lengths lnths[r] = strlen( label( s ) ); if ( lnths[r] > max ) max = lnths[r]; // fprintf( stderr, "%s %d %d\n", label( s ), lnths[r], max ); r += 1; } // for int mcol = -1; // last match column char ch, curr = '\0', prev = '\0'; fmt( is, " " ); // skip optional whitespace for ( c; max ) { // scan columns of the label matix (some columns missing) int args = fmt( is, "%c", &ch ); // read character // fprintf( stderr, "fmt args: %d eof: %d\n", args, eof(is) ); if ( eof( is ) ) { // fprintf( stderr, "Eof1\n" ); if ( c == 0 ) return is; // no characters read ? clear( is ); // => read something => reset EOF => detect again on next read // fprintf( stderr, "Eof2\n" ); break; } // if if ( args != 1 ) throwResume ExceptionInst( missing_data ); // may be unnecessary since reading single character // printf( "read '%c'\n", ch ); for ( r; N ) { // scan enumeration strings for matching character in current column // printf( "%d %d %d\n", c, r, lnths[r] ); if ( c < lnths[r] ) { // string long enough for this column check ? char match = label( fromInt( r ) )[c]; // optimization // printf( "%c '%c'\n", match, ch ); // Stop on first match, could be other matches. if ( (match == ch) && (c == 0 || curr == label( fromInt( r ) )[c - 1]) ) { // printf( "match %d %d %d '%c' '%c' '%c' '%c' 'c'\n", c, r, lnths[r], match, ch, prev, label( fromInt( r ) )[c - 1] ); mcol = c; // matching column prev = curr; // last matching character curr = ch; // current matching character break; } // if } // if } else { // fprintf( stderr, "finished mcol: %d ch: '%c' curr: '%c' prev: '%c'\n", mcol, ch, curr, prev ); ungetc( ch, is ); // push back last unmatching character if ( mcol == -1 ) throwResume ExceptionInst( missing_data ); // no matching character in first column break; } // for // printf( "\n" ); // } else { // fprintf( stderr, "finished2 %d\n", mcol ); } // for for ( c; N ) { // scan enumeration strings of length "mcol" for match if ( mcol == lnths[c] - 1 ) { char match = label( fromInt( c ) )[mcol]; // optimization // printf( "finished1 mcol: %d c: %d lnth: %d match: '%c' curr: '%c' prev: '%c'\n", mcol, c, lnths[c], match, curr, prev ); if ( (match == curr) && (mcol == 0 || prev == label( fromInt( c ) )[mcol - 1]) ) { e = fromInt( c ); break; } // if } // if } else { // fprintf( stderr, "finished3 %d\n", mcol ); throwResume ExceptionInst( missing_data ); // no match in this column } // for return is; } forall( ostype & | ostream( ostype ), E | CfaEnum( E ) ) { ostype & ?|?( ostype & os, E e ) { return os | label( e ); } OSTYPE_VOID_IMPL( E ) }