]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/io/format.c
1 /* Copyright (C) 2002-2021 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 F2003 I/O support contributed by Jerry DeLisle
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran 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 3, or (at your option)
12 Libgfortran 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 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
27 /* format.c-- parse a FORMAT string into a binary format suitable for
28 interpretation during I/O statements. */
35 static const fnode colon_node
= { FMT_COLON
, 0, NULL
, NULL
, {{ 0, 0, 0 }}, 0,
40 static const char posint_required
[] = "Positive integer required in format",
41 period_required
[] = "Period required in format",
42 nonneg_required
[] = "Nonnegative width required in format",
43 unexpected_element
[] = "Unexpected element '%c' in format\n",
44 unexpected_end
[] = "Unexpected end of format string",
45 bad_string
[] = "Unterminated character constant in format",
46 bad_hollerith
[] = "Hollerith constant extends past the end of the format",
47 reversion_error
[] = "Exhausted data descriptors in format",
48 zero_width
[] = "Zero width in format descriptor";
50 /* The following routines support caching format data from parsed format strings
51 into a hash table. This avoids repeatedly parsing duplicate format strings
52 or format strings in I/O statements that are repeated in loops. */
55 /* Traverse the table and free all data. */
58 free_format_hash_table (gfc_unit
*u
)
62 /* free_format_data handles any NULL pointers. */
63 for (i
= 0; i
< FORMAT_HASH_SIZE
; i
++)
65 if (u
->format_hash_table
[i
].hashed_fmt
!= NULL
)
67 free_format_data (u
->format_hash_table
[i
].hashed_fmt
);
68 free (u
->format_hash_table
[i
].key
);
70 u
->format_hash_table
[i
].key
= NULL
;
71 u
->format_hash_table
[i
].key_len
= 0;
72 u
->format_hash_table
[i
].hashed_fmt
= NULL
;
76 /* Traverse the format_data structure and reset the fnode counters. */
79 reset_node (fnode
*fn
)
86 if (fn
->format
!= FMT_LPAREN
)
89 for (f
= fn
->u
.child
; f
; f
= f
->next
)
91 if (f
->format
== FMT_RPAREN
)
98 reset_fnode_counters (st_parameter_dt
*dtp
)
105 /* Clear this pointer at the head so things start at the right place. */
106 fmt
->array
.array
[0].current
= NULL
;
108 for (f
= fmt
->array
.array
[0].u
.child
; f
; f
= f
->next
)
113 /* A simple hashing function to generate an index into the hash table. */
116 format_hash (st_parameter_dt
*dtp
)
119 gfc_charlen_type key_len
;
123 /* Hash the format string. Super simple, but what the heck! */
125 key_len
= dtp
->format_len
;
126 for (i
= 0; i
< key_len
; i
++)
128 hash
&= (FORMAT_HASH_SIZE
- 1);
134 save_parsed_format (st_parameter_dt
*dtp
)
139 hash
= format_hash (dtp
);
140 u
= dtp
->u
.p
.current_unit
;
142 /* Index into the hash table. We are simply replacing whatever is there
143 relying on probability. */
144 if (u
->format_hash_table
[hash
].hashed_fmt
!= NULL
)
145 free_format_data (u
->format_hash_table
[hash
].hashed_fmt
);
146 u
->format_hash_table
[hash
].hashed_fmt
= NULL
;
148 free (u
->format_hash_table
[hash
].key
);
149 u
->format_hash_table
[hash
].key
= dtp
->format
;
151 u
->format_hash_table
[hash
].key_len
= dtp
->format_len
;
152 u
->format_hash_table
[hash
].hashed_fmt
= dtp
->u
.p
.fmt
;
157 find_parsed_format (st_parameter_dt
*dtp
)
162 hash
= format_hash (dtp
);
163 u
= dtp
->u
.p
.current_unit
;
165 if (u
->format_hash_table
[hash
].key
!= NULL
)
167 /* See if it matches. */
168 if (u
->format_hash_table
[hash
].key_len
== dtp
->format_len
)
170 /* So far so good. */
171 if (strncmp (u
->format_hash_table
[hash
].key
,
172 dtp
->format
, dtp
->format_len
) == 0)
173 return u
->format_hash_table
[hash
].hashed_fmt
;
180 /* next_char()-- Return the next character in the format string.
181 Returns -1 when the string is done. If the literal flag is set,
182 spaces are significant, otherwise they are not. */
185 next_char (format_data
*fmt
, int literal
)
191 if (fmt
->format_string_len
== 0)
194 fmt
->format_string_len
--;
195 c
= safe_toupper (*fmt
->format_string
++);
196 fmt
->error_element
= c
;
198 while ((c
== ' ' || c
== '\t') && !literal
);
204 /* unget_char()-- Back up one character position. */
206 #define unget_char(fmt) \
207 { fmt->format_string--; fmt->format_string_len++; }
210 /* get_fnode()-- Allocate a new format node, inserting it into the
211 current singly linked list. These are initially allocated from the
215 get_fnode (format_data
*fmt
, fnode
**head
, fnode
**tail
, format_token t
)
219 if (fmt
->avail
== &fmt
->last
->array
[FARRAY_SIZE
])
221 fmt
->last
->next
= xmalloc (sizeof (fnode_array
));
222 fmt
->last
= fmt
->last
->next
;
223 fmt
->last
->next
= NULL
;
224 fmt
->avail
= &fmt
->last
->array
[0];
227 memset (f
, '\0', sizeof (fnode
));
239 f
->source
= fmt
->format_string
;
244 /* free_format()-- Free allocated format string. */
246 free_format (st_parameter_dt
*dtp
)
248 if ((dtp
->common
.flags
& IOPARM_DT_HAS_FORMAT
) && dtp
->format
)
256 /* free_format_data()-- Free all allocated format data. */
259 free_format_data (format_data
*fmt
)
261 fnode_array
*fa
, *fa_next
;
267 /* Free vlist descriptors in the fnode_array if one was allocated. */
268 for (fnp
= fmt
->array
.array
; fnp
< &fmt
->array
.array
[FARRAY_SIZE
] &&
269 fnp
->format
!= FMT_NONE
; fnp
++)
270 if (fnp
->format
== FMT_DT
)
272 if (GFC_DESCRIPTOR_DATA(fnp
->u
.udf
.vlist
))
273 free (GFC_DESCRIPTOR_DATA(fnp
->u
.udf
.vlist
));
274 free (fnp
->u
.udf
.vlist
);
277 for (fa
= fmt
->array
.next
; fa
; fa
= fa_next
)
288 /* format_lex()-- Simple lexical analyzer for getting the next token
289 in a FORMAT string. We support a one-level token pushback in the
290 fmt->saved_token variable. */
293 format_lex (format_data
*fmt
)
300 if (fmt
->saved_token
!= FMT_NONE
)
302 token
= fmt
->saved_token
;
303 fmt
->saved_token
= FMT_NONE
;
308 c
= next_char (fmt
, 0);
329 c
= next_char (fmt
, 0);
330 if (!safe_isdigit (c
))
336 fmt
->value
= c
- '0';
340 c
= next_char (fmt
, 0);
341 if (!safe_isdigit (c
))
344 fmt
->value
= 10 * fmt
->value
+ c
- '0';
350 fmt
->value
= -fmt
->value
;
351 token
= FMT_SIGNED_INT
;
364 fmt
->value
= c
- '0';
368 c
= next_char (fmt
, 0);
369 if (!safe_isdigit (c
))
372 fmt
->value
= 10 * fmt
->value
+ c
- '0';
376 token
= (fmt
->value
== 0) ? FMT_ZERO
: FMT_POSINT
;
400 switch (next_char (fmt
, 0))
421 switch (next_char (fmt
, 0))
438 switch (next_char (fmt
, 0))
458 fmt
->string
= fmt
->format_string
;
459 fmt
->value
= 0; /* This is the length of the string */
463 c
= next_char (fmt
, 1);
466 token
= FMT_BADSTRING
;
467 fmt
->error
= bad_string
;
473 c
= next_char (fmt
, 1);
477 token
= FMT_BADSTRING
;
478 fmt
->error
= bad_string
;
516 switch (next_char (fmt
, 0))
548 switch (next_char (fmt
, 0))
567 switch (next_char (fmt
, 0))
607 /* parse_format_list()-- Parse a format list. Assumes that a left
608 paren has already been seen. Returns a list representing the
609 parenthesis node which contains the rest of the list. */
612 parse_format_list (st_parameter_dt
*dtp
, bool *seen_dd
)
615 format_token t
, u
, t2
;
617 format_data
*fmt
= dtp
->u
.p
.fmt
;
618 bool seen_data_desc
= false;
623 /* Get the next format item */
625 t
= format_lex (fmt
);
630 t
= format_lex (fmt
);
633 fmt
->error
= "Left parenthesis required after '*'";
636 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
637 tail
->repeat
= -2; /* Signifies unlimited format. */
638 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
639 *seen_dd
= seen_data_desc
;
640 if (fmt
->error
!= NULL
)
644 fmt
->error
= "'*' requires at least one associated data descriptor";
652 t
= format_lex (fmt
);
656 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
657 tail
->repeat
= repeat
;
658 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
659 *seen_dd
= seen_data_desc
;
660 if (fmt
->error
!= NULL
)
666 get_fnode (fmt
, &head
, &tail
, FMT_SLASH
);
667 tail
->repeat
= repeat
;
671 get_fnode (fmt
, &head
, &tail
, FMT_X
);
673 tail
->u
.k
= fmt
->value
;
684 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
686 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
687 *seen_dd
= seen_data_desc
;
688 if (fmt
->error
!= NULL
)
693 case FMT_SIGNED_INT
: /* Signed integer can only precede a P format. */
694 case FMT_ZERO
: /* Same for zero. */
695 t
= format_lex (fmt
);
698 fmt
->error
= "Expected P edit descriptor in format";
703 get_fnode (fmt
, &head
, &tail
, FMT_P
);
704 tail
->u
.k
= fmt
->value
;
707 t
= format_lex (fmt
);
708 if (t
== FMT_F
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_D
709 || t
== FMT_G
|| t
== FMT_E
)
715 if (t
!= FMT_COMMA
&& t
!= FMT_RPAREN
&& t
!= FMT_SLASH
718 fmt
->error
= "Comma required after P descriptor";
722 fmt
->saved_token
= t
;
725 case FMT_P
: /* P and X require a prior number */
726 fmt
->error
= "P descriptor requires leading scale factor";
733 If we would be pedantic in the library, we would have to reject
734 an X descriptor without an integer prefix:
736 fmt->error = "X descriptor requires leading space count";
739 However, this is an extension supported by many Fortran compilers,
740 including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
741 runtime library, and make the front end reject it if the compiler
742 is in pedantic mode. The interpretation of 'X' is '1X'.
744 get_fnode (fmt
, &head
, &tail
, FMT_X
);
750 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
751 tail
->u
.string
.p
= fmt
->string
;
752 tail
->u
.string
.length
= fmt
->value
;
762 notify_std (&dtp
->common
, GFC_STD_F2003
, "Fortran 2003: Round "
763 "descriptor not allowed");
764 get_fnode (fmt
, &head
, &tail
, t
);
770 notify_std (&dtp
->common
, GFC_STD_F2003
, "Fortran 2003: DC or DP "
771 "descriptor not allowed");
778 get_fnode (fmt
, &head
, &tail
, t
);
783 get_fnode (fmt
, &head
, &tail
, FMT_COLON
);
788 get_fnode (fmt
, &head
, &tail
, FMT_SLASH
);
794 get_fnode (fmt
, &head
, &tail
, FMT_DOLLAR
);
796 notify_std (&dtp
->common
, GFC_STD_GNU
, "Extension: $ descriptor");
802 t2
= format_lex (fmt
);
803 if (t2
!= FMT_POSINT
)
805 fmt
->error
= posint_required
;
808 get_fnode (fmt
, &head
, &tail
, t
);
809 tail
->u
.n
= fmt
->value
;
831 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
832 if (fmt
->format_string_len
< 1)
834 fmt
->error
= bad_hollerith
;
838 tail
->u
.string
.p
= fmt
->format_string
;
839 tail
->u
.string
.length
= 1;
842 fmt
->format_string
++;
843 fmt
->format_string_len
--;
848 fmt
->error
= unexpected_end
;
858 fmt
->error
= unexpected_element
;
862 /* In this state, t must currently be a data descriptor. Deal with
863 things that can/must follow the descriptor */
870 t
= format_lex (fmt
);
875 if (notification_std(GFC_STD_GNU
) == NOTIFICATION_ERROR
)
877 fmt
->error
= "Extension: Zero width after L descriptor";
881 notify_std (&dtp
->common
, GFC_STD_GNU
,
882 "Zero width after L descriptor");
886 fmt
->saved_token
= t
;
887 notify_std (&dtp
->common
, GFC_STD_GNU
,
888 "Positive width required with L descriptor");
890 fmt
->value
= 1; /* Default width */
892 get_fnode (fmt
, &head
, &tail
, FMT_L
);
893 tail
->u
.n
= fmt
->value
;
894 tail
->repeat
= repeat
;
899 t
= format_lex (fmt
);
902 fmt
->error
= zero_width
;
908 fmt
->saved_token
= t
;
909 fmt
->value
= -1; /* Width not present */
912 get_fnode (fmt
, &head
, &tail
, FMT_A
);
913 tail
->repeat
= repeat
;
914 tail
->u
.n
= fmt
->value
;
924 get_fnode (fmt
, &head
, &tail
, t
);
925 tail
->repeat
= repeat
;
927 u
= format_lex (fmt
);
929 /* Processing for zero width formats. */
933 standard
= GFC_STD_F95
;
935 standard
= GFC_STD_F2008
;
937 standard
= GFC_STD_F2018
;
939 if (notification_std (standard
) == NOTIFICATION_ERROR
940 || dtp
->u
.p
.mode
== READING
)
942 fmt
->error
= zero_width
;
947 /* Look for the dot seperator. */
948 u
= format_lex (fmt
);
951 fmt
->saved_token
= u
;
955 /* Look for the precision. */
956 u
= format_lex (fmt
);
957 if (u
!= FMT_ZERO
&& u
!= FMT_POSINT
)
959 fmt
->error
= nonneg_required
;
962 tail
->u
.real
.d
= fmt
->value
;
964 /* Look for optional exponent, not allowed for FMT_D */
967 u
= format_lex (fmt
);
969 fmt
->saved_token
= u
;
972 u
= format_lex (fmt
);
977 notify_std (&dtp
->common
, GFC_STD_F2018
,
978 "Positive exponent width required");
982 fmt
->error
= "Positive exponent width required in "
983 "format string at %L";
987 tail
->u
.real
.e
= fmt
->value
;
992 /* Processing for positive width formats. */
995 tail
->u
.real
.w
= fmt
->value
;
997 /* Look for the dot separator. Because of legacy behaviors
998 we do some look ahead for missing things. */
1000 t
= format_lex (fmt
);
1001 if (t
!= FMT_PERIOD
)
1003 /* We treat a missing decimal descriptor as 0. Note: This is only
1004 allowed if -std=legacy, otherwise an error occurs. */
1005 if (compile_options
.warn_std
!= 0)
1007 fmt
->error
= period_required
;
1010 fmt
->saved_token
= t
;
1012 tail
->u
.real
.e
= -1;
1016 /* If we made it here, we should have the dot so look for the
1018 t
= format_lex (fmt
);
1019 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1021 fmt
->error
= nonneg_required
;
1024 tail
->u
.real
.d
= fmt
->value
;
1025 tail
->u
.real
.e
= -1;
1027 /* Done with D and F formats. */
1028 if (t2
== FMT_D
|| t2
== FMT_F
)
1034 /* Look for optional exponent */
1035 u
= format_lex (fmt
);
1037 fmt
->saved_token
= u
;
1040 u
= format_lex (fmt
);
1041 if (u
!= FMT_POSINT
)
1045 notify_std (&dtp
->common
, GFC_STD_F2018
,
1046 "Positive exponent width required");
1050 fmt
->error
= "Positive exponent width required in "
1051 "format string at %L";
1055 tail
->u
.real
.e
= fmt
->value
;
1060 /* Old DEC codes may not have width or precision specified. */
1061 if (dtp
->u
.p
.mode
== WRITING
&& (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
))
1063 tail
->u
.real
.w
= DEFAULT_WIDTH
;
1065 tail
->u
.real
.e
= -1;
1066 fmt
->saved_token
= u
;
1072 get_fnode (fmt
, &head
, &tail
, t
);
1073 tail
->repeat
= repeat
;
1075 t
= format_lex (fmt
);
1077 /* Initialize the vlist to a zero size, rank-one array. */
1078 tail
->u
.udf
.vlist
= xmalloc (sizeof(gfc_array_i4
)
1079 + sizeof (descriptor_dimension
));
1080 GFC_DESCRIPTOR_DATA(tail
->u
.udf
.vlist
) = NULL
;
1081 GFC_DIMENSION_SET(tail
->u
.udf
.vlist
->dim
[0],1, 0, 0);
1083 if (t
== FMT_STRING
)
1085 /* Get pointer to the optional format string. */
1086 tail
->u
.udf
.string
= fmt
->string
;
1087 tail
->u
.udf
.string_len
= fmt
->value
;
1088 t
= format_lex (fmt
);
1090 if (t
== FMT_LPAREN
)
1092 /* Temporary buffer to hold the vlist values. */
1093 GFC_INTEGER_4 temp
[FARRAY_SIZE
];
1096 t
= format_lex (fmt
);
1097 if (t
!= FMT_POSINT
)
1099 fmt
->error
= posint_required
;
1102 /* Save the positive integer value. */
1103 temp
[i
++] = fmt
->value
;
1104 t
= format_lex (fmt
);
1107 if (t
== FMT_RPAREN
)
1109 /* We have parsed the complete vlist so initialize the
1110 array descriptor and save it in the format node. */
1111 gfc_full_array_i4
*vp
= tail
->u
.udf
.vlist
;
1112 GFC_DESCRIPTOR_DATA(vp
) = xmalloc (i
* sizeof(GFC_INTEGER_4
));
1113 GFC_DIMENSION_SET(vp
->dim
[0],1, i
, 1);
1114 memcpy (GFC_DESCRIPTOR_DATA(vp
), temp
, i
* sizeof(GFC_INTEGER_4
));
1117 fmt
->error
= unexpected_element
;
1120 fmt
->saved_token
= t
;
1123 if (repeat
> fmt
->format_string_len
)
1125 fmt
->error
= bad_hollerith
;
1129 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
1130 tail
->u
.string
.p
= fmt
->format_string
;
1131 tail
->u
.string
.length
= repeat
;
1134 fmt
->format_string
+= fmt
->value
;
1135 fmt
->format_string_len
-= repeat
;
1144 get_fnode (fmt
, &head
, &tail
, t
);
1145 tail
->repeat
= repeat
;
1147 t
= format_lex (fmt
);
1149 if (dtp
->u
.p
.mode
== READING
)
1151 if (t
!= FMT_POSINT
)
1153 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1155 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1156 tail
->u
.integer
.m
= -1;
1157 fmt
->saved_token
= t
;
1160 fmt
->error
= posint_required
;
1166 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1168 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1170 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1171 tail
->u
.integer
.m
= -1;
1172 fmt
->saved_token
= t
;
1175 fmt
->error
= nonneg_required
;
1180 tail
->u
.integer
.w
= fmt
->value
;
1181 tail
->u
.integer
.m
= -1;
1183 t
= format_lex (fmt
);
1184 if (t
!= FMT_PERIOD
)
1186 fmt
->saved_token
= t
;
1190 t
= format_lex (fmt
);
1191 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1193 fmt
->error
= nonneg_required
;
1197 tail
->u
.integer
.m
= fmt
->value
;
1200 if (tail
->u
.integer
.w
!= 0 && tail
->u
.integer
.m
> tail
->u
.integer
.w
)
1202 fmt
->error
= "Minimum digits exceeds field width";
1209 fmt
->error
= unexpected_element
;
1213 /* Between a descriptor and what comes next */
1215 t
= format_lex (fmt
);
1226 get_fnode (fmt
, &head
, &tail
, t
);
1228 goto optional_comma
;
1231 fmt
->error
= unexpected_end
;
1235 /* Assume a missing comma, this is a GNU extension */
1239 /* Optional comma is a weird between state where we've just finished
1240 reading a colon, slash or P descriptor. */
1242 t
= format_lex (fmt
);
1251 default: /* Assume that we have another format item */
1252 fmt
->saved_token
= t
;
1264 /* format_error()-- Generate an error message for a format statement.
1265 If the node that gives the location of the error is NULL, the error
1266 is assumed to happen at parse time, and the current location of the
1269 We generate a message showing where the problem is. We take extra
1270 care to print only the relevant part of the format if it is longer
1271 than a standard 80 column display. */
1274 format_error (st_parameter_dt
*dtp
, const fnode
*f
, const char *message
)
1276 int width
, i
, offset
;
1278 char *p
, buffer
[BUFLEN
];
1279 format_data
*fmt
= dtp
->u
.p
.fmt
;
1283 else /* This should not happen. */
1286 if (message
== unexpected_element
)
1287 snprintf (buffer
, BUFLEN
, message
, fmt
->error_element
);
1289 snprintf (buffer
, BUFLEN
, "%s\n", message
);
1291 /* Get the offset into the format string where the error occurred. */
1292 offset
= dtp
->format_len
- (fmt
->reversion_ok
?
1293 (int) strlen(p
) : fmt
->format_string_len
);
1295 width
= dtp
->format_len
;
1300 /* Show the format */
1302 p
= strchr (buffer
, '\0');
1305 memcpy (p
, dtp
->format
, width
);
1310 /* Show where the problem is */
1312 for (i
= 1; i
< offset
; i
++)
1318 generate_error (&dtp
->common
, LIBERROR_FORMAT
, buffer
);
1322 /* revert()-- Do reversion of the format. Control reverts to the left
1323 parenthesis that matches the rightmost right parenthesis. From our
1324 tree structure, we are looking for the rightmost parenthesis node
1325 at the second level, the first level always being a single
1326 parenthesis node. If this node doesn't exit, we use the top
1330 revert (st_parameter_dt
*dtp
)
1333 format_data
*fmt
= dtp
->u
.p
.fmt
;
1335 dtp
->u
.p
.reversion_flag
= 1;
1339 for (f
= fmt
->array
.array
[0].u
.child
; f
; f
= f
->next
)
1340 if (f
->format
== FMT_LPAREN
)
1343 /* If r is NULL because no node was found, the whole tree will be used */
1345 fmt
->array
.array
[0].current
= r
;
1346 fmt
->array
.array
[0].count
= 0;
1349 /* parse_format()-- Parse a format string. */
1352 parse_format (st_parameter_dt
*dtp
)
1355 bool format_cache_ok
, seen_data_desc
= false;
1357 /* Don't cache for internal units and set an arbitrary limit on the
1358 size of format strings we will cache. (Avoids memory issues.)
1359 Also, the format_hash_table resides in the current_unit, so
1360 child_dtio procedures would overwrite the parent table */
1361 format_cache_ok
= !is_internal_unit (dtp
)
1362 && (dtp
->u
.p
.current_unit
->child_dtio
== 0);
1364 /* Lookup format string to see if it has already been parsed. */
1365 if (format_cache_ok
)
1367 dtp
->u
.p
.fmt
= find_parsed_format (dtp
);
1369 if (dtp
->u
.p
.fmt
!= NULL
)
1371 dtp
->u
.p
.fmt
->reversion_ok
= 0;
1372 dtp
->u
.p
.fmt
->saved_token
= FMT_NONE
;
1373 dtp
->u
.p
.fmt
->saved_format
= NULL
;
1374 reset_fnode_counters (dtp
);
1379 /* Not found so proceed as follows. */
1381 char *fmt_string
= fc_strdup_notrim (dtp
->format
, dtp
->format_len
);
1382 dtp
->format
= fmt_string
;
1384 dtp
->u
.p
.fmt
= fmt
= xmalloc (sizeof (format_data
));
1385 fmt
->format_string
= dtp
->format
;
1386 fmt
->format_string_len
= dtp
->format_len
;
1389 fmt
->saved_token
= FMT_NONE
;
1393 /* Initialize variables used during traversal of the tree. */
1395 fmt
->reversion_ok
= 0;
1396 fmt
->saved_format
= NULL
;
1398 /* Initialize the fnode_array. */
1400 memset (&(fmt
->array
), 0, sizeof(fmt
->array
));
1402 /* Allocate the first format node as the root of the tree. */
1404 fmt
->last
= &fmt
->array
;
1405 fmt
->last
->next
= NULL
;
1406 fmt
->avail
= &fmt
->array
.array
[0];
1408 memset (fmt
->avail
, 0, sizeof (*fmt
->avail
));
1409 fmt
->avail
->format
= FMT_LPAREN
;
1410 fmt
->avail
->repeat
= 1;
1413 if (format_lex (fmt
) == FMT_LPAREN
)
1414 fmt
->array
.array
[0].u
.child
= parse_format_list (dtp
, &seen_data_desc
);
1416 fmt
->error
= "Missing initial left parenthesis in format";
1418 if (format_cache_ok
)
1419 save_parsed_format (dtp
);
1421 dtp
->u
.p
.format_not_saved
= 1;
1424 format_error (dtp
, NULL
, fmt
->error
);
1428 /* next_format0()-- Get the next format node without worrying about
1429 reversion. Returns NULL when we hit the end of the list.
1430 Parenthesis nodes are incremented after the list has been
1431 exhausted, other nodes are incremented before they are returned. */
1433 static const fnode
*
1434 next_format0 (fnode
*f
)
1441 if (f
->format
!= FMT_LPAREN
)
1444 if (f
->count
<= f
->repeat
)
1451 /* Deal with a parenthesis node with unlimited format. */
1453 if (f
->repeat
== -2) /* -2 signifies unlimited. */
1456 if (f
->current
== NULL
)
1457 f
->current
= f
->u
.child
;
1459 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1461 r
= next_format0 (f
->current
);
1467 /* Deal with a parenthesis node with specific repeat count. */
1468 for (; f
->count
< f
->repeat
; f
->count
++)
1470 if (f
->current
== NULL
)
1471 f
->current
= f
->u
.child
;
1473 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1475 r
= next_format0 (f
->current
);
1486 /* next_format()-- Return the next format node. If the format list
1487 ends up being exhausted, we do reversion. Reversion is only
1488 allowed if we've seen a data descriptor since the
1489 initialization or the last reversion. We return NULL if there
1490 are no more data descriptors to return (which is an error
1494 next_format (st_parameter_dt
*dtp
)
1498 format_data
*fmt
= dtp
->u
.p
.fmt
;
1500 if (fmt
->saved_format
!= NULL
)
1501 { /* Deal with a pushed-back format node */
1502 f
= fmt
->saved_format
;
1503 fmt
->saved_format
= NULL
;
1507 f
= next_format0 (&fmt
->array
.array
[0]);
1510 if (!fmt
->reversion_ok
)
1513 fmt
->reversion_ok
= 0;
1516 f
= next_format0 (&fmt
->array
.array
[0]);
1519 format_error (dtp
, NULL
, reversion_error
);
1523 /* Push the first reverted token and return a colon node in case
1524 there are no more data items. */
1526 fmt
->saved_format
= f
;
1530 /* If this is a data edit descriptor, then reversion has become OK. */
1534 if (!fmt
->reversion_ok
&&
1535 (t
== FMT_I
|| t
== FMT_B
|| t
== FMT_O
|| t
== FMT_Z
|| t
== FMT_F
||
1536 t
== FMT_E
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_G
|| t
== FMT_L
||
1537 t
== FMT_A
|| t
== FMT_D
|| t
== FMT_DT
))
1538 fmt
->reversion_ok
= 1;
1543 /* unget_format()-- Push the given format back so that it will be
1544 returned on the next call to next_format() without affecting
1545 counts. This is necessary when we've encountered a data
1546 descriptor, but don't know what the data item is yet. The format
1547 node is pushed back, and we return control to the main program,
1548 which calls the library back with the data item (or not). */
1551 unget_format (st_parameter_dt
*dtp
, const fnode
*f
)
1553 dtp
->u
.p
.fmt
->saved_format
= f
;