diff options
author | Fritz Reese <fritzoreese@gmail.com> | 2016-10-26 12:11:44 +0000 |
---|---|---|
committer | Fritz Reese <foreese@gcc.gnu.org> | 2016-10-26 12:11:44 +0000 |
commit | 0ef33d44629066e33ffdc46014374a3ef5c5f009 (patch) | |
tree | 45d5f5c66da6b5b2820d025ba02eb604ab6a5b91 /gcc/fortran/io.c | |
parent | 9dbe100a4157843d12b192e4aae504b43af4774b (diff) | |
download | gcc-0ef33d44629066e33ffdc46014374a3ef5c5f009.zip gcc-0ef33d44629066e33ffdc46014374a3ef5c5f009.tar.gz gcc-0ef33d44629066e33ffdc46014374a3ef5c5f009.tar.bz2 |
New I/O specifiers CARRIAGECONTROL, READONLY, SHARE with -fdec.
gcc/fortran/
* gfortran.texi: Document.
* frontend-passes.c (gfc_code_walker): Add SHARE and CARRIAGECONTROL.
* io.c (gfc_free_open, gfc_resolve_open, gfc_match_open): Ditto.
* gfortran.h (gfc_open): Add SHARE, CARRIAGECONTROL, and READONLY.
* io.c (io_tag, match_open_element): Ditto.
* ioparm.def: Ditto.
* trans-io.c (gfc_trans_open): Ditto.
* io.c (match_dec_etag, match_dec_ftag): New functions.
libgfortran/io/
* libgfortran.h (IOPARM_OPEN_HAS_READONLY, IOPARM_OPEN_HAS_SHARE,
IOPARM_OPEN_HAS_CC): New for READONLY, SHARE, and CARRIAGECONTROL.
* close.c (st_close): Support READONLY.
* io.h (st_parameter_open, unit_flags): Support SHARE, CARRIAGECONTROL,
and READONLY.
* open.c (st_open): Ditto.
* transfer.c (data_transfer_init): Ditto.
* io.h (st_parameter_dt): New member 'cc' for CARRIAGECONTROL.
* write.c (write_check_cc, write_cc): New functions for CARRIAGECONTROL.
* transfer.c (next_record_cc): Ditto.
* file_pos.c (st_endfile): Support SHARE and CARRIAGECONTROL.
* io.h (st_parameter_inquire): Ditto.
* open.c (edit_modes, new_unit): Ditto.
* inquire.c (inquire_via_unit, inquire_via_filename): Ditto.
* io.h (unit_share, unit_cc, cc_fortran, IOPARM_INQUIRE_HAS_SHARE,
IOPARM_INQUIRE_HAS_CC): New for SHARE and CARRIAGECONTROL.
* open.c (share_opt, cc_opt): Ditto.
* read.c (read_x): Support CARRIAGECONTROL.
* transfer.c (read_sf, next_record_r, next_record_w): Ditto.
* write.c (list_formatted_write_scalar, write_a): Ditto.
* unix.h (close_share): New prototype.
* unix.c (open_share, close_share): New functions to handle SHARE.
* unix.c (open_external): Handle READONLY. Call open_share.
* close.c (st_close): Call close_share.
gcc/testsuite/
* dec_io_1.f90: New test.
* dec_io_2.f90: New test.
* dec_io_3.f90: New test.
* dec_io_4.f90: New test.
* dec_io_5.f90: New test.
* dec_io_6.f90: New test.
From-SVN: r241550
Diffstat (limited to 'gcc/fortran/io.c')
-rw-r--r-- | gcc/fortran/io.c | 177 |
1 files changed, 175 insertions, 2 deletions
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c index 7c48c49..dce0f7c 100644 --- a/gcc/fortran/io.c +++ b/gcc/fortran/io.c @@ -38,6 +38,15 @@ typedef struct io_tag; static const io_tag + tag_readonly = {"READONLY", " readonly", NULL, BT_UNKNOWN }, + tag_shared = {"SHARE", " shared", NULL, BT_UNKNOWN }, + tag_noshared = {"SHARE", " noshared", NULL, BT_UNKNOWN }, + tag_e_share = {"SHARE", " share =", " %e", BT_CHARACTER }, + tag_v_share = {"SHARE", " share =", " %v", BT_CHARACTER }, + tag_cc = {"CARRIAGECONTROL", " carriagecontrol =", " %e", + BT_CHARACTER }, + tag_v_cc = {"CARRIAGECONTROL", " carriagecontrol =", " %v", + BT_CHARACTER }, tag_file = {"FILE", " file =", " %e", BT_CHARACTER }, tag_status = {"STATUS", " status =", " %e", BT_CHARACTER}, tag_e_access = {"ACCESS", " access =", " %e", BT_CHARACTER}, @@ -1495,6 +1504,97 @@ match_ltag (const io_tag *tag, gfc_st_label ** label) } +/* Match a tag using match_etag, but only if -fdec is enabled. */ +static match +match_dec_etag (const io_tag *tag, gfc_expr **e) +{ + match m = match_etag (tag, e); + if (flag_dec && m != MATCH_NO) + return m; + else if (m != MATCH_NO) + { + gfc_error ("%s is a DEC extension at %C, re-compile with " + "-fdec to enable", tag->name); + return MATCH_ERROR; + } + return m; +} + + +/* Match a tag using match_vtag, but only if -fdec is enabled. */ +static match +match_dec_vtag (const io_tag *tag, gfc_expr **e) +{ + match m = match_vtag(tag, e); + if (flag_dec && m != MATCH_NO) + return m; + else if (m != MATCH_NO) + { + gfc_error ("%s is a DEC extension at %C, re-compile with " + "-fdec to enable", tag->name); + return MATCH_ERROR; + } + return m; +} + + +/* Match a DEC I/O flag tag - a tag with no expression such as READONLY. */ + +static match +match_dec_ftag (const io_tag *tag, gfc_open *o) +{ + match m; + + m = gfc_match (tag->spec); + if (m != MATCH_YES) + return m; + + if (!flag_dec) + { + gfc_error ("%s is a DEC extension at %C, re-compile with " + "-fdec to enable", tag->name); + return MATCH_ERROR; + } + + /* Just set the READONLY flag, which we use at runtime to avoid delete on + close. */ + if (tag == &tag_readonly) + { + o->readonly |= 1; + return MATCH_YES; + } + + /* Interpret SHARED as SHARE='DENYNONE' (read lock). */ + else if (tag == &tag_shared) + { + if (o->share != NULL) + { + gfc_error ("Duplicate %s specification at %C", tag->name); + return MATCH_ERROR; + } + o->share = gfc_get_character_expr (gfc_default_character_kind, + &gfc_current_locus, "denynone", 8); + return MATCH_YES; + } + + /* Interpret NOSHARED as SHARE='DENYRW' (exclusive lock). */ + else if (tag == &tag_noshared) + { + if (o->share != NULL) + { + gfc_error ("Duplicate %s specification at %C", tag->name); + return MATCH_ERROR; + } + o->share = gfc_get_character_expr (gfc_default_character_kind, + &gfc_current_locus, "denyrw", 6); + return MATCH_YES; + } + + /* We handle all DEC tags above. */ + gcc_unreachable (); +} + + /* Resolution of the FORMAT tag, to be called from resolve_tag. */ static bool @@ -1743,6 +1843,23 @@ match_open_element (gfc_open *open) if (m != MATCH_NO) return m; + /* The following are extensions enabled with -fdec. */ + m = match_dec_etag (&tag_e_share, &open->share); + if (m != MATCH_NO) + return m; + m = match_dec_etag (&tag_cc, &open->cc); + if (m != MATCH_NO) + return m; + m = match_dec_ftag (&tag_readonly, open); + if (m != MATCH_NO) + return m; + m = match_dec_ftag (&tag_shared, open); + if (m != MATCH_NO) + return m; + m = match_dec_ftag (&tag_noshared, open); + if (m != MATCH_NO) + return m; + return MATCH_NO; } @@ -1775,6 +1892,8 @@ gfc_free_open (gfc_open *open) gfc_free_expr (open->convert); gfc_free_expr (open->asynchronous); gfc_free_expr (open->newunit); + gfc_free_expr (open->share); + gfc_free_expr (open->cc); free (open); } @@ -1805,6 +1924,8 @@ gfc_resolve_open (gfc_open *open) RESOLVE_TAG (&tag_e_sign, open->sign); RESOLVE_TAG (&tag_convert, open->convert); RESOLVE_TAG (&tag_newunit, open->newunit); + RESOLVE_TAG (&tag_e_share, open->share); + RESOLVE_TAG (&tag_cc, open->cc); if (!gfc_reference_st_label (open->err, ST_LABEL_TARGET)) return false; @@ -2014,15 +2135,29 @@ gfc_match_open (void) /* Checks on the ACTION specifier. */ if (open->action && open->action->expr_type == EXPR_CONSTANT) { + gfc_char_t *str = open->action->value.character.string; static const char *action[] = { "READ", "WRITE", "READWRITE", NULL }; if (!is_char_type ("ACTION", open->action)) goto cleanup; if (!compare_to_allowed_values ("ACTION", action, NULL, NULL, - open->action->value.character.string, - "OPEN", warn)) + str, "OPEN", warn)) goto cleanup; + + /* With READONLY, only allow ACTION='READ'. */ + if (open->readonly && (gfc_wide_strlen (str) != 4 + || gfc_wide_strncasecmp (str, "READ", 4) != 0)) + { + gfc_error ("ACTION type conflicts with READONLY specifier at %C"); + goto cleanup; + } + } + /* If we see READONLY and no ACTION, set ACTION='READ'. */ + else if (open->readonly && open->action == NULL) + { + open->action = gfc_get_character_expr (gfc_default_character_kind, + &gfc_current_locus, "read", 4); } /* Checks on the ASYNCHRONOUS specifier. */ @@ -2067,6 +2202,22 @@ gfc_match_open (void) } } + /* Checks on the CARRIAGECONTROL specifier. */ + if (open->cc) + { + if (!is_char_type ("CARRIAGECONTROL", open->cc)) + goto cleanup; + + if (open->cc->expr_type == EXPR_CONSTANT) + { + static const char *cc[] = { "LIST", "FORTRAN", "NONE", NULL }; + if (!compare_to_allowed_values ("CARRIAGECONTROL", cc, NULL, NULL, + open->cc->value.character.string, + "OPEN", warn)) + goto cleanup; + } + } + /* Checks on the DECIMAL specifier. */ if (open->decimal) { @@ -2191,6 +2342,22 @@ gfc_match_open (void) } } + /* Checks on the SHARE specifier. */ + if (open->share) + { + if (!is_char_type ("SHARE", open->share)) + goto cleanup; + + if (open->share->expr_type == EXPR_CONSTANT) + { + static const char *share[] = { "DENYNONE", "DENYRW", NULL }; + if (!compare_to_allowed_values ("SHARE", share, NULL, NULL, + open->share->value.character.string, + "OPEN", warn)) + goto cleanup; + } + } + /* Checks on the SIGN specifier. */ if (open->sign) { @@ -4102,6 +4269,8 @@ gfc_free_inquire (gfc_inquire *inquire) gfc_free_expr (inquire->sign); gfc_free_expr (inquire->size); gfc_free_expr (inquire->round); + gfc_free_expr (inquire->share); + gfc_free_expr (inquire->cc); free (inquire); } @@ -4157,6 +4326,8 @@ match_inquire_element (gfc_inquire *inquire) RETM m = match_vtag (&tag_pending, &inquire->pending); RETM m = match_vtag (&tag_id, &inquire->id); RETM m = match_vtag (&tag_s_iqstream, &inquire->iqstream); + RETM m = match_dec_vtag (&tag_v_share, &inquire->share); + RETM m = match_dec_vtag (&tag_v_cc, &inquire->cc); RETM return MATCH_NO; } @@ -4354,6 +4525,8 @@ gfc_resolve_inquire (gfc_inquire *inquire) INQUIRE_RESOLVE_TAG (&tag_size, inquire->size); INQUIRE_RESOLVE_TAG (&tag_s_decimal, inquire->decimal); INQUIRE_RESOLVE_TAG (&tag_s_iqstream, inquire->iqstream); + INQUIRE_RESOLVE_TAG (&tag_v_share, inquire->share); + INQUIRE_RESOLVE_TAG (&tag_v_cc, inquire->cc); #undef INQUIRE_RESOLVE_TAG if (!gfc_reference_st_label (inquire->err, ST_LABEL_TARGET)) |