diff options
Diffstat (limited to 'libgfortran/io')
-rw-r--r-- | libgfortran/io/backspace.c | 15 | ||||
-rw-r--r-- | libgfortran/io/format.c | 1 | ||||
-rw-r--r-- | libgfortran/io/inquire.c | 7 | ||||
-rw-r--r-- | libgfortran/io/io.h | 7 | ||||
-rw-r--r-- | libgfortran/io/list_read.c | 19 | ||||
-rw-r--r-- | libgfortran/io/open.c | 5 | ||||
-rw-r--r-- | libgfortran/io/transfer.c | 10 | ||||
-rw-r--r-- | libgfortran/io/write.c | 39 |
8 files changed, 76 insertions, 27 deletions
diff --git a/libgfortran/io/backspace.c b/libgfortran/io/backspace.c index f8ab01c3488..225f69cc45a 100644 --- a/libgfortran/io/backspace.c +++ b/libgfortran/io/backspace.c @@ -111,7 +111,7 @@ unformatted_backspace (void) if (p == NULL) goto io_error; - new = file_position (current_unit->s) - *p - length; + new = file_position (current_unit->s) - *p - 2*length; if (sseek (current_unit->s, new) == FAILURE) goto io_error; @@ -155,16 +155,23 @@ st_backspace (void) u->endfile = AT_ENDFILE; else { - if (u->current_record) - next_record (1); - if (file_position (u->s) == 0) goto done; /* Common special case */ + if (u->mode == WRITING) + { + flush (u->s); + struncate (u->s); + u->mode = READING; + } + if (u->flags.form == FORM_FORMATTED) formatted_backspace (); else unformatted_backspace (); + + u->endfile = NO_ENDFILE; + u->current_record = 0; } done: diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c index db5e0fe7372..f8d858af7a7 100644 --- a/libgfortran/io/format.c +++ b/libgfortran/io/format.c @@ -564,6 +564,7 @@ parse_format_list (void) case FMT_COLON: get_fnode (&head, &tail, FMT_COLON); + tail->repeat = 1; goto optional_comma; case FMT_SLASH: diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c index 28c2f6afbc5..1f0fcac6530 100644 --- a/libgfortran/io/inquire.c +++ b/libgfortran/io/inquire.c @@ -46,7 +46,12 @@ inquire_via_unit (gfc_unit * u) const char *p; if (ioparm.exist != NULL) - *ioparm.exist = (u != NULL); + { + if (ioparm.unit >= 0) + *ioparm.exist = 1; + else + *ioparm.exist = 0; + } if (ioparm.opened != NULL) *ioparm.opened = (u != NULL); diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h index 694ca1d7ac5..05c4355ad00 100644 --- a/libgfortran/io/io.h +++ b/libgfortran/io/io.h @@ -245,10 +245,11 @@ typedef struct unit_flags; -/* The default value of record length is defined here. This value can - be overriden by the OPEN statement or by an environment variable. */ +/* The default value of record length for preconnected units is defined + here. This value can be overriden by an environment variable. + Default value is 1 Gb. */ -#define DEFAULT_RECL 10000 +#define DEFAULT_RECL 1073741824 typedef struct gfc_unit diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c index eecc11491e3..0a869b9a16e 100644 --- a/libgfortran/io/list_read.c +++ b/libgfortran/io/list_read.c @@ -66,12 +66,13 @@ static char value[20]; #define CASE_DIGITS case '0': case '1': case '2': case '3': case '4': \ case '5': case '6': case '7': case '8': case '9' -#define CASE_SEPARATORS case ' ': case ',': case '/': case '\n': case '\t' +#define CASE_SEPARATORS case ' ': case ',': case '/': case '\n': case '\t': \ + case '\r' /* This macro assumes that we're operating on a variable. */ #define is_separator(c) (c == '/' || c == ',' || c == '\n' || c == ' ' \ - || c == '\t') + || c == '\t' || c == '\r') /* Maximum repeat count. Less than ten times the maximum signed int32. */ @@ -163,7 +164,7 @@ next_char (void) c = *p; done: - at_eol = (c == '\n'); + at_eol = (c == '\n' || c == '\r'); return c; } @@ -230,6 +231,7 @@ eat_separator (void) break; case '\n': + case '\r': break; case '!': @@ -284,6 +286,7 @@ finish_separator (void) break; case '\n': + case '\r': goto restart; case '!': @@ -1052,8 +1055,9 @@ read_real (int length) goto got_repeat; CASE_SEPARATORS: - if (c != '\n' && c != ',') - unget_char (c); /* Real number that is just a digit-string. */ + if (c != '\n' && c != ',' && c != '\r') + unget_char (c); + goto done; default: @@ -1164,8 +1168,6 @@ read_real (int length) break; CASE_SEPARATORS: - unget_char (c); - eat_separator (); goto done; default: @@ -1174,6 +1176,8 @@ read_real (int length) } done: + unget_char (c); + eat_separator (); push_char ('\0'); if (convert_real (value, saved_string, length)) return; @@ -1485,6 +1489,7 @@ namelist_read (void) return; case ' ': case '\n': + case '\r': case '\t': break; case ',': diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c index eaeb5a298c0..82a862b7c47 100644 --- a/libgfortran/io/open.c +++ b/libgfortran/io/open.c @@ -358,7 +358,7 @@ new_unit (unit_flags * flags) /* Unspecified recl ends up with a processor dependent value. */ - u->recl = (ioparm.recl_in != 0) ? ioparm.recl_in : DEFAULT_RECL; + u->recl = (ioparm.recl_in != 0) ? ioparm.recl_in : g.max_offset; u->last_record = 0; u->current_record = 0; @@ -481,7 +481,10 @@ st_open (void) flags.position = POSITION_ASIS; if (ioparm.library_return != LIBRARY_OK) + { + library_end (); return; + } u = find_unit (ioparm.unit); diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index a55936f9e6c..4d4832395d9 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -177,7 +177,7 @@ read_sf (int *length) return NULL; } - if (readlen < 1 || *q == '\n') + if (readlen < 1 || *q == '\n' || *q == '\r') { /* ??? What is this for? */ if (current_unit->unit_number == options.stdin_unit) @@ -386,7 +386,7 @@ write_constant_string (fnode * f) for (; length > 0; length--) { c = *p++ = *q++; - if (c == delimiter && c != 'H') + if (c == delimiter && c != 'H' && c != 'h') q++; /* Skip the doubled delimiter. */ } } @@ -935,6 +935,12 @@ data_transfer_init (int read_flag) current_unit = get_unit (read_flag); if (current_unit == NULL) { /* Open the unit with some default flags. */ + if (ioparm.unit < 0) + { + generate_error (ERROR_BAD_OPTION, "Bad unit number in OPEN statement"); + library_end (); + return; + } memset (&u_flags, '\0', sizeof (u_flags)); u_flags.access = ACCESS_SEQUENTIAL; u_flags.action = ACTION_READWRITE; diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index 403b9afe322..d97caec8bc7 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Andy Vaught This file is part of the GNU Fortran 95 runtime library (libgfortran). @@ -286,6 +286,8 @@ output_float (fnode *f, double value, int len) int nzero; /* Number of digits after the decimal point. */ int nafter; + /* Number of zeros after the decimal point, whatever the precision. */ + int nzero_real; int leadzero; int nblanks; int i; @@ -295,9 +297,12 @@ output_float (fnode *f, double value, int len) w = f->u.real.w; d = f->u.real.d; + nzero_real = -1; + + /* We should always know the field width and precision. */ if (d < 0) - internal_error ("Uspecified precision"); + internal_error ("Unspecified precision"); /* Use sprintf to print the number in the format +D.DDDDe+ddd For an N digit exponent, this gives us (32-6)-N digits after the @@ -359,6 +364,7 @@ output_float (fnode *f, double value, int len) if (nbefore < 0) { nzero = -nbefore; + nzero_real = nzero; if (nzero > d) nzero = d; nafter = d - nzero; @@ -375,7 +381,8 @@ output_float (fnode *f, double value, int len) case FMT_E: case FMT_D: i = g.scale_factor; - e -= i; + if (value != 0.0) + e -= i; if (i < 0) { nbefore = 0; @@ -395,7 +402,7 @@ output_float (fnode *f, double value, int len) nafter = d; } - if (ft = FMT_E) + if (ft == FMT_E) expchar = 'E'; else expchar = 'D'; @@ -404,7 +411,8 @@ output_float (fnode *f, double value, int len) case FMT_EN: /* The exponent must be a multiple of three, with 1-3 digits before the decimal point. */ - e--; + if (value != 0.0) + e--; if (e >= 0) nbefore = e % 3; else @@ -421,7 +429,8 @@ output_float (fnode *f, double value, int len) break; case FMT_ES: - e--; + if (value != 0.0) + e--; nbefore = 1; nzero = 0; nafter = d; @@ -435,7 +444,17 @@ output_float (fnode *f, double value, int len) /* Round the value. */ if (nbefore + nafter == 0) - ndigits = 0; + { + ndigits = 0; + if (nzero_real == d && digits[0] >= '5') + { + /* We rounded to zero but shouldn't have */ + nzero--; + nafter = 1; + digits[0] = '1'; + ndigits = 1; + } + } else if (nbefore + nafter < ndigits) { ndigits = nbefore + nafter; @@ -518,7 +537,7 @@ output_float (fnode *f, double value, int len) /* Pick a field size if none was specified. */ if (w <= 0) - w = nbefore + nzero + nafter + 2; + w = nbefore + nzero + nafter + (sign != SIGN_NONE ? 2 : 1); /* Create the ouput buffer. */ out = write_block (w); @@ -655,7 +674,7 @@ static void write_float (fnode *f, const char *source, int len) { double n; - int nb =0, res; + int nb =0, res, save_scale_factor; char * p, fin; fnode *f2 = NULL; @@ -704,8 +723,10 @@ write_float (fnode *f, const char *source, int len) } else { + save_scale_factor = g.scale_factor; f2 = calculate_G_format(f, n, len, &nb); output_float (f2, n, len); + g.scale_factor = save_scale_factor; if (f2 != NULL) free_mem(f2); |