]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/io/format.c
3be861fb19c48c995de3e4d42dd8cc15cbeee97f
1 /* Copyright (C) 2002-2020 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;
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. */
932 if (notification_std (GFC_STD_F2008
) == NOTIFICATION_ERROR
933 || dtp
->u
.p
.mode
== READING
)
935 fmt
->error
= zero_width
;
940 /* Look for the dot seperator. */
941 u
= format_lex (fmt
);
944 fmt
->saved_token
= u
;
948 /* Look for the precision. */
949 u
= format_lex (fmt
);
950 if (u
!= FMT_ZERO
&& u
!= FMT_POSINT
)
952 fmt
->error
= nonneg_required
;
955 tail
->u
.real
.d
= fmt
->value
;
957 /* Look for optional exponent, not allowed for FMT_D */
960 u
= format_lex (fmt
);
962 fmt
->saved_token
= u
;
965 u
= format_lex (fmt
);
970 notify_std (&dtp
->common
, GFC_STD_F2018
,
971 "Positive exponent width required");
975 fmt
->error
= "Positive exponent width required in "
976 "format string at %L";
980 tail
->u
.real
.e
= fmt
->value
;
985 /* Processing for positive width formats. */
988 tail
->u
.real
.w
= fmt
->value
;
990 /* Look for the dot separator. Because of legacy behaviors
991 we do some look ahead for missing things. */
993 t
= format_lex (fmt
);
996 /* We treat a missing decimal descriptor as 0. Note: This is only
997 allowed if -std=legacy, otherwise an error occurs. */
998 if (compile_options
.warn_std
!= 0)
1000 fmt
->error
= period_required
;
1003 fmt
->saved_token
= t
;
1005 tail
->u
.real
.e
= -1;
1009 /* If we made it here, we should have the dot so look for the
1011 t
= format_lex (fmt
);
1012 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1014 fmt
->error
= nonneg_required
;
1017 tail
->u
.real
.d
= fmt
->value
;
1018 tail
->u
.real
.e
= -1;
1020 /* Done with D and F formats. */
1021 if (t2
== FMT_D
|| t2
== FMT_F
)
1027 /* Look for optional exponent */
1028 u
= format_lex (fmt
);
1030 fmt
->saved_token
= u
;
1033 u
= format_lex (fmt
);
1034 if (u
!= FMT_POSINT
)
1038 notify_std (&dtp
->common
, GFC_STD_F2018
,
1039 "Positive exponent width required");
1043 fmt
->error
= "Positive exponent width required in "
1044 "format string at %L";
1048 tail
->u
.real
.e
= fmt
->value
;
1053 /* Old DEC codes may not have width or precision specified. */
1054 if (dtp
->u
.p
.mode
== WRITING
&& (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
))
1056 tail
->u
.real
.w
= DEFAULT_WIDTH
;
1058 tail
->u
.real
.e
= -1;
1059 fmt
->saved_token
= u
;
1065 get_fnode (fmt
, &head
, &tail
, t
);
1066 tail
->repeat
= repeat
;
1068 t
= format_lex (fmt
);
1070 /* Initialize the vlist to a zero size, rank-one array. */
1071 tail
->u
.udf
.vlist
= xmalloc (sizeof(gfc_array_i4
)
1072 + sizeof (descriptor_dimension
));
1073 GFC_DESCRIPTOR_DATA(tail
->u
.udf
.vlist
) = NULL
;
1074 GFC_DIMENSION_SET(tail
->u
.udf
.vlist
->dim
[0],1, 0, 0);
1076 if (t
== FMT_STRING
)
1078 /* Get pointer to the optional format string. */
1079 tail
->u
.udf
.string
= fmt
->string
;
1080 tail
->u
.udf
.string_len
= fmt
->value
;
1081 t
= format_lex (fmt
);
1083 if (t
== FMT_LPAREN
)
1085 /* Temporary buffer to hold the vlist values. */
1086 GFC_INTEGER_4 temp
[FARRAY_SIZE
];
1089 t
= format_lex (fmt
);
1090 if (t
!= FMT_POSINT
)
1092 fmt
->error
= posint_required
;
1095 /* Save the positive integer value. */
1096 temp
[i
++] = fmt
->value
;
1097 t
= format_lex (fmt
);
1100 if (t
== FMT_RPAREN
)
1102 /* We have parsed the complete vlist so initialize the
1103 array descriptor and save it in the format node. */
1104 gfc_full_array_i4
*vp
= tail
->u
.udf
.vlist
;
1105 GFC_DESCRIPTOR_DATA(vp
) = xmalloc (i
* sizeof(GFC_INTEGER_4
));
1106 GFC_DIMENSION_SET(vp
->dim
[0],1, i
, 1);
1107 memcpy (GFC_DESCRIPTOR_DATA(vp
), temp
, i
* sizeof(GFC_INTEGER_4
));
1110 fmt
->error
= unexpected_element
;
1113 fmt
->saved_token
= t
;
1116 if (repeat
> fmt
->format_string_len
)
1118 fmt
->error
= bad_hollerith
;
1122 get_fnode (fmt
, &head
, &tail
, FMT_STRING
);
1123 tail
->u
.string
.p
= fmt
->format_string
;
1124 tail
->u
.string
.length
= repeat
;
1127 fmt
->format_string
+= fmt
->value
;
1128 fmt
->format_string_len
-= repeat
;
1137 get_fnode (fmt
, &head
, &tail
, t
);
1138 tail
->repeat
= repeat
;
1140 t
= format_lex (fmt
);
1142 if (dtp
->u
.p
.mode
== READING
)
1144 if (t
!= FMT_POSINT
)
1146 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1148 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1149 tail
->u
.integer
.m
= -1;
1150 fmt
->saved_token
= t
;
1153 fmt
->error
= posint_required
;
1159 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1161 if (dtp
->common
.flags
& IOPARM_DT_DEC_EXT
)
1163 tail
->u
.integer
.w
= DEFAULT_WIDTH
;
1164 tail
->u
.integer
.m
= -1;
1165 fmt
->saved_token
= t
;
1168 fmt
->error
= nonneg_required
;
1173 tail
->u
.integer
.w
= fmt
->value
;
1174 tail
->u
.integer
.m
= -1;
1176 t
= format_lex (fmt
);
1177 if (t
!= FMT_PERIOD
)
1179 fmt
->saved_token
= t
;
1183 t
= format_lex (fmt
);
1184 if (t
!= FMT_ZERO
&& t
!= FMT_POSINT
)
1186 fmt
->error
= nonneg_required
;
1190 tail
->u
.integer
.m
= fmt
->value
;
1193 if (tail
->u
.integer
.w
!= 0 && tail
->u
.integer
.m
> tail
->u
.integer
.w
)
1195 fmt
->error
= "Minimum digits exceeds field width";
1202 fmt
->error
= unexpected_element
;
1206 /* Between a descriptor and what comes next */
1208 t
= format_lex (fmt
);
1219 get_fnode (fmt
, &head
, &tail
, t
);
1221 goto optional_comma
;
1224 fmt
->error
= unexpected_end
;
1228 /* Assume a missing comma, this is a GNU extension */
1232 /* Optional comma is a weird between state where we've just finished
1233 reading a colon, slash or P descriptor. */
1235 t
= format_lex (fmt
);
1244 default: /* Assume that we have another format item */
1245 fmt
->saved_token
= t
;
1257 /* format_error()-- Generate an error message for a format statement.
1258 If the node that gives the location of the error is NULL, the error
1259 is assumed to happen at parse time, and the current location of the
1262 We generate a message showing where the problem is. We take extra
1263 care to print only the relevant part of the format if it is longer
1264 than a standard 80 column display. */
1267 format_error (st_parameter_dt
*dtp
, const fnode
*f
, const char *message
)
1269 int width
, i
, offset
;
1271 char *p
, buffer
[BUFLEN
];
1272 format_data
*fmt
= dtp
->u
.p
.fmt
;
1276 else /* This should not happen. */
1279 if (message
== unexpected_element
)
1280 snprintf (buffer
, BUFLEN
, message
, fmt
->error_element
);
1282 snprintf (buffer
, BUFLEN
, "%s\n", message
);
1284 /* Get the offset into the format string where the error occurred. */
1285 offset
= dtp
->format_len
- (fmt
->reversion_ok
?
1286 (int) strlen(p
) : fmt
->format_string_len
);
1288 width
= dtp
->format_len
;
1293 /* Show the format */
1295 p
= strchr (buffer
, '\0');
1298 memcpy (p
, dtp
->format
, width
);
1303 /* Show where the problem is */
1305 for (i
= 1; i
< offset
; i
++)
1311 generate_error (&dtp
->common
, LIBERROR_FORMAT
, buffer
);
1315 /* revert()-- Do reversion of the format. Control reverts to the left
1316 parenthesis that matches the rightmost right parenthesis. From our
1317 tree structure, we are looking for the rightmost parenthesis node
1318 at the second level, the first level always being a single
1319 parenthesis node. If this node doesn't exit, we use the top
1323 revert (st_parameter_dt
*dtp
)
1326 format_data
*fmt
= dtp
->u
.p
.fmt
;
1328 dtp
->u
.p
.reversion_flag
= 1;
1332 for (f
= fmt
->array
.array
[0].u
.child
; f
; f
= f
->next
)
1333 if (f
->format
== FMT_LPAREN
)
1336 /* If r is NULL because no node was found, the whole tree will be used */
1338 fmt
->array
.array
[0].current
= r
;
1339 fmt
->array
.array
[0].count
= 0;
1342 /* parse_format()-- Parse a format string. */
1345 parse_format (st_parameter_dt
*dtp
)
1348 bool format_cache_ok
, seen_data_desc
= false;
1350 /* Don't cache for internal units and set an arbitrary limit on the
1351 size of format strings we will cache. (Avoids memory issues.)
1352 Also, the format_hash_table resides in the current_unit, so
1353 child_dtio procedures would overwrite the parent table */
1354 format_cache_ok
= !is_internal_unit (dtp
)
1355 && (dtp
->u
.p
.current_unit
->child_dtio
== 0);
1357 /* Lookup format string to see if it has already been parsed. */
1358 if (format_cache_ok
)
1360 dtp
->u
.p
.fmt
= find_parsed_format (dtp
);
1362 if (dtp
->u
.p
.fmt
!= NULL
)
1364 dtp
->u
.p
.fmt
->reversion_ok
= 0;
1365 dtp
->u
.p
.fmt
->saved_token
= FMT_NONE
;
1366 dtp
->u
.p
.fmt
->saved_format
= NULL
;
1367 reset_fnode_counters (dtp
);
1372 /* Not found so proceed as follows. */
1374 char *fmt_string
= fc_strdup_notrim (dtp
->format
, dtp
->format_len
);
1375 dtp
->format
= fmt_string
;
1377 dtp
->u
.p
.fmt
= fmt
= xmalloc (sizeof (format_data
));
1378 fmt
->format_string
= dtp
->format
;
1379 fmt
->format_string_len
= dtp
->format_len
;
1382 fmt
->saved_token
= FMT_NONE
;
1386 /* Initialize variables used during traversal of the tree. */
1388 fmt
->reversion_ok
= 0;
1389 fmt
->saved_format
= NULL
;
1391 /* Initialize the fnode_array. */
1393 memset (&(fmt
->array
), 0, sizeof(fmt
->array
));
1395 /* Allocate the first format node as the root of the tree. */
1397 fmt
->last
= &fmt
->array
;
1398 fmt
->last
->next
= NULL
;
1399 fmt
->avail
= &fmt
->array
.array
[0];
1401 memset (fmt
->avail
, 0, sizeof (*fmt
->avail
));
1402 fmt
->avail
->format
= FMT_LPAREN
;
1403 fmt
->avail
->repeat
= 1;
1406 if (format_lex (fmt
) == FMT_LPAREN
)
1407 fmt
->array
.array
[0].u
.child
= parse_format_list (dtp
, &seen_data_desc
);
1409 fmt
->error
= "Missing initial left parenthesis in format";
1411 if (format_cache_ok
)
1412 save_parsed_format (dtp
);
1414 dtp
->u
.p
.format_not_saved
= 1;
1417 format_error (dtp
, NULL
, fmt
->error
);
1421 /* next_format0()-- Get the next format node without worrying about
1422 reversion. Returns NULL when we hit the end of the list.
1423 Parenthesis nodes are incremented after the list has been
1424 exhausted, other nodes are incremented before they are returned. */
1426 static const fnode
*
1427 next_format0 (fnode
*f
)
1434 if (f
->format
!= FMT_LPAREN
)
1437 if (f
->count
<= f
->repeat
)
1444 /* Deal with a parenthesis node with unlimited format. */
1446 if (f
->repeat
== -2) /* -2 signifies unlimited. */
1449 if (f
->current
== NULL
)
1450 f
->current
= f
->u
.child
;
1452 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1454 r
= next_format0 (f
->current
);
1460 /* Deal with a parenthesis node with specific repeat count. */
1461 for (; f
->count
< f
->repeat
; f
->count
++)
1463 if (f
->current
== NULL
)
1464 f
->current
= f
->u
.child
;
1466 for (; f
->current
!= NULL
; f
->current
= f
->current
->next
)
1468 r
= next_format0 (f
->current
);
1479 /* next_format()-- Return the next format node. If the format list
1480 ends up being exhausted, we do reversion. Reversion is only
1481 allowed if we've seen a data descriptor since the
1482 initialization or the last reversion. We return NULL if there
1483 are no more data descriptors to return (which is an error
1487 next_format (st_parameter_dt
*dtp
)
1491 format_data
*fmt
= dtp
->u
.p
.fmt
;
1493 if (fmt
->saved_format
!= NULL
)
1494 { /* Deal with a pushed-back format node */
1495 f
= fmt
->saved_format
;
1496 fmt
->saved_format
= NULL
;
1500 f
= next_format0 (&fmt
->array
.array
[0]);
1503 if (!fmt
->reversion_ok
)
1506 fmt
->reversion_ok
= 0;
1509 f
= next_format0 (&fmt
->array
.array
[0]);
1512 format_error (dtp
, NULL
, reversion_error
);
1516 /* Push the first reverted token and return a colon node in case
1517 there are no more data items. */
1519 fmt
->saved_format
= f
;
1523 /* If this is a data edit descriptor, then reversion has become OK. */
1527 if (!fmt
->reversion_ok
&&
1528 (t
== FMT_I
|| t
== FMT_B
|| t
== FMT_O
|| t
== FMT_Z
|| t
== FMT_F
||
1529 t
== FMT_E
|| t
== FMT_EN
|| t
== FMT_ES
|| t
== FMT_G
|| t
== FMT_L
||
1530 t
== FMT_A
|| t
== FMT_D
|| t
== FMT_DT
))
1531 fmt
->reversion_ok
= 1;
1536 /* unget_format()-- Push the given format back so that it will be
1537 returned on the next call to next_format() without affecting
1538 counts. This is necessary when we've encountered a data
1539 descriptor, but don't know what the data item is yet. The format
1540 node is pushed back, and we return control to the main program,
1541 which calls the library back with the data item (or not). */
1544 unget_format (st_parameter_dt
*dtp
, const fnode
*f
)
1546 dtp
->u
.p
.fmt
->saved_format
= f
;