/* Implement Input/Output runtime actions for CHILL. Copyright (C) 1992,1993 Free Software Foundation, Inc. Author: Wilfried Moser, et al This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* As a special exception, if you link this library with other files, some of which are compiled with GCC, to produce an executable, this library does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ #include #include #include #include #include #include #include #if _TEXTIO_DEBUG_ #include #endif #include "bitstring.h" #include "auxtypes.h" #include "iomodes.h" #include "format.h" #include "fileio.h" #include "ioerror.h" #define CH_BYTE_MIN 0xffffff80L #define CH_BYTE_MAX 0x0000007fL #define CH_UBYTE_MAX 0x000000ffUL #define CH_INT_MIN 0xffff8000L #define CH_INT_MAX 0x00007fffL #define CH_UINT_MAX 0x0000ffffUL #define CH_LONG_MIN 0x80000000L #define CH_LONG_MAX 0x7fffffffL #define CH_ULONG_MAX 0xffffffffUL #ifndef M_LN2 #define M_LN2 0.69314718055994530942 #endif #ifndef M_LN10 #define M_LN10 2.30258509299404568402 #endif #define DMANTDIGS (1 + (int)(DBL_MANT_DIG * M_LN2 / M_LN10)) #define FMANTDIGS (1 + (int)(FLT_MANT_DIG * M_LN2 / M_LN10)) /* float register length */ #define MAXPREC 40 #define LET 0x0001 #define BIN 0x0002 #define DEC 0x0004 #define OCT 0x0008 #define HEX 0x0010 #define USC 0x0020 #define BIL 0x0040 #define SPC 0x0080 #define SCS 0x0100 #define IOC 0x0200 #define EDC 0x0400 #define CVC 0x0800 #define isDEC(c) ( chartab[(c)] & DEC ) #define isCVC(c) ( chartab[(c)] & CVC ) #define isEDC(c) ( chartab[(c)] & EDC ) #define isIOC(c) ( chartab[(c)] & IOC ) #define isUSC(c) #define isXXX(c,XXX) ( chartab[(c)] & XXX ) /* * local definitions */ static short int chartab[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, SPC, SPC, SPC, SPC, SPC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SPC, IOC, 0, 0, 0, 0, 0, 0, SCS, SCS, SCS, SCS+IOC, SCS, SCS+IOC, SCS, SCS+IOC, BIN+OCT+DEC+HEX, BIN+OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, DEC+HEX, DEC+HEX, SCS, SCS, SCS+EDC, SCS+IOC, SCS+EDC, IOC, 0, LET+HEX+BIL, LET+HEX+BIL+CVC, LET+HEX+BIL+CVC, LET+HEX+BIL, LET+HEX, LET+HEX+CVC, LET, LET+BIL+CVC, LET, LET, LET, LET, LET, LET, LET+CVC, LET, LET, LET, LET, LET+EDC, LET, LET, LET, LET+EDC, LET, LET, SCS, 0, SCS, 0, USC, 0, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, LET, 0, 0, 0, 0, 0 }; typedef enum { FormatText, FirstPercent, RepFact, ConvClause, EditClause, ClauseEnd, AfterWidth, FractWidth, FractWidthCont, ExpoWidth, ExpoWidthCont, ClauseWidth, CatchPadding, LastPercent } fcsstate_t; #define CONVERSIONCODES "CHOBF" typedef enum { DefaultConv, HexConv, OctalConv, BinaryConv, ScientConv } convcode_t; static short int base[4] = { 10, 16, 8, 2 }; static short int dset[4] = { DEC, HEX, OCT, BIN }; #define EDITCODES "X<>T" typedef enum { SpaceSkip, SkipLeft, SkipRight, Tabulation } editcode_t; #define IOCODES "/+-?!=" typedef enum { NextRecord, NextPage, CurrentLine, Prompt, Emit, EndPage } iocode_t; typedef enum { ConvAct, EditAct, IOAct } acttype_t; typedef enum { NormalEnd, EndAtParen, TextFailEnd } formatexit_t; static double ep_1[10] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 }; static double ep_10[10] = { 1e0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; static double ep_100 = 1e100; /* float register */ static unsigned char floatdig[MAXPREC]; /* * global io variables */ static Text_Mode* textptr = NULL; static VarString* textrecptr; static int actual_index; static int maximum_index; static int iolist_index; static __tmp_IO_list* iolistptr; static int iolistlen; static char* iostrptr; static int iostrlen; static convcode_t convcode; static editcode_t editcode; static iocode_t iocode; static unsigned long repetition; static Boolean leftadjust; static Boolean overflowev; static Boolean dynamicwid; static Boolean paddingdef; static char paddingchar; static Boolean fractiondef; static unsigned long fractionwidth; static Boolean exponentdef; static unsigned long exponentwidth; static unsigned long clausewidth; static signed long textindex; static __tmp_IO_enum_table_type bool_tab[] = { { 0, "FALSE" }, { 1, "TRUE" }, { 0 , NULL } }; /* * case insensitive compare: s1 is zero delimited, s2 has n chars */ static int casncmp( const char* s1, const char* s2, int n ) { int res = 0; while( n-- ) { if( (res = toupper(*s1++) - toupper(*s2++)) ) return res; } return *s1; } /* * skip spaces with blank equal to tab */ static int skip_space( int limit ) { int skipped = 0; while( actual_index < limit && (iostrptr[actual_index] == ' ' || iostrptr[actual_index] == '\t' ) ) { actual_index++; skipped++; } return skipped; } /* * skip leading pad characters */ static int skip_pad( int limit ) { int skipped = 0; while( actual_index < limit && iostrptr[actual_index] == paddingchar ) { actual_index++; skipped++; } #if _TEXTIO_DEBUG_ printf( "skipping '%c' until %d: %d\n", paddingchar, limit, skipped ); #endif return skipped; } /* * backup trailing pad characters */ static int piks_pad( int start, int limit ) { int skipped = 0; while( start >/***=*/ limit && iostrptr[--start] == paddingchar ) { skipped++; } #if _TEXTIO_DEBUG_ printf( "piksing '%c' from %d until %d: %d\n", paddingchar, start, limit, skipped ); #endif return skipped; } /* * parse an integer */ static int parse_int( int limit, int SET, int base, unsigned long* valptr, int* signptr ) { int parsed = actual_index; Boolean digits = False; unsigned long value = 0; char curr; int dig; if( actual_index >= limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_INT ); *signptr = +1; if( iostrptr[actual_index] == '+' ) actual_index++; else if( iostrptr[actual_index] == '-' ) { *signptr = -1; actual_index++; } for( ; actual_index < limit; actual_index++ ) { curr = iostrptr[actual_index]; if( curr == '_' ) continue; if( isXXX(curr,SET) ) { digits = True; dig = curr <= '9' ? curr - '0' : toupper(curr) - 'A' + 10; if( value > (ULONG_MAX - dig)/base ) IOEXCEPTION( TEXTFAIL, INT_VAL_OVERFLOW ); value = value*base + dig; continue; } break; } if( !digits ) IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_INT ); *valptr = value; #if _TEXTIO_DEBUG_ printf( "parsing for int until %d, base %d: %u\n", limit, base, value ); #endif return actual_index - parsed; } static double make_float( int dexp, int sign ) { double value = atof( floatdig ); #if _TEXTIO_DEBUG_ printf( " value = %25.20e, dexp = %d\n", value, dexp ); #endif while( dexp >= 100 ) value *= ep_100, dexp -= 100; if( dexp >= 10 ) value *= ep_10[dexp/10], dexp %= 10; if( dexp > 0 ) value *= ep_1[dexp]; while( dexp <= -100 ) value /= ep_100, dexp += 100; if( dexp <= -10 ) value /= ep_10[-dexp/10], dexp %= 10; if( dexp < 0 ) value /= ep_1[-dexp]; return sign ? -value : value; } /* %C -> fixed point [+|-]+[.*] */ static int parse_fixedpoint( int limit, double* valptr ) { int parsed = actual_index; Boolean digits = False; int sdig = 0; double value; char curr; int sign = False; int expo = 0; if( actual_index >= limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_FLOAT ); if( iostrptr[actual_index] == '+' ) actual_index++; else if( iostrptr[actual_index] == '-' ) { sign = True; actual_index++; } floatdig[0] = '.'; for( ; actual_index < limit; actual_index++ ) { curr = iostrptr[actual_index]; if( ! isDEC(curr) ) break; digits = True; if( sdig < MAXPREC - 1 ) { if( sdig || curr != '0' ) { floatdig[++sdig] = curr; expo++; } } else if( sdig ) expo++; } if( digits && curr == '.' ) { actual_index++; for( ; actual_index < limit; actual_index++ ) { curr = iostrptr[actual_index]; if( !isDEC(curr) ) break; if( sdig < MAXPREC - 1 ) { if( sdig || curr != '0' ) floatdig[++sdig] = curr; else expo--; } } } floatdig[++sdig] = '\0'; if( !digits ) IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT ); *valptr = make_float( expo, sign); return actual_index - parsed; } typedef enum { s_sign, s_dig, s_period, s_fraca, s_fracb, s_expo, s_exposign, s_expoa, s_expob } scient_t; /* %C -> scientific [+|-][.*]E[=|-]+ */ static int parse_scientific( int limit, double* valptr, double dmin, double dmax ) { int parsed = actual_index; int sdig = 0; char curr; double value; int sign = False; int expo = 0; int expo_sign = +1; scient_t state = s_sign; if( actual_index >= limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_FLOAT ); floatdig[0] = '.'; for( ; actual_index < limit; actual_index++ ) { curr = iostrptr[actual_index]; switch( state ) { case s_sign: if( iostrptr[actual_index] == '+' ) { state = s_dig; break; } if( iostrptr[actual_index] == '-' ) { sign = True; state = s_dig; break; } /* fall through - no break */ case s_dig: if( isDEC(curr) && curr > '0' ) { floatdig[++sdig] = curr; state = s_period; break; } IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT ); case s_period: if( curr == '.' ) { state = s_fraca; break; } if( curr == 'E' ) { state = s_exposign; break; } IOEXCEPTION( TEXTFAIL, NO_EXPONENT ); case s_fraca: if( isDEC(curr) ) { floatdig[++sdig] = curr; state = s_fracb; break; } IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT ); case s_fracb: if( isDEC(curr) ) { if( sdig < MAXPREC - 1 ) floatdig[++sdig] = curr; break; } if( curr == 'E' ) { state = s_exposign; break; } IOEXCEPTION( TEXTFAIL, NO_EXPONENT ); case s_exposign: if( iostrptr[actual_index] == '+' ) { state = s_expoa; break; } if( iostrptr[actual_index] == '-' ) { expo_sign = -1; state = s_expoa; break; } case s_expoa: if( isDEC(curr) ) { expo = curr - '0'; state = s_expob; break; } IOEXCEPTION( TEXTFAIL, NO_EXPONENT ); case s_expob: expo = expo*10 + (curr - '0'); if( expo > 1000 ) IOEXCEPTION( TEXTFAIL, REAL_OVERFLOW ); } } if( state != s_expob ) IOEXCEPTION( TEXTFAIL, NO_EXPONENT ); expo *= expo_sign; expo++; floatdig[++sdig] = '\0'; *valptr = make_float( expo, sign ); return actual_index - parsed; } static int parse_set( int limit, __tmp_IO_enum_table_type* tabptr, unsigned long* valptr ) { int parsed = actual_index; char curr; __tmp_IO_enum_table_type* etptr; if( actual_index >= limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_SET ); curr = iostrptr[actual_index]; if( isXXX(curr,LET+USC) ) actual_index++; else IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_SET ); for( ; actual_index < limit; actual_index++ ) { if( ! isXXX(iostrptr[actual_index],LET+DEC+USC) ) break; } if( tabptr ) while( tabptr->name ) { if( !casncmp( tabptr->name, &iostrptr[parsed], actual_index-parsed ) ) { *valptr = tabptr->value; #if _TEXTIO_DEBUG_ printf( "parsing set value until %d: %u\n", limit, tabptr->value ); #endif return actual_index - parsed; } tabptr++; } IOEXCEPTION( TEXTFAIL, SET_CONVERSION_ERROR ); } static int parse_bit( int limit, char* bitptr ) { int parsed = actual_index; int i = 0; char curr; if( actual_index >= limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_BOOLS ); for( ; actual_index < limit; actual_index++ ) { curr = iostrptr[actual_index] - '0'; if( curr == 0 || curr == 1 ) /* __setbitinset( i++, bitptr, limit, curr ); */ __setbitpowerset (bitptr, limit, 0, i++, curr, __FILE__, __LINE__); else break; } return actual_index - parsed; } static char* myultoa( unsigned long ul, char* buf, int base ) { char* res = buf; unsigned long h = ul/base; unsigned long q = 1; while( h >= q ) q *= base; while( q > 0 ) { *buf++ = "0123456789ABCDEF"[ul/q]; ul %= q; q /= base; } *buf++ = '\0'; return res; } /* * convert a bit string from src, bit offset up to len */ static char* bitput( char* dst, char* src, int offset, int len ) { char* res = dst; int i; for( i = offset; i < len; i++ ) { *dst++ = __inpowerset( i, src, len, 0 ) ? '1' : '0'; } return res; } /* * dround: round decimal register *digptr starting at digit mdigs, * on carry advance begin of digit sequence and bump exponent */ static char* dround( char* digptr, int mdigs, int* deptr ) { int carry; #if _TEXTIO_DEBUG_ printf( "Rounding from %d\n", mdigs ); #endif if( digptr[mdigs] >= 5 ) { carry = 1; while( carry ) { digptr[--mdigs]++; if( digptr[mdigs] >= 10 ) digptr[mdigs] = 0; else carry = 0; } } if( mdigs < 0 ) { digptr[--mdigs] = 1; (*deptr)++; return digptr - 1; } else return digptr; } /* * mydtoa: convert val with a precision of mantdigs to a decimal fraction * first digit is at **fstdiptr, decimal exponent is at *deptr */ static char* mydtoa( double val, int mantdigs, int* deptr, int* sgnptr ) { double m; int be; int de = -1; int fstdig = 0; int idig; char* digptr = floatdig+2; floatdig[0] = floatdig[1] = 0; if( val < 0 ) *sgnptr = -1, val = fabs( val ); else *sgnptr = +1; /* split the value */ m = frexp( val, &be ) * 10.0; /* 5.0 <= m < 10.0 */ while( be > 0 ) { de++; be--; m /= 5.0; if( m < 1.0 ) m *= 10.0, de--; } while( be < 0 ) { de--; be++; m *= 5.0; if( m >= 10.0 ) m /= 10.0, de++; } for( idig = 0; idig < mantdigs; idig++ ) { digptr[idig] = (int)m; m = (m - digptr[idig])*10.0; } digptr[idig] = (int)m; *deptr = de; return dround( digptr, mantdigs, deptr ); } #define PUT(c) \ { if( ifst <= ++iprt && iprt <= ilst ) *dst++ = c; } static char* fixput( char* dst, char* src, int ifst, int ilst, int sign, int fst, int lst, int nid, int nfd ) { char* dstsav = dst; int idig; int iprt = 0; if( sign < 0 ) PUT( '-' ); for( idig = nid; idig >= -nfd; idig-- ) { if (idig == -1) PUT( '.' ); PUT( idig > fst || lst >= idig ? '0': '0' + *src++ ); } return dstsav; } static char* sciput( char* dst, char* src, char* expbeg, int ifst, int ilst, int sign, int de, int expwid ) { char* dstsav = dst; int iprt = 0; int nfd = fractionwidth; int explen = strlen( expbeg ); if( sign < 0 ) PUT( '-' ); PUT( '0' + *src++ ); PUT( '.' ); while( nfd-- ) PUT( '0' + *src++ ); PUT( 'E' ); PUT( de >= 0 ? '+' : '-' ); while( expwid > explen ) { PUT( '0' ); expwid--; } while( explen-- ) PUT( *expbeg++ ); return dstsav; } /* * handle dynamic field width */ static get_field_width( void ) { unsigned long width; unsigned long ulongval; long longval; __tmp_IO_list io; if( ++iolist_index > iolistlen ) IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED ); io = *iolistptr++; /* must be integer, >= 0 */ switch( io.__descr ) { case __IO_ByteVal: longval = io.__t.__valbyte; goto signed_fieldwidth; case __IO_UByteVal: width = io.__t.__valubyte; goto unsigned_fieldwidth; case __IO_IntVal: longval = io.__t.__valint; goto signed_fieldwidth; case __IO_UIntVal: width = io.__t.__valuint; goto unsigned_fieldwidth; case __IO_LongVal: longval = io.__t.__vallong; goto signed_fieldwidth; case __IO_ULongVal: width = io.__t.__valulong; goto unsigned_fieldwidth; case __IO_ByteLoc: longval = *(signed char*)io.__t.__locint; goto signed_fieldwidth; case __IO_UByteLoc: width = *(unsigned char*)io.__t.__locint; goto unsigned_fieldwidth; case __IO_IntLoc: longval = *(signed short*)io.__t.__locint; goto signed_fieldwidth; case __IO_UIntLoc: width = *(unsigned short*)io.__t.__locint; goto unsigned_fieldwidth; case __IO_LongLoc: longval = *(signed long*) io.__t.__locint; goto signed_fieldwidth; case __IO_ULongLoc: width = *(unsigned long*)io.__t.__locint; goto unsigned_fieldwidth; default: IOEXCEPTION( TEXTFAIL, NON_INT_FIELD_WIDTH ); } signed_fieldwidth: ; if( longval < 0 ) IOEXCEPTION( TEXTFAIL, NEGATIVE_FIELD_WIDTH ); width = longval; unsigned_fieldwidth: ; return width; } static void inpconv( void ) { __tmp_IO_list io; int width; int limit; int skiplim; int skipped; int bypass; int parsed; Boolean fixedchars; int fixedlen; unsigned char curr; double dval; float fval; __tmp_IO_long lval; int sign; unsigned long umin; unsigned long umax; signed long smin; signed long smax; int ilen; short unsigned slen; __tmp_IO_enum_table_type* settabptr; while( repetition-- ) { if( ++iolist_index > iolistlen ) IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED ); io = *iolistptr++; if( dynamicwid ) width = get_field_width(); else width = clausewidth; bypass = skipped = 0; if( width ) { if( actual_index + width > iostrlen ) IOEXCEPTION( TEXTFAIL, NOT_ENOUGH_CHARS ); switch(io.__descr) { case __IO_CharLoc: case __IO_CharRangeLoc: fixedchars = True; fixedlen = 1; break; case __IO_CharStrLoc: fixedchars = True; fixedlen = io.__t.__loccharstring.string_length; break; default: fixedchars = False; break; } if( leftadjust ) { skiplim = fixedchars ? actual_index + fixedlen : actual_index; bypass = skipped = piks_pad( actual_index + width, skiplim ); } else { skiplim = fixedchars ? actual_index + width - fixedlen : actual_index + width; skipped = skip_pad( skiplim ); } width -= skipped; limit = actual_index + width; } else { /* free format */ if( paddingdef || !( io.__descr == __IO_CharLoc || io.__descr == __IO_CharRangeLoc || io.__descr == __IO_CharStrLoc || io.__descr == __IO_CharVaryingLoc ) ) if( paddingchar == ' ' || paddingchar == '\t' ) skip_space( iostrlen ); else skip_pad( iostrlen ); limit = iostrlen; } switch( io.__descr ) { case __IO_ByteLoc: ilen = 1; smin = CH_BYTE_MIN; smax = CH_BYTE_MAX; goto parse_signed_int; case __IO_UByteLoc: ilen = 1; umin = 0; umax = CH_UBYTE_MAX; goto parse_unsigned_int; case __IO_IntLoc: ilen = 2; smin = CH_INT_MIN; smax = CH_INT_MAX; goto parse_signed_int; case __IO_UIntLoc: ilen = 2; umin = 0; umax = CH_UINT_MAX; goto parse_unsigned_int; case __IO_LongLoc: ilen = 4; smin = CH_LONG_MIN; smax = CH_LONG_MAX; goto parse_signed_int; case __IO_ULongLoc: ilen = 4; umin = 0; umax = CH_ULONG_MAX; goto parse_unsigned_int; case __IO_ByteRangeLoc: ilen = 1; smin = io.__t.__locintrange.lower.slong; smax = io.__t.__locintrange.upper.slong; goto parse_signed_int; case __IO_UByteRangeLoc: ilen = 1; umin = io.__t.__locintrange.lower.ulong; umax = io.__t.__locintrange.upper.ulong; goto parse_unsigned_int; case __IO_IntRangeLoc: ilen = 2; smin = io.__t.__locintrange.lower.slong; smax = io.__t.__locintrange.upper.slong; goto parse_signed_int; case __IO_UIntRangeLoc: ilen = 2; umin = io.__t.__locintrange.lower.ulong; umax = io.__t.__locintrange.upper.ulong; goto parse_unsigned_int; case __IO_LongRangeLoc: ilen = 4; smin = io.__t.__locintrange.lower.slong; smax = io.__t.__locintrange.upper.slong; goto parse_signed_int; case __IO_ULongRangeLoc: ilen = 4; umin = io.__t.__locintrange.lower.ulong; umax = io.__t.__locintrange.upper.ulong; goto parse_unsigned_int; case __IO_BoolLoc: ilen = 1; umin = 0; umax = 1; settabptr = bool_tab; goto parse_set; case __IO_BoolRangeLoc: ilen = 1; umin = io.__t.__locboolrange.lower; umax = io.__t.__locboolrange.upper; settabptr = bool_tab; goto parse_set; case __IO_SetLoc: ilen = io.__t.__locsetrange.length; settabptr = io.__t.__locsetrange.name_table; umin = 0; umax = CH_ULONG_MAX; goto parse_set; case __IO_SetRangeLoc: ilen = io.__t.__locsetrange.length; settabptr = io.__t.__locsetrange.name_table; umin = io.__t.__locsetrange.lower; umax = io.__t.__locsetrange.upper; goto parse_set; case __IO_CharLoc: umin = 0; umax = 0xff; goto parse_char; case __IO_CharRangeLoc: umin = io.__t.__loccharrange.lower; umax = io.__t.__loccharrange.upper; goto parse_char; case __IO_CharVaryingLoc: if( convcode != DefaultConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); slen = io.__t.__loccharstring.string_length; if( (parsed = limit - actual_index) < slen ) slen = parsed; else parsed = slen; memcpy( io.__t.__loccharstring.string + 2, &iostrptr[actual_index], parsed ); MOV2(io.__t.__loccharstring.string,&slen); actual_index += parsed; goto check_field_complete; case __IO_CharStrLoc: if( convcode != DefaultConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); if( actual_index + io.__t.__loccharstring.string_length > limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_CHARS ); memcpy( io.__t.__loccharstring.string, &iostrptr[actual_index], parsed = io.__t.__loccharstring.string_length ); actual_index += parsed; goto check_field_complete; case __IO_BitStrLoc: if( convcode != DefaultConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); parsed = parse_bit( limit, io.__t.__loccharstring.string ); if( parsed < io.__t.__loccharstring.string_length ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_BOOLS ); goto check_field_complete; case __IO_LongRealLoc: case __IO_RealLoc: switch( convcode ) { case ScientConv: parse_scientific( limit, &dval, DBL_MIN, DBL_MAX ); break; case DefaultConv: parse_fixedpoint( limit, &dval ); break; default: IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); } if( io.__descr == __IO_LongRealLoc ) memcpy( io.__t.__loclongreal, &dval, sizeof(double) ); else { fval = (float)dval; MOV4(io.__t.__locreal,&fval); } goto check_field_complete; default: IOEXCEPTION( TEXTFAIL, INVALID_IO_LIST ); } parse_signed_int: ; if( convcode == ScientConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); parsed = parse_int( limit, dset[convcode], base[convcode], &lval.ulong, &sign ); if( sign < 0 ) { if( lval.ulong > (unsigned long)CH_LONG_MIN ) IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR ); lval.slong = -lval.ulong; } else { /* not needed: lval.slong = lval.ulong; */ /* Hack: sign extension for bin/oct/dec if no sign present */ if( convcode != DefaultConv && lval.ulong & (1 << (ilen*8-1)) ) { if( ilen < 4 ) lval.ulong |= 0xFFFFFFFF << ilen*8; } else if( lval.ulong > (unsigned long)CH_LONG_MAX ) IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR ); } if( lval.slong < smin || smax < lval.slong ) IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR ); goto store_int; parse_unsigned_int: ; if( convcode == ScientConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); parsed = parse_int( limit, dset[convcode], base[convcode], &lval.ulong, &sign ); if( sign < 0 || lval.ulong < umin || umax < lval.ulong ) IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR ); goto store_int; parse_set: ; if( convcode != DefaultConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); parsed = parse_set( limit, settabptr, &lval.ulong ); if( lval.ulong < umin || umax < lval.ulong ) IOEXCEPTION( TEXTFAIL, SET_RANGE_ERROR ); goto store_int; store_int: ; switch( ilen ) { case 1: *(unsigned char*)io.__t.__locint = lval.ulong; break; case 2: slen = lval.ulong; MOV2(io.__t.__locint,&slen); break; case 4: MOV4(io.__t.__locint,&lval.ulong); break; default: IOEXCEPTION( TEXTFAIL, INTERNAL_ERROR ); } goto check_field_complete; parse_char: ; if( convcode != DefaultConv ) IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); if( actual_index >= limit ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_CHARS ); curr = iostrptr[actual_index++]; parsed = 1; if( curr < umin || umax < curr ) IOEXCEPTION( TEXTFAIL, CHAR_RANGE_ERROR ); *io.__t.__locchar = curr; goto check_field_complete; check_field_complete: ; actual_index += bypass; if( width > parsed ) IOEXCEPTION( TEXTFAIL, INVALID_CHAR ); } } static void inpedit( void ) { int nchars; if( dynamicwid ) clausewidth = get_field_width(); switch( editcode ) { case SpaceSkip: nchars = repetition*clausewidth; if( actual_index + nchars > iostrlen ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT ); for( ; nchars ; nchars-- ) if( iostrptr[actual_index++] != ' ' ) IOEXCEPTION( TEXTFAIL, NO_SPACE_TO_SKIP ); break; case SkipLeft: nchars = repetition*clausewidth; if( (actual_index -= nchars) < 0 ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT ); break; case SkipRight: nchars = repetition*clausewidth; if( (actual_index += nchars) > iostrlen ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT ); break; case Tabulation: if( (actual_index = clausewidth) > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); break; } } static void outconv( void ) { unsigned long width; char itembuf[33]; unsigned long ulongval; long longval; __tmp_IO_list io; __tmp_IO_enum_table_type* etptr; char* itembeg; unsigned long itemlen; double doubleval; int de; int sign; int mantdigs; int nid; int nfd; char* expbeg; int explen; unsigned int expwid; while( repetition-- ) { if( ++iolist_index > iolistlen ) IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED ); io = *iolistptr++; width = dynamicwid ? get_field_width() : clausewidth; switch( convcode ) { case DefaultConv: switch( io.__descr ) { case __IO_ByteVal: longval = io.__t.__valbyte; goto signed_conversion; case __IO_UByteVal: ulongval = io.__t.__valubyte; goto unsigned_conversion; case __IO_IntVal: longval = io.__t.__valint; goto signed_conversion; case __IO_UIntVal: ulongval = io.__t.__valuint; goto unsigned_conversion; case __IO_LongVal: longval = io.__t.__vallong; goto signed_conversion; case __IO_ULongVal: ulongval = io.__t.__valulong; goto unsigned_conversion; case __IO_BoolVal: switch( io.__t.__valbool ) { case 0: itembeg = "FALSE"; itemlen = 5; goto move_item; case 1: itembeg = "TRUE"; itemlen = 4; goto move_item; default: IOEXCEPTION( TEXTFAIL, BOOL_CONVERSION_ERROR ); } case __IO_CharVal: itembeg = &io.__t.__valchar; itemlen = 1; goto move_item; case __IO_SetVal: /* locate name string using set mode name table */ itembeg = 0; if( (etptr = io.__t.__valset.name_table) ) while( etptr->name ) { if( etptr->value == io.__t.__valset.value ) { itembeg = etptr->name; itemlen = strlen( itembeg ); goto move_item; } etptr++; } IOEXCEPTION( TEXTFAIL, SET_CONVERSION_ERROR ); case __IO_CharVaryingLoc: { unsigned short l; itembeg = (char*)io.__t.__loccharstring.string; MOV2(&l,itembeg); itembeg += 2; itemlen = l; goto move_item; } case __IO_CharStrLoc: itembeg = io.__t.__loccharstring.string; itemlen = io.__t.__loccharstring.string_length; goto move_item; case __IO_BitStrLoc: itemlen = io.__t.__loccharstring.string_length; itembeg = io.__t.__loccharstring.string; if( !width ) width = itemlen; /* check remaining space */ if( actual_index + width > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); if( itemlen == width ) bitput( iostrptr + actual_index, itembeg, 0, itemlen ); else if( itemlen < width ) if( leftadjust ) memset( bitput( iostrptr + actual_index, itembeg, 0, itemlen ) + itemlen, paddingchar, width - itemlen ); else bitput( memset( iostrptr + actual_index, paddingchar, width - itemlen ) + width - itemlen, itembeg, itemlen - width, itemlen ); else if( overflowev ) memset( iostrptr + actual_index, '*', width ); else if( leftadjust ) bitput( iostrptr + actual_index, itembeg, 0, width ); else bitput( iostrptr + actual_index, itembeg, itemlen - width, itemlen ); goto adjust_index; case __IO_RealVal: doubleval = io.__t.__valreal; mantdigs = FMANTDIGS; goto fixed_point_conversion; case __IO_LongRealVal: doubleval = io.__t.__vallongreal; mantdigs = DBL_DIG; goto fixed_point_conversion; break; default: IOEXCEPTION( TEXTFAIL, INVALID_IO_LIST ); } case HexConv: case OctalConv: case BinaryConv: switch( io.__descr ) { case __IO_ByteVal: case __IO_UByteVal: ulongval = io.__t.__valubyte; break; case __IO_IntVal: case __IO_UIntVal: ulongval = io.__t.__valuint; break; case __IO_LongVal: case __IO_ULongVal: ulongval = io.__t.__valulong; break; default: IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); } itembeg = myultoa( ulongval, itembuf, base[convcode] ); itemlen = strlen( itembeg ); goto move_item; case ScientConv: switch( io.__descr ) { case __IO_RealVal: doubleval = io.__t.__valreal; mantdigs = FMANTDIGS; if( !fractiondef ) fractionwidth = FMANTDIGS - 1; goto scientific_conversion; case __IO_LongRealVal: doubleval = io.__t.__vallongreal; mantdigs = DBL_DIG; if( !fractiondef ) fractionwidth = DBL_DIG - 1; goto scientific_conversion; break; default: IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT ); } } fixed_point_conversion: ; itembeg = mydtoa( doubleval, mantdigs, &de, &sign ); if( fractiondef && de >= -fractionwidth - 1 && -fractionwidth > de - mantdigs ) itembeg = dround( itembeg, de + fractionwidth + 1, &de ); nid = de >= 0 ? de : 0; nfd = fractiondef ? fractionwidth : ( de + 1 - mantdigs > 0 ? 0 : mantdigs - de - 1 ); itemlen = ( sign < 0 ? 1 : 0 ) + 2 + nid + nfd; #if _TEXTIO_DEBUG_ printf( "fixed item length %d\n", itemlen ); #endif if( !width ) width = itemlen; #if _TEXTIO_DEBUG_ printf( "fixed item width %d\n", width ); #endif /* check remaining space */ if( actual_index + width > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); if( itemlen == width ) fixput( iostrptr + actual_index, itembeg, 1, itemlen, sign, de, de - mantdigs, nid, nfd ); else if( itemlen < width ) if( leftadjust ) memset( fixput( iostrptr + actual_index, itembeg, 1, itemlen, sign, de, de - mantdigs, nid, nfd ) + itemlen, paddingchar, width - itemlen ); else fixput( memset( iostrptr + actual_index, paddingchar, width - itemlen ) + width - itemlen, itembeg, 1, itemlen, sign, de, de - mantdigs, nid, nfd ); else if( overflowev ) memset( iostrptr + actual_index, '*', width ); else if( leftadjust ) fixput( iostrptr + actual_index, itembeg, 1, width, sign, de, de - mantdigs, nid, nfd ); else fixput( iostrptr + actual_index, itembeg, itemlen - width + 1, itemlen, sign, de, de - mantdigs, nid, nfd ); goto adjust_index; scientific_conversion: ; itembeg = mydtoa( doubleval, mantdigs, &de, &sign ); if( fractiondef && fractionwidth < mantdigs ) itembeg = dround( itembeg, fractionwidth + 1, &de ); expbeg = myultoa( abs(de), itembuf, 10 ); explen = strlen( expbeg ); expwid = explen > exponentwidth ? explen : exponentwidth; itemlen = ( sign < 0 ? 1 : 0 ) + 2 + fractionwidth + 2 + expwid; #if _TEXTIO_DEBUG_ printf( "floating item length %d, fraction %d, exponent %d\n", itemlen, fractionwidth, expwid ); #endif if( width == 0 ) width = itemlen; #if _TEXTIO_DEBUG_ printf( "floating item width %d\n", width ); #endif /* check remaining space */ if( actual_index + width > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); if( itemlen == width ) sciput( iostrptr + actual_index, itembeg, expbeg, 1, itemlen, sign, de, expwid ); else if( itemlen < width ) if( leftadjust ) memset( sciput( iostrptr + actual_index, itembeg, expbeg, 1, itemlen, sign, de, expwid ) + itemlen, paddingchar, width - itemlen ); else sciput( memset( iostrptr + actual_index, paddingchar, width - itemlen ) + width - itemlen, itembeg, expbeg, 1, itemlen, sign, de, expwid ); else if( overflowev ) memset( iostrptr + actual_index, '*', width ); else if( leftadjust ) sciput( iostrptr + actual_index, itembeg, expbeg, 1, width, sign, de, expwid ); else sciput( iostrptr + actual_index, itembeg, expbeg, itemlen - width + 1, itemlen, sign, de, expwid ); goto adjust_index; signed_conversion: ; if( longval >= 0 ) itembeg = myultoa( longval, itembuf, 10 ); else { itembuf[0] = '-'; myultoa( -longval, itembuf+1, 10 ); itembeg = itembuf; } itemlen = strlen( itembeg ); goto move_item; unsigned_conversion: ; itembeg = myultoa( ulongval, itembuf, 10 ); itemlen = strlen( itembeg ); goto move_item; move_item: ; if( !width ) width = itemlen; /* check remaining space */ if( actual_index + width > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); /* move item, filling or truncating or overflow-evidencing */ if( itemlen == width ) memcpy( iostrptr + actual_index, itembeg, itemlen ); else if( itemlen < width ) if( leftadjust ) memset( memcpy( iostrptr + actual_index, itembeg, itemlen ) + itemlen, paddingchar, width - itemlen ); else memcpy( memset( iostrptr + actual_index, paddingchar, width - itemlen ) + width - itemlen, itembeg, itemlen ); else if( overflowev ) memset( iostrptr + actual_index, '*', width ); else if( leftadjust ) memcpy( iostrptr + actual_index, itembeg, width ); else memcpy( iostrptr + actual_index, itembeg + itemlen - width, width ); /* * adjust. */ adjust_index: ; actual_index += width; if( actual_index > maximum_index ) maximum_index = actual_index; } } static void outedit( void ) { int nchars; if( dynamicwid ) clausewidth = get_field_width(); switch( editcode ) { case SpaceSkip: nchars = repetition*clausewidth; if( actual_index + nchars > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); memset( iostrptr + actual_index, ' ', nchars ); actual_index += nchars; if( actual_index > maximum_index ) maximum_index = actual_index; break; case SkipLeft: nchars = repetition*clausewidth; if( actual_index - nchars < 0 ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); actual_index -= nchars; break; case SkipRight: nchars = repetition*clausewidth; if( actual_index + nchars > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); actual_index += nchars; if( actual_index > maximum_index ) { memset( iostrptr + maximum_index, ' ', actual_index - maximum_index ); maximum_index = actual_index; } break; case Tabulation: if( clausewidth >= iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); actual_index = clausewidth; if( actual_index > maximum_index ) { memset( iostrptr + maximum_index, ' ', actual_index - maximum_index ); maximum_index = actual_index; } break; } } static void inpioctrl( void ) { unsigned short hlen; if( !textptr ) IOEXCEPTION( TEXTFAIL, IO_CONTROL_NOT_VALID ); if( iocode != EndPage ) { jmp_buf ioerror; unsigned long info; if (textptr->access_sub->association) { if( (info = setjmp( ioerror )) ) IOEXCEPTION( info>>16, info & 0xffff ); while( repetition-- ) { __readrecord( textptr->access_sub, textindex, (char*)textptr->text_record, __FILE__, __LINE__ ); actual_index = 0; MOV2(&hlen,&textptr->text_record->len); iostrlen = hlen; } } else IOEXCEPTION (NOTCONNECTED, IS_NOT_CONNECTED); } } /* specify pre/post in the order "/+-?!" */ static char* pre_char = "\0\f\0\r\0"; /* Z.200: "\n\f\0\n\0" */ static char* post_char = "\n\n\r\0\0"; /* Z.200: "\r\r\r\0\0" */ static void outioctrl( void ) { Association_Mode* assoc; unsigned short hlen; if( !textptr ) IOEXCEPTION( TEXTFAIL, IO_CONTROL_NOT_VALID ); if( (assoc = textptr->access_sub->association) ) { jmp_buf ioerror; unsigned long info; if( (info = setjmp( ioerror )) ) IOEXCEPTION( info>>16, info & 0xffff ); while( repetition-- ) { if( iocode != EndPage ) { if( TEST_FLAG( assoc, IO_FIRSTLINE ) ) { CLR_FLAG( assoc, IO_FIRSTLINE ); assoc->ctl_pre = '\0'; } else { if( TEST_FLAG( assoc, IO_FORCE_PAGE ) ) { CLR_FLAG( assoc, IO_FORCE_PAGE ); assoc->ctl_pre = '\f'; } else assoc->ctl_pre = pre_char[iocode]; } assoc->ctl_post = post_char[iocode]; hlen = actual_index; MOV2(&textptr->text_record->len,&hlen); __writerecord( textptr->access_sub, textindex, (char*)textptr->text_record, textptr->text_record->len, __FILE__, __LINE__ ); hlen = actual_index = 0; MOV2(&textptr->text_record->len,&hlen); } else if( !TEST_FLAG( textptr, IO_FIRSTLINE ) ) SET_FLAG( textptr, IO_FORCE_PAGE ); assoc->ctl_pre = assoc->ctl_post = '\0'; } } else IOEXCEPTION (NOTCONNECTED, IS_NOT_CONNECTED); } static void (**actionptr)( void ); static void (*readactions[])( void ) = { inpconv, inpedit, inpioctrl }; static void (*writeactions[])( void ) = { outconv, outedit, outioctrl }; static void emitstr( char* begtxt, char* endtxt ) { char c; int nchars = endtxt - begtxt; if( actual_index + nchars > iostrlen ) IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW ); memcpy( iostrptr + actual_index, begtxt, nchars ); actual_index += nchars; if( actual_index > maximum_index ) maximum_index = actual_index; } static void scanstr( char* begtxt, char* endtxt ) { int nchars = endtxt - begtxt; if( actual_index + nchars > iostrlen ) IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_TEXT ); if( strncmp( iostrptr + actual_index, begtxt, nchars ) ) IOEXCEPTION( TEXTFAIL, FORMAT_TEXT_MISMATCH ); actual_index += nchars; } void (*ftextptr) ( char*, char* ); static formatexit_t scanformcont( char* fcs, int len, char** fcsptr, int* lenptr ) { char curr; fcsstate_t state = FormatText; unsigned long buf; int dig; acttype_t action; char* begtxt = fcs; while( len-- ) { curr = *fcs++; switch( state ) { case FormatText: if( curr == '%' ) { ftextptr( begtxt, fcs-1 ); state = FirstPercent; } break; after_first_percent: ; case FirstPercent: if( curr == '%' ) { state = FormatText; begtxt = fcs - 1; break; } if( curr == ')' ) { *lenptr = len; *fcsptr = fcs; return EndAtParen; } if( isDEC(curr) ) { state = RepFact; repetition = curr - '0'; break; } repetition = 1; test_for_control_codes: ; if( isCVC(curr) ) { state = ConvClause; action = ConvAct; convcode = strchr( CONVERSIONCODES, curr ) - CONVERSIONCODES; leftadjust = False; overflowev = False; dynamicwid = False; paddingdef = False; paddingchar = ' '; fractiondef = False; /* fractionwidth = 0; default depends on mode ! */ exponentdef = False; exponentwidth = 3; clausewidth = 0; break; } if( isEDC(curr) ) { state = EditClause; action = EditAct; editcode = strchr( EDITCODES, curr ) - EDITCODES; dynamicwid = False; clausewidth = editcode == Tabulation ? 0 : 1; break; } if( isIOC(curr) ) { state = ClauseEnd; action = IOAct; iocode = strchr( IOCODES, curr ) - IOCODES; break; } if( curr == '(' ) { unsigned long times = repetition; int cntlen; char* cntfcs; while( times-- ) { if( scanformcont( fcs, len, &cntfcs, &cntlen ) != EndAtParen ) IOEXCEPTION( TEXTFAIL, UNMATCHED_OPENING_PAREN ); } fcs = cntfcs; len = cntlen; state = FormatText; begtxt = fcs; break; } IOEXCEPTION( TEXTFAIL, BAD_FORMAT_SPEC_CHAR ); case RepFact: if( isDEC(curr) ) { dig = curr - '0'; if( repetition > (ULONG_MAX - dig)/10 ) IOEXCEPTION( TEXTFAIL, REPFAC_OVERFLOW ); repetition = repetition*10 + dig; break; } goto test_for_control_codes; case ConvClause: if( isDEC(curr) ) { state = ClauseWidth; clausewidth = curr - '0'; break; } if( curr == 'L' ) { if( leftadjust ) IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER ); leftadjust = True; break; } if( curr == 'E' ) { if( overflowev ) IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER ); overflowev = True; break; } if( curr == 'P' ) { if( paddingdef ) IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER ); paddingdef = True; state = CatchPadding; break; } test_for_variable_width: ; if( curr == 'V' ) { dynamicwid = True; state = AfterWidth; break; } goto test_for_fraction_width; case ClauseWidth: if( isDEC(curr) ) { dig = curr - '0'; if( clausewidth > (ULONG_MAX - dig)/10 ) IOEXCEPTION( TEXTFAIL, CLAUSE_WIDTH_OVERFLOW ); clausewidth = clausewidth*10 + dig; break; } /* fall through */ test_for_fraction_width: ; case AfterWidth: if( curr == '.' ) { if( convcode != DefaultConv && convcode != ScientConv ) IOEXCEPTION( TEXTFAIL, NO_FRACTION ); fractiondef = True; state = FractWidth; break; } goto test_for_exponent_width; case FractWidth: if( isDEC( curr ) ) { state = FractWidthCont; fractionwidth = curr - '0'; break; } else IOEXCEPTION( TEXTFAIL, NO_FRACTION_WIDTH ); case FractWidthCont: if( isDEC( curr ) ) { dig = curr - '0'; if( fractionwidth > (ULONG_MAX - dig)/10 ) IOEXCEPTION( TEXTFAIL, FRACTION_WIDTH_OVERFLOW ); fractionwidth = fractionwidth*10 + dig; break; } test_for_exponent_width: ; if( curr == ':' ) { if( convcode != ScientConv ) IOEXCEPTION( TEXTFAIL, NO_EXPONENT ); exponentdef = True; state = ExpoWidth; break; } goto test_for_final_percent; case ExpoWidth: if( isDEC( curr ) ) { state = ExpoWidthCont; exponentwidth = curr - '0'; break; } else IOEXCEPTION( TEXTFAIL, NO_EXPONENT_WIDTH ); case ExpoWidthCont: if( isDEC( curr ) ) { dig = curr - '0'; if( exponentwidth > (ULONG_MAX - dig)/10 ) IOEXCEPTION( TEXTFAIL, EXPONENT_WIDTH_OVERFLOW ); exponentwidth = exponentwidth*10 + dig; break; } /* fall through */ test_for_final_percent: ; case ClauseEnd: if( curr == '%' ) { state = LastPercent; break; } do_the_action: ; actionptr[action](); state = FormatText; begtxt = fcs - 1; break; case CatchPadding: paddingchar = curr; state = ConvClause; break; case EditClause: if( isDEC(curr) ) { state = ClauseWidth; clausewidth = curr - '0'; break; } goto test_for_variable_width; case LastPercent: actionptr[action](); if( curr == '.' ) { state = FormatText; begtxt = fcs; break; } goto after_first_percent; default: IOEXCEPTION( TEXTFAIL, INTERNAL_ERROR ); } } switch( state ) { case FormatText: ftextptr( begtxt, fcs ); break; case FirstPercent: case LastPercent: case RepFact: case FractWidth: case ExpoWidth: IOEXCEPTION( TEXTFAIL, BAD_FORMAT_SPEC_CHAR ); case CatchPadding: IOEXCEPTION( TEXTFAIL, NO_PAD_CHAR ); default: actionptr[action](); } *lenptr = len; *fcsptr = fcs; return NormalEnd; } static void __read_format (char* fmtptr, int fmtlen, __tmp_IO_list* ioptr, int iolen, void* inpptr, int inplen ) { formatexit_t res; unsigned short l; iostrptr = (char*)inpptr; iostrlen = inplen; /* initialisation */ iolist_index = 0; iolistptr = ioptr; iolistlen = iolen; actionptr = readactions; ftextptr = scanstr; if( (res = scanformcont( fmtptr, fmtlen, &fmtptr, &fmtlen )) == EndAtParen ) IOEXCEPTION( TEXTFAIL, UNMATCHED_CLOSING_PAREN ); if( iolist_index != iolen ) IOEXCEPTION( TEXTFAIL, EXCESS_IOLIST_ELEMENTS ); return; } void __readtext_f( Text_Mode* the_text_loc, signed long the_index, char* fmtptr, int fmtlen, __tmp_IO_list* ioptr, int iolen, char* file, int line ) { unsigned long info; if( (info = setjmp( __io_exception )) ) CHILLEXCEPTION( file, line, info>>16, info & 0xffff ); textptr = the_text_loc; textrecptr = textptr->text_record; actual_index = textptr->actual_index; textindex = the_index; __read_format ( fmtptr, fmtlen, ioptr, iolen, (char*)textrecptr + 2, textptr->text_record->len ); textptr->actual_index = actual_index; } void __readtext_s( void* string_ptr, int string_len, char* fmtptr, int fmtlen, __tmp_IO_list* ioptr, int iolen, char* file, int line ) { int info; if( (info = setjmp( __io_exception )) ) CHILLEXCEPTION( file, line, info>>16, info & 0xffff ); textptr = NULL; actual_index = 0; __read_format ( fmtptr, fmtlen, ioptr, iolen, string_ptr, string_len ); } static void __write_format (char* fmtptr, int fmtlen, __tmp_IO_list* ioptr, int iolen, void* outptr, int outlen ) { formatexit_t res; unsigned short l; /* initialisation */ maximum_index = actual_index; iolist_index = 0; actionptr = writeactions; ftextptr = emitstr; iolistptr = ioptr; iolistlen = iolen; iostrptr = (char *)outptr + 2; iostrlen = outlen; if( (res = scanformcont( fmtptr, fmtlen, &fmtptr, &fmtlen )) == EndAtParen ) IOEXCEPTION( TEXTFAIL, UNMATCHED_CLOSING_PAREN ); if( iolist_index != iolen ) IOEXCEPTION( TEXTFAIL, EXCESS_IOLIST_ELEMENTS ); /* set length of output string */ #if _TEXTIO_DEBUG_ printf( "maximum index = %d\n", maximum_index ); #endif l = maximum_index; MOV2(outptr,&l); return; } void __writetext_f( Text_Mode* the_text_loc, signed long the_index, char* fmtptr, int fmtlen, __tmp_IO_list* ioptr, int iolen, char* file, int line ) { int info; if( (info = setjmp( __io_exception )) ) CHILLEXCEPTION( file, line, info>>16, info & 0xffff ); textptr = the_text_loc; textrecptr = the_text_loc->text_record; textindex = the_index; iolistptr = ioptr; iolistlen = iolen; actual_index = textptr->actual_index; __write_format ( fmtptr, fmtlen, ioptr, iolen, textrecptr, textptr->access_sub->reclength - 2 ); textptr->actual_index = actual_index; } void __writetext_s( void* string_ptr, int string_len, char* fmtptr, int fmtlen, __tmp_IO_list* ioptr, int iolen, char* file, int line ) { int info; if( (info = setjmp( __io_exception )) ) CHILLEXCEPTION( file, line, info>>16, info & 0xffff ); textptr = NULL; actual_index = 0; __write_format ( fmtptr, fmtlen, ioptr, iolen, string_ptr, string_len ); }