Fix for PR1654 - implement "movstrsi" pattern to copy simple blocks of memory.
[official-gcc.git] / libchill / format.c
blob22226f07b512a9b7626bee6ccbace374f1fe2e74
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* As a special exception, if you link this library with other files,
22 some of which are compiled with GCC, to produce an executable,
23 this library does not by itself cause the resulting executable
24 to be covered by the GNU General Public License.
25 This exception does not however invalidate any other reasons why
26 the executable file might be covered by the GNU General Public License. */
28 #include <limits.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <setjmp.h>
32 #include <float.h>
33 #include <math.h>
34 #include <stdlib.h>
35 #if _TEXTIO_DEBUG_
36 #include <stdio.h>
37 #endif
39 #include "bitstring.h"
40 #include "auxtypes.h"
41 #include "iomodes.h"
42 #include "format.h"
43 #include "fileio.h"
44 #include "ioerror.h"
46 #define CH_BYTE_MIN 0xffffff80L
47 #define CH_BYTE_MAX 0x0000007fL
48 #define CH_UBYTE_MAX 0x000000ffUL
49 #define CH_INT_MIN 0xffff8000L
50 #define CH_INT_MAX 0x00007fffL
51 #define CH_UINT_MAX 0x0000ffffUL
52 #define CH_LONG_MIN 0x80000000L
53 #define CH_LONG_MAX 0x7fffffffL
54 #define CH_ULONG_MAX 0xffffffffUL
56 #ifndef M_LN2
57 #define M_LN2 0.69314718055994530942
58 #endif
59 #ifndef M_LN10
60 #define M_LN10 2.30258509299404568402
61 #endif
63 #define DMANTDIGS (1 + (int)(DBL_MANT_DIG * M_LN2 / M_LN10))
64 #define FMANTDIGS (1 + (int)(FLT_MANT_DIG * M_LN2 / M_LN10))
66 /* float register length */
67 #define MAXPREC 40
69 #define LET 0x0001
70 #define BIN 0x0002
71 #define DEC 0x0004
72 #define OCT 0x0008
73 #define HEX 0x0010
74 #define USC 0x0020
75 #define BIL 0x0040
76 #define SPC 0x0080
77 #define SCS 0x0100
78 #define IOC 0x0200
79 #define EDC 0x0400
80 #define CVC 0x0800
82 #define isDEC(c) ( chartab[(c)] & DEC )
83 #define isCVC(c) ( chartab[(c)] & CVC )
84 #define isEDC(c) ( chartab[(c)] & EDC )
85 #define isIOC(c) ( chartab[(c)] & IOC )
86 #define isUSC(c)
87 #define isXXX(c,XXX) ( chartab[(c)] & XXX )
90 * local definitions
93 static
94 short int chartab[256] = {
95 0, 0, 0, 0, 0, 0, 0, 0,
96 0, SPC, SPC, SPC, SPC, SPC, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0,
101 SPC, IOC, 0, 0, 0, 0, 0, 0,
102 SCS, SCS, SCS, SCS+IOC, SCS, SCS+IOC, SCS, SCS+IOC,
103 BIN+OCT+DEC+HEX, BIN+OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX,
104 OCT+DEC+HEX, OCT+DEC+HEX, OCT+DEC+HEX,
105 DEC+HEX, DEC+HEX, SCS, SCS, SCS+EDC, SCS+IOC, SCS+EDC, IOC,
107 0, LET+HEX+BIL, LET+HEX+BIL+CVC, LET+HEX+BIL+CVC, LET+HEX+BIL, LET+HEX,
108 LET+HEX+CVC, LET,
109 LET+BIL+CVC, LET, LET, LET, LET, LET, LET, LET+CVC,
111 LET, LET, LET, LET, LET+EDC, LET, LET, LET,
112 LET+EDC, LET, LET, SCS, 0, SCS, 0, USC,
114 0, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET+HEX, LET,
115 LET, LET, LET, LET, LET, LET, LET, LET,
117 LET, LET, LET, LET, LET, LET, LET, LET,
118 LET, LET, LET, 0, 0, 0, 0, 0
121 typedef enum {
122 FormatText, FirstPercent, RepFact, ConvClause, EditClause, ClauseEnd,
123 AfterWidth, FractWidth, FractWidthCont, ExpoWidth, ExpoWidthCont,
124 ClauseWidth, CatchPadding, LastPercent
125 } fcsstate_t;
127 #define CONVERSIONCODES "CHOBF"
128 typedef enum {
129 DefaultConv, HexConv, OctalConv, BinaryConv, ScientConv
130 } convcode_t;
132 static
133 short int base[4] = { 10, 16, 8, 2 };
135 static
136 short int dset[4] = { DEC, HEX, OCT, BIN };
138 #define EDITCODES "X<>T"
139 typedef enum {
140 SpaceSkip, SkipLeft, SkipRight, Tabulation
141 } editcode_t;
143 #define IOCODES "/+-?!="
144 typedef enum {
145 NextRecord, NextPage, CurrentLine, Prompt, Emit, EndPage
146 } iocode_t;
148 typedef enum {
149 ConvAct, EditAct, IOAct
150 } acttype_t;
152 typedef enum {
153 NormalEnd, EndAtParen, TextFailEnd
154 } formatexit_t;
156 static
157 double ep_1[10] = {
158 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 };
159 static
160 double ep_10[10] = {
161 1e0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 };
162 static
163 double ep_100 = 1e100;
165 /* float register */
166 static
167 unsigned char floatdig[MAXPREC];
170 * global io variables
173 static Text_Mode* textptr = NULL;
174 static VarString* textrecptr;
176 static int actual_index;
177 static int maximum_index;
178 static int iolist_index;
180 static __tmp_IO_list* iolistptr;
181 static int iolistlen;
182 static char* iostrptr;
183 static int iostrlen;
186 static convcode_t convcode;
187 static editcode_t editcode;
188 static iocode_t iocode;
189 static unsigned long repetition;
190 static Boolean leftadjust;
191 static Boolean overflowev;
192 static Boolean dynamicwid;
193 static Boolean paddingdef;
194 static char paddingchar;
195 static Boolean fractiondef;
196 static unsigned long fractionwidth;
197 static Boolean exponentdef;
198 static unsigned long exponentwidth;
199 static unsigned long clausewidth;
200 static signed long textindex;
202 static
203 __tmp_IO_enum_table_type bool_tab[] =
204 { { 0, "FALSE" },
205 { 1, "TRUE" },
206 { 0 , NULL } };
209 * case insensitive compare: s1 is zero delimited, s2 has n chars
211 static
212 int casncmp( const char* s1, const char* s2, int n )
214 int res = 0;
215 while( n-- )
217 if( (res = toupper(*s1++) - toupper(*s2++)) )
218 return res;
220 return *s1;
224 * skip spaces with blank equal to tab
226 static
227 int skip_space( int limit )
229 int skipped = 0;
230 while( actual_index < limit &&
231 (iostrptr[actual_index] == ' ' || iostrptr[actual_index] == '\t' ) )
233 actual_index++;
234 skipped++;
236 return skipped;
240 * skip leading pad characters
242 static
243 int skip_pad( int limit )
245 int skipped = 0;
246 while( actual_index < limit && iostrptr[actual_index] == paddingchar )
248 actual_index++;
249 skipped++;
251 #if _TEXTIO_DEBUG_
252 printf( "skipping '%c' until %d: %d\n", paddingchar, limit, skipped );
253 #endif
254 return skipped;
258 * backup trailing pad characters
260 static
261 int piks_pad( int start, int limit )
263 int skipped = 0;
264 while( start >/***=*/ limit && iostrptr[--start] == paddingchar )
266 skipped++;
268 #if _TEXTIO_DEBUG_
269 printf( "piksing '%c' from %d until %d: %d\n",
270 paddingchar, start, limit, skipped );
271 #endif
272 return skipped;
276 * parse an integer
278 static
279 int parse_int( int limit, int SET, int base,
280 unsigned long* valptr, int* signptr )
282 int parsed = actual_index;
283 Boolean digits = False;
284 unsigned long value = 0;
285 char curr;
286 int dig;
288 if( actual_index >= limit )
289 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_INT );
290 *signptr = +1;
291 if( iostrptr[actual_index] == '+' )
292 actual_index++;
293 else
294 if( iostrptr[actual_index] == '-' )
295 { *signptr = -1;
296 actual_index++;
299 for( ; actual_index < limit; actual_index++ )
301 curr = iostrptr[actual_index];
302 if( curr == '_' ) continue;
303 if( isXXX(curr,SET) )
305 digits = True;
306 dig = curr <= '9' ? curr - '0' : toupper(curr) - 'A' + 10;
307 if( value > (ULONG_MAX - dig)/base )
308 IOEXCEPTION( TEXTFAIL, INT_VAL_OVERFLOW );
309 value = value*base + dig;
310 continue;
312 break;
314 if( !digits )
315 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_INT );
317 *valptr = value;
318 #if _TEXTIO_DEBUG_
319 printf( "parsing for int until %d, base %d: %u\n", limit, base, value );
320 #endif
321 return actual_index - parsed;
324 static
325 double
326 make_float( int dexp, int sign )
328 double value = atof( floatdig );
329 #if _TEXTIO_DEBUG_
330 printf( " value = %25.20e, dexp = %d\n", value, dexp );
331 #endif
332 while( dexp >= 100 )
333 value *= ep_100, dexp -= 100;
334 if( dexp >= 10 )
335 value *= ep_10[dexp/10], dexp %= 10;
336 if( dexp > 0 )
337 value *= ep_1[dexp];
339 while( dexp <= -100 )
340 value /= ep_100, dexp += 100;
341 if( dexp <= -10 )
342 value /= ep_10[-dexp/10], dexp %= 10;
343 if( dexp < 0 )
344 value /= ep_1[-dexp];
346 return sign ? -value : value;
349 /* %C -> fixed point [+|-]<digit>+[.<digit>*] */
350 static
351 int parse_fixedpoint( int limit, double* valptr )
353 int parsed = actual_index;
354 Boolean digits = False;
355 int sdig = 0;
356 double value;
357 char curr;
358 int sign = False;
359 int expo = 0;
361 if( actual_index >= limit )
362 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_FLOAT );
363 if( iostrptr[actual_index] == '+' )
364 actual_index++;
365 else
366 if( iostrptr[actual_index] == '-' )
368 sign = True;
369 actual_index++;
372 floatdig[0] = '.';
373 for( ; actual_index < limit; actual_index++ )
375 curr = iostrptr[actual_index];
376 if( ! isDEC(curr) )
377 break;
378 digits = True;
379 if( sdig < MAXPREC - 1 )
381 if( sdig || curr != '0' )
383 floatdig[++sdig] = curr;
384 expo++;
387 else
388 if( sdig )
389 expo++;
391 if( digits && curr == '.' )
393 actual_index++;
394 for( ; actual_index < limit; actual_index++ )
396 curr = iostrptr[actual_index];
397 if( !isDEC(curr) )
398 break;
399 if( sdig < MAXPREC - 1 )
401 if( sdig || curr != '0' )
402 floatdig[++sdig] = curr;
403 else
404 expo--;
408 floatdig[++sdig] = '\0';
410 if( !digits )
411 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT );
413 *valptr = make_float( expo, sign);
414 return actual_index - parsed;
418 typedef enum {
419 s_sign, s_dig, s_period, s_fraca, s_fracb, s_expo, s_exposign,
420 s_expoa, s_expob }
421 scient_t;
423 /* %C -> scientific [+|-]<digit>[.<digit>*]E[=|-]<digit>+ */
424 static
425 int parse_scientific( int limit, double* valptr, double dmin, double dmax )
427 int parsed = actual_index;
428 int sdig = 0;
429 char curr;
430 double value;
431 int sign = False;
432 int expo = 0;
433 int expo_sign = +1;
435 scient_t state = s_sign;
437 if( actual_index >= limit )
438 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_FLOAT );
440 floatdig[0] = '.';
441 for( ; actual_index < limit; actual_index++ )
443 curr = iostrptr[actual_index];
444 switch( state )
446 case s_sign:
447 if( iostrptr[actual_index] == '+' )
449 state = s_dig;
450 break;
452 if( iostrptr[actual_index] == '-' )
454 sign = True;
455 state = s_dig;
456 break;
458 /* fall through - no break */
459 case s_dig:
460 if( isDEC(curr) && curr > '0' )
462 floatdig[++sdig] = curr;
463 state = s_period;
464 break;
466 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT );
467 case s_period:
468 if( curr == '.' )
470 state = s_fraca;
471 break;
473 if( curr == 'E' )
475 state = s_exposign;
476 break;
478 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
479 case s_fraca:
480 if( isDEC(curr) )
482 floatdig[++sdig] = curr;
483 state = s_fracb;
484 break;
486 IOEXCEPTION( TEXTFAIL, NO_DIGITS_FOR_FLOAT );
487 case s_fracb:
488 if( isDEC(curr) )
490 if( sdig < MAXPREC - 1 )
491 floatdig[++sdig] = curr;
492 break;
494 if( curr == 'E' )
496 state = s_exposign;
497 break;
499 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
500 case s_exposign:
501 if( iostrptr[actual_index] == '+' )
503 state = s_expoa;
504 break;
506 if( iostrptr[actual_index] == '-' )
508 expo_sign = -1;
509 state = s_expoa;
510 break;
512 case s_expoa:
513 if( isDEC(curr) )
515 expo = curr - '0';
516 state = s_expob;
517 break;
519 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
520 case s_expob:
521 expo = expo*10 + (curr - '0');
522 if( expo > 1000 )
523 IOEXCEPTION( TEXTFAIL, REAL_OVERFLOW );
526 if( state != s_expob )
527 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
529 expo *= expo_sign;
530 expo++;
532 floatdig[++sdig] = '\0';
534 *valptr = make_float( expo, sign );
535 return actual_index - parsed;
539 static
540 int parse_set( int limit, __tmp_IO_enum_table_type* tabptr,
541 unsigned long* valptr )
543 int parsed = actual_index;
544 char curr;
545 __tmp_IO_enum_table_type* etptr;
547 if( actual_index >= limit )
548 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_SET );
550 curr = iostrptr[actual_index];
551 if( isXXX(curr,LET+USC) )
552 actual_index++;
553 else
554 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_SET );
556 for( ; actual_index < limit; actual_index++ )
558 if( ! isXXX(iostrptr[actual_index],LET+DEC+USC) )
559 break;
562 if( tabptr )
563 while( tabptr->name )
565 if( !casncmp( tabptr->name, &iostrptr[parsed], actual_index-parsed ) )
567 *valptr = tabptr->value;
568 #if _TEXTIO_DEBUG_
569 printf( "parsing set value until %d: %u\n", limit, tabptr->value );
570 #endif
571 return actual_index - parsed;
573 tabptr++;
575 IOEXCEPTION( TEXTFAIL, SET_CONVERSION_ERROR );
578 static
579 int parse_bit( int limit, char* bitptr )
581 int parsed = actual_index;
582 int i = 0;
583 char curr;
585 if( actual_index >= limit )
586 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_BOOLS );
588 for( ; actual_index < limit; actual_index++ )
590 curr = iostrptr[actual_index] - '0';
591 if( curr == 0 || curr == 1 )
592 /* __setbitinset( i++, bitptr, limit, curr ); */
593 __setbitpowerset (bitptr, limit, 0, i++, curr, __FILE__, __LINE__);
594 else
595 break;
597 return actual_index - parsed;
600 static
601 char* myultoa( unsigned long ul, char* buf, int base )
603 char* res = buf;
604 unsigned long h = ul/base;
605 unsigned long q = 1;
607 while( h >= q ) q *= base;
608 while( q > 0 )
610 *buf++ = "0123456789ABCDEF"[ul/q];
611 ul %= q;
612 q /= base;
614 *buf++ = '\0';
615 return res;
619 * convert a bit string from src, bit offset up to len
621 static
622 char* bitput( char* dst, char* src, int offset, int len )
624 char* res = dst;
625 int i;
626 for( i = offset; i < len; i++ )
628 *dst++ = __inpowerset( i, src, len, 0 ) ? '1' : '0';
630 return res;
634 * dround: round decimal register *digptr starting at digit mdigs,
635 * on carry advance begin of digit sequence and bump exponent
637 static
638 char*
639 dround( char* digptr, int mdigs, int* deptr )
641 int carry;
642 #if _TEXTIO_DEBUG_
643 printf( "Rounding from %d\n", mdigs );
644 #endif
645 if( digptr[mdigs] >= 5 )
647 carry = 1;
648 while( carry )
650 digptr[--mdigs]++;
651 if( digptr[mdigs] >= 10 )
652 digptr[mdigs] = 0;
653 else
654 carry = 0;
657 if( mdigs < 0 )
659 digptr[--mdigs] = 1;
660 (*deptr)++;
661 return digptr - 1;
663 else
664 return digptr;
668 * mydtoa: convert val with a precision of mantdigs to a decimal fraction
669 * first digit is at **fstdiptr, decimal exponent is at *deptr
671 static
672 char*
673 mydtoa( double val, int mantdigs, int* deptr, int* sgnptr )
675 double m;
676 int be;
677 int de = -1;
678 int fstdig = 0;
679 int idig;
680 char* digptr = floatdig+2;
682 floatdig[0] = floatdig[1] = 0;
684 if( val < 0 )
685 *sgnptr = -1, val = fabs( val );
686 else
687 *sgnptr = +1;
689 /* split the value */
690 m = frexp( val, &be ) * 10.0;
692 /* 5.0 <= m < 10.0 */
693 while( be > 0 )
695 de++; be--; m /= 5.0;
696 if( m < 1.0 )
697 m *= 10.0, de--;
699 while( be < 0 )
701 de--; be++; m *= 5.0;
702 if( m >= 10.0 )
703 m /= 10.0, de++;
706 for( idig = 0; idig < mantdigs; idig++ )
708 digptr[idig] = (int)m;
709 m = (m - digptr[idig])*10.0;
711 digptr[idig] = (int)m;
713 *deptr = de;
714 return dround( digptr, mantdigs, deptr );
717 #define PUT(c) \
718 { if( ifst <= ++iprt && iprt <= ilst ) *dst++ = c; }
720 static
721 char*
722 fixput( char* dst, char* src,
723 int ifst, int ilst,
724 int sign, int fst, int lst,
725 int nid, int nfd )
727 char* dstsav = dst;
728 int idig;
729 int iprt = 0;
731 if( sign < 0 )
732 PUT( '-' );
733 for( idig = nid; idig >= -nfd; idig-- )
735 if (idig == -1)
736 PUT( '.' );
737 PUT( idig > fst || lst >= idig ? '0': '0' + *src++ );
739 return dstsav;
742 static
743 char*
744 sciput( char* dst, char* src, char* expbeg,
745 int ifst, int ilst,
746 int sign, int de, int expwid )
748 char* dstsav = dst;
749 int iprt = 0;
750 int nfd = fractionwidth;
751 int explen = strlen( expbeg );
753 if( sign < 0 )
754 PUT( '-' );
755 PUT( '0' + *src++ );
756 PUT( '.' );
758 while( nfd-- )
759 PUT( '0' + *src++ );
760 PUT( 'E' );
761 PUT( de >= 0 ? '+' : '-' );
762 while( expwid > explen )
764 PUT( '0' );
765 expwid--;
767 while( explen-- )
768 PUT( *expbeg++ );
769 return dstsav;
773 * handle dynamic field width
775 static
776 get_field_width( void )
778 unsigned long width;
779 unsigned long ulongval;
780 long longval;
781 __tmp_IO_list io;
784 if( ++iolist_index > iolistlen )
785 IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED );
787 io = *iolistptr++;
789 /* must be integer, >= 0 */
790 switch( io.__descr )
792 case __IO_ByteVal:
793 longval = io.__t.__valbyte;
794 goto signed_fieldwidth;
795 case __IO_UByteVal:
796 width = io.__t.__valubyte;
797 goto unsigned_fieldwidth;
798 case __IO_IntVal:
799 longval = io.__t.__valint;
800 goto signed_fieldwidth;
801 case __IO_UIntVal:
802 width = io.__t.__valuint;
803 goto unsigned_fieldwidth;
804 case __IO_LongVal:
805 longval = io.__t.__vallong;
806 goto signed_fieldwidth;
807 case __IO_ULongVal:
808 width = io.__t.__valulong;
809 goto unsigned_fieldwidth;
810 case __IO_ByteLoc:
811 longval = *(signed char*)io.__t.__locint;
812 goto signed_fieldwidth;
813 case __IO_UByteLoc:
814 width = *(unsigned char*)io.__t.__locint;
815 goto unsigned_fieldwidth;
816 case __IO_IntLoc:
817 longval = *(signed short*)io.__t.__locint;
818 goto signed_fieldwidth;
819 case __IO_UIntLoc:
820 width = *(unsigned short*)io.__t.__locint;
821 goto unsigned_fieldwidth;
822 case __IO_LongLoc:
823 longval = *(signed long*) io.__t.__locint;
824 goto signed_fieldwidth;
825 case __IO_ULongLoc:
826 width = *(unsigned long*)io.__t.__locint;
827 goto unsigned_fieldwidth;
828 default:
829 IOEXCEPTION( TEXTFAIL, NON_INT_FIELD_WIDTH );
832 signed_fieldwidth: ;
833 if( longval < 0 )
834 IOEXCEPTION( TEXTFAIL, NEGATIVE_FIELD_WIDTH );
835 width = longval;
837 unsigned_fieldwidth: ;
838 return width;
842 static
843 void inpconv( void )
845 __tmp_IO_list io;
846 int width;
847 int limit;
848 int skiplim;
849 int skipped;
850 int bypass;
851 int parsed;
852 Boolean fixedchars;
853 int fixedlen;
854 unsigned char curr;
855 double dval;
856 float fval;
858 __tmp_IO_long lval;
859 int sign;
860 unsigned long umin;
861 unsigned long umax;
862 signed long smin;
863 signed long smax;
864 int ilen;
865 short unsigned slen;
866 __tmp_IO_enum_table_type* settabptr;
868 while( repetition-- )
870 if( ++iolist_index > iolistlen )
871 IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED );
873 io = *iolistptr++;
875 if( dynamicwid )
876 width = get_field_width();
877 else
878 width = clausewidth;
880 bypass = skipped = 0;
881 if( width )
883 if( actual_index + width > iostrlen )
884 IOEXCEPTION( TEXTFAIL, NOT_ENOUGH_CHARS );
886 switch(io.__descr)
888 case __IO_CharLoc:
889 case __IO_CharRangeLoc:
890 fixedchars = True;
891 fixedlen = 1;
892 break;
893 case __IO_CharStrLoc:
894 fixedchars = True;
895 fixedlen = io.__t.__loccharstring.string_length;
896 break;
897 default:
898 fixedchars = False;
899 break;
902 if( leftadjust )
904 skiplim = fixedchars ? actual_index + fixedlen
905 : actual_index;
906 bypass = skipped = piks_pad( actual_index + width, skiplim );
908 else
910 skiplim = fixedchars ? actual_index + width - fixedlen
911 : actual_index + width;
912 skipped = skip_pad( skiplim );
914 width -= skipped;
915 limit = actual_index + width;
917 else
918 { /* free format */
919 if( paddingdef || !( io.__descr == __IO_CharLoc ||
920 io.__descr == __IO_CharRangeLoc ||
921 io.__descr == __IO_CharStrLoc ||
922 io.__descr == __IO_CharVaryingLoc ) )
923 if( paddingchar == ' ' || paddingchar == '\t' )
924 skip_space( iostrlen );
925 else
926 skip_pad( iostrlen );
927 limit = iostrlen;
930 switch( io.__descr )
932 case __IO_ByteLoc:
933 ilen = 1;
934 smin = CH_BYTE_MIN;
935 smax = CH_BYTE_MAX;
936 goto parse_signed_int;
937 case __IO_UByteLoc:
938 ilen = 1;
939 umin = 0;
940 umax = CH_UBYTE_MAX;
941 goto parse_unsigned_int;
942 case __IO_IntLoc:
943 ilen = 2;
944 smin = CH_INT_MIN;
945 smax = CH_INT_MAX;
946 goto parse_signed_int;
947 case __IO_UIntLoc:
948 ilen = 2;
949 umin = 0;
950 umax = CH_UINT_MAX;
951 goto parse_unsigned_int;
952 case __IO_LongLoc:
953 ilen = 4;
954 smin = CH_LONG_MIN;
955 smax = CH_LONG_MAX;
956 goto parse_signed_int;
957 case __IO_ULongLoc:
958 ilen = 4;
959 umin = 0;
960 umax = CH_ULONG_MAX;
961 goto parse_unsigned_int;
963 case __IO_ByteRangeLoc:
964 ilen = 1;
965 smin = io.__t.__locintrange.lower.slong;
966 smax = io.__t.__locintrange.upper.slong;
967 goto parse_signed_int;
968 case __IO_UByteRangeLoc:
969 ilen = 1;
970 umin = io.__t.__locintrange.lower.ulong;
971 umax = io.__t.__locintrange.upper.ulong;
972 goto parse_unsigned_int;
973 case __IO_IntRangeLoc:
974 ilen = 2;
975 smin = io.__t.__locintrange.lower.slong;
976 smax = io.__t.__locintrange.upper.slong;
977 goto parse_signed_int;
978 case __IO_UIntRangeLoc:
979 ilen = 2;
980 umin = io.__t.__locintrange.lower.ulong;
981 umax = io.__t.__locintrange.upper.ulong;
982 goto parse_unsigned_int;
983 case __IO_LongRangeLoc:
984 ilen = 4;
985 smin = io.__t.__locintrange.lower.slong;
986 smax = io.__t.__locintrange.upper.slong;
987 goto parse_signed_int;
988 case __IO_ULongRangeLoc:
989 ilen = 4;
990 umin = io.__t.__locintrange.lower.ulong;
991 umax = io.__t.__locintrange.upper.ulong;
992 goto parse_unsigned_int;
994 case __IO_BoolLoc:
995 ilen = 1;
996 umin = 0;
997 umax = 1;
998 settabptr = bool_tab;
999 goto parse_set;
1000 case __IO_BoolRangeLoc:
1001 ilen = 1;
1002 umin = io.__t.__locboolrange.lower;
1003 umax = io.__t.__locboolrange.upper;
1004 settabptr = bool_tab;
1005 goto parse_set;
1007 case __IO_SetLoc:
1008 ilen = io.__t.__locsetrange.length;
1009 settabptr = io.__t.__locsetrange.name_table;
1010 umin = 0;
1011 umax = CH_ULONG_MAX;
1012 goto parse_set;
1013 case __IO_SetRangeLoc:
1014 ilen = io.__t.__locsetrange.length;
1015 settabptr = io.__t.__locsetrange.name_table;
1016 umin = io.__t.__locsetrange.lower;
1017 umax = io.__t.__locsetrange.upper;
1018 goto parse_set;
1020 case __IO_CharLoc:
1021 umin = 0;
1022 umax = 0xff;
1023 goto parse_char;
1024 case __IO_CharRangeLoc:
1025 umin = io.__t.__loccharrange.lower;
1026 umax = io.__t.__loccharrange.upper;
1027 goto parse_char;
1029 case __IO_CharVaryingLoc:
1030 if( convcode != DefaultConv )
1031 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1032 slen = io.__t.__loccharstring.string_length;
1033 if( (parsed = limit - actual_index) < slen )
1034 slen = parsed;
1035 else
1036 parsed = slen;
1037 memcpy( io.__t.__loccharstring.string + 2,
1038 &iostrptr[actual_index], parsed );
1039 MOV2(io.__t.__loccharstring.string,&slen);
1040 actual_index += parsed;
1041 goto check_field_complete;
1044 case __IO_CharStrLoc:
1045 if( convcode != DefaultConv )
1046 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1047 if( actual_index + io.__t.__loccharstring.string_length > limit )
1048 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_CHARS );
1049 memcpy( io.__t.__loccharstring.string,
1050 &iostrptr[actual_index],
1051 parsed = io.__t.__loccharstring.string_length );
1052 actual_index += parsed;
1053 goto check_field_complete;
1055 case __IO_BitStrLoc:
1056 if( convcode != DefaultConv )
1057 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1058 parsed = parse_bit( limit, io.__t.__loccharstring.string );
1059 if( parsed < io.__t.__loccharstring.string_length )
1060 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_BOOLS );
1061 goto check_field_complete;
1063 case __IO_LongRealLoc:
1064 case __IO_RealLoc:
1065 switch( convcode )
1067 case ScientConv:
1068 parse_scientific( limit, &dval, DBL_MIN, DBL_MAX );
1069 break;
1070 case DefaultConv:
1071 parse_fixedpoint( limit, &dval );
1072 break;
1073 default:
1074 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1076 if( io.__descr == __IO_LongRealLoc )
1077 memcpy( io.__t.__loclongreal, &dval, sizeof(double) );
1078 else
1080 fval = (float)dval;
1081 MOV4(io.__t.__locreal,&fval);
1083 goto check_field_complete;
1084 default:
1085 IOEXCEPTION( TEXTFAIL, INVALID_IO_LIST );
1089 parse_signed_int: ;
1090 if( convcode == ScientConv )
1091 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1092 parsed = parse_int( limit, dset[convcode], base[convcode],
1093 &lval.ulong, &sign );
1094 if( sign < 0 )
1096 if( lval.ulong > (unsigned long)CH_LONG_MIN )
1097 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1098 lval.slong = -lval.ulong;
1100 else
1102 /* not needed: lval.slong = lval.ulong; */
1103 /* Hack: sign extension for bin/oct/dec if no sign present */
1104 if( convcode != DefaultConv && lval.ulong & (1 << (ilen*8-1)) )
1106 if( ilen < 4 )
1107 lval.ulong |= 0xFFFFFFFF << ilen*8;
1109 else
1110 if( lval.ulong > (unsigned long)CH_LONG_MAX )
1111 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1113 if( lval.slong < smin || smax < lval.slong )
1114 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1115 goto store_int;
1117 parse_unsigned_int: ;
1118 if( convcode == ScientConv )
1119 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1120 parsed = parse_int( limit, dset[convcode], base[convcode],
1121 &lval.ulong, &sign );
1122 if( sign < 0 || lval.ulong < umin || umax < lval.ulong )
1123 IOEXCEPTION( TEXTFAIL, INTEGER_RANGE_ERROR );
1124 goto store_int;
1126 parse_set: ;
1127 if( convcode != DefaultConv )
1128 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1129 parsed = parse_set( limit, settabptr, &lval.ulong );
1130 if( lval.ulong < umin || umax < lval.ulong )
1131 IOEXCEPTION( TEXTFAIL, SET_RANGE_ERROR );
1132 goto store_int;
1134 store_int: ;
1135 switch( ilen )
1137 case 1:
1138 *(unsigned char*)io.__t.__locint = lval.ulong;
1139 break;
1140 case 2:
1141 slen = lval.ulong;
1142 MOV2(io.__t.__locint,&slen);
1143 break;
1144 case 4:
1145 MOV4(io.__t.__locint,&lval.ulong);
1146 break;
1147 default:
1148 IOEXCEPTION( TEXTFAIL, INTERNAL_ERROR );
1150 goto check_field_complete;
1152 parse_char: ;
1153 if( convcode != DefaultConv )
1154 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1155 if( actual_index >= limit )
1156 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_CHARS );
1157 curr = iostrptr[actual_index++];
1158 parsed = 1;
1159 if( curr < umin || umax < curr )
1160 IOEXCEPTION( TEXTFAIL, CHAR_RANGE_ERROR );
1161 *io.__t.__locchar = curr;
1162 goto check_field_complete;
1164 check_field_complete: ;
1165 actual_index += bypass;
1166 if( width > parsed )
1167 IOEXCEPTION( TEXTFAIL, INVALID_CHAR );
1171 static
1172 void inpedit( void )
1174 int nchars;
1176 if( dynamicwid )
1177 clausewidth = get_field_width();
1179 switch( editcode )
1181 case SpaceSkip:
1182 nchars = repetition*clausewidth;
1183 if( actual_index + nchars > iostrlen )
1184 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT );
1185 for( ; nchars ; nchars-- )
1186 if( iostrptr[actual_index++] != ' ' )
1187 IOEXCEPTION( TEXTFAIL, NO_SPACE_TO_SKIP );
1188 break;
1190 case SkipLeft:
1191 nchars = repetition*clausewidth;
1192 if( (actual_index -= nchars) < 0 )
1193 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT );
1194 break;
1196 case SkipRight:
1197 nchars = repetition*clausewidth;
1198 if( (actual_index += nchars) > iostrlen )
1199 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_EDIT );
1200 break;
1202 case Tabulation:
1203 if( (actual_index = clausewidth) > iostrlen )
1204 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1205 break;
1209 static
1210 void outconv( void )
1212 unsigned long width;
1213 char itembuf[33];
1214 unsigned long ulongval;
1215 long longval;
1216 __tmp_IO_list io;
1217 __tmp_IO_enum_table_type* etptr;
1218 char* itembeg;
1219 unsigned long itemlen;
1220 double doubleval;
1221 int de;
1222 int sign;
1223 int mantdigs;
1224 int nid;
1225 int nfd;
1226 char* expbeg;
1227 int explen;
1228 unsigned int expwid;
1230 while( repetition-- )
1232 if( ++iolist_index > iolistlen )
1233 IOEXCEPTION( TEXTFAIL, IOLIST_EXHAUSTED );
1235 io = *iolistptr++;
1236 width = dynamicwid ? get_field_width() : clausewidth;
1238 switch( convcode )
1240 case DefaultConv:
1241 switch( io.__descr )
1243 case __IO_ByteVal:
1244 longval = io.__t.__valbyte;
1245 goto signed_conversion;
1246 case __IO_UByteVal:
1247 ulongval = io.__t.__valubyte;
1248 goto unsigned_conversion;
1249 case __IO_IntVal:
1250 longval = io.__t.__valint;
1251 goto signed_conversion;
1252 case __IO_UIntVal:
1253 ulongval = io.__t.__valuint;
1254 goto unsigned_conversion;
1255 case __IO_LongVal:
1256 longval = io.__t.__vallong;
1257 goto signed_conversion;
1258 case __IO_ULongVal:
1259 ulongval = io.__t.__valulong;
1260 goto unsigned_conversion;
1262 case __IO_BoolVal:
1263 switch( io.__t.__valbool )
1265 case 0:
1266 itembeg = "FALSE";
1267 itemlen = 5;
1268 goto move_item;
1269 case 1:
1270 itembeg = "TRUE";
1271 itemlen = 4;
1272 goto move_item;
1273 default:
1274 IOEXCEPTION( TEXTFAIL, BOOL_CONVERSION_ERROR );
1277 case __IO_CharVal:
1278 itembeg = &io.__t.__valchar;
1279 itemlen = 1;
1280 goto move_item;
1282 case __IO_SetVal:
1283 /* locate name string using set mode name table */
1284 itembeg = 0;
1286 if( (etptr = io.__t.__valset.name_table) )
1287 while( etptr->name )
1289 if( etptr->value == io.__t.__valset.value )
1291 itembeg = etptr->name;
1292 itemlen = strlen( itembeg );
1293 goto move_item;
1295 etptr++;
1297 IOEXCEPTION( TEXTFAIL, SET_CONVERSION_ERROR );
1299 case __IO_CharVaryingLoc:
1301 unsigned short l;
1302 itembeg = (char*)io.__t.__loccharstring.string;
1303 MOV2(&l,itembeg);
1304 itembeg += 2;
1305 itemlen = l;
1306 goto move_item;
1309 case __IO_CharStrLoc:
1310 itembeg = io.__t.__loccharstring.string;
1311 itemlen = io.__t.__loccharstring.string_length;
1312 goto move_item;
1314 case __IO_BitStrLoc:
1315 itemlen = io.__t.__loccharstring.string_length;
1316 itembeg = io.__t.__loccharstring.string;
1318 if( !width )
1319 width = itemlen;
1321 /* check remaining space */
1322 if( actual_index + width > iostrlen )
1323 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1325 if( itemlen == width )
1326 bitput( iostrptr + actual_index, itembeg, 0, itemlen );
1327 else
1328 if( itemlen < width )
1329 if( leftadjust )
1330 memset( bitput( iostrptr + actual_index, itembeg, 0, itemlen )
1331 + itemlen,
1332 paddingchar, width - itemlen );
1333 else
1334 bitput( memset( iostrptr + actual_index,
1335 paddingchar, width - itemlen )
1336 + width - itemlen,
1337 itembeg, itemlen - width, itemlen );
1338 else
1339 if( overflowev )
1340 memset( iostrptr + actual_index, '*', width );
1341 else
1342 if( leftadjust )
1343 bitput( iostrptr + actual_index, itembeg, 0, width );
1344 else
1345 bitput( iostrptr + actual_index, itembeg,
1346 itemlen - width, itemlen );
1347 goto adjust_index;
1349 case __IO_RealVal:
1350 doubleval = io.__t.__valreal;
1351 mantdigs = FMANTDIGS;
1352 goto fixed_point_conversion;
1353 case __IO_LongRealVal:
1354 doubleval = io.__t.__vallongreal;
1355 mantdigs = DBL_DIG;
1356 goto fixed_point_conversion;
1357 break;
1359 default:
1360 IOEXCEPTION( TEXTFAIL, INVALID_IO_LIST );
1363 case HexConv:
1364 case OctalConv:
1365 case BinaryConv:
1366 switch( io.__descr )
1368 case __IO_ByteVal:
1369 case __IO_UByteVal:
1370 ulongval = io.__t.__valubyte;
1371 break;
1372 case __IO_IntVal:
1373 case __IO_UIntVal:
1374 ulongval = io.__t.__valuint;
1375 break;
1376 case __IO_LongVal:
1377 case __IO_ULongVal:
1378 ulongval = io.__t.__valulong;
1379 break;
1380 default:
1381 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1383 itembeg = myultoa( ulongval, itembuf, base[convcode] );
1384 itemlen = strlen( itembeg );
1385 goto move_item;
1387 case ScientConv:
1388 switch( io.__descr )
1390 case __IO_RealVal:
1391 doubleval = io.__t.__valreal;
1392 mantdigs = FMANTDIGS;
1393 if( !fractiondef )
1394 fractionwidth = FMANTDIGS - 1;
1395 goto scientific_conversion;
1396 case __IO_LongRealVal:
1397 doubleval = io.__t.__vallongreal;
1398 mantdigs = DBL_DIG;
1399 if( !fractiondef )
1400 fractionwidth = DBL_DIG - 1;
1401 goto scientific_conversion;
1402 break;
1403 default:
1404 IOEXCEPTION( TEXTFAIL, CONVCODE_MODE_MISFIT );
1408 fixed_point_conversion: ;
1409 itembeg = mydtoa( doubleval, mantdigs, &de, &sign );
1410 if( fractiondef && de >= -fractionwidth - 1
1411 && -fractionwidth > de - mantdigs )
1412 itembeg = dround( itembeg, de + fractionwidth + 1, &de );
1414 nid = de >= 0 ? de : 0;
1415 nfd = fractiondef ? fractionwidth
1416 : ( de + 1 - mantdigs > 0 ? 0 : mantdigs - de - 1 );
1417 itemlen = ( sign < 0 ? 1 : 0 ) + 2 + nid + nfd;
1418 #if _TEXTIO_DEBUG_
1419 printf( "fixed item length %d\n", itemlen );
1420 #endif
1421 if( !width )
1422 width = itemlen;
1423 #if _TEXTIO_DEBUG_
1424 printf( "fixed item width %d\n", width );
1425 #endif
1426 /* check remaining space */
1427 if( actual_index + width > iostrlen )
1428 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1430 if( itemlen == width )
1431 fixput( iostrptr + actual_index, itembeg,
1432 1, itemlen, sign, de, de - mantdigs, nid, nfd );
1433 else
1434 if( itemlen < width )
1435 if( leftadjust )
1436 memset( fixput( iostrptr + actual_index, itembeg,
1437 1, itemlen, sign, de, de - mantdigs, nid, nfd )
1438 + itemlen,
1439 paddingchar, width - itemlen );
1440 else
1441 fixput( memset( iostrptr + actual_index,
1442 paddingchar, width - itemlen )
1443 + width - itemlen,
1444 itembeg, 1, itemlen, sign, de, de - mantdigs, nid, nfd );
1445 else
1446 if( overflowev )
1447 memset( iostrptr + actual_index, '*', width );
1448 else
1449 if( leftadjust )
1450 fixput( iostrptr + actual_index, itembeg,
1451 1, width, sign, de, de - mantdigs, nid, nfd );
1452 else
1453 fixput( iostrptr + actual_index, itembeg,
1454 itemlen - width + 1, itemlen,
1455 sign, de, de - mantdigs, nid, nfd );
1456 goto adjust_index;
1458 scientific_conversion: ;
1459 itembeg = mydtoa( doubleval, mantdigs, &de, &sign );
1461 if( fractiondef && fractionwidth < mantdigs )
1462 itembeg = dround( itembeg, fractionwidth + 1, &de );
1464 expbeg = myultoa( abs(de), itembuf, 10 );
1465 explen = strlen( expbeg );
1467 expwid = explen > exponentwidth ? explen : exponentwidth;
1468 itemlen = ( sign < 0 ? 1 : 0 ) + 2 + fractionwidth + 2 + expwid;
1469 #if _TEXTIO_DEBUG_
1470 printf( "floating item length %d, fraction %d, exponent %d\n",
1471 itemlen, fractionwidth, expwid );
1472 #endif
1473 if( width == 0 )
1474 width = itemlen;
1475 #if _TEXTIO_DEBUG_
1476 printf( "floating item width %d\n", width );
1477 #endif
1478 /* check remaining space */
1479 if( actual_index + width > iostrlen )
1480 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1482 if( itemlen == width )
1483 sciput( iostrptr + actual_index, itembeg, expbeg,
1484 1, itemlen, sign, de, expwid );
1485 else
1486 if( itemlen < width )
1487 if( leftadjust )
1488 memset( sciput( iostrptr + actual_index, itembeg, expbeg,
1489 1, itemlen, sign, de, expwid )
1490 + itemlen,
1491 paddingchar, width - itemlen );
1492 else
1493 sciput( memset( iostrptr + actual_index,
1494 paddingchar, width - itemlen )
1495 + width - itemlen,
1496 itembeg, expbeg, 1, itemlen, sign, de, expwid );
1497 else
1498 if( overflowev )
1499 memset( iostrptr + actual_index, '*', width );
1500 else
1501 if( leftadjust )
1502 sciput( iostrptr + actual_index, itembeg, expbeg,
1503 1, width, sign, de, expwid );
1504 else
1505 sciput( iostrptr + actual_index, itembeg, expbeg,
1506 itemlen - width + 1, itemlen,
1507 sign, de, expwid );
1508 goto adjust_index;
1510 signed_conversion: ;
1511 if( longval >= 0 )
1512 itembeg = myultoa( longval, itembuf, 10 );
1513 else
1515 itembuf[0] = '-';
1516 myultoa( -longval, itembuf+1, 10 );
1517 itembeg = itembuf;
1519 itemlen = strlen( itembeg );
1520 goto move_item;
1522 unsigned_conversion: ;
1523 itembeg = myultoa( ulongval, itembuf, 10 );
1524 itemlen = strlen( itembeg );
1525 goto move_item;
1527 move_item: ;
1528 if( !width )
1529 width = itemlen;
1531 /* check remaining space */
1532 if( actual_index + width > iostrlen )
1533 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1535 /* move item, filling or truncating or overflow-evidencing */
1536 if( itemlen == width )
1537 memcpy( iostrptr + actual_index, itembeg, itemlen );
1538 else
1539 if( itemlen < width )
1540 if( leftadjust )
1541 memset( memcpy( iostrptr + actual_index, itembeg, itemlen )
1542 + itemlen,
1543 paddingchar, width - itemlen );
1544 else
1545 memcpy( memset( iostrptr + actual_index,
1546 paddingchar, width - itemlen )
1547 + width - itemlen,
1548 itembeg, itemlen );
1549 else
1550 if( overflowev )
1551 memset( iostrptr + actual_index, '*', width );
1552 else
1553 if( leftadjust )
1554 memcpy( iostrptr + actual_index, itembeg, width );
1555 else
1556 memcpy( iostrptr + actual_index,
1557 itembeg + itemlen - width, width );
1560 * adjust.
1562 adjust_index: ;
1563 actual_index += width;
1564 if( actual_index > maximum_index )
1565 maximum_index = actual_index;
1569 static
1570 void outedit( void )
1572 int nchars;
1574 if( dynamicwid )
1575 clausewidth = get_field_width();
1576 switch( editcode )
1578 case SpaceSkip:
1579 nchars = repetition*clausewidth;
1580 if( actual_index + nchars > iostrlen )
1581 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1582 memset( iostrptr + actual_index, ' ', nchars );
1583 actual_index += nchars;
1584 if( actual_index > maximum_index )
1585 maximum_index = actual_index;
1586 break;
1588 case SkipLeft:
1589 nchars = repetition*clausewidth;
1590 if( actual_index - nchars < 0 )
1591 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1592 actual_index -= nchars;
1593 break;
1595 case SkipRight:
1596 nchars = repetition*clausewidth;
1597 if( actual_index + nchars > iostrlen )
1598 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1599 actual_index += nchars;
1600 if( actual_index > maximum_index )
1602 memset( iostrptr + maximum_index, ' ', actual_index - maximum_index );
1603 maximum_index = actual_index;
1605 break;
1607 case Tabulation:
1608 if( clausewidth >= iostrlen )
1609 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1610 actual_index = clausewidth;
1611 if( actual_index > maximum_index )
1613 memset( iostrptr + maximum_index, ' ', actual_index - maximum_index );
1614 maximum_index = actual_index;
1616 break;
1621 static
1622 void inpioctrl( void )
1624 unsigned short hlen;
1625 if( !textptr )
1626 IOEXCEPTION( TEXTFAIL, IO_CONTROL_NOT_VALID );
1627 if( iocode != EndPage )
1629 jmp_buf ioerror;
1630 unsigned long info;
1632 if (textptr->access_sub->association)
1634 if( (info = setjmp( ioerror )) )
1635 IOEXCEPTION( info>>16, info & 0xffff );
1636 while( repetition-- )
1638 __readrecord( textptr->access_sub, textindex,
1639 (char*)textptr->text_record,
1640 __FILE__, __LINE__ );
1641 actual_index = 0;
1642 MOV2(&hlen,&textptr->text_record->len);
1643 iostrlen = hlen;
1646 else
1647 IOEXCEPTION (NOTCONNECTED, IS_NOT_CONNECTED);
1651 /* specify pre/post in the order "/+-?!" */
1652 static
1653 char* pre_char = "\0\f\0\r\0"; /* Z.200: "\n\f\0\n\0" */
1654 static
1655 char* post_char = "\n\n\r\0\0"; /* Z.200: "\r\r\r\0\0" */
1657 static
1658 void outioctrl( void )
1660 Association_Mode* assoc;
1661 unsigned short hlen;
1662 if( !textptr )
1663 IOEXCEPTION( TEXTFAIL, IO_CONTROL_NOT_VALID );
1664 if( (assoc = textptr->access_sub->association) )
1666 jmp_buf ioerror;
1667 unsigned long info;
1668 if( (info = setjmp( ioerror )) )
1669 IOEXCEPTION( info>>16, info & 0xffff );
1671 while( repetition-- )
1673 if( iocode != EndPage )
1675 if( TEST_FLAG( assoc, IO_FIRSTLINE ) )
1677 CLR_FLAG( assoc, IO_FIRSTLINE );
1678 assoc->ctl_pre = '\0';
1680 else
1682 if( TEST_FLAG( assoc, IO_FORCE_PAGE ) )
1684 CLR_FLAG( assoc, IO_FORCE_PAGE );
1685 assoc->ctl_pre = '\f';
1687 else
1688 assoc->ctl_pre = pre_char[iocode];
1690 assoc->ctl_post = post_char[iocode];
1691 hlen = actual_index;
1692 MOV2(&textptr->text_record->len,&hlen);
1693 __writerecord( textptr->access_sub, textindex,
1694 (char*)textptr->text_record,
1695 textptr->text_record->len,
1696 __FILE__, __LINE__ );
1697 hlen = actual_index = 0;
1698 MOV2(&textptr->text_record->len,&hlen);
1700 else if( !TEST_FLAG( textptr, IO_FIRSTLINE ) )
1701 SET_FLAG( textptr, IO_FORCE_PAGE );
1702 assoc->ctl_pre = assoc->ctl_post = '\0';
1705 else
1706 IOEXCEPTION (NOTCONNECTED, IS_NOT_CONNECTED);
1709 static
1710 void (**actionptr)( void );
1711 static
1712 void (*readactions[])( void ) = { inpconv, inpedit, inpioctrl };
1713 static
1714 void (*writeactions[])( void ) = { outconv, outedit, outioctrl };
1717 static
1718 void emitstr( char* begtxt, char* endtxt )
1720 char c;
1721 int nchars = endtxt - begtxt;
1722 if( actual_index + nchars > iostrlen )
1723 IOEXCEPTION( TEXTFAIL, TEXT_LOC_OVERFLOW );
1724 memcpy( iostrptr + actual_index, begtxt, nchars );
1725 actual_index += nchars;
1726 if( actual_index > maximum_index )
1727 maximum_index = actual_index;
1730 static
1731 void scanstr( char* begtxt, char* endtxt )
1733 int nchars = endtxt - begtxt;
1734 if( actual_index + nchars > iostrlen )
1735 IOEXCEPTION( TEXTFAIL, NO_CHARS_FOR_TEXT );
1736 if( strncmp( iostrptr + actual_index, begtxt, nchars ) )
1737 IOEXCEPTION( TEXTFAIL, FORMAT_TEXT_MISMATCH );
1738 actual_index += nchars;
1741 void (*ftextptr) ( char*, char* );
1743 static
1744 formatexit_t scanformcont( char* fcs, int len,
1745 char** fcsptr, int* lenptr )
1747 char curr;
1748 fcsstate_t state = FormatText;
1749 unsigned long buf;
1750 int dig;
1751 acttype_t action;
1752 char* begtxt = fcs;
1754 while( len-- )
1756 curr = *fcs++;
1757 switch( state )
1759 case FormatText:
1760 if( curr == '%' )
1762 ftextptr( begtxt, fcs-1 );
1763 state = FirstPercent;
1765 break;
1767 after_first_percent: ;
1768 case FirstPercent:
1769 if( curr == '%' )
1771 state = FormatText;
1772 begtxt = fcs - 1;
1773 break;
1775 if( curr == ')' )
1777 *lenptr = len;
1778 *fcsptr = fcs;
1779 return EndAtParen;
1781 if( isDEC(curr) )
1783 state = RepFact;
1784 repetition = curr - '0';
1785 break;
1788 repetition = 1;
1790 test_for_control_codes: ;
1791 if( isCVC(curr) )
1793 state = ConvClause;
1794 action = ConvAct;
1795 convcode = strchr( CONVERSIONCODES, curr ) - CONVERSIONCODES;
1796 leftadjust = False;
1797 overflowev = False;
1798 dynamicwid = False;
1799 paddingdef = False;
1800 paddingchar = ' ';
1801 fractiondef = False;
1802 /* fractionwidth = 0; default depends on mode ! */
1803 exponentdef = False;
1804 exponentwidth = 3;
1805 clausewidth = 0;
1806 break;
1808 if( isEDC(curr) )
1810 state = EditClause;
1811 action = EditAct;
1812 editcode = strchr( EDITCODES, curr ) - EDITCODES;
1813 dynamicwid = False;
1814 clausewidth = editcode == Tabulation ? 0 : 1;
1815 break;
1817 if( isIOC(curr) )
1819 state = ClauseEnd;
1820 action = IOAct;
1821 iocode = strchr( IOCODES, curr ) - IOCODES;
1822 break;
1824 if( curr == '(' )
1826 unsigned long times = repetition;
1827 int cntlen;
1828 char* cntfcs;
1829 while( times-- )
1831 if( scanformcont( fcs, len, &cntfcs, &cntlen ) != EndAtParen )
1832 IOEXCEPTION( TEXTFAIL, UNMATCHED_OPENING_PAREN );
1834 fcs = cntfcs;
1835 len = cntlen;
1836 state = FormatText;
1837 begtxt = fcs;
1838 break;
1840 IOEXCEPTION( TEXTFAIL, BAD_FORMAT_SPEC_CHAR );
1842 case RepFact:
1843 if( isDEC(curr) )
1845 dig = curr - '0';
1846 if( repetition > (ULONG_MAX - dig)/10 )
1847 IOEXCEPTION( TEXTFAIL, REPFAC_OVERFLOW );
1848 repetition = repetition*10 + dig;
1849 break;
1851 goto test_for_control_codes;
1853 case ConvClause:
1854 if( isDEC(curr) )
1856 state = ClauseWidth;
1857 clausewidth = curr - '0';
1858 break;
1860 if( curr == 'L' )
1862 if( leftadjust )
1863 IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER );
1864 leftadjust = True;
1865 break;
1867 if( curr == 'E' )
1869 if( overflowev )
1870 IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER );
1871 overflowev = True;
1872 break;
1874 if( curr == 'P' )
1876 if( paddingdef )
1877 IOEXCEPTION( TEXTFAIL, DUPLICATE_QUALIFIER );
1878 paddingdef = True;
1879 state = CatchPadding;
1880 break;
1883 test_for_variable_width: ;
1884 if( curr == 'V' )
1886 dynamicwid = True;
1887 state = AfterWidth;
1888 break;
1890 goto test_for_fraction_width;
1892 case ClauseWidth:
1893 if( isDEC(curr) )
1895 dig = curr - '0';
1896 if( clausewidth > (ULONG_MAX - dig)/10 )
1897 IOEXCEPTION( TEXTFAIL, CLAUSE_WIDTH_OVERFLOW );
1898 clausewidth = clausewidth*10 + dig;
1899 break;
1901 /* fall through */
1903 test_for_fraction_width: ;
1904 case AfterWidth:
1905 if( curr == '.' )
1907 if( convcode != DefaultConv && convcode != ScientConv )
1908 IOEXCEPTION( TEXTFAIL, NO_FRACTION );
1909 fractiondef = True;
1910 state = FractWidth;
1911 break;
1913 goto test_for_exponent_width;
1915 case FractWidth:
1916 if( isDEC( curr ) )
1918 state = FractWidthCont;
1919 fractionwidth = curr - '0';
1920 break;
1922 else
1923 IOEXCEPTION( TEXTFAIL, NO_FRACTION_WIDTH );
1925 case FractWidthCont:
1926 if( isDEC( curr ) )
1928 dig = curr - '0';
1929 if( fractionwidth > (ULONG_MAX - dig)/10 )
1930 IOEXCEPTION( TEXTFAIL, FRACTION_WIDTH_OVERFLOW );
1931 fractionwidth = fractionwidth*10 + dig;
1932 break;
1935 test_for_exponent_width: ;
1936 if( curr == ':' )
1938 if( convcode != ScientConv )
1939 IOEXCEPTION( TEXTFAIL, NO_EXPONENT );
1940 exponentdef = True;
1941 state = ExpoWidth;
1942 break;
1944 goto test_for_final_percent;
1946 case ExpoWidth:
1947 if( isDEC( curr ) )
1949 state = ExpoWidthCont;
1950 exponentwidth = curr - '0';
1951 break;
1953 else
1954 IOEXCEPTION( TEXTFAIL, NO_EXPONENT_WIDTH );
1956 case ExpoWidthCont:
1957 if( isDEC( curr ) )
1959 dig = curr - '0';
1960 if( exponentwidth > (ULONG_MAX - dig)/10 )
1961 IOEXCEPTION( TEXTFAIL, EXPONENT_WIDTH_OVERFLOW );
1962 exponentwidth = exponentwidth*10 + dig;
1963 break;
1965 /* fall through */
1967 test_for_final_percent: ;
1968 case ClauseEnd:
1969 if( curr == '%' )
1971 state = LastPercent;
1972 break;
1975 do_the_action: ;
1976 actionptr[action]();
1977 state = FormatText;
1978 begtxt = fcs - 1;
1979 break;
1981 case CatchPadding:
1982 paddingchar = curr;
1983 state = ConvClause;
1984 break;
1986 case EditClause:
1987 if( isDEC(curr) )
1989 state = ClauseWidth;
1990 clausewidth = curr - '0';
1991 break;
1993 goto test_for_variable_width;
1995 case LastPercent:
1996 actionptr[action]();
1997 if( curr == '.' )
1999 state = FormatText;
2000 begtxt = fcs;
2001 break;
2003 goto after_first_percent;
2005 default:
2006 IOEXCEPTION( TEXTFAIL, INTERNAL_ERROR );
2009 switch( state )
2011 case FormatText:
2012 ftextptr( begtxt, fcs );
2013 break;
2014 case FirstPercent:
2015 case LastPercent:
2016 case RepFact:
2017 case FractWidth:
2018 case ExpoWidth:
2019 IOEXCEPTION( TEXTFAIL, BAD_FORMAT_SPEC_CHAR );
2020 case CatchPadding:
2021 IOEXCEPTION( TEXTFAIL, NO_PAD_CHAR );
2022 default:
2023 actionptr[action]();
2026 *lenptr = len;
2027 *fcsptr = fcs;
2028 return NormalEnd;
2031 static
2032 void
2033 __read_format (char* fmtptr,
2034 int fmtlen,
2035 __tmp_IO_list* ioptr,
2036 int iolen,
2037 void* inpptr,
2038 int inplen )
2040 formatexit_t res;
2041 unsigned short l;
2043 iostrptr = (char*)inpptr;
2044 iostrlen = inplen;
2046 /* initialisation */
2047 iolist_index = 0;
2048 iolistptr = ioptr;
2049 iolistlen = iolen;
2051 actionptr = readactions;
2052 ftextptr = scanstr;
2054 if( (res = scanformcont( fmtptr, fmtlen, &fmtptr, &fmtlen )) == EndAtParen )
2055 IOEXCEPTION( TEXTFAIL, UNMATCHED_CLOSING_PAREN );
2057 if( iolist_index != iolen )
2058 IOEXCEPTION( TEXTFAIL, EXCESS_IOLIST_ELEMENTS );
2060 return;
2063 void
2064 __readtext_f( Text_Mode* the_text_loc,
2065 signed long the_index,
2066 char* fmtptr,
2067 int fmtlen,
2068 __tmp_IO_list* ioptr,
2069 int iolen,
2070 char* file,
2071 int line )
2073 unsigned long info;
2075 if( (info = setjmp( __io_exception )) )
2076 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2078 textptr = the_text_loc;
2079 textrecptr = textptr->text_record;
2080 actual_index = textptr->actual_index;
2081 textindex = the_index;
2083 __read_format ( fmtptr, fmtlen, ioptr, iolen,
2084 (char*)textrecptr + 2, textptr->text_record->len );
2085 textptr->actual_index = actual_index;
2088 void
2089 __readtext_s( void* string_ptr,
2090 int string_len,
2091 char* fmtptr,
2092 int fmtlen,
2093 __tmp_IO_list* ioptr,
2094 int iolen,
2095 char* file,
2096 int line )
2098 int info;
2100 if( (info = setjmp( __io_exception )) )
2101 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2103 textptr = NULL;
2104 actual_index = 0;
2106 __read_format ( fmtptr, fmtlen, ioptr, iolen, string_ptr, string_len );
2109 static
2110 void
2111 __write_format (char* fmtptr,
2112 int fmtlen,
2113 __tmp_IO_list* ioptr,
2114 int iolen,
2115 void* outptr,
2116 int outlen )
2118 formatexit_t res;
2119 unsigned short l;
2121 /* initialisation */
2122 maximum_index = actual_index;
2123 iolist_index = 0;
2125 actionptr = writeactions;
2126 ftextptr = emitstr;
2127 iolistptr = ioptr;
2128 iolistlen = iolen;
2129 iostrptr = (char *)outptr + 2;
2130 iostrlen = outlen;
2132 if( (res = scanformcont( fmtptr, fmtlen, &fmtptr, &fmtlen )) == EndAtParen )
2133 IOEXCEPTION( TEXTFAIL, UNMATCHED_CLOSING_PAREN );
2135 if( iolist_index != iolen )
2136 IOEXCEPTION( TEXTFAIL, EXCESS_IOLIST_ELEMENTS );
2138 /* set length of output string */
2139 #if _TEXTIO_DEBUG_
2140 printf( "maximum index = %d\n", maximum_index );
2141 #endif
2142 l = maximum_index;
2143 MOV2(outptr,&l);
2144 return;
2147 void
2148 __writetext_f( Text_Mode* the_text_loc,
2149 signed long the_index,
2150 char* fmtptr,
2151 int fmtlen,
2152 __tmp_IO_list* ioptr,
2153 int iolen,
2154 char* file,
2155 int line )
2157 int info;
2159 if( (info = setjmp( __io_exception )) )
2160 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2162 textptr = the_text_loc;
2163 textrecptr = the_text_loc->text_record;
2164 textindex = the_index;
2165 iolistptr = ioptr;
2166 iolistlen = iolen;
2168 actual_index = textptr->actual_index;
2169 __write_format ( fmtptr, fmtlen, ioptr, iolen,
2170 textrecptr, textptr->access_sub->reclength - 2 );
2171 textptr->actual_index = actual_index;
2174 void
2175 __writetext_s( void* string_ptr,
2176 int string_len,
2177 char* fmtptr,
2178 int fmtlen,
2179 __tmp_IO_list* ioptr,
2180 int iolen,
2181 char* file,
2182 int line )
2184 int info;
2186 if( (info = setjmp( __io_exception )) )
2187 CHILLEXCEPTION( file, line, info>>16, info & 0xffff );
2189 textptr = NULL;
2190 actual_index = 0;
2192 __write_format ( fmtptr, fmtlen, ioptr, iolen, string_ptr, string_len );