2001-02-18 Kazu Hirata <kazu@hxi.com>
[official-gcc.git] / libchill / format.c
blobda05e5edb7eab6640c1d20640ce0a758b97c836c
1 /* Implement Input/Output runtime actions for CHILL.
2 Copyright (C) 1992,1993 Free Software Foundation, Inc.
3 Author: Wilfried Moser, et al
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
29 #include <limits.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <setjmp.h>
33 #include <float.h>
34 #include <math.h>
35 #include <stdlib.h>
36 #if _TEXTIO_DEBUG_
37 #include <stdio.h>
38 #endif
40 #include "bitstring.h"
41 #include "auxtypes.h"
42 #include "iomodes.h"
43 #include "format.h"
44 #include "fileio.h"
45 #include "ioerror.h"
47 #define CH_BYTE_MIN 0xffffff80L
48 #define CH_BYTE_MAX 0x0000007fL
49 #define CH_UBYTE_MAX 0x000000ffUL
50 #define CH_INT_MIN 0xffff8000L
51 #define CH_INT_MAX 0x00007fffL
52 #define CH_UINT_MAX 0x0000ffffUL
53 #define CH_LONG_MIN 0x80000000L
54 #define CH_LONG_MAX 0x7fffffffL
55 #define CH_ULONG_MAX 0xffffffffUL
57 #ifndef M_LN2
58 #define M_LN2 0.69314718055994530942
59 #endif
60 #ifndef M_LN10
61 #define M_LN10 2.30258509299404568402
62 #endif
64 #define DMANTDIGS (1 + (int)(DBL_MANT_DIG * M_LN2 / M_LN10))
65 #define FMANTDIGS (1 + (int)(FLT_MANT_DIG * M_LN2 / M_LN10))
67 /* float register length */
68 #define MAXPREC 40
70 #define LET 0x0001
71 #define BIN 0x0002
72 #define DEC 0x0004
73 #define OCT 0x0008
74 #define HEX 0x0010
75 #define USC 0x0020
76 #define BIL 0x0040
77 #define SPC 0x0080
78 #define SCS 0x0100
79 #define IOC 0x0200
80 #define EDC 0x0400
81 #define CVC 0x0800
83 #define isDEC(c) ( chartab[(c)] & DEC )
84 #define isCVC(c) ( chartab[(c)] & CVC )
85 #define isEDC(c) ( chartab[(c)] & EDC )
86 #define isIOC(c) ( chartab[(c)] & IOC )
87 #define isUSC(c)
88 #define isXXX(c,XXX) ( chartab[(c)] & XXX )
91 * local definitions
94 static
95 short int chartab[256] = {
96 0, 0, 0, 0, 0, 0, 0, 0,
97 0, SPC, SPC, SPC, SPC, SPC, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0,
102 SPC, IOC, 0, 0, 0, 0, 0, 0,
103 SCS, SCS, SCS, SCS+IOC, SCS, SCS+IOC, SCS, SCS+IOC,
104 BIN+OCT+DEC+HEX, BIN+OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX,
105 OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX,
106 DEC+HEX, DEC+HEX, SCS, SCS, SCS+EDC, SCS+IOC, SCS+EDC, IOC,
108 0, LET+HEX+BIL, LET+HEX+BIL+CVC, LET+HEX+BIL+CVC, LET+HEX+BIL, LET+HEX,
109 LET+HEX+CVC, LET,
110 LET+BIL+CVC, LET, LET, LET, LET, LET, LET, LET+CVC,
112 LET, LET, LET, LET, LET+EDC, LET, LET, LET,
113 LET+EDC, LET, LET, SCS, 0, SCS, 0, USC,
115 0, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET,
116 LET, LET, LET, LET, LET, LET, LET, LET,
118 LET, LET, LET, LET, LET, LET, LET, LET,
119 LET, LET, LET, 0, 0, 0, 0, 0
122 typedef enum {
123 FormatText, FirstPercent, RepFact, ConvClause, EditClause, ClauseEnd,
124 AfterWidth, FractWidth, FractWidthCont, ExpoWidth, ExpoWidthCont,
125 ClauseWidth, CatchPadding, LastPercent
126 } fcsstate_t;
128 #define CONVERSIONCODES "CHOBF"
129 typedef enum {
130 DefaultConv, HexConv, OctalConv, BinaryConv, ScientConv
131 } convcode_t;
133 static
134 short int base[4] = { 10, 16, 8, 2 };
136 static
137 short int dset[4] = { DEC, HEX, OCT, BIN };
139 #define EDITCODES "X<>T"
140 typedef enum {
141 SpaceSkip, SkipLeft, SkipRight, Tabulation
142 } editcode_t;
144 #define IOCODES "/+-?!="
145 typedef enum {
146 NextRecord, NextPage, CurrentLine, Prompt, Emit, EndPage
147 } iocode_t;
149 typedef enum {
150 ConvAct, EditAct, IOAct
151 } acttype_t;
153 typedef enum {
154 NormalEnd, EndAtParen, TextFailEnd
155 } formatexit_t;
157 static
158 double ep_1[10] = {
159 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 };
160 static
161 double ep_10[10] = {
162 1e0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 };
163 static
164 double ep_100 = 1e100;
166 /* float register */
167 static
168 unsigned char floatdig[MAXPREC];
171 * global io variables
174 static Text_Mode* textptr = NULL;
175 static VarString* textrecptr;
177 static int actual_index;
178 static int maximum_index;
179 static int iolist_index;
181 static __tmp_IO_list* iolistptr;
182 static int iolistlen;
183 static char* iostrptr;
184 static int iostrlen;
187 static convcode_t convcode;
188 static editcode_t editcode;
189 static iocode_t iocode;
190 static unsigned long repetition;
191 static Boolean leftadjust;
192 static Boolean overflowev;
193 static Boolean dynamicwid;
194 static Boolean paddingdef;
195 static char paddingchar;
196 static Boolean fractiondef;
197 static unsigned long fractionwidth;
198 static Boolean exponentdef;
199 static unsigned long exponentwidth;
200 static unsigned long clausewidth;
201 static signed long textindex;
203 static
204 __tmp_IO_enum_table_type bool_tab[] =
205 { { 0, "FALSE" },
206 { 1, "TRUE" },
207 { 0 , NULL } };
210 * case insensitive compare: s1 is zero delimited, s2 has n chars
212 static
213 int casncmp( const char* s1, const char* s2, int n )
215 int res = 0;
216 while( n-- )
218 if( (res = toupper(*s1++) - toupper(*s2++)) )
219 return res;
221 return *s1;
225 * skip spaces with blank equal to tab
227 static
228 int skip_space( int limit )
230 int skipped = 0;
231 while( actual_index < limit &&
232 (iostrptr[actual_index] == ' ' || iostrptr[actual_index] == '\t' ) )
234 actual_index++;
235 skipped++;
237 return skipped;
241 * skip leading pad characters
243 static
244 int skip_pad( int limit )
246 int skipped = 0;
247 while( actual_index < limit && iostrptr[actual_index] == paddingchar )
249 actual_index++;
250 skipped++;
252 #if _TEXTIO_DEBUG_
253 printf( "skipping '%c' until %d: %d\n", paddingchar, limit, skipped );
254 #endif
255 return skipped;
259 * backup trailing pad characters
261 static
262 int piks_pad( int start, int limit )
264 int skipped = 0;
265 while( start >/***=*/ limit && iostrptr[--start] == paddingchar )
267 skipped++;
269 #if _TEXTIO_DEBUG_
270 printf( "piksing '%c' from %d until %d: %d\n",
271 paddingchar, start, limit, skipped );
272 #endif
273 return skipped;
277 * parse an integer
279 static
280 int parse_int( int limit, int SET, int base,
281 unsigned long* valptr, int* signptr )
283 int parsed = actual_index;
284 Boolean digits = False;
285 unsigned long value = 0;
286 char curr;
287 int dig;
289 if( actual_index >= limit )
290 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_INT );
291 *signptr = +1;
292 if( iostrptr[actual_index] == '+' )
293 actual_index++;
294 else
295 if( iostrptr[actual_index] == '-' )
296 { *signptr = -1;
297 actual_index++;
300 for( ; actual_index < limit; actual_index++ )
302 curr = iostrptr[actual_index];
303 if( curr == '_' ) continue;
304 if( isXXX(curr,SET) )
306 digits = True;
307 dig = curr <= '9' ? curr - '0' : toupper(curr) - 'A' + 10;
308 if( value > (ULONG_MAX - dig)/base )
309 IOEXCEPTION( TEXTFAIL, INT_VAL_OVERFLOW );
310 value = value*base + dig;
311 continue;
313 break;
315 if( !digits )
316 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_INT );
318 *valptr = value;
319 #if _TEXTIO_DEBUG_
320 printf( "parsing for int until %d, base %d: %u\n", limit, base, value );
321 #endif
322 return actual_index - parsed;
325 static
326 double
327 make_float( int dexp, int sign )
329 double value = atof( floatdig );
330 #if _TEXTIO_DEBUG_
331 printf( " value = %25.20e, dexp = %d\n", value, dexp );
332 #endif
333 while( dexp >= 100 )
334 value *= ep_100, dexp -= 100;
335 if( dexp >= 10 )
336 value *= ep_10[dexp/10], dexp %= 10;
337 if( dexp > 0 )
338 value *= ep_1[dexp];
340 while( dexp <= -100 )
341 value /= ep_100, dexp += 100;
342 if( dexp <= -10 )
343 value /= ep_10[-dexp/10], dexp %= 10;
344 if( dexp < 0 )
345 value /= ep_1[-dexp];
347 return sign ? -value : value;
350 /* %C -> fixed point [+|-]<digit>+[.<digit>*] */
351 static
352 int parse_fixedpoint( int limit, double* valptr )
354 int parsed = actual_index;
355 Boolean digits = False;
356 int sdig = 0;
357 double value;
358 char curr;
359 int sign = False;
360 int expo = 0;
362 if( actual_index >= limit )
363 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_FLOAT );
364 if( iostrptr[actual_index] == '+' )
365 actual_index++;
366 else
367 if( iostrptr[actual_index] == '-' )
369 sign = True;
370 actual_index++;
373 floatdig[0] = '.';
374 for( ; actual_index < limit; actual_index++ )
376 curr = iostrptr[actual_index];
377 if( ! isDEC(curr) )
378 break;
379 digits = True;
380 if( sdig < MAXPREC - 1 )
382 if( sdig || curr != '0' )
384 floatdig[++sdig] = curr;
385 expo++;
388 else
389 if( sdig )
390 expo++;
392 if( digits && curr == '.' )
394 actual_index++;
395 for( ; actual_index < limit; actual_index++ )
397 curr = iostrptr[actual_index];
398 if( !isDEC(curr) )
399 break;
400 if( sdig < MAXPREC - 1 )
402 if( sdig || curr != '0' )
403 floatdig[++sdig] = curr;
404 else
405 expo--;
409 floatdig[++sdig] = '\0';
411 if( !digits )
412 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT );
414 *valptr = make_float( expo, sign);
415 return actual_index - parsed;
419 typedef enum {
420 s_sign, s_dig, s_period, s_fraca, s_fracb, s_expo, s_exposign,
421 s_expoa, s_expob }
422 scient_t;
424 /* %C -> scientific [+|-]<digit>[.<digit>*]E[=|-]<digit>+ */
425 static
426 int parse_scientific( int limit, double* valptr, double dmin, double dmax )
428 int parsed = actual_index;
429 int sdig = 0;
430 char curr;
431 double value;
432 int sign = False;
433 int expo = 0;
434 int expo_sign = +1;
436 scient_t state = s_sign;
438 if( actual_index >= limit )
439 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_FLOAT );
441 floatdig[0] = '.';
442 for( ; actual_index < limit; actual_index++ )
444 curr = iostrptr[actual_index];
445 switch( state )
447 case s_sign:
448 if( iostrptr[actual_index] == '+' )
450 state = s_dig;
451 break;
453 if( iostrptr[actual_index] == '-' )
455 sign = True;
456 state = s_dig;
457 break;
459 /* fall through - no break */
460 case s_dig:
461 if( isDEC(curr) && curr > '0' )
463 floatdig[++sdig] = curr;
464 state = s_period;
465 break;
467 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT );
468 case s_period:
469 if( curr == '.' )
471 state = s_fraca;
472 break;
474 if( curr == 'E' )
476 state = s_exposign;
477 break;
479 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
480 case s_fraca:
481 if( isDEC(curr) )
483 floatdig[++sdig] = curr;
484 state = s_fracb;
485 break;
487 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT );
488 case s_fracb:
489 if( isDEC(curr) )
491 if( sdig < MAXPREC - 1 )
492 floatdig[++sdig] = curr;
493 break;
495 if( curr == 'E' )
497 state = s_exposign;
498 break;
500 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
501 case s_exposign:
502 if( iostrptr[actual_index] == '+' )
504 state = s_expoa;
505 break;
507 if( iostrptr[actual_index] == '-' )
509 expo_sign = -1;
510 state = s_expoa;
511 break;
513 case s_expoa:
514 if( isDEC(curr) )
516 expo = curr - '0';
517 state = s_expob;
518 break;
520 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
521 case s_expob:
522 expo = expo*10 + (curr - '0');
523 if( expo > 1000 )
524 IOEXCEPTION( TEXTFAIL, REAL_OVERFLOW );
527 if( state != s_expob )
528 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
530 expo *= expo_sign;
531 expo++;
533 floatdig[++sdig] = '\0';
535 *valptr = make_float( expo, sign );
536 return actual_index - parsed;
540 static
541 int parse_set( int limit, __tmp_IO_enum_table_type* tabptr,
542 unsigned long* valptr )
544 int parsed = actual_index;
545 char curr;
546 __tmp_IO_enum_table_type* etptr;
548 if( actual_index >= limit )
549 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_SET );
551 curr = iostrptr[actual_index];
552 if( isXXX(curr,LET+USC) )
553 actual_index++;
554 else
555 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_SET );
557 for( ; actual_index < limit; actual_index++ )
559 if( ! isXXX(iostrptr[actual_index],LET+DEC+USC) )
560 break;
563 if( tabptr )
564 while( tabptr->name )
566 if( !casncmp( tabptr->name, &iostrptr[parsed], actual_index-parsed ) )
568 *valptr = tabptr->value;
569 #if _TEXTIO_DEBUG_
570 printf( "parsing set value until %d: %u\n", limit, tabptr->value );
571 #endif
572 return actual_index - parsed;
574 tabptr++;
576 IOEXCEPTION( TEXTFAIL, SET_CONVERSION_ERROR );
579 static
580 int parse_bit( int limit, char* bitptr )
582 int parsed = actual_index;
583 int i = 0;
584 char curr;
586 if( actual_index >= limit )
587 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_BOOLS );
589 for( ; actual_index < limit; actual_index++ )
591 curr = iostrptr[actual_index] - '0';
592 if( curr == 0 || curr == 1 )
593 /* __setbitinset( i++, bitptr, limit, curr ); */
594 __setbitpowerset (bitptr, limit, 0, i++, curr, __FILE__, __LINE__);
595 else
596 break;
598 return actual_index - parsed;
601 static
602 char* myultoa( unsigned long ul, char* buf, int base )
604 char* res = buf;
605 unsigned long h = ul/base;
606 unsigned long q = 1;
608 while( h >= q ) q *= base;
609 while( q > 0 )
611 *buf++ = "0123456789ABCDEF"[ul/q];
612 ul %= q;
613 q /= base;
615 *buf++ = '\0';
616 return res;
620 * convert a bit string from src, bit offset up to len
622 static
623 char* bitput( char* dst, char* src, int offset, int len )
625 char* res = dst;
626 int i;
627 for( i = offset; i < len; i++ )
629 *dst++ = __inpowerset( i, src, len, 0 ) ? '1' : '0';
631 return res;
635 * dround: round decimal register *digptr starting at digit mdigs,
636 * on carry advance begin of digit sequence and bump exponent
638 static
639 char*
640 dround( char* digptr, int mdigs, int* deptr )
642 int carry;
643 #if _TEXTIO_DEBUG_
644 printf( "Rounding from %d\n", mdigs );
645 #endif
646 if( digptr[mdigs] >= 5 )
648 carry = 1;
649 while( carry )
651 digptr[--mdigs]++;
652 if( digptr[mdigs] >= 10 )
653 digptr[mdigs] = 0;
654 else
655 carry = 0;
658 if( mdigs < 0 )
660 digptr[--mdigs] = 1;
661 (*deptr)++;
662 return digptr - 1;
664 else
665 return digptr;
669 * mydtoa: convert val with a precision of mantdigs to a decimal fraction
670 * first digit is at **fstdiptr, decimal exponent is at *deptr
672 static
673 char*
674 mydtoa( double val, int mantdigs, int* deptr, int* sgnptr )
676 double m;
677 int be;
678 int de = -1;
679 int fstdig = 0;
680 int idig;
681 char* digptr = floatdig+2;
683 floatdig[0] = floatdig[1] = 0;
685 if( val < 0 )
686 *sgnptr = -1, val = fabs( val );
687 else
688 *sgnptr = +1;
690 /* split the value */
691 m = frexp( val, &be ) * 10.0;
693 /* 5.0 <= m < 10.0 */
694 while( be > 0 )
696 de++; be--; m /= 5.0;
697 if( m < 1.0 )
698 m *= 10.0, de--;
700 while( be < 0 )
702 de--; be++; m *= 5.0;
703 if( m >= 10.0 )
704 m /= 10.0, de++;
707 for( idig = 0; idig < mantdigs; idig++ )
709 digptr[idig] = (int)m;
710 m = (m - digptr[idig])*10.0;
712 digptr[idig] = (int)m;
714 *deptr = de;
715 return dround( digptr, mantdigs, deptr );
718 #define PUT(c) \
719 { if( ifst <= ++iprt && iprt <= ilst ) *dst++ = c; }
721 static
722 char*
723 fixput( char* dst, char* src,
724 int ifst, int ilst,
725 int sign, int fst, int lst,
726 int nid, int nfd )
728 char* dstsav = dst;
729 int idig;
730 int iprt = 0;
732 if( sign < 0 )
733 PUT( '-' );
734 for( idig = nid; idig >= -nfd; idig-- )
736 if (idig == -1)
737 PUT( '.' );
738 PUT( idig > fst || lst >= idig ? '0': '0' + *src++ );
740 return dstsav;
743 static
744 char*
745 sciput( char* dst, char* src, char* expbeg,
746 int ifst, int ilst,
747 int sign, int de, int expwid )
749 char* dstsav = dst;
750 int iprt = 0;
751 int nfd = fractionwidth;
752 int explen = strlen( expbeg );
754 if( sign < 0 )
755 PUT( '-' );
756 PUT( '0' + *src++ );
757 PUT( '.' );
759 while( nfd-- )
760 PUT( '0' + *src++ );
761 PUT( 'E' );
762 PUT( de >= 0 ? '+' : '-' );
763 while( expwid > explen )
765 PUT( '0' );
766 expwid--;
768 while( explen-- )
769 PUT( *expbeg++ );
770 return dstsav;
774 * handle dynamic field width
776 static
777 get_field_width( void )
779 unsigned long width;
780 unsigned long ulongval;
781 long longval;
782 __tmp_IO_list io;
785 if( ++iolist_index > iolistlen )
786 IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED );
788 io = *iolistptr++;
790 /* must be integer, >= 0 */
791 switch( io.__descr )
793 case __IO_ByteVal:
794 longval = io.__t.__valbyte;
795 goto signed_fieldwidth;
796 case __IO_UByteVal:
797 width = io.__t.__valubyte;
798 goto unsigned_fieldwidth;
799 case __IO_IntVal:
800 longval = io.__t.__valint;
801 goto signed_fieldwidth;
802 case __IO_UIntVal:
803 width = io.__t.__valuint;
804 goto unsigned_fieldwidth;
805 case __IO_LongVal:
806 longval = io.__t.__vallong;
807 goto signed_fieldwidth;
808 case __IO_ULongVal:
809 width = io.__t.__valulong;
810 goto unsigned_fieldwidth;
811 case __IO_ByteLoc:
812 longval = *(signed char*)io.__t.__locint;
813 goto signed_fieldwidth;
814 case __IO_UByteLoc:
815 width = *(unsigned char*)io.__t.__locint;
816 goto unsigned_fieldwidth;
817 case __IO_IntLoc:
818 longval = *(signed short*)io.__t.__locint;
819 goto signed_fieldwidth;
820 case __IO_UIntLoc:
821 width = *(unsigned short*)io.__t.__locint;
822 goto unsigned_fieldwidth;
823 case __IO_LongLoc:
824 longval = *(signed long*) io.__t.__locint;
825 goto signed_fieldwidth;
826 case __IO_ULongLoc:
827 width = *(unsigned long*)io.__t.__locint;
828 goto unsigned_fieldwidth;
829 default:
830 IOEXCEPTION( TEXTFAIL, NON_INT_FIELD_WIDTH );
833 signed_fieldwidth: ;
834 if( longval < 0 )
835 IOEXCEPTION( TEXTFAIL, NEGATIVE_FIELD_WIDTH );
836 width = longval;
838 unsigned_fieldwidth: ;
839 return width;
843 static
844 void inpconv( void )
846 __tmp_IO_list io;
847 int width;
848 int limit;
849 int skiplim;
850 int skipped;
851 int bypass;
852 int parsed;
853 Boolean fixedchars;
854 int fixedlen;
855 unsigned char curr;
856 double dval;
857 float fval;
859 __tmp_IO_long lval;
860 int sign;
861 unsigned long umin;
862 unsigned long umax;
863 signed long smin;
864 signed long smax;
865 int ilen;
866 short unsigned slen;
867 __tmp_IO_enum_table_type* settabptr;
869 while( repetition-- )
871 if( ++iolist_index > iolistlen )
872 IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED );
874 io = *iolistptr++;
876 if( dynamicwid )
877 width = get_field_width();
878 else
879 width = clausewidth;
881 bypass = skipped = 0;
882 if( width )
884 if( actual_index + width > iostrlen )
885 IOEXCEPTION( TEXTFAIL, NOT_ENOUGH_CHARS );
887 switch(io.__descr)
889 case __IO_CharLoc:
890 case __IO_CharRangeLoc:
891 fixedchars = True;
892 fixedlen = 1;
893 break;
894 case __IO_CharStrLoc:
895 fixedchars = True;
896 fixedlen = io.__t.__loccharstring.string_length;
897 break;
898 default:
899 fixedchars = False;
900 break;
903 if( leftadjust )
905 skiplim = fixedchars ? actual_index + fixedlen
906 : actual_index;
907 bypass = skipped = piks_pad( actual_index + width, skiplim );
909 else
911 skiplim = fixedchars ? actual_index + width - fixedlen
912 : actual_index + width;
913 skipped = skip_pad( skiplim );
915 width -= skipped;
916 limit = actual_index + width;
918 else
919 { /* free format */
920 if( paddingdef || !( io.__descr == __IO_CharLoc ||
921 io.__descr == __IO_CharRangeLoc ||
922 io.__descr == __IO_CharStrLoc ||
923 io.__descr == __IO_CharVaryingLoc ) )
924 if( paddingchar == ' ' || paddingchar == '\t' )
925 skip_space( iostrlen );
926 else
927 skip_pad( iostrlen );
928 limit = iostrlen;
931 switch( io.__descr )
933 case __IO_ByteLoc:
934 ilen = 1;
935 smin = CH_BYTE_MIN;
936 smax = CH_BYTE_MAX;
937 goto parse_signed_int;
938 case __IO_UByteLoc:
939 ilen = 1;
940 umin = 0;
941 umax = CH_UBYTE_MAX;
942 goto parse_unsigned_int;
943 case __IO_IntLoc:
944 ilen = 2;
945 smin = CH_INT_MIN;
946 smax = CH_INT_MAX;
947 goto parse_signed_int;
948 case __IO_UIntLoc:
949 ilen = 2;
950 umin = 0;
951 umax = CH_UINT_MAX;
952 goto parse_unsigned_int;
953 case __IO_LongLoc:
954 ilen = 4;
955 smin = CH_LONG_MIN;
956 smax = CH_LONG_MAX;
957 goto parse_signed_int;
958 case __IO_ULongLoc:
959 ilen = 4;
960 umin = 0;
961 umax = CH_ULONG_MAX;
962 goto parse_unsigned_int;
964 case __IO_ByteRangeLoc:
965 ilen = 1;
966 smin = io.__t.__locintrange.lower.slong;
967 smax = io.__t.__locintrange.upper.slong;
968 goto parse_signed_int;
969 case __IO_UByteRangeLoc:
970 ilen = 1;
971 umin = io.__t.__locintrange.lower.ulong;
972 umax = io.__t.__locintrange.upper.ulong;
973 goto parse_unsigned_int;
974 case __IO_IntRangeLoc:
975 ilen = 2;
976 smin = io.__t.__locintrange.lower.slong;
977 smax = io.__t.__locintrange.upper.slong;
978 goto parse_signed_int;
979 case __IO_UIntRangeLoc:
980 ilen = 2;
981 umin = io.__t.__locintrange.lower.ulong;
982 umax = io.__t.__locintrange.upper.ulong;
983 goto parse_unsigned_int;
984 case __IO_LongRangeLoc:
985 ilen = 4;
986 smin = io.__t.__locintrange.lower.slong;
987 smax = io.__t.__locintrange.upper.slong;
988 goto parse_signed_int;
989 case __IO_ULongRangeLoc:
990 ilen = 4;
991 umin = io.__t.__locintrange.lower.ulong;
992 umax = io.__t.__locintrange.upper.ulong;
993 goto parse_unsigned_int;
995 case __IO_BoolLoc:
996 ilen = 1;
997 umin = 0;
998 umax = 1;
999 settabptr = bool_tab;
1000 goto parse_set;
1001 case __IO_BoolRangeLoc:
1002 ilen = 1;
1003 umin = io.__t.__locboolrange.lower;
1004 umax = io.__t.__locboolrange.upper;
1005 settabptr = bool_tab;
1006 goto parse_set;
1008 case __IO_SetLoc:
1009 ilen = io.__t.__locsetrange.length;
1010 settabptr = io.__t.__locsetrange.name_table;
1011 umin = 0;
1012 umax = CH_ULONG_MAX;
1013 goto parse_set;
1014 case __IO_SetRangeLoc:
1015 ilen = io.__t.__locsetrange.length;
1016 settabptr = io.__t.__locsetrange.name_table;
1017 umin = io.__t.__locsetrange.lower;
1018 umax = io.__t.__locsetrange.upper;
1019 goto parse_set;
1021 case __IO_CharLoc:
1022 umin = 0;
1023 umax = 0xff;
1024 goto parse_char;
1025 case __IO_CharRangeLoc:
1026 umin = io.__t.__loccharrange.lower;
1027 umax = io.__t.__loccharrange.upper;
1028 goto parse_char;
1030 case __IO_CharVaryingLoc:
1031 if( convcode != DefaultConv )
1032 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1033 slen = io.__t.__loccharstring.string_length;
1034 if( (parsed = limit - actual_index) < slen )
1035 slen = parsed;
1036 else
1037 parsed = slen;
1038 memcpy( io.__t.__loccharstring.string + 2,
1039 &iostrptr[actual_index], parsed );
1040 MOV2(io.__t.__loccharstring.string,&slen);
1041 actual_index += parsed;
1042 goto check_field_complete;
1045 case __IO_CharStrLoc:
1046 if( convcode != DefaultConv )
1047 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1048 if( actual_index + io.__t.__loccharstring.string_length > limit )
1049 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_CHARS );
1050 memcpy( io.__t.__loccharstring.string,
1051 &iostrptr[actual_index],
1052 parsed = io.__t.__loccharstring.string_length );
1053 actual_index += parsed;
1054 goto check_field_complete;
1056 case __IO_BitStrLoc:
1057 if( convcode != DefaultConv )
1058 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1059 parsed = parse_bit( limit, io.__t.__loccharstring.string );
1060 if( parsed < io.__t.__loccharstring.string_length )
1061 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_BOOLS );
1062 goto check_field_complete;
1064 case __IO_LongRealLoc:
1065 case __IO_RealLoc:
1066 switch( convcode )
1068 case ScientConv:
1069 parse_scientific( limit, &dval, DBL_MIN, DBL_MAX );
1070 break;
1071 case DefaultConv:
1072 parse_fixedpoint( limit, &dval );
1073 break;
1074 default:
1075 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1077 if( io.__descr == __IO_LongRealLoc )
1078 memcpy( io.__t.__loclongreal, &dval, sizeof(double) );
1079 else
1081 fval = (float)dval;
1082 MOV4(io.__t.__locreal,&fval);
1084 goto check_field_complete;
1085 default:
1086 IOEXCEPTION( TEXTFAIL, INVALID_IO_LIST );
1090 parse_signed_int: ;
1091 if( convcode == ScientConv )
1092 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1093 parsed = parse_int( limit, dset[convcode], base[convcode],
1094 &lval.ulong, &sign );
1095 if( sign < 0 )
1097 if( lval.ulong > (unsigned long)CH_LONG_MIN )
1098 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1099 lval.slong = -lval.ulong;
1101 else
1103 /* not needed: lval.slong = lval.ulong; */
1104 /* Hack: sign extension for bin/oct/dec if no sign present */
1105 if( convcode != DefaultConv && lval.ulong & (1 << (ilen*8-1)) )
1107 if( ilen < 4 )
1108 lval.ulong |= 0xFFFFFFFF << ilen*8;
1110 else
1111 if( lval.ulong > (unsigned long)CH_LONG_MAX )
1112 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1114 if( lval.slong < smin || smax < lval.slong )
1115 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1116 goto store_int;
1118 parse_unsigned_int: ;
1119 if( convcode == ScientConv )
1120 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1121 parsed = parse_int( limit, dset[convcode], base[convcode],
1122 &lval.ulong, &sign );
1123 if( sign < 0 || lval.ulong < umin || umax < lval.ulong )
1124 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1125 goto store_int;
1127 parse_set: ;
1128 if( convcode != DefaultConv )
1129 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1130 parsed = parse_set( limit, settabptr, &lval.ulong );
1131 if( lval.ulong < umin || umax < lval.ulong )
1132 IOEXCEPTION( TEXTFAIL, SET_RANGE_ERROR );
1133 goto store_int;
1135 store_int: ;
1136 switch( ilen )
1138 case 1:
1139 *(unsigned char*)io.__t.__locint = lval.ulong;
1140 break;
1141 case 2:
1142 slen = lval.ulong;
1143 MOV2(io.__t.__locint,&slen);
1144 break;
1145 case 4:
1146 MOV4(io.__t.__locint,&lval.ulong);
1147 break;
1148 default:
1149 IOEXCEPTION( TEXTFAIL, INTERNAL_ERROR );
1151 goto check_field_complete;
1153 parse_char: ;
1154 if( convcode != DefaultConv )
1155 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1156 if( actual_index >= limit )
1157 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_CHARS );
1158 curr = iostrptr[actual_index++];
1159 parsed = 1;
1160 if( curr < umin || umax < curr )
1161 IOEXCEPTION( TEXTFAIL, CHAR_RANGE_ERROR );
1162 *io.__t.__locchar = curr;
1163 goto check_field_complete;
1165 check_field_complete: ;
1166 actual_index += bypass;
1167 if( width > parsed )
1168 IOEXCEPTION( TEXTFAIL, INVALID_CHAR );
1172 static
1173 void inpedit( void )
1175 int nchars;
1177 if( dynamicwid )
1178 clausewidth = get_field_width();
1180 switch( editcode )
1182 case SpaceSkip:
1183 nchars = repetition*clausewidth;
1184 if( actual_index + nchars > iostrlen )
1185 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT );
1186 for( ; nchars ; nchars-- )
1187 if( iostrptr[actual_index++] != ' ' )
1188 IOEXCEPTION( TEXTFAIL, NO_SPACE_TO_SKIP );
1189 break;
1191 case SkipLeft:
1192 nchars = repetition*clausewidth;
1193 if( (actual_index -= nchars) < 0 )
1194 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT );
1195 break;
1197 case SkipRight:
1198 nchars = repetition*clausewidth;
1199 if( (actual_index += nchars) > iostrlen )
1200 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT );
1201 break;
1203 case Tabulation:
1204 if( (actual_index = clausewidth) > iostrlen )
1205 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1206 break;
1210 static
1211 void outconv( void )
1213 unsigned long width;
1214 char itembuf[33];
1215 unsigned long ulongval;
1216 long longval;
1217 __tmp_IO_list io;
1218 __tmp_IO_enum_table_type* etptr;
1219 char* itembeg;
1220 unsigned long itemlen;
1221 double doubleval;
1222 int de;
1223 int sign;
1224 int mantdigs;
1225 int nid;
1226 int nfd;
1227 char* expbeg;
1228 int explen;
1229 unsigned int expwid;
1231 while( repetition-- )
1233 if( ++iolist_index > iolistlen )
1234 IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED );
1236 io = *iolistptr++;
1237 width = dynamicwid ? get_field_width() : clausewidth;
1239 switch( convcode )
1241 case DefaultConv:
1242 switch( io.__descr )
1244 case __IO_ByteVal:
1245 longval = io.__t.__valbyte;
1246 goto signed_conversion;
1247 case __IO_UByteVal:
1248 ulongval = io.__t.__valubyte;
1249 goto unsigned_conversion;
1250 case __IO_IntVal:
1251 longval = io.__t.__valint;
1252 goto signed_conversion;
1253 case __IO_UIntVal:
1254 ulongval = io.__t.__valuint;
1255 goto unsigned_conversion;
1256 case __IO_LongVal:
1257 longval = io.__t.__vallong;
1258 goto signed_conversion;
1259 case __IO_ULongVal:
1260 ulongval = io.__t.__valulong;
1261 goto unsigned_conversion;
1263 case __IO_BoolVal:
1264 switch( io.__t.__valbool )
1266 case 0:
1267 itembeg = "FALSE";
1268 itemlen = 5;
1269 goto move_item;
1270 case 1:
1271 itembeg = "TRUE";
1272 itemlen = 4;
1273 goto move_item;
1274 default:
1275 IOEXCEPTION( TEXTFAIL, BOOL_CONVERSION_ERROR );
1278 case __IO_CharVal:
1279 itembeg = &io.__t.__valchar;
1280 itemlen = 1;
1281 goto move_item;
1283 case __IO_SetVal:
1284 /* locate name string using set mode name table */
1285 itembeg = 0;
1287 if( (etptr = io.__t.__valset.name_table) )
1288 while( etptr->name )
1290 if( etptr->value == io.__t.__valset.value )
1292 itembeg = etptr->name;
1293 itemlen = strlen( itembeg );
1294 goto move_item;
1296 etptr++;
1298 IOEXCEPTION( TEXTFAIL, SET_CONVERSION_ERROR );
1300 case __IO_CharVaryingLoc:
1302 unsigned short l;
1303 itembeg = (char*)io.__t.__loccharstring.string;
1304 MOV2(&l,itembeg);
1305 itembeg += 2;
1306 itemlen = l;
1307 goto move_item;
1310 case __IO_CharStrLoc:
1311 itembeg = io.__t.__loccharstring.string;
1312 itemlen = io.__t.__loccharstring.string_length;
1313 goto move_item;
1315 case __IO_BitStrLoc:
1316 itemlen = io.__t.__loccharstring.string_length;
1317 itembeg = io.__t.__loccharstring.string;
1319 if( !width )
1320 width = itemlen;
1322 /* check remaining space */
1323 if( actual_index + width > iostrlen )
1324 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1326 if( itemlen == width )
1327 bitput( iostrptr + actual_index, itembeg, 0, itemlen );
1328 else
1329 if( itemlen < width )
1330 if( leftadjust )
1331 memset( bitput( iostrptr + actual_index, itembeg, 0, itemlen )
1332 + itemlen,
1333 paddingchar, width - itemlen );
1334 else
1335 bitput( memset( iostrptr + actual_index,
1336 paddingchar, width - itemlen )
1337 + width - itemlen,
1338 itembeg, itemlen - width, itemlen );
1339 else
1340 if( overflowev )
1341 memset( iostrptr + actual_index, '*', width );
1342 else
1343 if( leftadjust )
1344 bitput( iostrptr + actual_index, itembeg, 0, width );
1345 else
1346 bitput( iostrptr + actual_index, itembeg,
1347 itemlen - width, itemlen );
1348 goto adjust_index;
1350 case __IO_RealVal:
1351 doubleval = io.__t.__valreal;
1352 mantdigs = FMANTDIGS;
1353 goto fixed_point_conversion;
1354 case __IO_LongRealVal:
1355 doubleval = io.__t.__vallongreal;
1356 mantdigs = DBL_DIG;
1357 goto fixed_point_conversion;
1358 break;
1360 default:
1361 IOEXCEPTION( TEXTFAIL, INVALID_IO_LIST );
1364 case HexConv:
1365 case OctalConv:
1366 case BinaryConv:
1367 switch( io.__descr )
1369 case __IO_ByteVal:
1370 case __IO_UByteVal:
1371 ulongval = io.__t.__valubyte;
1372 break;
1373 case __IO_IntVal:
1374 case __IO_UIntVal:
1375 ulongval = io.__t.__valuint;
1376 break;
1377 case __IO_LongVal:
1378 case __IO_ULongVal:
1379 ulongval = io.__t.__valulong;
1380 break;
1381 default:
1382 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1384 itembeg = myultoa( ulongval, itembuf, base[convcode] );
1385 itemlen = strlen( itembeg );
1386 goto move_item;
1388 case ScientConv:
1389 switch( io.__descr )
1391 case __IO_RealVal:
1392 doubleval = io.__t.__valreal;
1393 mantdigs = FMANTDIGS;
1394 if( !fractiondef )
1395 fractionwidth = FMANTDIGS - 1;
1396 goto scientific_conversion;
1397 case __IO_LongRealVal:
1398 doubleval = io.__t.__vallongreal;
1399 mantdigs = DBL_DIG;
1400 if( !fractiondef )
1401 fractionwidth = DBL_DIG - 1;
1402 goto scientific_conversion;
1403 break;
1404 default:
1405 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1409 fixed_point_conversion: ;
1410 itembeg = mydtoa( doubleval, mantdigs, &de, &sign );
1411 if( fractiondef && de >= -fractionwidth - 1
1412 && -fractionwidth > de - mantdigs )
1413 itembeg = dround( itembeg, de + fractionwidth + 1, &de );
1415 nid = de >= 0 ? de : 0;
1416 nfd = fractiondef ? fractionwidth
1417 : ( de + 1 - mantdigs > 0 ? 0 : mantdigs - de - 1 );
1418 itemlen = ( sign < 0 ? 1 : 0 ) + 2 + nid + nfd;
1419 #if _TEXTIO_DEBUG_
1420 printf( "fixed item length %d\n", itemlen );
1421 #endif
1422 if( !width )
1423 width = itemlen;
1424 #if _TEXTIO_DEBUG_
1425 printf( "fixed item width %d\n", width );
1426 #endif
1427 /* check remaining space */
1428 if( actual_index + width > iostrlen )
1429 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1431 if( itemlen == width )
1432 fixput( iostrptr + actual_index, itembeg,
1433 1, itemlen, sign, de, de - mantdigs, nid, nfd );
1434 else
1435 if( itemlen < width )
1436 if( leftadjust )
1437 memset( fixput( iostrptr + actual_index, itembeg,
1438 1, itemlen, sign, de, de - mantdigs, nid, nfd )
1439 + itemlen,
1440 paddingchar, width - itemlen );
1441 else
1442 fixput( memset( iostrptr + actual_index,
1443 paddingchar, width - itemlen )
1444 + width - itemlen,
1445 itembeg, 1, itemlen, sign, de, de - mantdigs, nid, nfd );
1446 else
1447 if( overflowev )
1448 memset( iostrptr + actual_index, '*', width );
1449 else
1450 if( leftadjust )
1451 fixput( iostrptr + actual_index, itembeg,
1452 1, width, sign, de, de - mantdigs, nid, nfd );
1453 else
1454 fixput( iostrptr + actual_index, itembeg,
1455 itemlen - width + 1, itemlen,
1456 sign, de, de - mantdigs, nid, nfd );
1457 goto adjust_index;
1459 scientific_conversion: ;
1460 itembeg = mydtoa( doubleval, mantdigs, &de, &sign );
1462 if( fractiondef && fractionwidth < mantdigs )
1463 itembeg = dround( itembeg, fractionwidth + 1, &de );
1465 expbeg = myultoa( abs(de), itembuf, 10 );
1466 explen = strlen( expbeg );
1468 expwid = explen > exponentwidth ? explen : exponentwidth;
1469 itemlen = ( sign < 0 ? 1 : 0 ) + 2 + fractionwidth + 2 + expwid;
1470 #if _TEXTIO_DEBUG_
1471 printf( "floating item length %d, fraction %d, exponent %d\n",
1472 itemlen, fractionwidth, expwid );
1473 #endif
1474 if( width == 0 )
1475 width = itemlen;
1476 #if _TEXTIO_DEBUG_
1477 printf( "floating item width %d\n", width );
1478 #endif
1479 /* check remaining space */
1480 if( actual_index + width > iostrlen )
1481 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1483 if( itemlen == width )
1484 sciput( iostrptr + actual_index, itembeg, expbeg,
1485 1, itemlen, sign, de, expwid );
1486 else
1487 if( itemlen < width )
1488 if( leftadjust )
1489 memset( sciput( iostrptr + actual_index, itembeg, expbeg,
1490 1, itemlen, sign, de, expwid )
1491 + itemlen,
1492 paddingchar, width - itemlen );
1493 else
1494 sciput( memset( iostrptr + actual_index,
1495 paddingchar, width - itemlen )
1496 + width - itemlen,
1497 itembeg, expbeg, 1, itemlen, sign, de, expwid );
1498 else
1499 if( overflowev )
1500 memset( iostrptr + actual_index, '*', width );
1501 else
1502 if( leftadjust )
1503 sciput( iostrptr + actual_index, itembeg, expbeg,
1504 1, width, sign, de, expwid );
1505 else
1506 sciput( iostrptr + actual_index, itembeg, expbeg,
1507 itemlen - width + 1, itemlen,
1508 sign, de, expwid );
1509 goto adjust_index;
1511 signed_conversion: ;
1512 if( longval >= 0 )
1513 itembeg = myultoa( longval, itembuf, 10 );
1514 else
1516 itembuf[0] = '-';
1517 myultoa( -longval, itembuf+1, 10 );
1518 itembeg = itembuf;
1520 itemlen = strlen( itembeg );
1521 goto move_item;
1523 unsigned_conversion: ;
1524 itembeg = myultoa( ulongval, itembuf, 10 );
1525 itemlen = strlen( itembeg );
1526 goto move_item;
1528 move_item: ;
1529 if( !width )
1530 width = itemlen;
1532 /* check remaining space */
1533 if( actual_index + width > iostrlen )
1534 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1536 /* move item, filling or truncating or overflow-evidencing */
1537 if( itemlen == width )
1538 memcpy( iostrptr + actual_index, itembeg, itemlen );
1539 else
1540 if( itemlen < width )
1541 if( leftadjust )
1542 memset( memcpy( iostrptr + actual_index, itembeg, itemlen )
1543 + itemlen,
1544 paddingchar, width - itemlen );
1545 else
1546 memcpy( memset( iostrptr + actual_index,
1547 paddingchar, width - itemlen )
1548 + width - itemlen,
1549 itembeg, itemlen );
1550 else
1551 if( overflowev )
1552 memset( iostrptr + actual_index, '*', width );
1553 else
1554 if( leftadjust )
1555 memcpy( iostrptr + actual_index, itembeg, width );
1556 else
1557 memcpy( iostrptr + actual_index,
1558 itembeg + itemlen - width, width );
1561 * adjust.
1563 adjust_index: ;
1564 actual_index += width;
1565 if( actual_index > maximum_index )
1566 maximum_index = actual_index;
1570 static
1571 void outedit( void )
1573 int nchars;
1575 if( dynamicwid )
1576 clausewidth = get_field_width();
1577 switch( editcode )
1579 case SpaceSkip:
1580 nchars = repetition*clausewidth;
1581 if( actual_index + nchars > iostrlen )
1582 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1583 memset( iostrptr + actual_index, ' ', nchars );
1584 actual_index += nchars;
1585 if( actual_index > maximum_index )
1586 maximum_index = actual_index;
1587 break;
1589 case SkipLeft:
1590 nchars = repetition*clausewidth;
1591 if( actual_index - nchars < 0 )
1592 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1593 actual_index -= nchars;
1594 break;
1596 case SkipRight:
1597 nchars = repetition*clausewidth;
1598 if( actual_index + nchars > iostrlen )
1599 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1600 actual_index += nchars;
1601 if( actual_index > maximum_index )
1603 memset( iostrptr + maximum_index, ' ', actual_index - maximum_index );
1604 maximum_index = actual_index;
1606 break;
1608 case Tabulation:
1609 if( clausewidth >= iostrlen )
1610 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1611 actual_index = clausewidth;
1612 if( actual_index > maximum_index )
1614 memset( iostrptr + maximum_index, ' ', actual_index - maximum_index );
1615 maximum_index = actual_index;
1617 break;
1622 static
1623 void inpioctrl( void )
1625 unsigned short hlen;
1626 if( !textptr )
1627 IOEXCEPTION( TEXTFAIL, IO_CONTROL_NOT_VALID );
1628 if( iocode != EndPage )
1630 jmp_buf ioerror;
1631 unsigned long info;
1633 if (textptr->access_sub->association)
1635 if( (info = setjmp( ioerror )) )
1636 IOEXCEPTION( info>>16, info & 0xffff );
1637 while( repetition-- )
1639 __readrecord( textptr->access_sub, textindex,
1640 (char*)textptr->text_record,
1641 __FILE__, __LINE__ );
1642 actual_index = 0;
1643 MOV2(&hlen,&textptr->text_record->len);
1644 iostrlen = hlen;
1647 else
1648 IOEXCEPTION (NOTCONNECTED, IS_NOT_CONNECTED);
1652 /* specify pre/post in the order "/+-?!" */
1653 static
1654 char* pre_char = "\0\f\0\r\0"; /* Z.200: "\n\f\0\n\0" */
1655 static
1656 char* post_char = "\n\n\r\0\0"; /* Z.200: "\r\r\r\0\0" */
1658 static
1659 void outioctrl( void )
1661 Association_Mode* assoc;
1662 unsigned short hlen;
1663 if( !textptr )
1664 IOEXCEPTION( TEXTFAIL, IO_CONTROL_NOT_VALID );
1665 if( (assoc = textptr->access_sub->association) )
1667 jmp_buf ioerror;
1668 unsigned long info;
1669 if( (info = setjmp( ioerror )) )
1670 IOEXCEPTION( info>>16, info & 0xffff );
1672 while( repetition-- )
1674 if( iocode != EndPage )
1676 if( TEST_FLAG( assoc, IO_FIRSTLINE ) )
1678 CLR_FLAG( assoc, IO_FIRSTLINE );
1679 assoc->ctl_pre = '\0';
1681 else
1683 if( TEST_FLAG( assoc, IO_FORCE_PAGE ) )
1685 CLR_FLAG( assoc, IO_FORCE_PAGE );
1686 assoc->ctl_pre = '\f';
1688 else
1689 assoc->ctl_pre = pre_char[iocode];
1691 assoc->ctl_post = post_char[iocode];
1692 hlen = actual_index;
1693 MOV2(&textptr->text_record->len,&hlen);
1694 __writerecord( textptr->access_sub, textindex,
1695 (char*)textptr->text_record,
1696 textptr->text_record->len,
1697 __FILE__, __LINE__ );
1698 hlen = actual_index = 0;
1699 MOV2(&textptr->text_record->len,&hlen);
1701 else if( !TEST_FLAG( textptr, IO_FIRSTLINE ) )
1702 SET_FLAG( textptr, IO_FORCE_PAGE );
1703 assoc->ctl_pre = assoc->ctl_post = '\0';
1706 else
1707 IOEXCEPTION (NOTCONNECTED, IS_NOT_CONNECTED);
1710 static
1711 void (**actionptr)( void );
1712 static
1713 void (*readactions[])( void ) = { inpconv, inpedit, inpioctrl };
1714 static
1715 void (*writeactions[])( void ) = { outconv, outedit, outioctrl };
1718 static
1719 void emitstr( char* begtxt, char* endtxt )
1721 char c;
1722 int nchars = endtxt - begtxt;
1723 if( actual_index + nchars > iostrlen )
1724 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1725 memcpy( iostrptr + actual_index, begtxt, nchars );
1726 actual_index += nchars;
1727 if( actual_index > maximum_index )
1728 maximum_index = actual_index;
1731 static
1732 void scanstr( char* begtxt, char* endtxt )
1734 int nchars = endtxt - begtxt;
1735 if( actual_index + nchars > iostrlen )
1736 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_TEXT );
1737 if( strncmp( iostrptr + actual_index, begtxt, nchars ) )
1738 IOEXCEPTION( TEXTFAIL, FORMAT_TEXT_MISMATCH );
1739 actual_index += nchars;
1742 void (*ftextptr) ( char*, char* );
1744 static
1745 formatexit_t scanformcont( char* fcs, int len,
1746 char** fcsptr, int* lenptr )
1748 char curr;
1749 fcsstate_t state = FormatText;
1750 unsigned long buf;
1751 int dig;
1752 acttype_t action;
1753 char* begtxt = fcs;
1755 while( len-- )
1757 curr = *fcs++;
1758 switch( state )
1760 case FormatText:
1761 if( curr == '%' )
1763 ftextptr( begtxt, fcs-1 );
1764 state = FirstPercent;
1766 break;
1768 after_first_percent: ;
1769 case FirstPercent:
1770 if( curr == '%' )
1772 state = FormatText;
1773 begtxt = fcs - 1;
1774 break;
1776 if( curr == ')' )
1778 *lenptr = len;
1779 *fcsptr = fcs;
1780 return EndAtParen;
1782 if( isDEC(curr) )
1784 state = RepFact;
1785 repetition = curr - '0';
1786 break;
1789 repetition = 1;
1791 test_for_control_codes: ;
1792 if( isCVC(curr) )
1794 state = ConvClause;
1795 action = ConvAct;
1796 convcode = strchr( CONVERSIONCODES, curr ) - CONVERSIONCODES;
1797 leftadjust = False;
1798 overflowev = False;
1799 dynamicwid = False;
1800 paddingdef = False;
1801 paddingchar = ' ';
1802 fractiondef = False;
1803 /* fractionwidth = 0; default depends on mode ! */
1804 exponentdef = False;
1805 exponentwidth = 3;
1806 clausewidth = 0;
1807 break;
1809 if( isEDC(curr) )
1811 state = EditClause;
1812 action = EditAct;
1813 editcode = strchr( EDITCODES, curr ) - EDITCODES;
1814 dynamicwid = False;
1815 clausewidth = editcode == Tabulation ? 0 : 1;
1816 break;
1818 if( isIOC(curr) )
1820 state = ClauseEnd;
1821 action = IOAct;
1822 iocode = strchr( IOCODES, curr ) - IOCODES;
1823 break;
1825 if( curr == '(' )
1827 unsigned long times = repetition;
1828 int cntlen;
1829 char* cntfcs;
1830 while( times-- )
1832 if( scanformcont( fcs, len, &cntfcs, &cntlen ) != EndAtParen )
1833 IOEXCEPTION( TEXTFAIL, UNMATCHED_OPENING_PAREN );
1835 fcs = cntfcs;
1836 len = cntlen;
1837 state = FormatText;
1838 begtxt = fcs;
1839 break;
1841 IOEXCEPTION( TEXTFAIL, BAD_FORMAT_SPEC_CHAR );
1843 case RepFact:
1844 if( isDEC(curr) )
1846 dig = curr - '0';
1847 if( repetition > (ULONG_MAX - dig)/10 )
1848 IOEXCEPTION( TEXTFAIL, REPFAC_OVERFLOW );
1849 repetition = repetition*10 + dig;
1850 break;
1852 goto test_for_control_codes;
1854 case ConvClause:
1855 if( isDEC(curr) )
1857 state = ClauseWidth;
1858 clausewidth = curr - '0';
1859 break;
1861 if( curr == 'L' )
1863 if( leftadjust )
1864 IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER );
1865 leftadjust = True;
1866 break;
1868 if( curr == 'E' )
1870 if( overflowev )
1871 IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER );
1872 overflowev = True;
1873 break;
1875 if( curr == 'P' )
1877 if( paddingdef )
1878 IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER );
1879 paddingdef = True;
1880 state = CatchPadding;
1881 break;
1884 test_for_variable_width: ;
1885 if( curr == 'V' )
1887 dynamicwid = True;
1888 state = AfterWidth;
1889 break;
1891 goto test_for_fraction_width;
1893 case ClauseWidth:
1894 if( isDEC(curr) )
1896 dig = curr - '0';
1897 if( clausewidth > (ULONG_MAX - dig)/10 )
1898 IOEXCEPTION( TEXTFAIL, CLAUSE_WIDTH_OVERFLOW );
1899 clausewidth = clausewidth*10 + dig;
1900 break;
1902 /* fall through */
1904 test_for_fraction_width: ;
1905 case AfterWidth:
1906 if( curr == '.' )
1908 if( convcode != DefaultConv && convcode != ScientConv )
1909 IOEXCEPTION( TEXTFAIL, NO_FRACTION );
1910 fractiondef = True;
1911 state = FractWidth;
1912 break;
1914 goto test_for_exponent_width;
1916 case FractWidth:
1917 if( isDEC( curr ) )
1919 state = FractWidthCont;
1920 fractionwidth = curr - '0';
1921 break;
1923 else
1924 IOEXCEPTION( TEXTFAIL, NO_FRACTION_WIDTH );
1926 case FractWidthCont:
1927 if( isDEC( curr ) )
1929 dig = curr - '0';
1930 if( fractionwidth > (ULONG_MAX - dig)/10 )
1931 IOEXCEPTION( TEXTFAIL, FRACTION_WIDTH_OVERFLOW );
1932 fractionwidth = fractionwidth*10 + dig;
1933 break;
1936 test_for_exponent_width: ;
1937 if( curr == ':' )
1939 if( convcode != ScientConv )
1940 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
1941 exponentdef = True;
1942 state = ExpoWidth;
1943 break;
1945 goto test_for_final_percent;
1947 case ExpoWidth:
1948 if( isDEC( curr ) )
1950 state = ExpoWidthCont;
1951 exponentwidth = curr - '0';
1952 break;
1954 else
1955 IOEXCEPTION( TEXTFAIL, NO_EXPONENT_WIDTH );
1957 case ExpoWidthCont:
1958 if( isDEC( curr ) )
1960 dig = curr - '0';
1961 if( exponentwidth > (ULONG_MAX - dig)/10 )
1962 IOEXCEPTION( TEXTFAIL, EXPONENT_WIDTH_OVERFLOW );
1963 exponentwidth = exponentwidth*10 + dig;
1964 break;
1966 /* fall through */
1968 test_for_final_percent: ;
1969 case ClauseEnd:
1970 if( curr == '%' )
1972 state = LastPercent;
1973 break;
1976 do_the_action: ;
1977 actionptr[action]();
1978 state = FormatText;
1979 begtxt = fcs - 1;
1980 break;
1982 case CatchPadding:
1983 paddingchar = curr;
1984 state = ConvClause;
1985 break;
1987 case EditClause:
1988 if( isDEC(curr) )
1990 state = ClauseWidth;
1991 clausewidth = curr - '0';
1992 break;
1994 goto test_for_variable_width;
1996 case LastPercent:
1997 actionptr[action]();
1998 if( curr == '.' )
2000 state = FormatText;
2001 begtxt = fcs;
2002 break;
2004 goto after_first_percent;
2006 default:
2007 IOEXCEPTION( TEXTFAIL, INTERNAL_ERROR );
2010 switch( state )
2012 case FormatText:
2013 ftextptr( begtxt, fcs );
2014 break;
2015 case FirstPercent:
2016 case LastPercent:
2017 case RepFact:
2018 case FractWidth:
2019 case ExpoWidth:
2020 IOEXCEPTION( TEXTFAIL, BAD_FORMAT_SPEC_CHAR );
2021 case CatchPadding:
2022 IOEXCEPTION( TEXTFAIL, NO_PAD_CHAR );
2023 default:
2024 actionptr[action]();
2027 *lenptr = len;
2028 *fcsptr = fcs;
2029 return NormalEnd;
2032 static
2033 void
2034 __read_format (char* fmtptr,
2035 int fmtlen,
2036 __tmp_IO_list* ioptr,
2037 int iolen,
2038 void* inpptr,
2039 int inplen )
2041 formatexit_t res;
2042 unsigned short l;
2044 iostrptr = (char*)inpptr;
2045 iostrlen = inplen;
2047 /* initialisation */
2048 iolist_index = 0;
2049 iolistptr = ioptr;
2050 iolistlen = iolen;
2052 actionptr = readactions;
2053 ftextptr = scanstr;
2055 if( (res = scanformcont( fmtptr, fmtlen, &fmtptr, &fmtlen )) == EndAtParen )
2056 IOEXCEPTION( TEXTFAIL, UNMATCHED_CLOSING_PAREN );
2058 if( iolist_index != iolen )
2059 IOEXCEPTION( TEXTFAIL, EXCESS_IOLIST_ELEMENTS );
2061 return;
2064 void
2065 __readtext_f( Text_Mode* the_text_loc,
2066 signed long the_index,
2067 char* fmtptr,
2068 int fmtlen,
2069 __tmp_IO_list* ioptr,
2070 int iolen,
2071 char* file,
2072 int line )
2074 unsigned long info;
2076 if( (info = setjmp( __io_exception )) )
2077 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2079 textptr = the_text_loc;
2080 textrecptr = textptr->text_record;
2081 actual_index = textptr->actual_index;
2082 textindex = the_index;
2084 __read_format ( fmtptr, fmtlen, ioptr, iolen,
2085 (char*)textrecptr + 2, textptr->text_record->len );
2086 textptr->actual_index = actual_index;
2089 void
2090 __readtext_s( void* string_ptr,
2091 int string_len,
2092 char* fmtptr,
2093 int fmtlen,
2094 __tmp_IO_list* ioptr,
2095 int iolen,
2096 char* file,
2097 int line )
2099 int info;
2101 if( (info = setjmp( __io_exception )) )
2102 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2104 textptr = NULL;
2105 actual_index = 0;
2107 __read_format ( fmtptr, fmtlen, ioptr, iolen, string_ptr, string_len );
2110 static
2111 void
2112 __write_format (char* fmtptr,
2113 int fmtlen,
2114 __tmp_IO_list* ioptr,
2115 int iolen,
2116 void* outptr,
2117 int outlen )
2119 formatexit_t res;
2120 unsigned short l;
2122 /* initialisation */
2123 maximum_index = actual_index;
2124 iolist_index = 0;
2126 actionptr = writeactions;
2127 ftextptr = emitstr;
2128 iolistptr = ioptr;
2129 iolistlen = iolen;
2130 iostrptr = (char *)outptr + 2;
2131 iostrlen = outlen;
2133 if( (res = scanformcont( fmtptr, fmtlen, &fmtptr, &fmtlen )) == EndAtParen )
2134 IOEXCEPTION( TEXTFAIL, UNMATCHED_CLOSING_PAREN );
2136 if( iolist_index != iolen )
2137 IOEXCEPTION( TEXTFAIL, EXCESS_IOLIST_ELEMENTS );
2139 /* set length of output string */
2140 #if _TEXTIO_DEBUG_
2141 printf( "maximum index = %d\n", maximum_index );
2142 #endif
2143 l = maximum_index;
2144 MOV2(outptr,&l);
2145 return;
2148 void
2149 __writetext_f( Text_Mode* the_text_loc,
2150 signed long the_index,
2151 char* fmtptr,
2152 int fmtlen,
2153 __tmp_IO_list* ioptr,
2154 int iolen,
2155 char* file,
2156 int line )
2158 int info;
2160 if( (info = setjmp( __io_exception )) )
2161 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2163 textptr = the_text_loc;
2164 textrecptr = the_text_loc->text_record;
2165 textindex = the_index;
2166 iolistptr = ioptr;
2167 iolistlen = iolen;
2169 actual_index = textptr->actual_index;
2170 __write_format ( fmtptr, fmtlen, ioptr, iolen,
2171 textrecptr, textptr->access_sub->reclength - 2 );
2172 textptr->actual_index = actual_index;
2175 void
2176 __writetext_s( void* string_ptr,
2177 int string_len,
2178 char* fmtptr,
2179 int fmtlen,
2180 __tmp_IO_list* ioptr,
2181 int iolen,
2182 char* file,
2183 int line )
2185 int info;
2187 if( (info = setjmp( __io_exception )) )
2188 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2190 textptr = NULL;
2191 actual_index = 0;
2193 __write_format ( fmtptr, fmtlen, ioptr, iolen, string_ptr, string_len );