diff options
author | jvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-05 20:13:56 +0000 |
---|---|---|
committer | jvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-05 20:13:56 +0000 |
commit | 65f150109497089b84160c7cb3219f8dc69587a2 (patch) | |
tree | 9713a11310a5202d06a5ad2750bf0992f9c0e3f6 /libgfortran/io/read.c | |
parent | eb04d2ded6999d6662bc1efe4bed158072773ca8 (diff) | |
download | ppe42-gcc-65f150109497089b84160c7cb3219f8dc69587a2.tar.gz ppe42-gcc-65f150109497089b84160c7cb3219f8dc69587a2.zip |
2009-04-05 Daniel Kraft <d@domob.eu>
PR fortran/38654
* io/read.c (read_f): Reworked to speed up floating point parsing.
(convert_real): Use pointer-casting instead of memcpy and temporaries.
2009-04-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/37754
* io/io.h (format_hash_entry): New structure for hash table.
(format_hash_table): The hash table itself.
(free_format_data): Revise function prototype.
(free_format_hash_table, init_format_hash,
free_format_hash): New function prototypes.
* io/unit.c (close_unit_1): Use free_format_hash_table.
* io/transfer.c (st_read_done, st_write_done): Free format data if
internal unit.
* io/format.c (free_format_hash_table): New function that frees any
memory allocated previously for cached format data.
(reset_node): New static helper function to reset the format counters
for a format node.
(reset_fnode_counters): New static function recursively calls reset_node
to traverse the fnode tree.
(format_hash): New simple hash function based on XOR, probabalistic,
tosses collisions.
(save_parsed_format): New static function to save the parsed format
data to use again.
(find_parsed_format): New static function searches the hash table
looking for a match.
(free_format_data): Revised to accept pointer to format data rather than
the dtp pointer so that the function can be used in more places.
(format_lex): Editorial.
(parse_format_list): Set flag used to determine of format data hashing
is to be used. Internal units are not persistent enough for this.
(revert): Move to ne location in file.
(parse_format): Use new functions to look for previously parsed
format strings and use them rather than re-parse. If not found, saves
the parsed format data for later use.
2009-04-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/37754
* io/transfer.c (formatted_transfer_scalar): Remove this function by
factoring it into two new functions, one for read and one for write,
eliminating all the conditionals for read or write mode.
(formatted transfer_scalar_read): New function.
(formatted transfer_scalar_write): New function.
(formatted_transfer): Use new functions.
2009-04-05 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/25561 libfortran/37754
* io/io.h (struct stream): Define new stream interface function
pointers, and inline functions for accessing it.
(struct fbuf): Use int instead of size_t, remove flushed element.
(mem_alloc_w): New prototype.
(mem_alloc_r): New prototype.
(stream_at_bof): Remove prototype.
(stream_at_eof): Remove prototype.
(file_position): Remove prototype.
(flush): Remove prototype.
(stream_offset): Remove prototype.
(unit_truncate): New prototype.
(read_block_form): Change to return pointer, int* argument.
(hit_eof): New prototype.
(fbuf_init): Change prototype.
(fbuf_reset): Change prototype.
(fbuf_alloc): Change prototype.
(fbuf_flush): Change prototype.
(fbuf_seek): Change prototype.
(fbuf_read): New prototype.
(fbuf_getc_refill): New prototype.
(fbuf_getc): New inline function.
* io/fbuf.c (fbuf_init): Use int, get rid of flushed.
(fbuf_debug): New function.
(fbuf_reset): Flush, and return position offset.
(fbuf_alloc): Simplify, don't flush, just realloc.
(fbuf_flush): Make usable for read mode, salvage remaining bytes.
(fbuf_seek): New whence argument.
(fbuf_read): New function.
(fbuf_getc_refill): New function.
* io/file_pos.c (formatted_backspace): Use new stream interface.
(unformatted_backspace): Likewise.
(st_backspace): Make sure format buffer is reset, use new stream
interface, use unit_truncate.
(st_endfile): Likewise.
(st_rewind): Likewise.
* io/intrinsics.c: Use new stream interface.
* io/list_read.c (push_char): Don't use u.p.scratch, use realloc
to resize.
(free_saved): Don't check u.p.scratch.
(next_char): Use new stream interface, use fbuf_getc() for external files.
(finish_list_read): flush format buffer.
(nml_query): Update to use modified interface:s
* io/open.c (test_endfile): Use new stream interface.
(edit_modes): Likewise.
(new_unit): Likewise, set bytes_left to 1 for stream files.
* io/read.c (read_l): Use new read_block_form interface.
(read_utf8): Likewise.
(read_utf8_char1): Likewise.
(read_default_char1): Likewise.
(read_utf8_char4): Likewise.
(read_default_char4): Likewise.
(read_a): Likewise.
(read_a_char4): Likewise.
(read_decimal): Likewise.
(read_radix): Likewise.
(read_f): Likewise.
* io/transfer.c (read_sf): Use fbuf_read and mem_alloc_r, remove
usage of u.p.line_buffer.
(read_block_form): Update interface to return pointer, use
fbuf_read for direct access.
(read_block_direct): Update to new stream interface.
(write_block): Use mem_alloc_w for internal I/O.
(write_buf): Update to new stream interface.
(formatted_transfer_scalar): Don't use u.p.line_buffer, use
fbuf_seek for external files.
(us_read): Update to new stream interface.
(us_write): Likewise.
(data_transfer_init): Always check if we switch modes and flush.
(skip_record): Use new stream interface, fix comparison.
(next_record_r): Check for and reset u.p.at_eof, use new stream
interface, use fbuf_getc for spacing.
(write_us_marker): Update to new stream interface, don't inline.
(next_record_w_unf): Likewise.
(sset): New function.
(next_record_w): Use new stream interface, use fbuf for printing
newline.
(next_record): Use new stream interface.
(finalize_transfer): Remove sfree call, use new stream interface.
(st_iolength_done): Don't use u.p.scratch.
(st_read): Don't check for end of file.
(st_read_done): Don't use u.p.scratch, use unit_truncate.
(hit_eof): New function.
* io/unit.c (init_units): Always init fbuf for formatted units.
(update_position): Use new stream interface.
(unit_truncate): New function.
(finish_last_advance_record): Use fbuf to print newline.
* io/unix.c: Remove unused SSIZE_MAX macro.
(BUFFER_SIZE): Make static const variable rather than macro.
(struct unix_stream): Remove dirty_offset, len, method,
small_buffer. Order elements by decreasing size.
(struct int_stream): Remove.
(move_pos_offset): Remove usage of dirty_offset.
(reset_stream): Remove.
(do_read): Rename to raw_read, update to match new stream
interface.
(do_write): Rename to raw_write, update to new stream interface.
(raw_seek): New function.
(raw_tell): New function.
(raw_truncate): New function.
(raw_close): New function.
(raw_flush): New function.
(raw_init): New function.
(fd_alloc): Remove.
(fd_alloc_r_at): Remove.
(fd_alloc_w_at): Remove.
(fd_sfree): Remove.
(fd_seek): Remove.
(fd_truncate): Remove.
(fd_sset): Remove.
(fd_read): Remove.
(fd_write): Remove.
(fd_close): Remove.
(fd_open): Remove.
(fd_flush): Rename to buf_flush, update to new stream interface
and unix_stream.
(buf_read): New function.
(buf_write): New function.
(buf_seek): New function.
(buf_tell): New function.
(buf_truncate): New function.
(buf_close): New function.
(buf_init): New function.
(mem_alloc_r_at): Rename to mem_alloc_r, change prototype.
(mem_alloc_w_at): Rename to mem_alloc_w, change prototype.
(mem_read): Change to match new stream interface.
(mem_write): Likewise.
(mem_seek): Likewise.
(mem_tell): Likewise.
(mem_truncate): Likewise.
(mem_close): Likewise.
(mem_flush): New function.
(mem_sfree): Remove.
(empty_internal_buffer): Cast to correct type.
(open_internal): Use correct type, init function pointers.
(fd_to_stream): Test whether to open file as buffered or raw.
(output_stream): Remove mode set.
(error_stream): Likewise.
(flush_all_units_1): Use new stream interface.
(flush_all_units): Likewise.
(stream_at_bof): Remove.
(stream_at_eof): Remove.
(file_position): Remove.
(file_length): Update logic to use stream interface.
(flush): Remove.
(stream_offset): Remove.
* io/write.c (write_utf8_char4): Use int instead of size_t.
(write_x): Extra safety check.
(namelist_write_newline): Use new stream interface.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145571 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran/io/read.c')
-rw-r--r-- | libgfortran/io/read.c | 490 |
1 files changed, 221 insertions, 269 deletions
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c index a8ae3d73f53..b651665944f 100644 --- a/libgfortran/io/read.c +++ b/libgfortran/io/read.c @@ -33,6 +33,7 @@ Boston, MA 02110-1301, USA. */ #include <errno.h> #include <ctype.h> #include <stdlib.h> +#include <assert.h> typedef unsigned char uchar; @@ -141,38 +142,30 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length) switch (length) { case 4: - { - GFC_REAL_4 tmp = + *((GFC_REAL_4*) dest) = #if defined(HAVE_STRTOF) - strtof (buffer, NULL); + strtof (buffer, NULL); #else - (GFC_REAL_4) strtod (buffer, NULL); + (GFC_REAL_4) strtod (buffer, NULL); #endif - memcpy (dest, (void *) &tmp, length); - } break; + case 8: - { - GFC_REAL_8 tmp = strtod (buffer, NULL); - memcpy (dest, (void *) &tmp, length); - } + *((GFC_REAL_8*) dest) = strtod (buffer, NULL); break; + #if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD) case 10: - { - GFC_REAL_10 tmp = strtold (buffer, NULL); - memcpy (dest, (void *) &tmp, length); - } + *((GFC_REAL_10*) dest) = strtold (buffer, NULL); break; #endif + #if defined(HAVE_GFC_REAL_16) && defined (HAVE_STRTOLD) case 16: - { - GFC_REAL_16 tmp = strtold (buffer, NULL); - memcpy (dest, (void *) &tmp, length); - } + *((GFC_REAL_16*) dest) = strtold (buffer, NULL); break; #endif + default: internal_error (&dtp->common, "Unsupported real kind during IO"); } @@ -195,13 +188,13 @@ void read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length) { char *p; - size_t w; + int w; w = f->u.w; - p = gfc_alloca (w); + p = read_block_form (dtp, &w); - if (read_block_form (dtp, p, &w) == FAILURE) + if (p == NULL) return; while (*p == ' ') @@ -238,28 +231,26 @@ read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length) } -static inline gfc_char4_t -read_utf8 (st_parameter_dt *dtp, size_t *nbytes) +static gfc_char4_t +read_utf8 (st_parameter_dt *dtp, int *nbytes) { static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 }; static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - static uchar buffer[6]; - size_t i, nb, nread; + int i, nb, nread; gfc_char4_t c; - int status; char *s; *nbytes = 1; - s = (char *) &buffer[0]; - status = read_block_form (dtp, s, nbytes); - if (status == FAILURE) + + s = read_block_form (dtp, nbytes); + if (s == NULL) return 0; /* If this is a short read, just return. */ if (*nbytes == 0) return 0; - c = buffer[0]; + c = (uchar) s[0]; if (c < 0x80) return c; @@ -274,9 +265,8 @@ read_utf8 (st_parameter_dt *dtp, size_t *nbytes) c = (c & masks[nb-1]); nread = nb - 1; - s = (char *) &buffer[1]; - status = read_block_form (dtp, s, &nread); - if (status == FAILURE) + s = read_block_form (dtp, &nread); + if (s == NULL) return 0; /* Decode the bytes read. */ for (i = 1; i < nb; i++) @@ -309,14 +299,14 @@ read_utf8 (st_parameter_dt *dtp, size_t *nbytes) static void -read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, size_t width) +read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, int width) { gfc_char4_t c; char *dest; - size_t nbytes; + int nbytes; int i, j; - len = ((int) width < len) ? len : (int) width; + len = (width < len) ? len : width; dest = (char *) p; @@ -339,21 +329,19 @@ read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, size_t width) } static void -read_default_char1 (st_parameter_dt *dtp, char *p, int len, size_t width) +read_default_char1 (st_parameter_dt *dtp, char *p, int len, int width) { char *s; - int m, n, status; + int m, n; - s = gfc_alloca (width); - - status = read_block_form (dtp, s, &width); + s = read_block_form (dtp, &width); - if (status == FAILURE) + if (s == NULL) return; - if (width > (size_t) len) + if (width > len) s += (width - len); - m = ((int) width > len) ? len : (int) width; + m = (width > len) ? len : width; memcpy (p, s, m); n = len - width; @@ -363,13 +351,13 @@ read_default_char1 (st_parameter_dt *dtp, char *p, int len, size_t width) static void -read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, size_t width) +read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, int width) { gfc_char4_t *dest; - size_t nbytes; + int nbytes; int i, j; - len = ((int) width < len) ? len : (int) width; + len = (width < len) ? len : width; dest = (gfc_char4_t *) p; @@ -391,19 +379,17 @@ read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, size_t width) static void -read_default_char4 (st_parameter_dt *dtp, char *p, int len, size_t width) +read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width) { char *s; gfc_char4_t *dest; - int m, n, status; - - s = gfc_alloca (width); + int m, n; - status = read_block_form (dtp, s, &width); + s = read_block_form (dtp, &width); - if (status == FAILURE) + if (s == NULL) return; - if (width > (size_t) len) + if (width > len) s += (width - len); m = ((int) width > len) ? len : (int) width; @@ -425,7 +411,7 @@ void read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length) { int wi; - size_t w; + int w; wi = f->u.w; if (wi == -1) /* '(A)' edit descriptor */ @@ -451,13 +437,11 @@ read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length) void read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length) { - int wi; - size_t w; + int w; - wi = f->u.w; - if (wi == -1) /* '(A)' edit descriptor */ - wi = length; - w = wi; + w = f->u.w; + if (w == -1) /* '(A)' edit descriptor */ + w = length; /* Read in w characters, treating comma as not a separator. */ dtp->u.p.sf_read_comma = 0; @@ -532,18 +516,15 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length) GFC_UINTEGER_LARGEST value, maxv, maxv_10; GFC_INTEGER_LARGEST v; int w, negative; - size_t wu; char c, *p; - wu = f->u.w; + w = f->u.w; - p = gfc_alloca (wu); + p = read_block_form (dtp, &w); - if (read_block_form (dtp, p, &wu) == FAILURE) + if (p == NULL) return; - w = wu; - p = eat_leading_spaces (&w, p); if (w == 0) { @@ -636,17 +617,14 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length, GFC_INTEGER_LARGEST v; int w, negative; char c, *p; - size_t wu; - wu = f->u.w; + w = f->u.w; - p = gfc_alloca (wu); + p = read_block_form (dtp, &w); - if (read_block_form (dtp, p, &wu) == FAILURE) + if (p == NULL) return; - w = wu; - p = eat_leading_spaces (&w, p); if (w == 0) { @@ -783,75 +761,83 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length, void read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length) { - size_t wu; int w, seen_dp, exponent; - int exponent_sign, val_sign; - int ndigits; - int edigits; - int i; - char *p, *buffer; - char *digits; - char scratch[SCRATCH_SIZE]; - - val_sign = 1; - seen_dp = 0; - wu = f->u.w; + int exponent_sign; + const char *p; + char *buffer; + char *out; + int seen_int_digit; /* Seen a digit before the decimal point? */ + int seen_dec_digit; /* Seen a digit after the decimal point? */ - p = gfc_alloca (wu); + seen_dp = 0; + seen_int_digit = 0; + seen_dec_digit = 0; + exponent_sign = 1; + exponent = 0; + w = f->u.w; - if (read_block_form (dtp, p, &wu) == FAILURE) + /* Read in the next block. */ + p = read_block_form (dtp, &w); + if (p == NULL) return; - - w = wu; - - p = eat_leading_spaces (&w, p); + p = eat_leading_spaces (&w, (char*) p); if (w == 0) goto zero; - /* Optional sign */ + /* In this buffer we're going to re-format the number cleanly to be parsed + by convert_real in the end; this assures we're using strtod from the + C library for parsing and thus probably get the best accuracy possible. + This process may add a '+0.0' in front of the number as well as change the + exponent because of an implicit decimal point or the like. Thus allocating + strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the + original buffer had should be enough. */ + buffer = gfc_alloca (w + 11); + out = buffer; + /* Optional sign */ if (*p == '-' || *p == '+') { if (*p == '-') - val_sign = -1; - p++; - w--; + *(out++) = '-'; + ++p; + --w; } - exponent_sign = 1; - p = eat_leading_spaces (&w, p); + p = eat_leading_spaces (&w, (char*) p); if (w == 0) goto zero; - /* A digit, a '.' or a exponent character ('e', 'E', 'd' or 'D') - is required at this point */ - - if (!isdigit (*p) && *p != '.' && *p != ',' && *p != 'd' && *p != 'D' - && *p != 'e' && *p != 'E') - goto bad_float; - - /* Remember the position of the first digit. */ - digits = p; - ndigits = 0; - - /* Scan through the string to find the exponent. */ + /* Process the mantissa string. */ while (w > 0) { switch (*p) { case ',': - if (dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA - && *p == ',') - *p = '.'; - else + if (dtp->u.p.current_unit->decimal_status != DECIMAL_COMMA) goto bad_float; - /* Fall through */ + /* Fall through. */ case '.': if (seen_dp) goto bad_float; + if (!seen_int_digit) + *(out++) = '0'; + *(out++) = '.'; seen_dp = 1; - /* Fall through */ + break; + case ' ': + if (dtp->u.p.blank_status == BLANK_ZERO) + { + *(out++) = '0'; + goto found_digit; + } + else if (dtp->u.p.blank_status == BLANK_NULL) + break; + else + /* TODO: Should we check instead that there are only trailing + blanks here, as is done below for exponents? */ + goto done; + /* Fall through. */ case '0': case '1': case '2': @@ -862,207 +848,173 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length) case '7': case '8': case '9': - case ' ': - ndigits++; - p++; - w--; + *(out++) = *p; +found_digit: + if (!seen_dp) + seen_int_digit = 1; + else + seen_dec_digit = 1; break; case '-': - exponent_sign = -1; - /* Fall through */ - case '+': - p++; - w--; - goto exp2; + goto exponent; - case 'd': case 'e': - case 'D': case 'E': - p++; - w--; - goto exp1; + case 'd': + case 'D': + ++p; + --w; + goto exponent; default: goto bad_float; } - } - /* No exponent has been seen, so we use the current scale factor */ - exponent = -dtp->u.p.scale_factor; - goto done; - - bad_float: - generate_error (&dtp->common, LIBERROR_READ_VALUE, - "Bad value during floating point read"); - next_record (dtp, 1); - return; - - /* The value read is zero */ - zero: - switch (length) - { - case 4: - *((GFC_REAL_4 *) dest) = 0; - break; - - case 8: - *((GFC_REAL_8 *) dest) = 0; - break; - -#ifdef HAVE_GFC_REAL_10 - case 10: - *((GFC_REAL_10 *) dest) = 0; - break; -#endif - -#ifdef HAVE_GFC_REAL_16 - case 16: - *((GFC_REAL_16 *) dest) = 0; - break; -#endif - - default: - internal_error (&dtp->common, "Unsupported real kind during IO"); + ++p; + --w; } - return; + + /* No exponent has been seen, so we use the current scale factor. */ + exponent = - dtp->u.p.scale_factor; + goto done; - /* At this point the start of an exponent has been found */ - exp1: - while (w > 0 && *p == ' ') + /* At this point the start of an exponent has been found. */ +exponent: + p = eat_leading_spaces (&w, (char*) p); + if (*p == '-' || *p == '+') { - w--; - p++; + if (*p == '-') + exponent_sign = -1; + ++p; + --w; } - switch (*p) - { - case '-': - exponent_sign = -1; - /* Fall through */ - - case '+': - p++; - w--; - break; - } + /* At this point a digit string is required. We calculate the value + of the exponent in order to take account of the scale factor and + the d parameter before explict conversion takes place. */ if (w == 0) goto bad_float; - /* At this point a digit string is required. We calculate the value - of the exponent in order to take account of the scale factor and - the d parameter before explict conversion takes place. */ - exp2: - /* Normal processing of exponent */ - exponent = 0; if (dtp->u.p.blank_status == BLANK_UNSPECIFIED) { while (w > 0 && isdigit (*p)) - { - exponent = 10 * exponent + *p - '0'; - p++; - w--; - } - - /* Only allow trailing blanks */ - + { + exponent *= 10; + exponent += *p - '0'; + ++p; + --w; + } + + /* Only allow trailing blanks. */ while (w > 0) - { - if (*p != ' ') + { + if (*p != ' ') goto bad_float; - p++; - w--; - } + ++p; + --w; + } } - else /* BZ or BN status is enabled */ + else /* BZ or BN status is enabled. */ { while (w > 0) - { - if (*p == ' ') - { - if (dtp->u.p.blank_status == BLANK_ZERO) *p = '0'; - if (dtp->u.p.blank_status == BLANK_NULL) - { - p++; - w--; - continue; - } - } - else if (!isdigit (*p)) - goto bad_float; - - exponent = 10 * exponent + *p - '0'; - p++; - w--; - } + { + if (*p == ' ') + { + if (dtp->u.p.blank_status == BLANK_ZERO) + exponent *= 10; + else + assert (dtp->u.p.blank_status == BLANK_NULL); + } + else if (!isdigit (*p)) + goto bad_float; + else + { + exponent *= 10; + exponent += *p - '0'; + } + + ++p; + --w; + } } - exponent = exponent * exponent_sign; + exponent *= exponent_sign; - done: +done: /* Use the precision specified in the format if no decimal point has been seen. */ if (!seen_dp) exponent -= f->u.real.d; - if (exponent > 0) - { - edigits = 2; - i = exponent; - } - else - { - edigits = 3; - i = -exponent; - } + /* Output a trailing '0' after decimal point if not yet found. */ + if (seen_dp && !seen_dec_digit) + *(out++) = '0'; - while (i >= 10) + /* Print out the exponent to finish the reformatted number. Maximum 4 + digits for the exponent. */ + if (exponent != 0) { - i /= 10; - edigits++; - } + int dig; - i = ndigits + edigits + 1; - if (val_sign < 0) - i++; + *(out++) = 'e'; + if (exponent < 0) + { + *(out++) = '-'; + exponent = - exponent; + } - if (i < SCRATCH_SIZE) - buffer = scratch; - else - buffer = get_mem (i); - - /* Reformat the string into a temporary buffer. As we're using atof it's - easiest to just leave the decimal point in place. */ - p = buffer; - if (val_sign < 0) - *(p++) = '-'; - for (; ndigits > 0; ndigits--) - { - if (*digits == ' ') - { - if (dtp->u.p.blank_status == BLANK_ZERO) *digits = '0'; - if (dtp->u.p.blank_status == BLANK_NULL) - { - digits++; - continue; - } - } - *p = *digits; - p++; - digits++; + assert (exponent < 10000); + for (dig = 3; dig >= 0; --dig) + { + out[dig] = (char) ('0' + exponent % 10); + exponent /= 10; + } + out += 4; } - *(p++) = 'e'; - sprintf (p, "%d", exponent); + *(out++) = '\0'; /* Do the actual conversion. */ convert_real (dtp, dest, buffer, length); - if (buffer != scratch) - free_mem (buffer); + return; + /* The value read is zero. */ +zero: + switch (length) + { + case 4: + *((GFC_REAL_4 *) dest) = 0.0; + break; + + case 8: + *((GFC_REAL_8 *) dest) = 0.0; + break; + +#ifdef HAVE_GFC_REAL_10 + case 10: + *((GFC_REAL_10 *) dest) = 0.0; + break; +#endif + +#ifdef HAVE_GFC_REAL_16 + case 16: + *((GFC_REAL_16 *) dest) = 0.0; + break; +#endif + + default: + internal_error (&dtp->common, "Unsupported real kind during IO"); + } + return; + +bad_float: + generate_error (&dtp->common, LIBERROR_READ_VALUE, + "Bad value during floating point read"); + next_record (dtp, 1); + return; } |