2195 lines
53 KiB
C
2195 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, 59 Temple Place - Suite 330,
|
||
|
Boston, MA 02111-1307, 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 <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 );
|
||
|
}
|