gcc/libchill/format.c
Jeff Law b79f73df6a * Chill runtime moved into toplevel libchill.
* Makefile.in Revamped due to move.  Add multilib support.
        * configure.in: Similarly.  Use autoconf.
        * powerset.h: Do not depend on BITS_PER_UNIT.

From-SVN: r22238
1998-09-04 19:11:54 -06:00

2187 lines
53 KiB
C

/* 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. */
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>
#if _TEXTIO_DEBUG_
#include <stdio.h>
#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 [+|-]<digit>+[.<digit>*] */
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 [+|-]<digit>[.<digit>*]E[=|-]<digit>+ */
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 );
}