]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/io/format.c
1 /* Copyright (C) 2002-2023 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 free (GFC_DESCRIPTOR_DATA(fnp
->u
.udf
.vlist
));
273 free (fnp
->u
.udf
.vlist
);
276 for (fa
= fmt
->array
.next
; fa
; fa
= fa_next
)
287 /* format_lex()-- Simple lexical analyzer for getting the next token
288 in a FORMAT string. We support a one-level token pushback in the
289 fmt->saved_token variable. */
292 format_lex (format_data
*fmt
)
299 if (fmt
->saved_token
!= FMT_NONE
)
301 token
= fmt
->saved_token
;
302 fmt
->saved_token
= FMT_NONE
;
307 c
= next_char (fmt
, 0);
328 c
= next_char (fmt
, 0);
329 if (!safe_isdigit (c
))
335 fmt
->value
= c
- '0';
339 c
= next_char (fmt
, 0);
340 if (!safe_isdigit (c
))
343 fmt
->value
= 10 * fmt
->value
+ c
- '0';
349 fmt
->value
= -fmt
->value
;
350 token
= FMT_SIGNED_INT
;
363 fmt
->value
= c
- '0';
367 c
= next_char (fmt
, 0);
368 if (!safe_isdigit (c
))
371 fmt
->value
= 10 * fmt
->value
+ c
- '0';
375 token
= (fmt
->value
== 0) ? FMT_ZERO
: FMT_POSINT
;
399 switch (next_char (fmt
, 0))
420 switch (next_char (fmt
, 0))
437 switch (next_char (fmt
, 0))
457 fmt
->string
= fmt
->format_string
;
458 fmt
->value
= 0; /* This is the length of the string */
462 c
= next_char (fmt
, 1);
465 token
= FMT_BADSTRING
;
466 fmt
->error
= bad_string
;
472 c
= next_char (fmt
, 1);
476 token
= FMT_BADSTRING
;
477 fmt
->error
= bad_string
;
515 switch (next_char (fmt
, 0))
547 switch (next_char (fmt
, 0))
566 switch (next_char (fmt
, 0))
606 /* parse_format_list()-- Parse a format list. Assumes that a left
607 paren has already been seen. Returns a list representing the
608 parenthesis node which contains the rest of the list. */
611 parse_format_list (st_parameter_dt
*dtp
, bool *seen_dd
)
614 format_token t
, u
, t2
;
616 format_data
*fmt
= dtp
->u
.p
.fmt
;
617 bool seen_data_desc
= false;
622 /* Get the next format item */
624 t
= format_lex (fmt
);
629 t
= format_lex (fmt
);
632 fmt
->error
= "Left parenthesis required after '*'";
635 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
636 tail
->repeat
= -2; /* Signifies unlimited format. */
637 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
638 *seen_dd
= seen_data_desc
;
639 if (fmt
->error
!= NULL
)
643 fmt
->error
= "'*' requires at least one associated data descriptor";
651 t
= format_lex (fmt
);
655 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
656 tail
->repeat
= repeat
;
657 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
658 *seen_dd
= seen_data_desc
;
659 if (fmt
->error
!= NULL
)
665 get_fnode (fmt
, &head
, &tail
, FMT_SLASH
);
666 tail
->repeat
= repeat
;
670 get_fnode (fmt
, &head
, &tail
, FMT_X
);
672 tail
->u
.k
= fmt
->value
;
683 get_fnode (fmt
, &head
, &tail
, FMT_LPAREN
);
685 tail
->u
.child
= parse_format_list (dtp
, &seen_data_desc
);
686 *seen_dd
= seen_data_desc
;
687 if (fmt
->error
!= NULL
)
692 case FMT_SIGNED_INT
: /* Signed integer can only precede a P format. */
693 case FMT_ZERO
: /* Same for zero. */
694 t
= format_lex (fmt
);
697 fmt
->error
= "Expected P edit descriptor in format";
702 get_fnode (fmt
, &head
, &tail
, FMT_P
);
703 tail
->u
.k
= fmt
->value
;
706 t
= format_lex (fmt
);
707 if (t
== FMT_F
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_D
708 || t
== FMT_G
|| t
== FMT_E
)
714 if (t
!= FMT_COMMA
&& t
!= FMT_RPAREN
&& t
!= FMT_SLASH
717 fmt
->error
= "Comma required after P descriptor";
721 fmt
->saved_token
= t
;
724 case FMT_P
: /* P and X require a prior number */
725 fmt
->error
= "P descriptor requires leading scale factor";
732 If we would be pedantic in the library, we would have to reject
733 an X descriptor without an integer prefix:
735 fmt->error = "X descriptor requires leading space count";
738 However, this is an extension supported by many Fortran compilers,
739 including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
740 runtime library, and make the front end reject it if the compiler
741 is in pedantic mode. The interpretation of 'X' is '1X'.
743 get_fnode (fmt
, &head
, &tail
, FMT_X
);
749 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
750 tail
->u
.string
.p
= fmt
->string
;
751 tail
->u
.string
.length
= fmt
->value
;
761 notify_std (&dtp
->common
, GFC_STD_F2003
, "Fortran 2003: Round "
762 "descriptor not allowed");
763 get_fnode (fmt
, &head
, &tail
, t
);
769 notify_std (&dtp
->common
, GFC_STD_F2003
, "Fortran 2003: DC or DP "
770 "descriptor not allowed");
777 get_fnode (fmt
, &head
, &tail
, t
);
782 get_fnode (fmt
, &head
, &tail
, FMT_COLON
);
787 get_fnode (fmt
, &head
, &tail
, FMT_SLASH
);
793 get_fnode (fmt
, &head
, &tail
, FMT_DOLLAR
);
795 notify_std (&dtp
->common
, GFC_STD_GNU
, "Extension: $ descriptor");
801 t2
= format_lex (fmt
);
802 if (t2
!= FMT_POSINT
)
804 fmt
->error
= posint_required
;
807 get_fnode (fmt
, &head
, &tail
, t
);
808 tail
->u
.n
= fmt
->value
;
830 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
831 if (fmt
->format_string_len
< 1)
833 fmt
->error
= bad_hollerith
;
837 tail
->u
.string
.p
= fmt
->format_string
;
838 tail
->u
.string
.length
= 1;
841 fmt
->format_string
++;
842 fmt
->format_string_len
--;
847 fmt
->error
= unexpected_end
;
857 fmt
->error
= unexpected_element
;
861 /* In this state, t must currently be a data descriptor. Deal with
862 things that can/must follow the descriptor */
869 t
= format_lex (fmt
);
874 if (notification_std(GFC_STD_GNU
) == NOTIFICATION_ERROR
)
876 fmt
->error
= "Extension: Zero width after L descriptor";
880 notify_std (&dtp
->common
, GFC_STD_GNU
,
881 "Zero width after L descriptor");
885 fmt
->saved_token
= t
;
886 notify_std (&dtp
->common
, GFC_STD_GNU
,
887 "Positive width required with L descriptor");
889 fmt
->value
= 1; /* Default width */
891 get_fnode (fmt
, &head
, &tail
, FMT_L
);
892 tail
->u
.n
= fmt
->value
;
893 tail
->repeat
= repeat
;
898 t
= format_lex (fmt
);
901 fmt
->error
= zero_width
;
907 fmt
->saved_token
= t
;
908 fmt
->value
= -1; /* Width not present */
911 get_fnode (fmt
, &head
, &tail
, FMT_A
);
912 tail
->repeat
= repeat
;
913 tail
->u
.n
= fmt
->value
;
923 get_fnode (fmt
, &head
, &tail
, t
);
924 tail
->repeat
= repeat
;
926 u
= format_lex (fmt
);
928 /* Processing for zero width formats. */
932 standard
= GFC_STD_F95
;
934 standard
= GFC_STD_F2008
;
936 standard
= GFC_STD_F2018
;
938 if (notification_std (standard
) == NOTIFICATION_ERROR
939 || dtp
->u
.p
.mode
== READING
)
941 fmt
->error
= zero_width
;
946 /* Look for the dot seperator. */
947 u
= format_lex (fmt
);
950 fmt
->saved_token
= u
;
954 /* Look for the precision. */
955 u
= format_lex (fmt
);
956 if (u
!= FMT_ZERO
&& u
!= FMT_POSINT
)
958 fmt
->error
= nonneg_required
;
961 tail
->u
.real
.d
= fmt
->value
;
963 /* Look for optional exponent, not allowed for FMT_D */
966 u
= format_lex (fmt
);
968 fmt
->saved_token
= u
;
971 u
= format_lex (fmt
);
976 notify_std (&dtp
->common
, GFC_STD_F2018
,
977 "Positive exponent width required");
981 fmt
->error
= "Positive exponent width required in "
982 "format string at %L";
986 tail
->u
.real
.e
= fmt
->value
;
991 /* Processing for positive width formats. */
994 tail
->u
.real
.w
= fmt
->value
;
996 /* Look for the dot separator. Because of legacy behaviors
997 we do some look ahead for missing things. */
999 t
= format_lex (fmt
);
1000 if (t
!= FMT_PERIOD
)
1002 /* We treat a missing decimal descriptor as 0. Note: This is only
1003 allowed if -std=legacy, otherwise an error occurs. */
1004 if (compile_options
.warn_std
!= 0)
1006 fmt
->error
= period_required
;
1009 fmt
->saved_token
= t
;
1011 tail
->u
.real
.e
= -1;
1015 /* If we made it here, we should have the dot so look for the
1017 t
= format_lex (fmt
);
1018 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1020 fmt
->error
= nonneg_required
;
1023 tail
->u
.real
.d
= fmt
->value
;
1024 tail
->u
.real
.e
= -1;
1026 /* Done with D and F formats. */
1027 if (t2
== FMT_D
|| t2
== FMT_F
)
1033 /* Look for optional exponent */
1034 u
= format_lex (fmt
);
1036 fmt
->saved_token
= u
;
1039 u
= format_lex (fmt
);
1040 if (u
!= FMT_POSINT
)
1044 notify_std (&dtp
->common
, GFC_STD_F2018
,
1045 "Positive exponent width required");
1049 fmt
->error
= "Positive exponent width required in "
1050 "format string at %L";
1054 tail
->u
.real
.e
= fmt
->value
;
1059 /* Old DEC codes may not have width or precision specified. */
1060 if (dtp
->u
.p
.mode
== WRITING
&& (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
))
1062 tail
->u
.real
.w
= DEFAULT_WIDTH
;
1064 tail
->u
.real
.e
= -1;
1065 fmt
->saved_token
= u
;
1071 get_fnode (fmt
, &head
, &tail
, t
);
1072 tail
->repeat
= repeat
;
1074 t
= format_lex (fmt
);
1076 /* Initialize the vlist to a zero size, rank-one array. */
1077 tail
->u
.udf
.vlist
= xmalloc (sizeof(gfc_array_i4
)
1078 + sizeof (descriptor_dimension
));
1079 GFC_DESCRIPTOR_DATA(tail
->u
.udf
.vlist
) = NULL
;
1080 GFC_DIMENSION_SET(tail
->u
.udf
.vlist
->dim
[0],1, 0, 0);
1082 if (t
== FMT_STRING
)
1084 /* Get pointer to the optional format string. */
1085 tail
->u
.udf
.string
= fmt
->string
;
1086 tail
->u
.udf
.string_len
= fmt
->value
;
1087 t
= format_lex (fmt
);
1089 if (t
== FMT_LPAREN
)
1091 /* Temporary buffer to hold the vlist values. */
1092 GFC_INTEGER_4 temp
[FARRAY_SIZE
];
1095 t
= format_lex (fmt
);
1096 if (t
!= FMT_POSINT
)
1098 fmt
->error
= posint_required
;
1101 /* Save the positive integer value. */
1102 temp
[i
++] = fmt
->value
;
1103 t
= format_lex (fmt
);
1106 if (t
== FMT_RPAREN
)
1108 /* We have parsed the complete vlist so initialize the
1109 array descriptor and save it in the format node. */
1110 gfc_full_array_i4
*vp
= tail
->u
.udf
.vlist
;
1111 GFC_DESCRIPTOR_DATA(vp
) = xmalloc (i
* sizeof(GFC_INTEGER_4
));
1112 GFC_DIMENSION_SET(vp
->dim
[0],1, i
, 1);
1113 memcpy (GFC_DESCRIPTOR_DATA(vp
), temp
, i
* sizeof(GFC_INTEGER_4
));
1116 fmt
->error
= unexpected_element
;
1119 fmt
->saved_token
= t
;
1122 if (repeat
> fmt
->format_string_len
)
1124 fmt
->error
= bad_hollerith
;
1128 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
1129 tail
->u
.string
.p
= fmt
->format_string
;
1130 tail
->u
.string
.length
= repeat
;
1133 fmt
->format_string
+= fmt
->value
;
1134 fmt
->format_string_len
-= repeat
;
1143 get_fnode (fmt
, &head
, &tail
, t
);
1144 tail
->repeat
= repeat
;
1146 t
= format_lex (fmt
);
1148 if (dtp
->u
.p
.mode
== READING
)
1150 if (t
!= FMT_POSINT
)
1152 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1154 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1155 tail
->u
.integer
.m
= -1;
1156 fmt
->saved_token
= t
;
1159 fmt
->error
= posint_required
;
1165 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1167 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1169 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1170 tail
->u
.integer
.m
= -1;
1171 fmt
->saved_token
= t
;
1174 fmt
->error
= nonneg_required
;
1179 tail
->u
.integer
.w
= fmt
->value
;
1180 tail
->u
.integer
.m
= -1;
1182 t
= format_lex (fmt
);
1183 if (t
!= FMT_PERIOD
)
1185 fmt
->saved_token
= t
;
1189 t
= format_lex (fmt
);
1190 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1192 fmt
->error
= nonneg_required
;
1196 tail
->u
.integer
.m
= fmt
->value
;
1199 if (tail
->u
.integer
.w
!= 0 && tail
->u
.integer
.m
> tail
->u
.integer
.w
)
1201 fmt
->error
= "Minimum digits exceeds field width";
1208 fmt
->error
= unexpected_element
;
1212 /* Between a descriptor and what comes next */
1214 t
= format_lex (fmt
);
1225 get_fnode (fmt
, &head
, &tail
, t
);
1227 goto optional_comma
;
1230 fmt
->error
= unexpected_end
;
1234 /* Assume a missing comma, this is a GNU extension */
1238 /* Optional comma is a weird between state where we've just finished
1239 reading a colon, slash or P descriptor. */
1241 t
= format_lex (fmt
);
1250 default: /* Assume that we have another format item */
1251 fmt
->saved_token
= t
;
1263 /* format_error()-- Generate an error message for a format statement.
1264 If the node that gives the location of the error is NULL, the error
1265 is assumed to happen at parse time, and the current location of the
1268 We generate a message showing where the problem is. We take extra
1269 care to print only the relevant part of the format if it is longer
1270 than a standard 80 column display. */
1273 format_error (st_parameter_dt
*dtp
, const fnode
*f
, const char *message
)
1275 int width
, i
, offset
;
1277 char *p
, buffer
[BUFLEN
];
1278 format_data
*fmt
= dtp
->u
.p
.fmt
;
1282 else /* This should not happen. */
1285 if (message
== unexpected_element
)
1286 snprintf (buffer
, BUFLEN
, message
, fmt
->error_element
);
1288 snprintf (buffer
, BUFLEN
, "%s\n", message
);
1290 /* Get the offset into the format string where the error occurred. */
1291 offset
= dtp
->format_len
- (fmt
->reversion_ok
?
1292 (int) strlen(p
) : fmt
->format_string_len
);
1294 width
= dtp
->format_len
;
1299 /* Show the format */
1301 p
= strchr (buffer
, '\0');
1304 memcpy (p
, dtp
->format
, width
);
1309 /* Show where the problem is */
1311 for (i
= 1; i
< offset
; i
++)
1317 generate_error (&dtp
->common
, LIBERROR_FORMAT
, buffer
);
1321 /* revert()-- Do reversion of the format. Control reverts to the left
1322 parenthesis that matches the rightmost right parenthesis. From our
1323 tree structure, we are looking for the rightmost parenthesis node
1324 at the second level, the first level always being a single
1325 parenthesis node. If this node doesn't exit, we use the top
1329 revert (st_parameter_dt
*dtp
)
1332 format_data
*fmt
= dtp
->u
.p
.fmt
;
1334 dtp
->u
.p
.reversion_flag
= 1;
1338 for (f
= fmt
->array
.array
[0].u
.child
; f
; f
= f
->next
)
1339 if (f
->format
== FMT_LPAREN
)
1342 /* If r is NULL because no node was found, the whole tree will be used */
1344 fmt
->array
.array
[0].current
= r
;
1345 fmt
->array
.array
[0].count
= 0;
1348 /* parse_format()-- Parse a format string. */
1351 parse_format (st_parameter_dt
*dtp
)
1354 bool format_cache_ok
, seen_data_desc
= false;
1356 /* Don't cache for internal units and set an arbitrary limit on the
1357 size of format strings we will cache. (Avoids memory issues.)
1358 Also, the format_hash_table resides in the current_unit, so
1359 child_dtio procedures would overwrite the parent table */
1360 format_cache_ok
= !is_internal_unit (dtp
)
1361 && (dtp
->u
.p
.current_unit
->child_dtio
== 0);
1363 /* Lookup format string to see if it has already been parsed. */
1364 if (format_cache_ok
)
1366 dtp
->u
.p
.fmt
= find_parsed_format (dtp
);
1368 if (dtp
->u
.p
.fmt
!= NULL
)
1370 dtp
->u
.p
.fmt
->reversion_ok
= 0;
1371 dtp
->u
.p
.fmt
->saved_token
= FMT_NONE
;
1372 dtp
->u
.p
.fmt
->saved_format
= NULL
;
1373 reset_fnode_counters (dtp
);
1378 /* Not found so proceed as follows. */
1380 char *fmt_string
= fc_strdup_notrim (dtp
->format
, dtp
->format_len
);
1381 dtp
->format
= fmt_string
;
1383 dtp
->u
.p
.fmt
= fmt
= xmalloc (sizeof (format_data
));
1384 fmt
->format_string
= dtp
->format
;
1385 fmt
->format_string_len
= dtp
->format_len
;
1388 fmt
->saved_token
= FMT_NONE
;
1392 /* Initialize variables used during traversal of the tree. */
1394 fmt
->reversion_ok
= 0;
1395 fmt
->saved_format
= NULL
;
1397 /* Initialize the fnode_array. */
1399 memset (&(fmt
->array
), 0, sizeof(fmt
->array
));
1401 /* Allocate the first format node as the root of the tree. */
1403 fmt
->last
= &fmt
->array
;
1404 fmt
->last
->next
= NULL
;
1405 fmt
->avail
= &fmt
->array
.array
[0];
1407 memset (fmt
->avail
, 0, sizeof (*fmt
->avail
));
1408 fmt
->avail
->format
= FMT_LPAREN
;
1409 fmt
->avail
->repeat
= 1;
1412 if (format_lex (fmt
) == FMT_LPAREN
)
1413 fmt
->array
.array
[0].u
.child
= parse_format_list (dtp
, &seen_data_desc
);
1415 fmt
->error
= "Missing initial left parenthesis in format";
1417 if (format_cache_ok
)
1418 save_parsed_format (dtp
);
1420 dtp
->u
.p
.format_not_saved
= 1;
1423 format_error (dtp
, NULL
, fmt
->error
);
1427 /* next_format0()-- Get the next format node without worrying about
1428 reversion. Returns NULL when we hit the end of the list.
1429 Parenthesis nodes are incremented after the list has been
1430 exhausted, other nodes are incremented before they are returned. */
1432 static const fnode
*
1433 next_format0 (fnode
*f
)
1440 if (f
->format
!= FMT_LPAREN
)
1443 if (f
->count
<= f
->repeat
)
1450 /* Deal with a parenthesis node with unlimited format. */
1452 if (f
->repeat
== -2) /* -2 signifies unlimited. */
1455 if (f
->current
== NULL
)
1456 f
->current
= f
->u
.child
;
1458 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1460 r
= next_format0 (f
->current
);
1466 /* Deal with a parenthesis node with specific repeat count. */
1467 for (; f
->count
< f
->repeat
; f
->count
++)
1469 if (f
->current
== NULL
)
1470 f
->current
= f
->u
.child
;
1472 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1474 r
= next_format0 (f
->current
);
1485 /* next_format()-- Return the next format node. If the format list
1486 ends up being exhausted, we do reversion. Reversion is only
1487 allowed if we've seen a data descriptor since the
1488 initialization or the last reversion. We return NULL if there
1489 are no more data descriptors to return (which is an error
1493 next_format (st_parameter_dt
*dtp
)
1497 format_data
*fmt
= dtp
->u
.p
.fmt
;
1499 if (fmt
->saved_format
!= NULL
)
1500 { /* Deal with a pushed-back format node */
1501 f
= fmt
->saved_format
;
1502 fmt
->saved_format
= NULL
;
1506 f
= next_format0 (&fmt
->array
.array
[0]);
1509 if (!fmt
->reversion_ok
)
1512 fmt
->reversion_ok
= 0;
1515 f
= next_format0 (&fmt
->array
.array
[0]);
1518 format_error (dtp
, NULL
, reversion_error
);
1522 /* Push the first reverted token and return a colon node in case
1523 there are no more data items. */
1525 fmt
->saved_format
= f
;
1529 /* If this is a data edit descriptor, then reversion has become OK. */
1533 if (!fmt
->reversion_ok
&&
1534 (t
== FMT_I
|| t
== FMT_B
|| t
== FMT_O
|| t
== FMT_Z
|| t
== FMT_F
||
1535 t
== FMT_E
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_G
|| t
== FMT_L
||
1536 t
== FMT_A
|| t
== FMT_D
|| t
== FMT_DT
))
1537 fmt
->reversion_ok
= 1;
1542 /* unget_format()-- Push the given format back so that it will be
1543 returned on the next call to next_format() without affecting
1544 counts. This is necessary when we've encountered a data
1545 descriptor, but don't know what the data item is yet. The format
1546 node is pushed back, and we return control to the main program,
1547 which calls the library back with the data item (or not). */
1550 unget_format (st_parameter_dt
*dtp
, const fnode
*f
)
1552 dtp
->u
.p
.fmt
->saved_format
= f
;