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. */
36 static const fnode colon_node
= { FMT_COLON
, 0, NULL
, NULL
, {{ 0, 0, 0 }}, 0,
41 static const char posint_required
[] = "Positive integer required in format",
42 period_required
[] = "Period required in format",
43 nonneg_required
[] = "Nonnegative width required in format",
44 unexpected_element
[] = "Unexpected element '%c' in format\n",
45 unexpected_end
[] = "Unexpected end of format string",
46 bad_string
[] = "Unterminated character constant in format",
47 bad_hollerith
[] = "Hollerith constant extends past the end of the format",
48 reversion_error
[] = "Exhausted data descriptors in format",
49 zero_width
[] = "Zero width in format descriptor";
51 /* The following routines support caching format data from parsed format strings
52 into a hash table. This avoids repeatedly parsing duplicate format strings
53 or format strings in I/O statements that are repeated in loops. */
56 /* Traverse the table and free all data. */
59 free_format_hash_table (gfc_unit
*u
)
63 /* free_format_data handles any NULL pointers. */
64 for (i
= 0; i
< FORMAT_HASH_SIZE
; i
++)
66 if (u
->format_hash_table
[i
].hashed_fmt
!= NULL
)
68 free_format_data (u
->format_hash_table
[i
].hashed_fmt
);
69 free (u
->format_hash_table
[i
].key
);
71 u
->format_hash_table
[i
].key
= NULL
;
72 u
->format_hash_table
[i
].key_len
= 0;
73 u
->format_hash_table
[i
].hashed_fmt
= NULL
;
77 /* Traverse the format_data structure and reset the fnode counters. */
80 reset_node (fnode
*fn
)
87 if (fn
->format
!= FMT_LPAREN
)
90 for (f
= fn
->u
.child
; f
; f
= f
->next
)
92 if (f
->format
== FMT_RPAREN
)
99 reset_fnode_counters (st_parameter_dt
*dtp
)
106 /* Clear this pointer at the head so things start at the right place. */
107 fmt
->array
.array
[0].current
= NULL
;
109 for (f
= fmt
->array
.array
[0].u
.child
; f
; f
= f
->next
)
114 /* A simple hashing function to generate an index into the hash table. */
117 format_hash (st_parameter_dt
*dtp
)
120 gfc_charlen_type key_len
;
124 /* Hash the format string. Super simple, but what the heck! */
126 key_len
= dtp
->format_len
;
127 for (i
= 0; i
< key_len
; i
++)
129 hash
&= (FORMAT_HASH_SIZE
- 1);
135 save_parsed_format (st_parameter_dt
*dtp
)
140 hash
= format_hash (dtp
);
141 u
= dtp
->u
.p
.current_unit
;
143 /* Index into the hash table. We are simply replacing whatever is there
144 relying on probability. */
145 if (u
->format_hash_table
[hash
].hashed_fmt
!= NULL
)
146 free_format_data (u
->format_hash_table
[hash
].hashed_fmt
);
147 u
->format_hash_table
[hash
].hashed_fmt
= NULL
;
149 free (u
->format_hash_table
[hash
].key
);
150 u
->format_hash_table
[hash
].key
= dtp
->format
;
152 u
->format_hash_table
[hash
].key_len
= dtp
->format_len
;
153 u
->format_hash_table
[hash
].hashed_fmt
= dtp
->u
.p
.fmt
;
158 find_parsed_format (st_parameter_dt
*dtp
)
163 hash
= format_hash (dtp
);
164 u
= dtp
->u
.p
.current_unit
;
166 if (u
->format_hash_table
[hash
].key
!= NULL
)
168 /* See if it matches. */
169 if (u
->format_hash_table
[hash
].key_len
== dtp
->format_len
)
171 /* So far so good. */
172 if (strncmp (u
->format_hash_table
[hash
].key
,
173 dtp
->format
, dtp
->format_len
) == 0)
174 return u
->format_hash_table
[hash
].hashed_fmt
;
181 /* next_char()-- Return the next character in the format string.
182 Returns -1 when the string is done. If the literal flag is set,
183 spaces are significant, otherwise they are not. */
186 next_char (format_data
*fmt
, int literal
)
192 if (fmt
->format_string_len
== 0)
195 fmt
->format_string_len
--;
196 c
= toupper (*fmt
->format_string
++);
197 fmt
->error_element
= c
;
199 while ((c
== ' ' || c
== '\t') && !literal
);
205 /* unget_char()-- Back up one character position. */
207 #define unget_char(fmt) \
208 { fmt->format_string--; fmt->format_string_len++; }
211 /* get_fnode()-- Allocate a new format node, inserting it into the
212 current singly linked list. These are initially allocated from the
216 get_fnode (format_data
*fmt
, fnode
**head
, fnode
**tail
, format_token t
)
220 if (fmt
->avail
== &fmt
->last
->array
[FARRAY_SIZE
])
222 fmt
->last
->next
= xmalloc (sizeof (fnode_array
));
223 fmt
->last
= fmt
->last
->next
;
224 fmt
->last
->next
= NULL
;
225 fmt
->avail
= &fmt
->last
->array
[0];
228 memset (f
, '\0', sizeof (fnode
));
240 f
->source
= fmt
->format_string
;
245 /* free_format()-- Free allocated format string. */
247 free_format (st_parameter_dt
*dtp
)
249 if ((dtp
->common
.flags
& IOPARM_DT_HAS_FORMAT
) && dtp
->format
)
257 /* free_format_data()-- Free all allocated format data. */
260 free_format_data (format_data
*fmt
)
262 fnode_array
*fa
, *fa_next
;
268 /* Free vlist descriptors in the fnode_array if one was allocated. */
269 for (fnp
= fmt
->array
.array
; fnp
< &fmt
->array
.array
[FARRAY_SIZE
] &&
270 fnp
->format
!= FMT_NONE
; fnp
++)
271 if (fnp
->format
== FMT_DT
)
273 if (GFC_DESCRIPTOR_DATA(fnp
->u
.udf
.vlist
))
274 free (GFC_DESCRIPTOR_DATA(fnp
->u
.udf
.vlist
));
275 free (fnp
->u
.udf
.vlist
);
278 for (fa
= fmt
->array
.next
; fa
; fa
= fa_next
)
289 /* format_lex()-- Simple lexical analyzer for getting the next token
290 in a FORMAT string. We support a one-level token pushback in the
291 fmt->saved_token variable. */
294 format_lex (format_data
*fmt
)
301 if (fmt
->saved_token
!= FMT_NONE
)
303 token
= fmt
->saved_token
;
304 fmt
->saved_token
= FMT_NONE
;
309 c
= next_char (fmt
, 0);
330 c
= next_char (fmt
, 0);
337 fmt
->value
= c
- '0';
341 c
= next_char (fmt
, 0);
345 fmt
->value
= 10 * fmt
->value
+ c
- '0';
351 fmt
->value
= -fmt
->value
;
352 token
= FMT_SIGNED_INT
;
365 fmt
->value
= c
- '0';
369 c
= next_char (fmt
, 0);
373 fmt
->value
= 10 * fmt
->value
+ c
- '0';
377 token
= (fmt
->value
== 0) ? FMT_ZERO
: FMT_POSINT
;
401 switch (next_char (fmt
, 0))
422 switch (next_char (fmt
, 0))
439 switch (next_char (fmt
, 0))
459 fmt
->string
= fmt
->format_string
;
460 fmt
->value
= 0; /* This is the length of the string */
464 c
= next_char (fmt
, 1);
467 token
= FMT_BADSTRING
;
468 fmt
->error
= bad_string
;
474 c
= next_char (fmt
, 1);
478 token
= FMT_BADSTRING
;
479 fmt
->error
= bad_string
;
517 switch (next_char (fmt
, 0))
549 switch (next_char (fmt
, 0))
568 switch (next_char (fmt
, 0))
608 /* parse_format_list()-- Parse a format list. Assumes that a left
609 paren has already been seen. Returns a list representing the
610 parenthesis node which contains the rest of the list. */
613 parse_format_list (st_parameter_dt
*dtp
, bool *seen_dd
)
616 format_token t
, u
, t2
;
618 format_data
*fmt
= dtp
->u
.p
.fmt
;
619 bool seen_data_desc
= false;
624 /* Get the next format item */
626 t
= format_lex (fmt
);
631 t
= format_lex (fmt
);
634 fmt
->error
= "Left parenthesis required after '*'";
637 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
638 tail
->repeat
= -2; /* Signifies unlimited format. */
639 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
640 *seen_dd
= seen_data_desc
;
641 if (fmt
->error
!= NULL
)
645 fmt
->error
= "'*' requires at least one associated data descriptor";
653 t
= format_lex (fmt
);
657 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
658 tail
->repeat
= repeat
;
659 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
660 *seen_dd
= seen_data_desc
;
661 if (fmt
->error
!= NULL
)
667 get_fnode (fmt
, &head
, &tail
, FMT_SLASH
);
668 tail
->repeat
= repeat
;
672 get_fnode (fmt
, &head
, &tail
, FMT_X
);
674 tail
->u
.k
= fmt
->value
;
685 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
687 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
688 *seen_dd
= seen_data_desc
;
689 if (fmt
->error
!= NULL
)
694 case FMT_SIGNED_INT
: /* Signed integer can only precede a P format. */
695 case FMT_ZERO
: /* Same for zero. */
696 t
= format_lex (fmt
);
699 fmt
->error
= "Expected P edit descriptor in format";
704 get_fnode (fmt
, &head
, &tail
, FMT_P
);
705 tail
->u
.k
= fmt
->value
;
708 t
= format_lex (fmt
);
709 if (t
== FMT_F
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_D
710 || t
== FMT_G
|| t
== FMT_E
)
716 if (t
!= FMT_COMMA
&& t
!= FMT_RPAREN
&& t
!= FMT_SLASH
719 fmt
->error
= "Comma required after P descriptor";
723 fmt
->saved_token
= t
;
726 case FMT_P
: /* P and X require a prior number */
727 fmt
->error
= "P descriptor requires leading scale factor";
734 If we would be pedantic in the library, we would have to reject
735 an X descriptor without an integer prefix:
737 fmt->error = "X descriptor requires leading space count";
740 However, this is an extension supported by many Fortran compilers,
741 including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
742 runtime library, and make the front end reject it if the compiler
743 is in pedantic mode. The interpretation of 'X' is '1X'.
745 get_fnode (fmt
, &head
, &tail
, FMT_X
);
751 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
752 tail
->u
.string
.p
= fmt
->string
;
753 tail
->u
.string
.length
= fmt
->value
;
763 notify_std (&dtp
->common
, GFC_STD_F2003
, "Fortran 2003: Round "
764 "descriptor not allowed");
765 get_fnode (fmt
, &head
, &tail
, t
);
771 notify_std (&dtp
->common
, GFC_STD_F2003
, "Fortran 2003: DC or DP "
772 "descriptor not allowed");
779 get_fnode (fmt
, &head
, &tail
, t
);
784 get_fnode (fmt
, &head
, &tail
, FMT_COLON
);
789 get_fnode (fmt
, &head
, &tail
, FMT_SLASH
);
795 get_fnode (fmt
, &head
, &tail
, FMT_DOLLAR
);
797 notify_std (&dtp
->common
, GFC_STD_GNU
, "Extension: $ descriptor");
803 t2
= format_lex (fmt
);
804 if (t2
!= FMT_POSINT
)
806 fmt
->error
= posint_required
;
809 get_fnode (fmt
, &head
, &tail
, t
);
810 tail
->u
.n
= fmt
->value
;
832 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
833 if (fmt
->format_string_len
< 1)
835 fmt
->error
= bad_hollerith
;
839 tail
->u
.string
.p
= fmt
->format_string
;
840 tail
->u
.string
.length
= 1;
843 fmt
->format_string
++;
844 fmt
->format_string_len
--;
849 fmt
->error
= unexpected_end
;
859 fmt
->error
= unexpected_element
;
863 /* In this state, t must currently be a data descriptor. Deal with
864 things that can/must follow the descriptor */
871 t
= format_lex (fmt
);
876 if (notification_std(GFC_STD_GNU
) == NOTIFICATION_ERROR
)
878 fmt
->error
= "Extension: Zero width after L descriptor";
882 notify_std (&dtp
->common
, GFC_STD_GNU
,
883 "Zero width after L descriptor");
887 fmt
->saved_token
= t
;
888 notify_std (&dtp
->common
, GFC_STD_GNU
,
889 "Positive width required with L descriptor");
891 fmt
->value
= 1; /* Default width */
893 get_fnode (fmt
, &head
, &tail
, FMT_L
);
894 tail
->u
.n
= fmt
->value
;
895 tail
->repeat
= repeat
;
900 t
= format_lex (fmt
);
903 fmt
->error
= zero_width
;
909 fmt
->saved_token
= t
;
910 fmt
->value
= -1; /* Width not present */
913 get_fnode (fmt
, &head
, &tail
, FMT_A
);
914 tail
->repeat
= repeat
;
915 tail
->u
.n
= fmt
->value
;
925 get_fnode (fmt
, &head
, &tail
, t
);
926 tail
->repeat
= repeat
;
928 u
= format_lex (fmt
);
930 /* Processing for zero width formats. */
934 standard
= GFC_STD_F95
;
936 standard
= GFC_STD_F2008
;
938 standard
= GFC_STD_F2018
;
940 if (notification_std (standard
) == NOTIFICATION_ERROR
941 || dtp
->u
.p
.mode
== READING
)
943 fmt
->error
= zero_width
;
948 /* Look for the dot seperator. */
949 u
= format_lex (fmt
);
952 fmt
->saved_token
= u
;
956 /* Look for the precision. */
957 u
= format_lex (fmt
);
958 if (u
!= FMT_ZERO
&& u
!= FMT_POSINT
)
960 fmt
->error
= nonneg_required
;
963 tail
->u
.real
.d
= fmt
->value
;
965 /* Look for optional exponent, not allowed for FMT_D */
968 u
= format_lex (fmt
);
970 fmt
->saved_token
= u
;
973 u
= format_lex (fmt
);
978 notify_std (&dtp
->common
, GFC_STD_F2018
,
979 "Positive exponent width required");
983 fmt
->error
= "Positive exponent width required in "
984 "format string at %L";
988 tail
->u
.real
.e
= fmt
->value
;
993 /* Processing for positive width formats. */
996 tail
->u
.real
.w
= fmt
->value
;
998 /* Look for the dot separator. Because of legacy behaviors
999 we do some look ahead for missing things. */
1001 t
= format_lex (fmt
);
1002 if (t
!= FMT_PERIOD
)
1004 /* We treat a missing decimal descriptor as 0. Note: This is only
1005 allowed if -std=legacy, otherwise an error occurs. */
1006 if (compile_options
.warn_std
!= 0)
1008 fmt
->error
= period_required
;
1011 fmt
->saved_token
= t
;
1013 tail
->u
.real
.e
= -1;
1017 /* If we made it here, we should have the dot so look for the
1019 t
= format_lex (fmt
);
1020 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1022 fmt
->error
= nonneg_required
;
1025 tail
->u
.real
.d
= fmt
->value
;
1026 tail
->u
.real
.e
= -1;
1028 /* Done with D and F formats. */
1029 if (t2
== FMT_D
|| t2
== FMT_F
)
1035 /* Look for optional exponent */
1036 u
= format_lex (fmt
);
1038 fmt
->saved_token
= u
;
1041 u
= format_lex (fmt
);
1042 if (u
!= FMT_POSINT
)
1046 notify_std (&dtp
->common
, GFC_STD_F2018
,
1047 "Positive exponent width required");
1051 fmt
->error
= "Positive exponent width required in "
1052 "format string at %L";
1056 tail
->u
.real
.e
= fmt
->value
;
1061 /* Old DEC codes may not have width or precision specified. */
1062 if (dtp
->u
.p
.mode
== WRITING
&& (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
))
1064 tail
->u
.real
.w
= DEFAULT_WIDTH
;
1066 tail
->u
.real
.e
= -1;
1067 fmt
->saved_token
= u
;
1073 get_fnode (fmt
, &head
, &tail
, t
);
1074 tail
->repeat
= repeat
;
1076 t
= format_lex (fmt
);
1078 /* Initialize the vlist to a zero size, rank-one array. */
1079 tail
->u
.udf
.vlist
= xmalloc (sizeof(gfc_array_i4
)
1080 + sizeof (descriptor_dimension
));
1081 GFC_DESCRIPTOR_DATA(tail
->u
.udf
.vlist
) = NULL
;
1082 GFC_DIMENSION_SET(tail
->u
.udf
.vlist
->dim
[0],1, 0, 0);
1084 if (t
== FMT_STRING
)
1086 /* Get pointer to the optional format string. */
1087 tail
->u
.udf
.string
= fmt
->string
;
1088 tail
->u
.udf
.string_len
= fmt
->value
;
1089 t
= format_lex (fmt
);
1091 if (t
== FMT_LPAREN
)
1093 /* Temporary buffer to hold the vlist values. */
1094 GFC_INTEGER_4 temp
[FARRAY_SIZE
];
1097 t
= format_lex (fmt
);
1098 if (t
!= FMT_POSINT
)
1100 fmt
->error
= posint_required
;
1103 /* Save the positive integer value. */
1104 temp
[i
++] = fmt
->value
;
1105 t
= format_lex (fmt
);
1108 if (t
== FMT_RPAREN
)
1110 /* We have parsed the complete vlist so initialize the
1111 array descriptor and save it in the format node. */
1112 gfc_full_array_i4
*vp
= tail
->u
.udf
.vlist
;
1113 GFC_DESCRIPTOR_DATA(vp
) = xmalloc (i
* sizeof(GFC_INTEGER_4
));
1114 GFC_DIMENSION_SET(vp
->dim
[0],1, i
, 1);
1115 memcpy (GFC_DESCRIPTOR_DATA(vp
), temp
, i
* sizeof(GFC_INTEGER_4
));
1118 fmt
->error
= unexpected_element
;
1121 fmt
->saved_token
= t
;
1124 if (repeat
> fmt
->format_string_len
)
1126 fmt
->error
= bad_hollerith
;
1130 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
1131 tail
->u
.string
.p
= fmt
->format_string
;
1132 tail
->u
.string
.length
= repeat
;
1135 fmt
->format_string
+= fmt
->value
;
1136 fmt
->format_string_len
-= repeat
;
1145 get_fnode (fmt
, &head
, &tail
, t
);
1146 tail
->repeat
= repeat
;
1148 t
= format_lex (fmt
);
1150 if (dtp
->u
.p
.mode
== READING
)
1152 if (t
!= FMT_POSINT
)
1154 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1156 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1157 tail
->u
.integer
.m
= -1;
1158 fmt
->saved_token
= t
;
1161 fmt
->error
= posint_required
;
1167 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1169 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1171 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1172 tail
->u
.integer
.m
= -1;
1173 fmt
->saved_token
= t
;
1176 fmt
->error
= nonneg_required
;
1181 tail
->u
.integer
.w
= fmt
->value
;
1182 tail
->u
.integer
.m
= -1;
1184 t
= format_lex (fmt
);
1185 if (t
!= FMT_PERIOD
)
1187 fmt
->saved_token
= t
;
1191 t
= format_lex (fmt
);
1192 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1194 fmt
->error
= nonneg_required
;
1198 tail
->u
.integer
.m
= fmt
->value
;
1201 if (tail
->u
.integer
.w
!= 0 && tail
->u
.integer
.m
> tail
->u
.integer
.w
)
1203 fmt
->error
= "Minimum digits exceeds field width";
1210 fmt
->error
= unexpected_element
;
1214 /* Between a descriptor and what comes next */
1216 t
= format_lex (fmt
);
1227 get_fnode (fmt
, &head
, &tail
, t
);
1229 goto optional_comma
;
1232 fmt
->error
= unexpected_end
;
1236 /* Assume a missing comma, this is a GNU extension */
1240 /* Optional comma is a weird between state where we've just finished
1241 reading a colon, slash or P descriptor. */
1243 t
= format_lex (fmt
);
1252 default: /* Assume that we have another format item */
1253 fmt
->saved_token
= t
;
1265 /* format_error()-- Generate an error message for a format statement.
1266 If the node that gives the location of the error is NULL, the error
1267 is assumed to happen at parse time, and the current location of the
1270 We generate a message showing where the problem is. We take extra
1271 care to print only the relevant part of the format if it is longer
1272 than a standard 80 column display. */
1275 format_error (st_parameter_dt
*dtp
, const fnode
*f
, const char *message
)
1277 int width
, i
, offset
;
1279 char *p
, buffer
[BUFLEN
];
1280 format_data
*fmt
= dtp
->u
.p
.fmt
;
1284 else /* This should not happen. */
1287 if (message
== unexpected_element
)
1288 snprintf (buffer
, BUFLEN
, message
, fmt
->error_element
);
1290 snprintf (buffer
, BUFLEN
, "%s\n", message
);
1292 /* Get the offset into the format string where the error occurred. */
1293 offset
= dtp
->format_len
- (fmt
->reversion_ok
?
1294 (int) strlen(p
) : fmt
->format_string_len
);
1296 width
= dtp
->format_len
;
1301 /* Show the format */
1303 p
= strchr (buffer
, '\0');
1306 memcpy (p
, dtp
->format
, width
);
1311 /* Show where the problem is */
1313 for (i
= 1; i
< offset
; i
++)
1319 generate_error (&dtp
->common
, LIBERROR_FORMAT
, buffer
);
1323 /* revert()-- Do reversion of the format. Control reverts to the left
1324 parenthesis that matches the rightmost right parenthesis. From our
1325 tree structure, we are looking for the rightmost parenthesis node
1326 at the second level, the first level always being a single
1327 parenthesis node. If this node doesn't exit, we use the top
1331 revert (st_parameter_dt
*dtp
)
1334 format_data
*fmt
= dtp
->u
.p
.fmt
;
1336 dtp
->u
.p
.reversion_flag
= 1;
1340 for (f
= fmt
->array
.array
[0].u
.child
; f
; f
= f
->next
)
1341 if (f
->format
== FMT_LPAREN
)
1344 /* If r is NULL because no node was found, the whole tree will be used */
1346 fmt
->array
.array
[0].current
= r
;
1347 fmt
->array
.array
[0].count
= 0;
1350 /* parse_format()-- Parse a format string. */
1353 parse_format (st_parameter_dt
*dtp
)
1356 bool format_cache_ok
, seen_data_desc
= false;
1358 /* Don't cache for internal units and set an arbitrary limit on the
1359 size of format strings we will cache. (Avoids memory issues.)
1360 Also, the format_hash_table resides in the current_unit, so
1361 child_dtio procedures would overwrite the parent table */
1362 format_cache_ok
= !is_internal_unit (dtp
)
1363 && (dtp
->u
.p
.current_unit
->child_dtio
== 0);
1365 /* Lookup format string to see if it has already been parsed. */
1366 if (format_cache_ok
)
1368 dtp
->u
.p
.fmt
= find_parsed_format (dtp
);
1370 if (dtp
->u
.p
.fmt
!= NULL
)
1372 dtp
->u
.p
.fmt
->reversion_ok
= 0;
1373 dtp
->u
.p
.fmt
->saved_token
= FMT_NONE
;
1374 dtp
->u
.p
.fmt
->saved_format
= NULL
;
1375 reset_fnode_counters (dtp
);
1380 /* Not found so proceed as follows. */
1382 char *fmt_string
= fc_strdup_notrim (dtp
->format
, dtp
->format_len
);
1383 dtp
->format
= fmt_string
;
1385 dtp
->u
.p
.fmt
= fmt
= xmalloc (sizeof (format_data
));
1386 fmt
->format_string
= dtp
->format
;
1387 fmt
->format_string_len
= dtp
->format_len
;
1390 fmt
->saved_token
= FMT_NONE
;
1394 /* Initialize variables used during traversal of the tree. */
1396 fmt
->reversion_ok
= 0;
1397 fmt
->saved_format
= NULL
;
1399 /* Initialize the fnode_array. */
1401 memset (&(fmt
->array
), 0, sizeof(fmt
->array
));
1403 /* Allocate the first format node as the root of the tree. */
1405 fmt
->last
= &fmt
->array
;
1406 fmt
->last
->next
= NULL
;
1407 fmt
->avail
= &fmt
->array
.array
[0];
1409 memset (fmt
->avail
, 0, sizeof (*fmt
->avail
));
1410 fmt
->avail
->format
= FMT_LPAREN
;
1411 fmt
->avail
->repeat
= 1;
1414 if (format_lex (fmt
) == FMT_LPAREN
)
1415 fmt
->array
.array
[0].u
.child
= parse_format_list (dtp
, &seen_data_desc
);
1417 fmt
->error
= "Missing initial left parenthesis in format";
1419 if (format_cache_ok
)
1420 save_parsed_format (dtp
);
1422 dtp
->u
.p
.format_not_saved
= 1;
1425 format_error (dtp
, NULL
, fmt
->error
);
1429 /* next_format0()-- Get the next format node without worrying about
1430 reversion. Returns NULL when we hit the end of the list.
1431 Parenthesis nodes are incremented after the list has been
1432 exhausted, other nodes are incremented before they are returned. */
1434 static const fnode
*
1435 next_format0 (fnode
*f
)
1442 if (f
->format
!= FMT_LPAREN
)
1445 if (f
->count
<= f
->repeat
)
1452 /* Deal with a parenthesis node with unlimited format. */
1454 if (f
->repeat
== -2) /* -2 signifies unlimited. */
1457 if (f
->current
== NULL
)
1458 f
->current
= f
->u
.child
;
1460 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1462 r
= next_format0 (f
->current
);
1468 /* Deal with a parenthesis node with specific repeat count. */
1469 for (; f
->count
< f
->repeat
; f
->count
++)
1471 if (f
->current
== NULL
)
1472 f
->current
= f
->u
.child
;
1474 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1476 r
= next_format0 (f
->current
);
1487 /* next_format()-- Return the next format node. If the format list
1488 ends up being exhausted, we do reversion. Reversion is only
1489 allowed if we've seen a data descriptor since the
1490 initialization or the last reversion. We return NULL if there
1491 are no more data descriptors to return (which is an error
1495 next_format (st_parameter_dt
*dtp
)
1499 format_data
*fmt
= dtp
->u
.p
.fmt
;
1501 if (fmt
->saved_format
!= NULL
)
1502 { /* Deal with a pushed-back format node */
1503 f
= fmt
->saved_format
;
1504 fmt
->saved_format
= NULL
;
1508 f
= next_format0 (&fmt
->array
.array
[0]);
1511 if (!fmt
->reversion_ok
)
1514 fmt
->reversion_ok
= 0;
1517 f
= next_format0 (&fmt
->array
.array
[0]);
1520 format_error (dtp
, NULL
, reversion_error
);
1524 /* Push the first reverted token and return a colon node in case
1525 there are no more data items. */
1527 fmt
->saved_format
= f
;
1531 /* If this is a data edit descriptor, then reversion has become OK. */
1535 if (!fmt
->reversion_ok
&&
1536 (t
== FMT_I
|| t
== FMT_B
|| t
== FMT_O
|| t
== FMT_Z
|| t
== FMT_F
||
1537 t
== FMT_E
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_G
|| t
== FMT_L
||
1538 t
== FMT_A
|| t
== FMT_D
|| t
== FMT_DT
))
1539 fmt
->reversion_ok
= 1;
1544 /* unget_format()-- Push the given format back so that it will be
1545 returned on the next call to next_format() without affecting
1546 counts. This is necessary when we've encountered a data
1547 descriptor, but don't know what the data item is yet. The format
1548 node is pushed back, and we return control to the main program,
1549 which calls the library back with the data item (or not). */
1552 unget_format (st_parameter_dt
*dtp
, const fnode
*f
)
1554 dtp
->u
.p
.fmt
->saved_format
= f
;