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