diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 700cb60e786..6e0ec80714f 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,12 @@ +2010-08-07 Jerry DeLisle + + PR libfortran/45143 + * io/format.c: Remove fnode storage structure definitions, moving these + to format.h. (parse_format_list): Add check for data descriptors, + taking care of nested formats. Adjust calling parameters to pass a + check flag. (parse_format): Likewise. + * io/format.h: Add structures moved from format.c. + 2010-08-02 Janne Blomqvist * io/unit.c (update_position): Don't update the position flag for diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c index 5771777a121..d540fc47e32 100644 --- a/libgfortran/io/format.c +++ b/libgfortran/io/format.c @@ -35,28 +35,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include #include -#define FARRAY_SIZE 64 - -typedef struct fnode_array -{ - struct fnode_array *next; - fnode array[FARRAY_SIZE]; -} -fnode_array; - -typedef struct format_data -{ - char *format_string, *string; - const char *error; - char error_element; - format_token saved_token; - int value, format_string_len, reversion_ok; - fnode *avail; - const fnode *saved_format; - fnode_array *last; - fnode_array array; -} -format_data; static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0, NULL }; @@ -612,13 +590,13 @@ format_lex (format_data *fmt) * parenthesis node which contains the rest of the list. */ static fnode * -parse_format_list (st_parameter_dt *dtp, bool *save_ok) +parse_format_list (st_parameter_dt *dtp, bool *save_ok, bool *seen_dd) { fnode *head, *tail; format_token t, u, t2; int repeat; format_data *fmt = dtp->u.p.fmt; - bool saveit; + bool saveit, seen_data_desc = false; head = tail = NULL; saveit = *save_ok; @@ -638,10 +616,14 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok) } get_fnode (fmt, &head, &tail, FMT_LPAREN); tail->repeat = -2; /* Signifies unlimited format. */ - tail->u.child = parse_format_list (dtp, &saveit); + tail->u.child = parse_format_list (dtp, &saveit, &seen_data_desc); if (fmt->error != NULL) goto finished; - + if (!seen_data_desc) + { + fmt->error = "'*' requires at least one associated data descriptor"; + goto finished; + } goto between_desc; case FMT_POSINT: @@ -653,7 +635,8 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok) case FMT_LPAREN: get_fnode (fmt, &head, &tail, FMT_LPAREN); tail->repeat = repeat; - tail->u.child = parse_format_list (dtp, &saveit); + tail->u.child = parse_format_list (dtp, &saveit, &seen_data_desc); + *seen_dd = seen_data_desc; if (fmt->error != NULL) goto finished; @@ -680,7 +663,8 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok) case FMT_LPAREN: get_fnode (fmt, &head, &tail, FMT_LPAREN); tail->repeat = 1; - tail->u.child = parse_format_list (dtp, &saveit); + tail->u.child = parse_format_list (dtp, &saveit, &seen_data_desc); + *seen_dd = seen_data_desc; if (fmt->error != NULL) goto finished; @@ -821,6 +805,7 @@ parse_format_list (st_parameter_dt *dtp, bool *save_ok) case FMT_F: case FMT_G: repeat = 1; + *seen_dd = true; goto data_desc; case FMT_H: @@ -1217,7 +1202,7 @@ void parse_format (st_parameter_dt *dtp) { format_data *fmt; - bool format_cache_ok; + bool format_cache_ok, seen_data_desc = false; /* Don't cache for internal units and set an arbitrary limit on the size of format strings we will cache. (Avoids memory issues.) */ @@ -1266,7 +1251,8 @@ parse_format (st_parameter_dt *dtp) fmt->avail++; if (format_lex (fmt) == FMT_LPAREN) - fmt->array.array[0].u.child = parse_format_list (dtp, &format_cache_ok); + fmt->array.array[0].u.child = parse_format_list (dtp, &format_cache_ok, + &seen_data_desc); else fmt->error = "Missing initial left parenthesis in format"; diff --git a/libgfortran/io/format.h b/libgfortran/io/format.h index 4abbbea437e..84af2e4f2ed 100644 --- a/libgfortran/io/format.h +++ b/libgfortran/io/format.h @@ -92,6 +92,32 @@ struct fnode }; +/* A storage structures for format node data. */ + +#define FARRAY_SIZE 64 + +typedef struct fnode_array +{ + struct fnode_array *next; + fnode array[FARRAY_SIZE]; +} +fnode_array; + + +typedef struct format_data +{ + char *format_string, *string; + const char *error; + char error_element; + format_token saved_token; + int value, format_string_len, reversion_ok; + fnode *avail; + const fnode *saved_format; + fnode_array *last; + fnode_array array; +} +format_data; + extern void parse_format (st_parameter_dt *); internal_proto(parse_format);