2004-10-04 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / libgfortran / io / format.c
blob0e42810873ef0c946ee5fe783014318b07108a20
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Libgfortran; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* format.c-- parse a FORMAT string into a binary format suitable for
23 * interpretation during I/O statements */
25 #include "config.h"
26 #include <ctype.h>
27 #include <string.h>
28 #include "libgfortran.h"
29 #include "io.h"
33 /* Number of format nodes that we can store statically before we have
34 * to resort to dynamic allocation. The root node is array[0]. */
36 #define FARRAY_SIZE 200
38 static fnode *avail, array[FARRAY_SIZE];
40 /* Local variables for checking format strings. The saved_token is
41 * used to back up by a single format token during the parsing process. */
43 static char *format_string, *string;
44 static const char *error;
45 static format_token saved_token;
46 static int value, format_string_len, reversion_ok;
48 static fnode *saved_format, colon_node = { FMT_COLON };
50 /* Error messages */
52 static char posint_required[] = "Positive width required in format",
53 period_required[] = "Period required in format",
54 nonneg_required[] = "Nonnegative width required in format",
55 unexpected_element[] = "Unexpected element in format",
56 unexpected_end[] = "Unexpected end of format string",
57 bad_string[] = "Unterminated character constant in format",
58 bad_hollerith[] = "Hollerith constant extends past the end of the format",
59 reversion_error[] = "Exhausted data descriptors in format";
62 /* next_char()-- Return the next character in the format string.
63 * Returns -1 when the string is done. If the literal flag is set,
64 * spaces are significant, otherwise they are not. */
66 static int
67 next_char (int literal)
69 int c;
73 if (format_string_len == 0)
74 return -1;
76 format_string_len--;
77 c = toupper (*format_string++);
79 while (c == ' ' && !literal);
81 return c;
85 /* unget_char()-- Back up one character position. */
87 #define unget_char() { format_string--; format_string_len++; }
90 /* get_fnode()-- Allocate a new format node, inserting it into the
91 * current singly linked list. These are initially allocated from the
92 * static buffer. */
94 static fnode *
95 get_fnode (fnode ** head, fnode ** tail, format_token t)
97 fnode *f;
99 if (avail - array >= FARRAY_SIZE)
100 f = get_mem (sizeof (fnode));
101 else
103 f = avail++;
104 memset (f, '\0', sizeof (fnode));
107 if (*head == NULL)
108 *head = *tail = f;
109 else
111 (*tail)->next = f;
112 *tail = f;
115 f->format = t;
116 f->repeat = -1;
117 f->source = format_string;
118 return f;
122 /* free_fnode()-- Recursive function to free the given fnode and
123 * everything it points to. We only have to actually free something
124 * if it is outside of the static array. */
126 static void
127 free_fnode (fnode * f)
129 fnode *next;
131 for (; f; f = next)
133 next = f->next;
135 if (f->format == FMT_LPAREN)
136 free_fnode (f->u.child);
137 if (f < array || f >= array + FARRAY_SIZE)
138 free_mem (f);
143 /* free_fnodes()-- Free the current tree of fnodes. We only have to
144 * traverse the tree if some nodes were allocated dynamically. */
146 void
147 free_fnodes (void)
150 if (avail - array >= FARRAY_SIZE)
151 free_fnode (&array[0]);
153 avail = array;
154 memset(array, 0, sizeof(avail[0]) * FARRAY_SIZE);
158 /* format_lex()-- Simple lexical analyzer for getting the next token
159 * in a FORMAT string. We support a one-level token pushback in the
160 * saved_token variable. */
162 static format_token
163 format_lex (void)
165 format_token token;
166 int negative_flag;
167 int c;
168 char delim;
170 if (saved_token != FMT_NONE)
172 token = saved_token;
173 saved_token = FMT_NONE;
174 return token;
177 negative_flag = 0;
178 c = next_char (0);
180 switch (c)
182 case '-':
183 negative_flag = 1;
184 /* Fall Through */
186 case '+':
187 c = next_char (0);
188 if (!isdigit (c))
190 token = FMT_UNKNOWN;
191 break;
194 value = c - '0';
196 for (;;)
198 c = next_char (0);
199 if (!isdigit (c))
200 break;
202 value = 10 * value + c - '0';
205 unget_char ();
207 if (negative_flag)
208 value = -value;
209 token = FMT_SIGNED_INT;
210 break;
212 case '0':
213 case '1':
214 case '2':
215 case '3':
216 case '4':
217 case '5':
218 case '6':
219 case '7':
220 case '8':
221 case '9':
222 value = c - '0';
224 for (;;)
226 c = next_char (0);
227 if (!isdigit (c))
228 break;
230 value = 10 * value + c - '0';
233 unget_char ();
234 token = (value == 0) ? FMT_ZERO : FMT_POSINT;
235 break;
237 case '.':
238 token = FMT_PERIOD;
239 break;
241 case ',':
242 token = FMT_COMMA;
243 break;
245 case ':':
246 token = FMT_COLON;
247 break;
249 case '/':
250 token = FMT_SLASH;
251 break;
253 case '$':
254 token = FMT_DOLLAR;
255 break;
257 case 'T':
258 switch (next_char (0))
260 case 'L':
261 token = FMT_TL;
262 break;
263 case 'R':
264 token = FMT_TR;
265 break;
266 default:
267 token = FMT_T;
268 unget_char ();
269 break;
272 break;
274 case '(':
275 token = FMT_LPAREN;
276 break;
278 case ')':
279 token = FMT_RPAREN;
280 break;
282 case 'X':
283 token = FMT_X;
284 break;
286 case 'S':
287 switch (next_char (0))
289 case 'S':
290 token = FMT_SS;
291 break;
292 case 'P':
293 token = FMT_SP;
294 break;
295 default:
296 token = FMT_S;
297 unget_char ();
298 break;
301 break;
303 case 'B':
304 switch (next_char (0))
306 case 'N':
307 token = FMT_BN;
308 break;
309 case 'Z':
310 token = FMT_BZ;
311 break;
312 default:
313 token = FMT_B;
314 unget_char ();
315 break;
318 break;
320 case '\'':
321 case '"':
322 delim = c;
324 string = format_string;
325 value = 0; /* This is the length of the string */
327 for (;;)
329 c = next_char (1);
330 if (c == -1)
332 token = FMT_BADSTRING;
333 error = bad_string;
334 break;
337 if (c == delim)
339 c = next_char (1);
341 if (c == -1)
343 token = FMT_BADSTRING;
344 error = bad_string;
345 break;
348 if (c != delim)
350 unget_char ();
351 token = FMT_STRING;
352 break;
356 value++;
359 break;
361 case 'P':
362 token = FMT_P;
363 break;
365 case 'I':
366 token = FMT_I;
367 break;
369 case 'O':
370 token = FMT_O;
371 break;
373 case 'Z':
374 token = FMT_Z;
375 break;
377 case 'F':
378 token = FMT_F;
379 break;
381 case 'E':
382 switch (next_char (0))
384 case 'N':
385 token = FMT_EN;
386 break;
387 case 'S':
388 token = FMT_ES;
389 break;
390 default:
391 token = FMT_E;
392 unget_char ();
393 break;
396 break;
398 case 'G':
399 token = FMT_G;
400 break;
402 case 'H':
403 token = FMT_H;
404 break;
406 case 'L':
407 token = FMT_L;
408 break;
410 case 'A':
411 token = FMT_A;
412 break;
414 case 'D':
415 token = FMT_D;
416 break;
418 case -1:
419 token = FMT_END;
420 break;
422 default:
423 token = FMT_UNKNOWN;
424 break;
427 return token;
431 /* parse_format_list()-- Parse a format list. Assumes that a left
432 * paren has already been seen. Returns a list representing the
433 * parenthesis node which contains the rest of the list. */
435 static fnode *
436 parse_format_list (void)
438 fnode *head, *tail;
439 format_token t, u, t2;
440 int repeat;
442 head = tail = NULL;
444 /* Get the next format item */
446 format_item:
447 t = format_lex ();
448 switch (t)
450 case FMT_POSINT:
451 repeat = value;
453 t = format_lex ();
454 switch (t)
456 case FMT_LPAREN:
457 get_fnode (&head, &tail, FMT_LPAREN);
458 tail->repeat = repeat;
459 tail->u.child = parse_format_list ();
460 if (error != NULL)
461 goto finished;
463 goto between_desc;
465 case FMT_SLASH:
466 get_fnode (&head, &tail, FMT_SLASH);
467 tail->repeat = repeat;
468 goto optional_comma;
470 case FMT_X:
471 get_fnode (&head, &tail, FMT_X);
472 tail->repeat = 1;
473 tail->u.k = value;
474 goto between_desc;
476 case FMT_P:
477 goto p_descriptor;
479 default:
480 goto data_desc;
483 case FMT_LPAREN:
484 get_fnode (&head, &tail, FMT_LPAREN);
485 tail->repeat = 1;
486 tail->u.child = parse_format_list ();
487 if (error != NULL)
488 goto finished;
490 goto between_desc;
492 case FMT_SIGNED_INT: /* Signed integer can only precede a P format. */
493 case FMT_ZERO: /* Same for zero. */
494 t = format_lex ();
495 if (t != FMT_P)
497 error = "Expected P edit descriptor in format";
498 goto finished;
501 p_descriptor:
502 get_fnode (&head, &tail, FMT_P);
503 tail->u.k = value;
504 tail->repeat = 1;
506 t = format_lex ();
507 if (t == FMT_F || t == FMT_EN || t == FMT_ES || t == FMT_D
508 || t == FMT_G || t == FMT_E)
510 repeat = 1;
511 goto data_desc;
514 saved_token = t;
515 goto optional_comma;
517 case FMT_P: /* P and X require a prior number */
518 error = "P descriptor requires leading scale factor";
519 goto finished;
521 case FMT_X:
523 EXTENSION!
525 If we would be pedantic in the library, we would have to reject
526 an X descriptor without an integer prefix:
528 error = "X descriptor requires leading space count";
529 goto finished;
531 However, this is an extension supported by many Fortran compilers,
532 including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
533 runtime library, and make the front end reject it if the compiler
534 is in pedantic mode. The interpretation of 'X' is '1X'.
536 get_fnode (&head, &tail, FMT_X);
537 tail->repeat = 1;
538 tail->u.k = 1;
539 goto between_desc;
541 case FMT_STRING:
542 get_fnode (&head, &tail, FMT_STRING);
544 tail->u.string.p = string;
545 tail->u.string.length = value;
546 tail->repeat = 1;
547 goto optional_comma;
549 case FMT_S:
550 case FMT_SS:
551 case FMT_SP:
552 case FMT_BN:
553 case FMT_BZ:
554 get_fnode (&head, &tail, t);
555 tail->repeat = 1;
556 goto between_desc;
558 case FMT_COLON:
559 get_fnode (&head, &tail, FMT_COLON);
560 goto optional_comma;
562 case FMT_SLASH:
563 get_fnode (&head, &tail, FMT_SLASH);
564 tail->repeat = 1;
565 tail->u.r = 1;
566 goto optional_comma;
568 case FMT_DOLLAR:
569 get_fnode (&head, &tail, FMT_DOLLAR);
570 goto between_desc;
572 case FMT_T:
573 case FMT_TL:
574 case FMT_TR:
575 t2 = format_lex ();
576 if (t2 != FMT_POSINT)
578 error = posint_required;
579 goto finished;
581 get_fnode (&head, &tail, t);
582 tail->u.n = value;
583 tail->repeat = 1;
584 goto between_desc;
586 case FMT_I:
587 case FMT_B:
588 case FMT_O:
589 case FMT_Z:
590 case FMT_E:
591 case FMT_EN:
592 case FMT_ES:
593 case FMT_D:
594 case FMT_L:
595 case FMT_A:
596 case FMT_F:
597 case FMT_G:
598 repeat = 1;
599 goto data_desc;
601 case FMT_H:
602 get_fnode (&head, &tail, FMT_STRING);
604 if (format_string_len < 1)
606 error = bad_hollerith;
607 goto finished;
610 tail->u.string.p = format_string;
611 tail->u.string.length = 1;
612 tail->repeat = 1;
614 format_string++;
615 format_string_len--;
617 goto between_desc;
619 case FMT_END:
620 error = unexpected_end;
621 goto finished;
623 case FMT_BADSTRING:
624 goto finished;
626 case FMT_RPAREN:
627 goto finished;
629 default:
630 error = unexpected_element;
631 goto finished;
634 /* In this state, t must currently be a data descriptor. Deal with
635 * things that can/must follow the descriptor */
637 data_desc:
638 switch (t)
640 case FMT_P:
641 t = format_lex ();
642 if (t == FMT_POSINT)
644 error = "Repeat count cannot follow P descriptor";
645 goto finished;
648 saved_token = t;
649 get_fnode (&head, &tail, FMT_P);
651 goto optional_comma;
653 case FMT_L:
654 t = format_lex ();
655 if (t != FMT_POSINT)
657 error = posint_required;
658 goto finished;
661 get_fnode (&head, &tail, FMT_L);
662 tail->u.n = value;
663 tail->repeat = repeat;
664 break;
666 case FMT_A:
667 t = format_lex ();
668 if (t != FMT_POSINT)
670 saved_token = t;
671 value = -1; /* Width not present */
674 get_fnode (&head, &tail, FMT_A);
675 tail->repeat = repeat;
676 tail->u.n = value;
677 break;
679 case FMT_D:
680 case FMT_E:
681 case FMT_F:
682 case FMT_G:
683 case FMT_EN:
684 case FMT_ES:
685 get_fnode (&head, &tail, t);
686 tail->repeat = repeat;
688 u = format_lex ();
689 if (t == FMT_F || g.mode == WRITING)
691 if (u != FMT_POSINT && u != FMT_ZERO)
693 error = nonneg_required;
694 goto finished;
697 else
699 if (u != FMT_POSINT)
701 error = posint_required;
702 goto finished;
706 tail->u.real.w = value;
707 t2 = t;
708 t = format_lex ();
709 if (t != FMT_PERIOD)
711 error = period_required;
712 goto finished;
715 t = format_lex ();
716 if (t != FMT_ZERO && t != FMT_POSINT)
718 error = nonneg_required;
719 goto finished;
722 tail->u.real.d = value;
724 if (t == FMT_D || t == FMT_F)
725 break;
727 tail->u.real.e = -1;
729 /* Look for optional exponent */
731 t = format_lex ();
732 if (t != FMT_E)
733 saved_token = t;
734 else
736 t = format_lex ();
737 if (t != FMT_POSINT)
739 error = "Positive exponent width required in format";
740 goto finished;
743 tail->u.real.e = value;
746 break;
748 case FMT_H:
749 if (repeat > format_string_len)
751 error = bad_hollerith;
752 goto finished;
755 get_fnode (&head, &tail, FMT_STRING);
757 tail->u.string.p = format_string;
758 tail->u.string.length = repeat;
759 tail->repeat = 1;
761 format_string += value;
762 format_string_len -= repeat;
764 break;
766 case FMT_I:
767 case FMT_B:
768 case FMT_O:
769 case FMT_Z:
770 get_fnode (&head, &tail, t);
771 tail->repeat = repeat;
773 t = format_lex ();
775 if (g.mode == READING)
777 if (t != FMT_POSINT)
779 error = posint_required;
780 goto finished;
783 else
785 if (t != FMT_ZERO && t != FMT_POSINT)
787 error = nonneg_required;
788 goto finished;
792 tail->u.integer.w = value;
793 tail->u.integer.m = -1;
795 t = format_lex ();
796 if (t != FMT_PERIOD)
798 saved_token = t;
800 else
802 t = format_lex ();
803 if (t != FMT_ZERO && t != FMT_POSINT)
805 error = nonneg_required;
806 goto finished;
809 tail->u.integer.m = value;
812 if (tail->u.integer.w != 0 && tail->u.integer.m > tail->u.integer.w)
814 error = "Minimum digits exceeds field width";
815 goto finished;
818 break;
820 default:
821 error = unexpected_element;
822 goto finished;
825 /* Between a descriptor and what comes next */
826 between_desc:
827 t = format_lex ();
828 switch (t)
830 case FMT_COMMA:
831 goto format_item;
833 case FMT_RPAREN:
834 goto finished;
836 case FMT_SLASH:
837 get_fnode (&head, &tail, FMT_SLASH);
838 tail->repeat = 1;
840 /* Fall Through */
842 case FMT_COLON:
843 goto optional_comma;
845 case FMT_END:
846 error = unexpected_end;
847 goto finished;
849 default:
850 error = "Missing comma in format";
851 goto finished;
854 /* Optional comma is a weird between state where we've just finished
855 * reading a colon, slash or P descriptor. */
857 optional_comma:
858 t = format_lex ();
859 switch (t)
861 case FMT_COMMA:
862 break;
864 case FMT_RPAREN:
865 goto finished;
867 default: /* Assume that we have another format item */
868 saved_token = t;
869 break;
872 goto format_item;
874 finished:
875 return head;
879 /* format_error()-- Generate an error message for a format statement.
880 * If the node that gives the location of the error is NULL, the error
881 * is assumed to happen at parse time, and the current location of the
882 * parser is shown.
884 * After freeing any dynamically allocated fnodes, generate a message
885 * showing where the problem is. We take extra care to print only the
886 * relevant part of the format if it is longer than a standard 80
887 * column display. */
889 void
890 format_error (fnode * f, const char *message)
892 int width, i, j, offset;
893 char *p, buffer[300];
895 if (f != NULL)
896 format_string = f->source;
898 free_fnodes ();
900 st_sprintf (buffer, "%s\n", message);
902 j = format_string - ioparm.format;
904 offset = (j > 60) ? j - 40 : 0;
906 j -= offset;
907 width = ioparm.format_len - offset;
909 if (width > 80)
910 width = 80;
912 /* Show the format */
914 p = strchr (buffer, '\0');
916 memcpy (p, ioparm.format + offset, width);
918 p += width;
919 *p++ = '\n';
921 /* Show where the problem is */
923 for (i = 1; i < j; i++)
924 *p++ = ' ';
926 *p++ = '^';
927 *p = '\0';
929 generate_error (ERROR_FORMAT, buffer);
933 /* parse_format()-- Parse a format string. */
935 void
936 parse_format (void)
939 format_string = ioparm.format;
940 format_string_len = ioparm.format_len;
942 saved_token = FMT_NONE;
943 error = NULL;
945 /* Initialize variables used during traversal of the tree */
947 reversion_ok = 0;
948 g.reversion_flag = 0;
949 saved_format = NULL;
951 /* Allocate the first format node as the root of the tree */
953 avail = array;
955 avail->format = FMT_LPAREN;
956 avail->repeat = 1;
957 avail++;
959 if (format_lex () == FMT_LPAREN)
960 array[0].u.child = parse_format_list ();
961 else
962 error = "Missing initial left parenthesis in format";
964 if (error)
965 format_error (NULL, error);
969 /* revert()-- Do reversion of the format. Control reverts to the left
970 * parenthesis that matches the rightmost right parenthesis. From our
971 * tree structure, we are looking for the rightmost parenthesis node
972 * at the second level, the first level always being a single
973 * parenthesis node. If this node doesn't exit, we use the top
974 * level. */
976 static void
977 revert (void)
979 fnode *f, *r;
981 g.reversion_flag = 1;
983 r = NULL;
985 for (f = array[0].u.child; f; f = f->next)
986 if (f->format == FMT_LPAREN)
987 r = f;
989 /* If r is NULL because no node was found, the whole tree will be used */
991 array[0].current = r;
992 array[0].count = 0;
996 /* next_format0()-- Get the next format node without worrying about
997 * reversion. Returns NULL when we hit the end of the list.
998 * Parenthesis nodes are incremented after the list has been
999 * exhausted, other nodes are incremented before they are returned. */
1001 static fnode *
1002 next_format0 (fnode * f)
1004 fnode *r;
1006 if (f == NULL)
1007 return NULL;
1009 if (f->format != FMT_LPAREN)
1011 f->count++;
1012 if (f->count <= f->repeat)
1013 return f;
1015 f->count = 0;
1016 return NULL;
1019 /* Deal with a parenthesis node */
1021 for (; f->count < f->repeat; f->count++)
1023 if (f->current == NULL)
1024 f->current = f->u.child;
1026 for (; f->current != NULL; f->current = f->current->next)
1028 r = next_format0 (f->current);
1029 if (r != NULL)
1030 return r;
1034 f->count = 0;
1035 return NULL;
1039 /* next_format()-- Return the next format node. If the format list
1040 * ends up being exhausted, we do reversion. Reversion is only
1041 * allowed if the we've seen a data descriptor since the
1042 * initialization or the last reversion. We return NULL if the there
1043 * are no more data descriptors to return (which is an error
1044 * condition). */
1046 fnode *
1047 next_format (void)
1049 format_token t;
1050 fnode *f;
1052 if (saved_format != NULL)
1053 { /* Deal with a pushed-back format node */
1054 f = saved_format;
1055 saved_format = NULL;
1056 goto done;
1059 f = next_format0 (&array[0]);
1060 if (f == NULL)
1062 if (!reversion_ok)
1064 return NULL;
1067 reversion_ok = 0;
1068 revert ();
1070 f = next_format0 (&array[0]);
1071 if (f == NULL)
1073 format_error (NULL, reversion_error);
1074 return NULL;
1077 /* Push the first reverted token and return a colon node in case
1078 * there are no more data items. */
1080 saved_format = f;
1081 return &colon_node;
1084 /* If this is a data edit descriptor, then reversion has become OK. */
1086 done:
1087 t = f->format;
1089 if (!reversion_ok &&
1090 (t == FMT_I || t == FMT_B || t == FMT_O || t == FMT_Z || t == FMT_F ||
1091 t == FMT_E || t == FMT_EN || t == FMT_ES || t == FMT_G || t == FMT_L ||
1092 t == FMT_A || t == FMT_D))
1093 reversion_ok = 1;
1094 return f;
1098 /* unget_format()-- Push the given format back so that it will be
1099 * returned on the next call to next_format() without affecting
1100 * counts. This is necessary when we've encountered a data
1101 * descriptor, but don't know what the data item is yet. The format
1102 * node is pushed back, and we return control to the main program,
1103 * which calls the library back with the data item (or not). */
1105 void
1106 unget_format (fnode * f)
1109 saved_format = f;
1115 #if 0
1117 static void dump_format1 (fnode * f);
1119 /* dump_format0()-- Dump a single format node */
1121 void
1122 dump_format0 (fnode * f)
1124 char *p;
1125 int i;
1127 switch (f->format)
1129 case FMT_COLON:
1130 st_printf (" :");
1131 break;
1132 case FMT_SLASH:
1133 st_printf (" %d/", f->u.r);
1134 break;
1135 case FMT_DOLLAR:
1136 st_printf (" $");
1137 break;
1138 case FMT_T:
1139 st_printf (" T%d", f->u.n);
1140 break;
1141 case FMT_TR:
1142 st_printf (" TR%d", f->u.n);
1143 break;
1144 case FMT_TL:
1145 st_printf (" TL%d", f->u.n);
1146 break;
1147 case FMT_X:
1148 st_printf (" %dX", f->u.n);
1149 break;
1150 case FMT_S:
1151 st_printf (" S");
1152 break;
1153 case FMT_SS:
1154 st_printf (" SS");
1155 break;
1156 case FMT_SP:
1157 st_printf (" SP");
1158 break;
1160 case FMT_LPAREN:
1161 if (f->repeat == 1)
1162 st_printf (" (");
1163 else
1164 st_printf (" %d(", f->repeat);
1166 dump_format1 (f->u.child);
1167 st_printf (" )");
1168 break;
1170 case FMT_STRING:
1171 st_printf (" '");
1172 p = f->u.string.p;
1173 for (i = f->u.string.length; i > 0; i--)
1174 st_printf ("%c", *p++);
1176 st_printf ("'");
1177 break;
1179 case FMT_P:
1180 st_printf (" %dP", f->u.k);
1181 break;
1182 case FMT_I:
1183 st_printf (" %dI%d.%d", f->repeat, f->u.integer.w, f->u.integer.m);
1184 break;
1186 case FMT_B:
1187 st_printf (" %dB%d.%d", f->repeat, f->u.integer.w, f->u.integer.m);
1188 break;
1190 case FMT_O:
1191 st_printf (" %dO%d.%d", f->repeat, f->u.integer.w, f->u.integer.m);
1192 break;
1194 case FMT_Z:
1195 st_printf (" %dZ%d.%d", f->repeat, f->u.integer.w, f->u.integer.m);
1196 break;
1198 case FMT_BN:
1199 st_printf (" BN");
1200 break;
1201 case FMT_BZ:
1202 st_printf (" BZ");
1203 break;
1204 case FMT_D:
1205 st_printf (" %dD%d.%d", f->repeat, f->u.real.w, f->u.real.d);
1206 break;
1208 case FMT_EN:
1209 st_printf (" %dEN%d.%dE%d", f->repeat, f->u.real.w, f->u.real.d,
1210 f->u.real.e);
1211 break;
1213 case FMT_ES:
1214 st_printf (" %dES%d.%dE%d", f->repeat, f->u.real.w, f->u.real.d,
1215 f->u.real.e);
1216 break;
1218 case FMT_F:
1219 st_printf (" %dF%d.%d", f->repeat, f->u.real.w, f->u.real.d);
1220 break;
1222 case FMT_E:
1223 st_printf (" %dE%d.%dE%d", f->repeat, f->u.real.w, f->u.real.d,
1224 f->u.real.e);
1225 break;
1227 case FMT_G:
1228 st_printf (" %dG%d.%dE%d", f->repeat, f->u.real.w, f->u.real.d,
1229 f->u.real.e);
1230 break;
1232 case FMT_L:
1233 st_printf (" %dL%d", f->repeat, f->u.w);
1234 break;
1235 case FMT_A:
1236 st_printf (" %dA%d", f->repeat, f->u.w);
1237 break;
1239 default:
1240 st_printf (" ???");
1241 break;
1246 /* dump_format1()-- Dump a string of format nodes */
1248 static void
1249 dump_format1 (fnode * f)
1252 for (; f; f = f->next)
1253 dump_format1 (f);
1256 /* dump_format()-- Dump the whole format node tree */
1258 void
1259 dump_format (void)
1262 st_printf ("format = ");
1263 dump_format0 (&array[0]);
1264 st_printf ("\n");
1268 void
1269 next_test (void)
1271 fnode *f;
1272 int i;
1274 for (i = 0; i < 20; i++)
1276 f = next_format ();
1277 if (f == NULL)
1279 st_printf ("No format!\n");
1280 break;
1283 dump_format1 (f);
1284 st_printf ("\n");
1288 #endif