]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/io/format.c
Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[thirdparty/gcc.git] / libgfortran / io / format.c
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
5
6 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7
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.
12
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.
17
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.
21
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/>. */
26
27
28 /* format.c-- parse a FORMAT string into a binary format suitable for
29 * interpretation during I/O statements */
30
31 #include "io.h"
32 #include <ctype.h>
33 #include <string.h>
34 #include <stdbool.h>
35
36 #define FARRAY_SIZE 64
37
38 typedef struct fnode_array
39 {
40 struct fnode_array *next;
41 fnode array[FARRAY_SIZE];
42 }
43 fnode_array;
44
45 typedef struct format_data
46 {
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;
56 }
57 format_data;
58
59 static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0,
60 NULL };
61
62 /* Error messages. */
63
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";
73
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. */
77
78
79 /* Traverse the table and free all data. */
80
81 void
82 free_format_hash_table (gfc_unit *u)
83 {
84 size_t i;
85
86 /* free_format_data handles any NULL pointers. */
87 for (i = 0; i < FORMAT_HASH_SIZE; i++)
88 {
89 if (u->format_hash_table[i].hashed_fmt != NULL)
90 free_format_data (u->format_hash_table[i].hashed_fmt);
91 u->format_hash_table[i].hashed_fmt = NULL;
92 }
93 }
94
95 /* Traverse the format_data structure and reset the fnode counters. */
96
97 static void
98 reset_node (fnode *fn)
99 {
100 fnode *f;
101
102 fn->count = 0;
103 fn->current = NULL;
104
105 if (fn->format != FMT_LPAREN)
106 return;
107
108 for (f = fn->u.child; f; f = f->next)
109 {
110 if (f->format == FMT_RPAREN)
111 break;
112 reset_node (f);
113 }
114 }
115
116 static void
117 reset_fnode_counters (st_parameter_dt *dtp)
118 {
119 fnode *f;
120 format_data *fmt;
121
122 fmt = dtp->u.p.fmt;
123
124 /* Clear this pointer at the head so things start at the right place. */
125 fmt->array.array[0].current = NULL;
126
127 for (f = fmt->last->array[0].u.child; f; f = f->next)
128 reset_node (f);
129 }
130
131
132 /* A simple hashing function to generate an index into the hash table. */
133
134 static inline
135 uint32_t format_hash (st_parameter_dt *dtp)
136 {
137 char *key;
138 gfc_charlen_type key_len;
139 uint32_t hash = 0;
140 gfc_charlen_type i;
141
142 /* Hash the format string. Super simple, but what the heck! */
143 key = dtp->format;
144 key_len = dtp->format_len;
145 for (i = 0; i < key_len; i++)
146 hash ^= key[i];
147 hash &= (FORMAT_HASH_SIZE - 1);
148 return hash;
149 }
150
151
152 static void
153 save_parsed_format (st_parameter_dt *dtp)
154 {
155 uint32_t hash;
156 gfc_unit *u;
157
158 hash = format_hash (dtp);
159 u = dtp->u.p.current_unit;
160
161 /* Index into the hash table. We are simply replacing whatever is there
162 relying on probability. */
163 if (u->format_hash_table[hash].hashed_fmt != NULL)
164 free_format_data (u->format_hash_table[hash].hashed_fmt);
165 u->format_hash_table[hash].hashed_fmt = NULL;
166
167 u->format_hash_table[hash].key = dtp->format;
168 u->format_hash_table[hash].key_len = dtp->format_len;
169 u->format_hash_table[hash].hashed_fmt = dtp->u.p.fmt;
170 }
171
172
173 static format_data *
174 find_parsed_format (st_parameter_dt *dtp)
175 {
176 uint32_t hash;
177 gfc_unit *u;
178
179 hash = format_hash (dtp);
180 u = dtp->u.p.current_unit;
181
182 if (u->format_hash_table[hash].key != NULL)
183 {
184 /* See if it matches. */
185 if (u->format_hash_table[hash].key_len == dtp->format_len)
186 {
187 /* So far so good. */
188 if (strncmp (u->format_hash_table[hash].key,
189 dtp->format, dtp->format_len) == 0)
190 return u->format_hash_table[hash].hashed_fmt;
191 }
192 }
193 return NULL;
194 }
195
196
197 /* next_char()-- Return the next character in the format string.
198 * Returns -1 when the string is done. If the literal flag is set,
199 * spaces are significant, otherwise they are not. */
200
201 static int
202 next_char (format_data *fmt, int literal)
203 {
204 int c;
205
206 do
207 {
208 if (fmt->format_string_len == 0)
209 return -1;
210
211 fmt->format_string_len--;
212 c = toupper (*fmt->format_string++);
213 fmt->error_element = c;
214 }
215 while ((c == ' ' || c == '\t') && !literal);
216
217 return c;
218 }
219
220
221 /* unget_char()-- Back up one character position. */
222
223 #define unget_char(fmt) \
224 { fmt->format_string--; fmt->format_string_len++; }
225
226
227 /* get_fnode()-- Allocate a new format node, inserting it into the
228 * current singly linked list. These are initially allocated from the
229 * static buffer. */
230
231 static fnode *
232 get_fnode (format_data *fmt, fnode **head, fnode **tail, format_token t)
233 {
234 fnode *f;
235
236 if (fmt->avail == &fmt->last->array[FARRAY_SIZE])
237 {
238 fmt->last->next = get_mem (sizeof (fnode_array));
239 fmt->last = fmt->last->next;
240 fmt->last->next = NULL;
241 fmt->avail = &fmt->last->array[0];
242 }
243 f = fmt->avail++;
244 memset (f, '\0', sizeof (fnode));
245
246 if (*head == NULL)
247 *head = *tail = f;
248 else
249 {
250 (*tail)->next = f;
251 *tail = f;
252 }
253
254 f->format = t;
255 f->repeat = -1;
256 f->source = fmt->format_string;
257 return f;
258 }
259
260
261 /* free_format_data()-- Free all allocated format data. */
262
263 void
264 free_format_data (format_data *fmt)
265 {
266 fnode_array *fa, *fa_next;
267
268
269 if (fmt == NULL)
270 return;
271
272 for (fa = fmt->array.next; fa; fa = fa_next)
273 {
274 fa_next = fa->next;
275 free_mem (fa);
276 }
277
278 free_mem (fmt);
279 fmt = NULL;
280 }
281
282
283 /* format_lex()-- Simple lexical analyzer for getting the next token
284 * in a FORMAT string. We support a one-level token pushback in the
285 * fmt->saved_token variable. */
286
287 static format_token
288 format_lex (format_data *fmt)
289 {
290 format_token token;
291 int negative_flag;
292 int c;
293 char delim;
294
295 if (fmt->saved_token != FMT_NONE)
296 {
297 token = fmt->saved_token;
298 fmt->saved_token = FMT_NONE;
299 return token;
300 }
301
302 negative_flag = 0;
303 c = next_char (fmt, 0);
304
305 switch (c)
306 {
307 case '(':
308 token = FMT_LPAREN;
309 break;
310
311 case ')':
312 token = FMT_RPAREN;
313 break;
314
315 case '-':
316 negative_flag = 1;
317 /* Fall Through */
318
319 case '+':
320 c = next_char (fmt, 0);
321 if (!isdigit (c))
322 {
323 token = FMT_UNKNOWN;
324 break;
325 }
326
327 fmt->value = c - '0';
328
329 for (;;)
330 {
331 c = next_char (fmt, 0);
332 if (!isdigit (c))
333 break;
334
335 fmt->value = 10 * fmt->value + c - '0';
336 }
337
338 unget_char (fmt);
339
340 if (negative_flag)
341 fmt->value = -fmt->value;
342 token = FMT_SIGNED_INT;
343 break;
344
345 case '0':
346 case '1':
347 case '2':
348 case '3':
349 case '4':
350 case '5':
351 case '6':
352 case '7':
353 case '8':
354 case '9':
355 fmt->value = c - '0';
356
357 for (;;)
358 {
359 c = next_char (fmt, 0);
360 if (!isdigit (c))
361 break;
362
363 fmt->value = 10 * fmt->value + c - '0';
364 }
365
366 unget_char (fmt);
367 token = (fmt->value == 0) ? FMT_ZERO : FMT_POSINT;
368 break;
369
370 case '.':
371 token = FMT_PERIOD;
372 break;
373
374 case ',':
375 token = FMT_COMMA;
376 break;
377
378 case ':':
379 token = FMT_COLON;
380 break;
381
382 case '/':
383 token = FMT_SLASH;
384 break;
385
386 case '$':
387 token = FMT_DOLLAR;
388 break;
389
390 case 'T':
391 switch (next_char (fmt, 0))
392 {
393 case 'L':
394 token = FMT_TL;
395 break;
396 case 'R':
397 token = FMT_TR;
398 break;
399 default:
400 token = FMT_T;
401 unget_char (fmt);
402 break;
403 }
404
405 break;
406
407 case 'X':
408 token = FMT_X;
409 break;
410
411 case 'S':
412 switch (next_char (fmt, 0))
413 {
414 case 'S':
415 token = FMT_SS;
416 break;
417 case 'P':
418 token = FMT_SP;
419 break;
420 default:
421 token = FMT_S;
422 unget_char (fmt);
423 break;
424 }
425
426 break;
427
428 case 'B':
429 switch (next_char (fmt, 0))
430 {
431 case 'N':
432 token = FMT_BN;
433 break;
434 case 'Z':
435 token = FMT_BZ;
436 break;
437 default:
438 token = FMT_B;
439 unget_char (fmt);
440 break;
441 }
442
443 break;
444
445 case '\'':
446 case '"':
447 delim = c;
448
449 fmt->string = fmt->format_string;
450 fmt->value = 0; /* This is the length of the string */
451
452 for (;;)
453 {
454 c = next_char (fmt, 1);
455 if (c == -1)
456 {
457 token = FMT_BADSTRING;
458 fmt->error = bad_string;
459 break;
460 }
461
462 if (c == delim)
463 {
464 c = next_char (fmt, 1);
465
466 if (c == -1)
467 {
468 token = FMT_BADSTRING;
469 fmt->error = bad_string;
470 break;
471 }
472
473 if (c != delim)
474 {
475 unget_char (fmt);
476 token = FMT_STRING;
477 break;
478 }
479 }
480
481 fmt->value++;
482 }
483
484 break;
485
486 case 'P':
487 token = FMT_P;
488 break;
489
490 case 'I':
491 token = FMT_I;
492 break;
493
494 case 'O':
495 token = FMT_O;
496 break;
497
498 case 'Z':
499 token = FMT_Z;
500 break;
501
502 case 'F':
503 token = FMT_F;
504 break;
505
506 case 'E':
507 switch (next_char (fmt, 0))
508 {
509 case 'N':
510 token = FMT_EN;
511 break;
512 case 'S':
513 token = FMT_ES;
514 break;
515 default:
516 token = FMT_E;
517 unget_char (fmt);
518 break;
519 }
520 break;
521
522 case 'G':
523 token = FMT_G;
524 break;
525
526 case 'H':
527 token = FMT_H;
528 break;
529
530 case 'L':
531 token = FMT_L;
532 break;
533
534 case 'A':
535 token = FMT_A;
536 break;
537
538 case 'D':
539 switch (next_char (fmt, 0))
540 {
541 case 'P':
542 token = FMT_DP;
543 break;
544 case 'C':
545 token = FMT_DC;
546 break;
547 default:
548 token = FMT_D;
549 unget_char (fmt);
550 break;
551 }
552 break;
553
554 case -1:
555 token = FMT_END;
556 break;
557
558 default:
559 token = FMT_UNKNOWN;
560 break;
561 }
562
563 return token;
564 }
565
566
567 /* parse_format_list()-- Parse a format list. Assumes that a left
568 * paren has already been seen. Returns a list representing the
569 * parenthesis node which contains the rest of the list. */
570
571 static fnode *
572 parse_format_list (st_parameter_dt *dtp)
573 {
574 fnode *head, *tail;
575 format_token t, u, t2;
576 int repeat;
577 format_data *fmt = dtp->u.p.fmt;
578 bool save_format;
579
580 head = tail = NULL;
581 save_format = !is_internal_unit (dtp);
582
583 /* Get the next format item */
584 format_item:
585 t = format_lex (fmt);
586 format_item_1:
587 switch (t)
588 {
589 case FMT_POSINT:
590 repeat = fmt->value;
591
592 t = format_lex (fmt);
593 switch (t)
594 {
595 case FMT_LPAREN:
596 get_fnode (fmt, &head, &tail, FMT_LPAREN);
597 tail->repeat = repeat;
598 tail->u.child = parse_format_list (dtp);
599 if (fmt->error != NULL)
600 goto finished;
601
602 goto between_desc;
603
604 case FMT_SLASH:
605 get_fnode (fmt, &head, &tail, FMT_SLASH);
606 tail->repeat = repeat;
607 goto optional_comma;
608
609 case FMT_X:
610 get_fnode (fmt, &head, &tail, FMT_X);
611 tail->repeat = 1;
612 tail->u.k = fmt->value;
613 goto between_desc;
614
615 case FMT_P:
616 goto p_descriptor;
617
618 default:
619 goto data_desc;
620 }
621
622 case FMT_LPAREN:
623 get_fnode (fmt, &head, &tail, FMT_LPAREN);
624 tail->repeat = 1;
625 tail->u.child = parse_format_list (dtp);
626 if (fmt->error != NULL)
627 goto finished;
628
629 goto between_desc;
630
631 case FMT_SIGNED_INT: /* Signed integer can only precede a P format. */
632 case FMT_ZERO: /* Same for zero. */
633 t = format_lex (fmt);
634 if (t != FMT_P)
635 {
636 fmt->error = "Expected P edit descriptor in format";
637 goto finished;
638 }
639
640 p_descriptor:
641 get_fnode (fmt, &head, &tail, FMT_P);
642 tail->u.k = fmt->value;
643 tail->repeat = 1;
644
645 t = format_lex (fmt);
646 if (t == FMT_F || t == FMT_EN || t == FMT_ES || t == FMT_D
647 || t == FMT_G || t == FMT_E)
648 {
649 repeat = 1;
650 goto data_desc;
651 }
652
653 fmt->saved_token = t;
654 goto optional_comma;
655
656 case FMT_P: /* P and X require a prior number */
657 fmt->error = "P descriptor requires leading scale factor";
658 goto finished;
659
660 case FMT_X:
661 /*
662 EXTENSION!
663
664 If we would be pedantic in the library, we would have to reject
665 an X descriptor without an integer prefix:
666
667 fmt->error = "X descriptor requires leading space count";
668 goto finished;
669
670 However, this is an extension supported by many Fortran compilers,
671 including Cray, HP, AIX, and IRIX. Therefore, we allow it in the
672 runtime library, and make the front end reject it if the compiler
673 is in pedantic mode. The interpretation of 'X' is '1X'.
674 */
675 get_fnode (fmt, &head, &tail, FMT_X);
676 tail->repeat = 1;
677 tail->u.k = 1;
678 goto between_desc;
679
680 case FMT_STRING:
681 get_fnode (fmt, &head, &tail, FMT_STRING);
682
683 tail->u.string.p = fmt->string;
684 tail->u.string.length = fmt->value;
685 tail->repeat = 1;
686 goto optional_comma;
687
688 case FMT_DC:
689 case FMT_DP:
690 notify_std (&dtp->common, GFC_STD_F2003, "Fortran 2003: DC or DP "
691 "descriptor not allowed");
692 save_format = true;
693 /* Fall through. */
694 case FMT_S:
695 case FMT_SS:
696 case FMT_SP:
697 case FMT_BN:
698 case FMT_BZ:
699 get_fnode (fmt, &head, &tail, t);
700 tail->repeat = 1;
701 goto between_desc;
702
703 case FMT_COLON:
704 get_fnode (fmt, &head, &tail, FMT_COLON);
705 tail->repeat = 1;
706 goto optional_comma;
707
708 case FMT_SLASH:
709 get_fnode (fmt, &head, &tail, FMT_SLASH);
710 tail->repeat = 1;
711 tail->u.r = 1;
712 goto optional_comma;
713
714 case FMT_DOLLAR:
715 get_fnode (fmt, &head, &tail, FMT_DOLLAR);
716 tail->repeat = 1;
717 notify_std (&dtp->common, GFC_STD_GNU, "Extension: $ descriptor");
718 save_format = false;
719 goto between_desc;
720
721
722 case FMT_T:
723 case FMT_TL:
724 case FMT_TR:
725 t2 = format_lex (fmt);
726 if (t2 != FMT_POSINT)
727 {
728 fmt->error = posint_required;
729 goto finished;
730 }
731 get_fnode (fmt, &head, &tail, t);
732 tail->u.n = fmt->value;
733 tail->repeat = 1;
734 goto between_desc;
735
736 case FMT_I:
737 case FMT_B:
738 case FMT_O:
739 case FMT_Z:
740 case FMT_E:
741 case FMT_EN:
742 case FMT_ES:
743 case FMT_D:
744 case FMT_L:
745 case FMT_A:
746 case FMT_F:
747 case FMT_G:
748 repeat = 1;
749 goto data_desc;
750
751 case FMT_H:
752 get_fnode (fmt, &head, &tail, FMT_STRING);
753
754 if (fmt->format_string_len < 1)
755 {
756 fmt->error = bad_hollerith;
757 goto finished;
758 }
759
760 tail->u.string.p = fmt->format_string;
761 tail->u.string.length = 1;
762 tail->repeat = 1;
763
764 fmt->format_string++;
765 fmt->format_string_len--;
766
767 goto between_desc;
768
769 case FMT_END:
770 fmt->error = unexpected_end;
771 goto finished;
772
773 case FMT_BADSTRING:
774 goto finished;
775
776 case FMT_RPAREN:
777 goto finished;
778
779 default:
780 fmt->error = unexpected_element;
781 goto finished;
782 }
783
784 /* In this state, t must currently be a data descriptor. Deal with
785 things that can/must follow the descriptor */
786 data_desc:
787 switch (t)
788 {
789 case FMT_P:
790 t = format_lex (fmt);
791 if (t == FMT_POSINT)
792 {
793 fmt->error = "Repeat count cannot follow P descriptor";
794 goto finished;
795 }
796
797 fmt->saved_token = t;
798 get_fnode (fmt, &head, &tail, FMT_P);
799
800 goto optional_comma;
801
802 case FMT_L:
803 t = format_lex (fmt);
804 if (t != FMT_POSINT)
805 {
806 if (notification_std(GFC_STD_GNU) == ERROR)
807 {
808 fmt->error = posint_required;
809 goto finished;
810 }
811 else
812 {
813 fmt->saved_token = t;
814 fmt->value = 1; /* Default width */
815 notify_std (&dtp->common, GFC_STD_GNU, posint_required);
816 save_format = false;
817 }
818 }
819
820 get_fnode (fmt, &head, &tail, FMT_L);
821 tail->u.n = fmt->value;
822 tail->repeat = repeat;
823 break;
824
825 case FMT_A:
826 t = format_lex (fmt);
827 if (t == FMT_ZERO)
828 {
829 fmt->error = zero_width;
830 goto finished;
831 }
832
833 if (t != FMT_POSINT)
834 {
835 fmt->saved_token = t;
836 fmt->value = -1; /* Width not present */
837 }
838
839 get_fnode (fmt, &head, &tail, FMT_A);
840 tail->repeat = repeat;
841 tail->u.n = fmt->value;
842 break;
843
844 case FMT_D:
845 case FMT_E:
846 case FMT_F:
847 case FMT_G:
848 case FMT_EN:
849 case FMT_ES:
850 get_fnode (fmt, &head, &tail, t);
851 tail->repeat = repeat;
852
853 u = format_lex (fmt);
854 if (t == FMT_G && u == FMT_ZERO)
855 {
856 if (notification_std (GFC_STD_F2008) == ERROR
857 || dtp->u.p.mode == READING)
858 {
859 fmt->error = zero_width;
860 goto finished;
861 }
862 tail->u.real.w = 0;
863 u = format_lex (fmt);
864 if (u != FMT_PERIOD)
865 {
866 fmt->saved_token = u;
867 break;
868 }
869
870 u = format_lex (fmt);
871 if (u != FMT_POSINT)
872 {
873 fmt->error = posint_required;
874 goto finished;
875 }
876 tail->u.real.d = fmt->value;
877 break;
878 }
879 if (t == FMT_F || dtp->u.p.mode == WRITING)
880 {
881 if (u != FMT_POSINT && u != FMT_ZERO)
882 {
883 fmt->error = nonneg_required;
884 goto finished;
885 }
886 }
887 else
888 {
889 if (u != FMT_POSINT)
890 {
891 fmt->error = posint_required;
892 goto finished;
893 }
894 }
895
896 tail->u.real.w = fmt->value;
897 t2 = t;
898 t = format_lex (fmt);
899 if (t != FMT_PERIOD)
900 {
901 /* We treat a missing decimal descriptor as 0. Note: This is only
902 allowed if -std=legacy, otherwise an error occurs. */
903 if (compile_options.warn_std != 0)
904 {
905 fmt->error = period_required;
906 goto finished;
907 }
908 fmt->saved_token = t;
909 tail->u.real.d = 0;
910 break;
911 }
912
913 t = format_lex (fmt);
914 if (t != FMT_ZERO && t != FMT_POSINT)
915 {
916 fmt->error = nonneg_required;
917 goto finished;
918 }
919
920 tail->u.real.d = fmt->value;
921
922 if (t == FMT_D || t == FMT_F)
923 break;
924
925 tail->u.real.e = -1;
926
927 /* Look for optional exponent */
928 t = format_lex (fmt);
929 if (t != FMT_E)
930 fmt->saved_token = t;
931 else
932 {
933 t = format_lex (fmt);
934 if (t != FMT_POSINT)
935 {
936 fmt->error = "Positive exponent width required in format";
937 goto finished;
938 }
939
940 tail->u.real.e = fmt->value;
941 }
942
943 break;
944
945 case FMT_H:
946 if (repeat > fmt->format_string_len)
947 {
948 fmt->error = bad_hollerith;
949 goto finished;
950 }
951
952 get_fnode (fmt, &head, &tail, FMT_STRING);
953
954 tail->u.string.p = fmt->format_string;
955 tail->u.string.length = repeat;
956 tail->repeat = 1;
957
958 fmt->format_string += fmt->value;
959 fmt->format_string_len -= repeat;
960
961 break;
962
963 case FMT_I:
964 case FMT_B:
965 case FMT_O:
966 case FMT_Z:
967 get_fnode (fmt, &head, &tail, t);
968 tail->repeat = repeat;
969
970 t = format_lex (fmt);
971
972 if (dtp->u.p.mode == READING)
973 {
974 if (t != FMT_POSINT)
975 {
976 fmt->error = posint_required;
977 goto finished;
978 }
979 }
980 else
981 {
982 if (t != FMT_ZERO && t != FMT_POSINT)
983 {
984 fmt->error = nonneg_required;
985 goto finished;
986 }
987 }
988
989 tail->u.integer.w = fmt->value;
990 tail->u.integer.m = -1;
991
992 t = format_lex (fmt);
993 if (t != FMT_PERIOD)
994 {
995 fmt->saved_token = t;
996 }
997 else
998 {
999 t = format_lex (fmt);
1000 if (t != FMT_ZERO && t != FMT_POSINT)
1001 {
1002 fmt->error = nonneg_required;
1003 goto finished;
1004 }
1005
1006 tail->u.integer.m = fmt->value;
1007 }
1008
1009 if (tail->u.integer.w != 0 && tail->u.integer.m > tail->u.integer.w)
1010 {
1011 fmt->error = "Minimum digits exceeds field width";
1012 goto finished;
1013 }
1014
1015 break;
1016
1017 default:
1018 fmt->error = unexpected_element;
1019 goto finished;
1020 }
1021
1022 /* Between a descriptor and what comes next */
1023 between_desc:
1024 t = format_lex (fmt);
1025 switch (t)
1026 {
1027 case FMT_COMMA:
1028 goto format_item;
1029
1030 case FMT_RPAREN:
1031 goto finished;
1032
1033 case FMT_SLASH:
1034 case FMT_COLON:
1035 get_fnode (fmt, &head, &tail, t);
1036 tail->repeat = 1;
1037 goto optional_comma;
1038
1039 case FMT_END:
1040 fmt->error = unexpected_end;
1041 goto finished;
1042
1043 default:
1044 /* Assume a missing comma, this is a GNU extension */
1045 goto format_item_1;
1046 }
1047
1048 /* Optional comma is a weird between state where we've just finished
1049 reading a colon, slash or P descriptor. */
1050 optional_comma:
1051 t = format_lex (fmt);
1052 switch (t)
1053 {
1054 case FMT_COMMA:
1055 break;
1056
1057 case FMT_RPAREN:
1058 goto finished;
1059
1060 default: /* Assume that we have another format item */
1061 fmt->saved_token = t;
1062 break;
1063 }
1064
1065 goto format_item;
1066
1067 finished:
1068 return head;
1069 }
1070
1071
1072 /* format_error()-- Generate an error message for a format statement.
1073 * If the node that gives the location of the error is NULL, the error
1074 * is assumed to happen at parse time, and the current location of the
1075 * parser is shown.
1076 *
1077 * We generate a message showing where the problem is. We take extra
1078 * care to print only the relevant part of the format if it is longer
1079 * than a standard 80 column display. */
1080
1081 void
1082 format_error (st_parameter_dt *dtp, const fnode *f, const char *message)
1083 {
1084 int width, i, j, offset;
1085 char *p, buffer[300];
1086 format_data *fmt = dtp->u.p.fmt;
1087
1088 if (f != NULL)
1089 fmt->format_string = f->source;
1090
1091 if (message == unexpected_element)
1092 sprintf (buffer, message, fmt->error_element);
1093 else
1094 sprintf (buffer, "%s\n", message);
1095
1096 j = fmt->format_string - dtp->format;
1097
1098 offset = (j > 60) ? j - 40 : 0;
1099
1100 j -= offset;
1101 width = dtp->format_len - offset;
1102
1103 if (width > 80)
1104 width = 80;
1105
1106 /* Show the format */
1107
1108 p = strchr (buffer, '\0');
1109
1110 memcpy (p, dtp->format + offset, width);
1111
1112 p += width;
1113 *p++ = '\n';
1114
1115 /* Show where the problem is */
1116
1117 for (i = 1; i < j; i++)
1118 *p++ = ' ';
1119
1120 *p++ = '^';
1121 *p = '\0';
1122
1123 generate_error (&dtp->common, LIBERROR_FORMAT, buffer);
1124 }
1125
1126
1127 /* revert()-- Do reversion of the format. Control reverts to the left
1128 * parenthesis that matches the rightmost right parenthesis. From our
1129 * tree structure, we are looking for the rightmost parenthesis node
1130 * at the second level, the first level always being a single
1131 * parenthesis node. If this node doesn't exit, we use the top
1132 * level. */
1133
1134 static void
1135 revert (st_parameter_dt *dtp)
1136 {
1137 fnode *f, *r;
1138 format_data *fmt = dtp->u.p.fmt;
1139
1140 dtp->u.p.reversion_flag = 1;
1141
1142 r = NULL;
1143
1144 for (f = fmt->array.array[0].u.child; f; f = f->next)
1145 if (f->format == FMT_LPAREN)
1146 r = f;
1147
1148 /* If r is NULL because no node was found, the whole tree will be used */
1149
1150 fmt->array.array[0].current = r;
1151 fmt->array.array[0].count = 0;
1152 }
1153
1154 /* parse_format()-- Parse a format string. */
1155
1156 void
1157 parse_format (st_parameter_dt *dtp)
1158 {
1159 format_data *fmt;
1160
1161 /* Lookup format string to see if it has already been parsed. */
1162
1163 dtp->u.p.fmt = find_parsed_format (dtp);
1164
1165 if (dtp->u.p.fmt != NULL)
1166 {
1167 dtp->u.p.fmt->reversion_ok = 0;
1168 dtp->u.p.fmt->saved_token = FMT_NONE;
1169 dtp->u.p.fmt->saved_format = NULL;
1170 reset_fnode_counters (dtp);
1171 return;
1172 }
1173
1174 /* Not found so proceed as follows. */
1175
1176 dtp->u.p.fmt = fmt = get_mem (sizeof (format_data));
1177 fmt->format_string = dtp->format;
1178 fmt->format_string_len = dtp->format_len;
1179
1180 fmt->string = NULL;
1181 fmt->saved_token = FMT_NONE;
1182 fmt->error = NULL;
1183 fmt->value = 0;
1184
1185 /* Initialize variables used during traversal of the tree */
1186
1187 fmt->reversion_ok = 0;
1188 fmt->saved_format = NULL;
1189
1190 /* Allocate the first format node as the root of the tree */
1191
1192 fmt->last = &fmt->array;
1193 fmt->last->next = NULL;
1194 fmt->avail = &fmt->array.array[0];
1195
1196 memset (fmt->avail, 0, sizeof (*fmt->avail));
1197 fmt->avail->format = FMT_LPAREN;
1198 fmt->avail->repeat = 1;
1199 fmt->avail++;
1200
1201 if (format_lex (fmt) == FMT_LPAREN)
1202 fmt->array.array[0].u.child = parse_format_list (dtp);
1203 else
1204 fmt->error = "Missing initial left parenthesis in format";
1205
1206 if (fmt->error)
1207 {
1208 format_error (dtp, NULL, fmt->error);
1209 free_format_hash_table (dtp->u.p.current_unit);
1210 return;
1211 }
1212 save_parsed_format (dtp);
1213 }
1214
1215
1216 /* next_format0()-- Get the next format node without worrying about
1217 * reversion. Returns NULL when we hit the end of the list.
1218 * Parenthesis nodes are incremented after the list has been
1219 * exhausted, other nodes are incremented before they are returned. */
1220
1221 static const fnode *
1222 next_format0 (fnode * f)
1223 {
1224 const fnode *r;
1225
1226 if (f == NULL)
1227 return NULL;
1228
1229 if (f->format != FMT_LPAREN)
1230 {
1231 f->count++;
1232 if (f->count <= f->repeat)
1233 return f;
1234
1235 f->count = 0;
1236 return NULL;
1237 }
1238
1239 /* Deal with a parenthesis node */
1240
1241 for (; f->count < f->repeat; f->count++)
1242 {
1243 if (f->current == NULL)
1244 f->current = f->u.child;
1245
1246 for (; f->current != NULL; f->current = f->current->next)
1247 {
1248 r = next_format0 (f->current);
1249 if (r != NULL)
1250 return r;
1251 }
1252 }
1253
1254 f->count = 0;
1255 return NULL;
1256 }
1257
1258
1259 /* next_format()-- Return the next format node. If the format list
1260 * ends up being exhausted, we do reversion. Reversion is only
1261 * allowed if we've seen a data descriptor since the
1262 * initialization or the last reversion. We return NULL if there
1263 * are no more data descriptors to return (which is an error
1264 * condition). */
1265
1266 const fnode *
1267 next_format (st_parameter_dt *dtp)
1268 {
1269 format_token t;
1270 const fnode *f;
1271 format_data *fmt = dtp->u.p.fmt;
1272
1273 if (fmt->saved_format != NULL)
1274 { /* Deal with a pushed-back format node */
1275 f = fmt->saved_format;
1276 fmt->saved_format = NULL;
1277 goto done;
1278 }
1279
1280 f = next_format0 (&fmt->array.array[0]);
1281 if (f == NULL)
1282 {
1283 if (!fmt->reversion_ok)
1284 return NULL;
1285
1286 fmt->reversion_ok = 0;
1287 revert (dtp);
1288
1289 f = next_format0 (&fmt->array.array[0]);
1290 if (f == NULL)
1291 {
1292 format_error (dtp, NULL, reversion_error);
1293 return NULL;
1294 }
1295
1296 /* Push the first reverted token and return a colon node in case
1297 * there are no more data items. */
1298
1299 fmt->saved_format = f;
1300 return &colon_node;
1301 }
1302
1303 /* If this is a data edit descriptor, then reversion has become OK. */
1304 done:
1305 t = f->format;
1306
1307 if (!fmt->reversion_ok &&
1308 (t == FMT_I || t == FMT_B || t == FMT_O || t == FMT_Z || t == FMT_F ||
1309 t == FMT_E || t == FMT_EN || t == FMT_ES || t == FMT_G || t == FMT_L ||
1310 t == FMT_A || t == FMT_D))
1311 fmt->reversion_ok = 1;
1312 return f;
1313 }
1314
1315
1316 /* unget_format()-- Push the given format back so that it will be
1317 * returned on the next call to next_format() without affecting
1318 * counts. This is necessary when we've encountered a data
1319 * descriptor, but don't know what the data item is yet. The format
1320 * node is pushed back, and we return control to the main program,
1321 * which calls the library back with the data item (or not). */
1322
1323 void
1324 unget_format (st_parameter_dt *dtp, const fnode *f)
1325 {
1326 dtp->u.p.fmt->saved_format = f;
1327 }
1328