2009-10-11 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[official-gcc.git] / libgfortran / io / format.c
blob7e46e3a25df58456f2a972bf02af9e139af98ad9
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
2 Free Software Foundation, Inc.
3 Contributed by Andy Vaught
4 F2003 I/O support contributed by Jerry DeLisle
6 This file is part of the GNU Fortran 95 runtime library (libgfortran).
8 Libgfortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 Libgfortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
28 /* format.c-- parse a FORMAT string into a binary format suitable for
29 * interpretation during I/O statements */
31 #include "io.h"
32 #include <ctype.h>
33 #include <string.h>
34 #include <stdbool.h>
36 #define FARRAY_SIZE 64
38 typedef struct fnode_array
40 struct fnode_array *next;
41 fnode array[FARRAY_SIZE];
43 fnode_array;
45 typedef struct format_data
47 char *format_string, *string;
48 const char *error;
49 char error_element;
50 format_token saved_token;
51 int value, format_string_len, reversion_ok;
52 fnode *avail;
53 const fnode *saved_format;
54 fnode_array *last;
55 fnode_array array;
57 format_data;
59 static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0,
60 NULL };
62 /* Error messages. */
64 static const char posint_required[] = "Positive width required in format",
65 period_required[] = "Period required in format",
66 nonneg_required[] = "Nonnegative width required in format",
67 unexpected_element[] = "Unexpected element '%c' in format\n",
68 unexpected_end[] = "Unexpected end of format string",
69 bad_string[] = "Unterminated character constant in format",
70 bad_hollerith[] = "Hollerith constant extends past the end of the format",
71 reversion_error[] = "Exhausted data descriptors in format",
72 zero_width[] = "Zero width in format descriptor";
74 /* The following routines support caching format data from parsed format strings
75 into a hash table. This avoids repeatedly parsing duplicate format strings
76 or format strings in I/O statements that are repeated in loops. */
79 /* Traverse the table and free all data. */
81 void
82 free_format_hash_table (gfc_unit *u)
84 size_t i;
86 /* free_format_data handles any NULL pointers. */
87 for (i = 0; i < FORMAT_HASH_SIZE; i++)
89 if (u->format_hash_table[i].hashed_fmt != NULL)
91 free_format_data (u->format_hash_table[i].hashed_fmt);
92 free_mem (u->format_hash_table[i].key);
94 u->format_hash_table[i].key = NULL;
95 u->format_hash_table[i].key_len = 0;
96 u->format_hash_table[i].hashed_fmt = NULL;
100 /* Traverse the format_data structure and reset the fnode counters. */
102 static void
103 reset_node (fnode *fn)
105 fnode *f;
107 fn->count = 0;
108 fn->current = NULL;
110 if (fn->format != FMT_LPAREN)
111 return;
113 for (f = fn->u.child; f; f = f->next)
115 if (f->format == FMT_RPAREN)
116 break;
117 reset_node (f);
121 static void
122 reset_fnode_counters (st_parameter_dt *dtp)
124 fnode *f;
125 format_data *fmt;
127 fmt = dtp->u.p.fmt;
129 /* Clear this pointer at the head so things start at the right place. */
130 fmt->array.array[0].current = NULL;
132 for (f = fmt->last->array[0].u.child; f; f = f->next)
133 reset_node (f);
137 /* A simple hashing function to generate an index into the hash table. */
139 static inline
140 uint32_t format_hash (st_parameter_dt *dtp)
142 char *key;
143 gfc_charlen_type key_len;
144 uint32_t hash = 0;
145 gfc_charlen_type i;
147 /* Hash the format string. Super simple, but what the heck! */
148 key = dtp->format;
149 key_len = dtp->format_len;
150 for (i = 0; i < key_len; i++)
151 hash ^= key[i];
152 hash &= (FORMAT_HASH_SIZE - 1);
153 return hash;
157 static void
158 save_parsed_format (st_parameter_dt *dtp)
160 uint32_t hash;
161 gfc_unit *u;
163 hash = format_hash (dtp);
164 u = dtp->u.p.current_unit;
166 /* Index into the hash table. We are simply replacing whatever is there
167 relying on probability. */
168 if (u->format_hash_table[hash].hashed_fmt != NULL)
169 free_format_data (u->format_hash_table[hash].hashed_fmt);
170 u->format_hash_table[hash].hashed_fmt = NULL;
172 if (u->format_hash_table[hash].key != NULL)
173 free_mem (u->format_hash_table[hash].key);
174 u->format_hash_table[hash].key = get_mem (dtp->format_len);
175 memcpy (u->format_hash_table[hash].key, dtp->format, dtp->format_len);
177 u->format_hash_table[hash].key_len = dtp->format_len;
178 u->format_hash_table[hash].hashed_fmt = dtp->u.p.fmt;
182 static format_data *
183 find_parsed_format (st_parameter_dt *dtp)
185 uint32_t hash;
186 gfc_unit *u;
188 hash = format_hash (dtp);
189 u = dtp->u.p.current_unit;
191 if (u->format_hash_table[hash].key != NULL)
193 /* See if it matches. */
194 if (u->format_hash_table[hash].key_len == dtp->format_len)
196 /* So far so good. */
197 if (strncmp (u->format_hash_table[hash].key,
198 dtp->format, dtp->format_len) == 0)
199 return u->format_hash_table[hash].hashed_fmt;
202 return NULL;
206 /* next_char()-- Return the next character in the format string.
207 * Returns -1 when the string is done. If the literal flag is set,
208 * spaces are significant, otherwise they are not. */
210 static int
211 next_char (format_data *fmt, int literal)
213 int c;
217 if (fmt->format_string_len == 0)
218 return -1;
220 fmt->format_string_len--;
221 c = toupper (*fmt->format_string++);
222 fmt->error_element = c;
224 while ((c == ' ' || c == '\t') && !literal);
226 return c;
230 /* unget_char()-- Back up one character position. */
232 #define unget_char(fmt) \
233 { fmt->format_string--; fmt->format_string_len++; }
236 /* get_fnode()-- Allocate a new format node, inserting it into the
237 * current singly linked list. These are initially allocated from the
238 * static buffer. */
240 static fnode *
241 get_fnode (format_data *fmt, fnode **head, fnode **tail, format_token t)
243 fnode *f;
245 if (fmt->avail == &fmt->last->array[FARRAY_SIZE])
247 fmt->last->next = get_mem (sizeof (fnode_array));
248 fmt->last = fmt->last->next;
249 fmt->last->next = NULL;
250 fmt->avail = &fmt->last->array[0];
252 f = fmt->avail++;
253 memset (f, '\0', sizeof (fnode));
255 if (*head == NULL)
256 *head = *tail = f;
257 else
259 (*tail)->next = f;
260 *tail = f;
263 f->format = t;
264 f->repeat = -1;
265 f->source = fmt->format_string;
266 return f;
270 /* free_format_data()-- Free all allocated format data. */
272 void
273 free_format_data (format_data *fmt)
275 fnode_array *fa, *fa_next;
278 if (fmt == NULL)
279 return;
281 for (fa = fmt->array.next; fa; fa = fa_next)
283 fa_next = fa->next;
284 free_mem (fa);
287 free_mem (fmt);
288 fmt = NULL;
292 /* format_lex()-- Simple lexical analyzer for getting the next token
293 * in a FORMAT string. We support a one-level token pushback in the
294 * fmt->saved_token variable. */
296 static format_token
297 format_lex (format_data *fmt)
299 format_token token;
300 int negative_flag;
301 int c;
302 char delim;
304 if (fmt->saved_token != FMT_NONE)
306 token = fmt->saved_token;
307 fmt->saved_token = FMT_NONE;
308 return token;
311 negative_flag = 0;
312 c = next_char (fmt, 0);
314 switch (c)
316 case '*':
317 token = FMT_STAR;
318 break;
320 case '(':
321 token = FMT_LPAREN;
322 break;
324 case ')':
325 token = FMT_RPAREN;
326 break;
328 case '-':
329 negative_flag = 1;
330 /* Fall Through */
332 case '+':
333 c = next_char (fmt, 0);
334 if (!isdigit (c))
336 token = FMT_UNKNOWN;
337 break;
340 fmt->value = c - '0';
342 for (;;)
344 c = next_char (fmt, 0);
345 if (!isdigit (c))
346 break;
348 fmt->value = 10 * fmt->value + c - '0';
351 unget_char (fmt);
353 if (negative_flag)
354 fmt->value = -fmt->value;
355 token = FMT_SIGNED_INT;
356 break;
358 case '0':
359 case '1':
360 case '2':
361 case '3':
362 case '4':
363 case '5':
364 case '6':
365 case '7':
366 case '8':
367 case '9':
368 fmt->value = c - '0';
370 for (;;)
372 c = next_char (fmt, 0);
373 if (!isdigit (c))
374 break;
376 fmt->value = 10 * fmt->value + c - '0';
379 unget_char (fmt);
380 token = (fmt->value == 0) ? FMT_ZERO : FMT_POSINT;
381 break;
383 case '.':
384 token = FMT_PERIOD;
385 break;
387 case ',':
388 token = FMT_COMMA;
389 break;
391 case ':':
392 token = FMT_COLON;
393 break;
395 case '/':
396 token = FMT_SLASH;
397 break;
399 case '$':
400 token = FMT_DOLLAR;
401 break;
403 case 'T':
404 switch (next_char (fmt, 0))
406 case 'L':
407 token = FMT_TL;
408 break;
409 case 'R':
410 token = FMT_TR;
411 break;
412 default:
413 token = FMT_T;
414 unget_char (fmt);
415 break;
418 break;
420 case 'X':
421 token = FMT_X;
422 break;
424 case 'S':
425 switch (next_char (fmt, 0))
427 case 'S':
428 token = FMT_SS;
429 break;
430 case 'P':
431 token = FMT_SP;
432 break;
433 default:
434 token = FMT_S;
435 unget_char (fmt);
436 break;
439 break;
441 case 'B':
442 switch (next_char (fmt, 0))
444 case 'N':
445 token = FMT_BN;
446 break;
447 case 'Z':
448 token = FMT_BZ;
449 break;
450 default:
451 token = FMT_B;
452 unget_char (fmt);
453 break;
456 break;
458 case '\'':
459 case '"':
460 delim = c;
462 fmt->string = fmt->format_string;
463 fmt->value = 0; /* This is the length of the string */
465 for (;;)
467 c = next_char (fmt, 1);
468 if (c == -1)
470 token = FMT_BADSTRING;
471 fmt->error = bad_string;
472 break;
475 if (c == delim)
477 c = next_char (fmt, 1);
479 if (c == -1)
481 token = FMT_BADSTRING;
482 fmt->error = bad_string;
483 break;
486 if (c != delim)
488 unget_char (fmt);
489 token = FMT_STRING;
490 break;
494 fmt->value++;
497 break;
499 case 'P':
500 token = FMT_P;
501 break;
503 case 'I':
504 token = FMT_I;
505 break;
507 case 'O':
508 token = FMT_O;
509 break;
511 case 'Z':
512 token = FMT_Z;
513 break;
515 case 'F':
516 token = FMT_F;
517 break;
519 case 'E':
520 switch (next_char (fmt, 0))
522 case 'N':
523 token = FMT_EN;
524 break;
525 case 'S':
526 token = FMT_ES;
527 break;
528 default:
529 token = FMT_E;
530 unget_char (fmt);
531 break;
533 break;
535 case 'G':
536 token = FMT_G;
537 break;
539 case 'H':
540 token = FMT_H;
541 break;
543 case 'L':
544 token = FMT_L;
545 break;
547 case 'A':
548 token = FMT_A;
549 break;
551 case 'D':
552 switch (next_char (fmt, 0))
554 case 'P':
555 token = FMT_DP;
556 break;
557 case 'C':
558 token = FMT_DC;
559 break;
560 default:
561 token = FMT_D;
562 unget_char (fmt);
563 break;
565 break;
567 case 'R':
568 switch (next_char (fmt, 0))
570 case 'C':
571 token = FMT_RC;
572 break;
573 case 'D':
574 token = FMT_RD;
575 break;
576 case 'N':
577 token = FMT_RN;
578 break;
579 case 'P':
580 token = FMT_RP;
581 break;
582 case 'U':
583 token = FMT_RU;
584 break;
585 case 'Z':
586 token = FMT_RZ;
587 break;
588 default:
589 unget_char (fmt);
590 token = FMT_UNKNOWN;
591 break;
593 break;
595 case -1:
596 token = FMT_END;
597 break;
599 default:
600 token = FMT_UNKNOWN;
601 break;
604 return token;
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. */
612 static fnode *
613 parse_format_list (st_parameter_dt *dtp, bool *save_ok)
615 fnode *head, *tail;
616 format_token t, u, t2;
617 int repeat;
618 format_data *fmt = dtp->u.p.fmt;
619 bool saveit;
621 head = tail = NULL;
622 saveit = *save_ok;
624 /* Get the next format item */
625 format_item:
626 t = format_lex (fmt);
627 format_item_1:
628 switch (t)
630 case FMT_STAR:
631 t = format_lex (fmt);
632 if (t != FMT_LPAREN)
634 fmt->error = "Left parenthesis required after '*'";
635 goto finished;
637 get_fnode (fmt, &head, &tail, FMT_LPAREN);
638 tail->repeat = -2; /* Signifies unlimited format. */
639 tail->u.child = parse_format_list (dtp, &saveit);
640 if (fmt->error != NULL)
641 goto finished;
643 goto between_desc;
645 case FMT_POSINT:
646 repeat = fmt->value;
648 t = format_lex (fmt);
649 switch (t)
651 case FMT_LPAREN:
652 get_fnode (fmt, &head, &tail, FMT_LPAREN);
653 tail->repeat = repeat;
654 tail->u.child = parse_format_list (dtp, &saveit);
655 if (fmt->error != NULL)
656 goto finished;
658 goto between_desc;
660 case FMT_SLASH:
661 get_fnode (fmt, &head, &tail, FMT_SLASH);
662 tail->repeat = repeat;
663 goto optional_comma;
665 case FMT_X:
666 get_fnode (fmt, &head, &tail, FMT_X);
667 tail->repeat = 1;
668 tail->u.k = fmt->value;
669 goto between_desc;
671 case FMT_P:
672 goto p_descriptor;
674 default:
675 goto data_desc;
678 case FMT_LPAREN:
679 get_fnode (fmt, &head, &tail, FMT_LPAREN);
680 tail->repeat = 1;
681 tail->u.child = parse_format_list (dtp, &saveit);
682 if (fmt->error != NULL)
683 goto finished;
685 goto between_desc;
687 case FMT_SIGNED_INT: /* Signed integer can only precede a P format. */
688 case FMT_ZERO: /* Same for zero. */
689 t = format_lex (fmt);
690 if (t != FMT_P)
692 fmt->error = "Expected P edit descriptor in format";
693 goto finished;
696 p_descriptor:
697 get_fnode (fmt, &head, &tail, FMT_P);
698 tail->u.k = fmt->value;
699 tail->repeat = 1;
701 t = format_lex (fmt);
702 if (t == FMT_F || t == FMT_EN || t == FMT_ES || t == FMT_D
703 || t == FMT_G || t == FMT_E)
705 repeat = 1;
706 goto data_desc;
709 if (t != FMT_COMMA && t != FMT_RPAREN && t != FMT_SLASH)
711 fmt->error = "Comma required after P descriptor";
712 goto finished;
715 fmt->saved_token = t;
716 goto optional_comma;
718 case FMT_P: /* P and X require a prior number */
719 fmt->error = "P descriptor requires leading scale factor";
720 goto finished;
722 case FMT_X:
724 EXTENSION!
726 If we would be pedantic in the library, we would have to reject
727 an X descriptor without an integer prefix:
729 fmt->error = "X descriptor requires leading space count";
730 goto finished;
732 However, this is an extension supported by many Fortran compilers,
733 including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
734 runtime library, and make the front end reject it if the compiler
735 is in pedantic mode. The interpretation of 'X' is '1X'.
737 get_fnode (fmt, &head, &tail, FMT_X);
738 tail->repeat = 1;
739 tail->u.k = 1;
740 goto between_desc;
742 case FMT_STRING:
743 /* TODO: Find out why it is necessary to turn off format caching. */
744 saveit = false;
745 get_fnode (fmt, &head, &tail, FMT_STRING);
746 tail->u.string.p = fmt->string;
747 tail->u.string.length = fmt->value;
748 tail->repeat = 1;
749 goto optional_comma;
751 case FMT_RC:
752 case FMT_RD:
753 case FMT_RN:
754 case FMT_RP:
755 case FMT_RU:
756 case FMT_RZ:
757 notify_std (&dtp->common, GFC_STD_F2003, "Fortran 2003: Round "
758 "descriptor not allowed");
759 get_fnode (fmt, &head, &tail, t);
760 tail->repeat = 1;
761 goto between_desc;
763 case FMT_DC:
764 case FMT_DP:
765 notify_std (&dtp->common, GFC_STD_F2003, "Fortran 2003: DC or DP "
766 "descriptor not allowed");
767 /* Fall through. */
768 case FMT_S:
769 case FMT_SS:
770 case FMT_SP:
771 case FMT_BN:
772 case FMT_BZ:
773 get_fnode (fmt, &head, &tail, t);
774 tail->repeat = 1;
775 goto between_desc;
777 case FMT_COLON:
778 get_fnode (fmt, &head, &tail, FMT_COLON);
779 tail->repeat = 1;
780 goto optional_comma;
782 case FMT_SLASH:
783 get_fnode (fmt, &head, &tail, FMT_SLASH);
784 tail->repeat = 1;
785 tail->u.r = 1;
786 goto optional_comma;
788 case FMT_DOLLAR:
789 get_fnode (fmt, &head, &tail, FMT_DOLLAR);
790 tail->repeat = 1;
791 notify_std (&dtp->common, GFC_STD_GNU, "Extension: $ descriptor");
792 goto between_desc;
794 case FMT_T:
795 case FMT_TL:
796 case FMT_TR:
797 t2 = format_lex (fmt);
798 if (t2 != FMT_POSINT)
800 fmt->error = posint_required;
801 goto finished;
803 get_fnode (fmt, &head, &tail, t);
804 tail->u.n = fmt->value;
805 tail->repeat = 1;
806 goto between_desc;
808 case FMT_I:
809 case FMT_B:
810 case FMT_O:
811 case FMT_Z:
812 case FMT_E:
813 case FMT_EN:
814 case FMT_ES:
815 case FMT_D:
816 case FMT_L:
817 case FMT_A:
818 case FMT_F:
819 case FMT_G:
820 repeat = 1;
821 goto data_desc;
823 case FMT_H:
824 get_fnode (fmt, &head, &tail, FMT_STRING);
825 if (fmt->format_string_len < 1)
827 fmt->error = bad_hollerith;
828 goto finished;
831 tail->u.string.p = fmt->format_string;
832 tail->u.string.length = 1;
833 tail->repeat = 1;
835 fmt->format_string++;
836 fmt->format_string_len--;
838 goto between_desc;
840 case FMT_END:
841 fmt->error = unexpected_end;
842 goto finished;
844 case FMT_BADSTRING:
845 goto finished;
847 case FMT_RPAREN:
848 goto finished;
850 default:
851 fmt->error = unexpected_element;
852 goto finished;
855 /* In this state, t must currently be a data descriptor. Deal with
856 things that can/must follow the descriptor */
857 data_desc:
858 switch (t)
860 case FMT_L:
861 t = format_lex (fmt);
862 if (t != FMT_POSINT)
864 if (notification_std(GFC_STD_GNU) == ERROR)
866 fmt->error = posint_required;
867 goto finished;
869 else
871 fmt->saved_token = t;
872 fmt->value = 1; /* Default width */
873 notify_std (&dtp->common, GFC_STD_GNU, posint_required);
877 get_fnode (fmt, &head, &tail, FMT_L);
878 tail->u.n = fmt->value;
879 tail->repeat = repeat;
880 break;
882 case FMT_A:
883 t = format_lex (fmt);
884 if (t == FMT_ZERO)
886 fmt->error = zero_width;
887 goto finished;
890 if (t != FMT_POSINT)
892 fmt->saved_token = t;
893 fmt->value = -1; /* Width not present */
896 get_fnode (fmt, &head, &tail, FMT_A);
897 tail->repeat = repeat;
898 tail->u.n = fmt->value;
899 break;
901 case FMT_D:
902 case FMT_E:
903 case FMT_F:
904 case FMT_G:
905 case FMT_EN:
906 case FMT_ES:
907 get_fnode (fmt, &head, &tail, t);
908 tail->repeat = repeat;
910 u = format_lex (fmt);
911 if (t == FMT_G && u == FMT_ZERO)
913 if (notification_std (GFC_STD_F2008) == ERROR
914 || dtp->u.p.mode == READING)
916 fmt->error = zero_width;
917 goto finished;
919 tail->u.real.w = 0;
920 u = format_lex (fmt);
921 if (u != FMT_PERIOD)
923 fmt->saved_token = u;
924 break;
927 u = format_lex (fmt);
928 if (u != FMT_POSINT)
930 fmt->error = posint_required;
931 goto finished;
933 tail->u.real.d = fmt->value;
934 break;
936 if (t == FMT_F || dtp->u.p.mode == WRITING)
938 if (u != FMT_POSINT && u != FMT_ZERO)
940 fmt->error = nonneg_required;
941 goto finished;
944 else
946 if (u != FMT_POSINT)
948 fmt->error = posint_required;
949 goto finished;
953 tail->u.real.w = fmt->value;
954 t2 = t;
955 t = format_lex (fmt);
956 if (t != FMT_PERIOD)
958 /* We treat a missing decimal descriptor as 0. Note: This is only
959 allowed if -std=legacy, otherwise an error occurs. */
960 if (compile_options.warn_std != 0)
962 fmt->error = period_required;
963 goto finished;
965 fmt->saved_token = t;
966 tail->u.real.d = 0;
967 tail->u.real.e = -1;
968 break;
971 t = format_lex (fmt);
972 if (t != FMT_ZERO && t != FMT_POSINT)
974 fmt->error = nonneg_required;
975 goto finished;
978 tail->u.real.d = fmt->value;
979 tail->u.real.e = -1;
981 if (t2 == FMT_D || t2 == FMT_F)
982 break;
985 /* Look for optional exponent */
986 t = format_lex (fmt);
987 if (t != FMT_E)
988 fmt->saved_token = t;
989 else
991 t = format_lex (fmt);
992 if (t != FMT_POSINT)
994 fmt->error = "Positive exponent width required in format";
995 goto finished;
998 tail->u.real.e = fmt->value;
1001 break;
1003 case FMT_H:
1004 if (repeat > fmt->format_string_len)
1006 fmt->error = bad_hollerith;
1007 goto finished;
1010 get_fnode (fmt, &head, &tail, FMT_STRING);
1011 tail->u.string.p = fmt->format_string;
1012 tail->u.string.length = repeat;
1013 tail->repeat = 1;
1015 fmt->format_string += fmt->value;
1016 fmt->format_string_len -= repeat;
1018 break;
1020 case FMT_I:
1021 case FMT_B:
1022 case FMT_O:
1023 case FMT_Z:
1024 get_fnode (fmt, &head, &tail, t);
1025 tail->repeat = repeat;
1027 t = format_lex (fmt);
1029 if (dtp->u.p.mode == READING)
1031 if (t != FMT_POSINT)
1033 fmt->error = posint_required;
1034 goto finished;
1037 else
1039 if (t != FMT_ZERO && t != FMT_POSINT)
1041 fmt->error = nonneg_required;
1042 goto finished;
1046 tail->u.integer.w = fmt->value;
1047 tail->u.integer.m = -1;
1049 t = format_lex (fmt);
1050 if (t != FMT_PERIOD)
1052 fmt->saved_token = t;
1054 else
1056 t = format_lex (fmt);
1057 if (t != FMT_ZERO && t != FMT_POSINT)
1059 fmt->error = nonneg_required;
1060 goto finished;
1063 tail->u.integer.m = fmt->value;
1066 if (tail->u.integer.w != 0 && tail->u.integer.m > tail->u.integer.w)
1068 fmt->error = "Minimum digits exceeds field width";
1069 goto finished;
1072 break;
1074 default:
1075 fmt->error = unexpected_element;
1076 goto finished;
1079 /* Between a descriptor and what comes next */
1080 between_desc:
1081 t = format_lex (fmt);
1082 switch (t)
1084 case FMT_COMMA:
1085 goto format_item;
1087 case FMT_RPAREN:
1088 goto finished;
1090 case FMT_SLASH:
1091 case FMT_COLON:
1092 get_fnode (fmt, &head, &tail, t);
1093 tail->repeat = 1;
1094 goto optional_comma;
1096 case FMT_END:
1097 fmt->error = unexpected_end;
1098 goto finished;
1100 default:
1101 /* Assume a missing comma, this is a GNU extension */
1102 goto format_item_1;
1105 /* Optional comma is a weird between state where we've just finished
1106 reading a colon, slash or P descriptor. */
1107 optional_comma:
1108 t = format_lex (fmt);
1109 switch (t)
1111 case FMT_COMMA:
1112 break;
1114 case FMT_RPAREN:
1115 goto finished;
1117 default: /* Assume that we have another format item */
1118 fmt->saved_token = t;
1119 break;
1122 goto format_item;
1124 finished:
1126 *save_ok = saveit;
1128 return head;
1132 /* format_error()-- Generate an error message for a format statement.
1133 * If the node that gives the location of the error is NULL, the error
1134 * is assumed to happen at parse time, and the current location of the
1135 * parser is shown.
1137 * We generate a message showing where the problem is. We take extra
1138 * care to print only the relevant part of the format if it is longer
1139 * than a standard 80 column display. */
1141 void
1142 format_error (st_parameter_dt *dtp, const fnode *f, const char *message)
1144 int width, i, j, offset;
1145 char *p, buffer[300];
1146 format_data *fmt = dtp->u.p.fmt;
1148 if (f != NULL)
1149 fmt->format_string = f->source;
1151 if (message == unexpected_element)
1152 sprintf (buffer, message, fmt->error_element);
1153 else
1154 sprintf (buffer, "%s\n", message);
1156 j = fmt->format_string - dtp->format;
1158 offset = (j > 60) ? j - 40 : 0;
1160 j -= offset;
1161 width = dtp->format_len - offset;
1163 if (width > 80)
1164 width = 80;
1166 /* Show the format */
1168 p = strchr (buffer, '\0');
1170 memcpy (p, dtp->format + offset, width);
1172 p += width;
1173 *p++ = '\n';
1175 /* Show where the problem is */
1177 for (i = 1; i < j; i++)
1178 *p++ = ' ';
1180 *p++ = '^';
1181 *p = '\0';
1183 generate_error (&dtp->common, LIBERROR_FORMAT, buffer);
1187 /* revert()-- Do reversion of the format. Control reverts to the left
1188 * parenthesis that matches the rightmost right parenthesis. From our
1189 * tree structure, we are looking for the rightmost parenthesis node
1190 * at the second level, the first level always being a single
1191 * parenthesis node. If this node doesn't exit, we use the top
1192 * level. */
1194 static void
1195 revert (st_parameter_dt *dtp)
1197 fnode *f, *r;
1198 format_data *fmt = dtp->u.p.fmt;
1200 dtp->u.p.reversion_flag = 1;
1202 r = NULL;
1204 for (f = fmt->array.array[0].u.child; f; f = f->next)
1205 if (f->format == FMT_LPAREN)
1206 r = f;
1208 /* If r is NULL because no node was found, the whole tree will be used */
1210 fmt->array.array[0].current = r;
1211 fmt->array.array[0].count = 0;
1214 /* parse_format()-- Parse a format string. */
1216 void
1217 parse_format (st_parameter_dt *dtp)
1219 format_data *fmt;
1220 bool format_cache_ok;
1222 format_cache_ok = !is_internal_unit (dtp);
1224 /* Lookup format string to see if it has already been parsed. */
1225 if (format_cache_ok)
1227 dtp->u.p.fmt = find_parsed_format (dtp);
1229 if (dtp->u.p.fmt != NULL)
1231 dtp->u.p.fmt->reversion_ok = 0;
1232 dtp->u.p.fmt->saved_token = FMT_NONE;
1233 dtp->u.p.fmt->saved_format = NULL;
1234 reset_fnode_counters (dtp);
1235 return;
1239 /* Not found so proceed as follows. */
1241 dtp->u.p.fmt = fmt = get_mem (sizeof (format_data));
1242 fmt->format_string = dtp->format;
1243 fmt->format_string_len = dtp->format_len;
1245 fmt->string = NULL;
1246 fmt->saved_token = FMT_NONE;
1247 fmt->error = NULL;
1248 fmt->value = 0;
1250 /* Initialize variables used during traversal of the tree. */
1252 fmt->reversion_ok = 0;
1253 fmt->saved_format = NULL;
1255 /* Allocate the first format node as the root of the tree. */
1257 fmt->last = &fmt->array;
1258 fmt->last->next = NULL;
1259 fmt->avail = &fmt->array.array[0];
1261 memset (fmt->avail, 0, sizeof (*fmt->avail));
1262 fmt->avail->format = FMT_LPAREN;
1263 fmt->avail->repeat = 1;
1264 fmt->avail++;
1266 if (format_lex (fmt) == FMT_LPAREN)
1267 fmt->array.array[0].u.child = parse_format_list (dtp, &format_cache_ok);
1268 else
1269 fmt->error = "Missing initial left parenthesis in format";
1271 if (fmt->error)
1273 format_error (dtp, NULL, fmt->error);
1274 free_format_hash_table (dtp->u.p.current_unit);
1275 return;
1278 if (format_cache_ok)
1279 save_parsed_format (dtp);
1280 else
1281 dtp->u.p.format_not_saved = 1;
1285 /* next_format0()-- Get the next format node without worrying about
1286 * reversion. Returns NULL when we hit the end of the list.
1287 * Parenthesis nodes are incremented after the list has been
1288 * exhausted, other nodes are incremented before they are returned. */
1290 static const fnode *
1291 next_format0 (fnode * f)
1293 const fnode *r;
1295 if (f == NULL)
1296 return NULL;
1298 if (f->format != FMT_LPAREN)
1300 f->count++;
1301 if (f->count <= f->repeat)
1302 return f;
1304 f->count = 0;
1305 return NULL;
1308 /* Deal with a parenthesis node with unlimited format. */
1310 if (f->repeat == -2) /* -2 signifies unlimited. */
1311 for (;;)
1313 if (f->current == NULL)
1314 f->current = f->u.child;
1316 for (; f->current != NULL; f->current = f->current->next)
1318 r = next_format0 (f->current);
1319 if (r != NULL)
1320 return r;
1324 /* Deal with a parenthesis node with specific repeat count. */
1325 for (; f->count < f->repeat; f->count++)
1327 if (f->current == NULL)
1328 f->current = f->u.child;
1330 for (; f->current != NULL; f->current = f->current->next)
1332 r = next_format0 (f->current);
1333 if (r != NULL)
1334 return r;
1338 f->count = 0;
1339 return NULL;
1343 /* next_format()-- Return the next format node. If the format list
1344 * ends up being exhausted, we do reversion. Reversion is only
1345 * allowed if we've seen a data descriptor since the
1346 * initialization or the last reversion. We return NULL if there
1347 * are no more data descriptors to return (which is an error
1348 * condition). */
1350 const fnode *
1351 next_format (st_parameter_dt *dtp)
1353 format_token t;
1354 const fnode *f;
1355 format_data *fmt = dtp->u.p.fmt;
1357 if (fmt->saved_format != NULL)
1358 { /* Deal with a pushed-back format node */
1359 f = fmt->saved_format;
1360 fmt->saved_format = NULL;
1361 goto done;
1364 f = next_format0 (&fmt->array.array[0]);
1365 if (f == NULL)
1367 if (!fmt->reversion_ok)
1368 return NULL;
1370 fmt->reversion_ok = 0;
1371 revert (dtp);
1373 f = next_format0 (&fmt->array.array[0]);
1374 if (f == NULL)
1376 format_error (dtp, NULL, reversion_error);
1377 return NULL;
1380 /* Push the first reverted token and return a colon node in case
1381 * there are no more data items. */
1383 fmt->saved_format = f;
1384 return &colon_node;
1387 /* If this is a data edit descriptor, then reversion has become OK. */
1388 done:
1389 t = f->format;
1391 if (!fmt->reversion_ok &&
1392 (t == FMT_I || t == FMT_B || t == FMT_O || t == FMT_Z || t == FMT_F ||
1393 t == FMT_E || t == FMT_EN || t == FMT_ES || t == FMT_G || t == FMT_L ||
1394 t == FMT_A || t == FMT_D))
1395 fmt->reversion_ok = 1;
1396 return f;
1400 /* unget_format()-- Push the given format back so that it will be
1401 * returned on the next call to next_format() without affecting
1402 * counts. This is necessary when we've encountered a data
1403 * descriptor, but don't know what the data item is yet. The format
1404 * node is pushed back, and we return control to the main program,
1405 * which calls the library back with the data item (or not). */
1407 void
1408 unget_format (st_parameter_dt *dtp, const fnode *f)
1410 dtp->u.p.fmt->saved_format = f;