PR libfortran/90374
* io/format.c (parse_format_list): Zero width not allowed with
FMT_D.
* io/write_float.def (build_float_string): Include range of
higher exponent values that require wider width.
PR libfortran/90274
* io/format.c (parse_format_list): Implement the E0 exponent
width to provide smallest possible width for exponent fields.
Refactor code for correct parsing and better readability of the
code.
* io/io.h (write_real_w0): Change interface to pass in pointer
to fnode.
* io/transfer.c: Update all calls to write_real_w0 to use the
new interface.
* io/write.c ((write_real_w0): Use the new interface with fnode
to access both the decimal precision and exponent widths used in
build_float_string.
* io/write_float.def (build_float_string): Use the passed in
exponent width to calculate the used width in the case of E0.
From-SVN: r279828
2019-11-06 Jerry DeLisle <jvdelisle@gcc.ngu.org>
PR fortran/90374
* io.c (check_format): Allow zero width for D, E, EN, and ES
specifiers as default and when -std=F2018 is given. Retain
existing errors when using the -fdec family of flags.
* libgfortran/io/format.c (parse_format_list): Relax format checking for
zero width as default and when -std=f2018.
io/format.h (format_token): Move definition to io.h.
io/io.h (format_token): Add definition here to allow access to
this definition at higher levels. Rename the declaration of
write_real_g0 to write_real_w0 and add a new format_token
argument, allowing higher level functions to pass in the
token for handling of g0 vs the other zero width specifiers.
io/transfer.c (formatted_transfer_scalar_write): Add checks for
zero width and call write_real_w0 to handle it.
io/write.c (write_real_g0): Remove.
(write_real_w0): Add new, same as previous write_real_g0 except
check format token to handle the g0 case.
* gfortran.dg/fmt_error_10.f: Modify for new constraints.
* gfortran.dg/fmt_error_7.f: Add dg-options "-std=f95".
* gfortran.dg/fmt_error_9.f: Modify for new constraints.
* gfortran.dg/fmt_zero_width.f90: New test.
From-SVN: r277905
gcc/fortran ChangeLog:
2019-05-22 Jeff Law <law@redhat.com>
Mark Eggleston <mark.eggleston@codethink.com>
PR fortran/89100
* gfortran.texi: Add Default widths for F, G and I format
descriptors to Extensions section.
* invoke.texi: Add -fdec-format-defaults
* io.c (check_format): Use default widths for i, f and g when
flag_dec_format_defaults is enabled.
* lang.opt: Add new option.
* options.c (set_dec_flags): Add SET_BITFLAG for
flag_dec_format_defaults.
gcc/testsuite ChangeLog:
2019-05-22 Mark Eggleston <mark.eggleston@codethink.com>
PR fortran/89100
* gfortran.dg/fmt_f_default_field_width_1.f90: New test.
* gfortran.dg/fmt_f_default_field_width_2.f90: New test.
* gfortran.dg/fmt_f_default_field_width_3.f90: New test.
* gfortran.dg/fmt_g_default_field_width_1.f90: New test.
* gfortran.dg/fmt_g_default_field_width_2.f90: New test.
* gfortran.dg/fmt_g_default_field_width_3.f90: New test.
* gfortran.dg/fmt_i_default_field_width_1.f90: New test.
* gfortran.dg/fmt_i_default_field_width_2.f90: New test.
* gfortran.dg/fmt_i_default_field_width_3.f90: New test.
libgfortran ChangeLog:
2019-05-22 Jeff Law <law@redhat.com>
PR fortran/89100
* io/format.c (parse_format_list): set default width when the
IOPARM_DT_DEC_EXT flag is set for i, f and g.
* io/io.h: add default_width_for_integer, default_width_for_float
and default_precision_for_float.
* io/write.c (write_boz): extra parameter giving length of data
corresponding to the type's kind.
(write_b): pass data length as extra parameter in calls to
write_boz.
(write_o): pass data length as extra parameter in calls to
write_boz.
(write_z): pass data length as extra parameter in calls to
write_boz.
(size_from_kind): also set size is default width is set.
* io/write_float.def (build_float_string): new paramter inserted
before result parameter. If default width use values passed
instead of the values in fnode.
(FORMAT_FLOAT): macro modified to check for default width and
calls to build_float_string to pass in default width.
(get_float_string): set width and precision to defaults when
needed.
From-SVN: r271511
2018-09-01 Jerry DeLisle <jvdelisle@gcc.gnu.org>
* io/io.h: Change declaration of vlist type to
gfc_full_array_i4 to eliminate warning for mismatched type.
* io/format.c ((parse_format_list): Use gfc_full_array_i4.
* io/io.h: Use gfc_full_array_i4.
From-SVN: r264043
2017-10-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Rimvydas (RJ)
PR libgfortran/81938
io/format.c (free_format_data): Don't try to free vlist
descriptors past the end of the fnode array.
From-SVN: r254163
2016-10-31 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/54679
* io.c (check_format): Adjust checks for FMT_L to treat a zero
width as an extension, giving warnings or error as appropriate.
Improve messages.
PR libgfortran/54679
* io/format.c (parse_format_list): Adjust checks for FMT_L to
treat a zero width as an extension, giving warnings or error
as appropriate. Improve messages.
PR fortran/54679
* gfortran.dg/fmt_l.f90: Update test.
* gfortran.dg/fmt_l0.f90: New test.
From-SVN: r241720
2016-08-31 Paul Thomas <pault@gcc.gnu.org>
Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/48298
* decl.c (access_attr_decl): Include case INTERFACE_DTIO as
appropriate.
* gfortran.h : Add INTRINSIC_FORMATTED and
INTRINSIC_UNFORMATTED to gfc_intrinsic_op. Add INTERFACE_DTIO
to interface type. Add new enum 'dtio_codes'. Add bitfield
'has_dtio_procs' to symbol_attr. Add prototypes
'gfc_check_dtio_interfaces' and 'gfc_find_specific_dtio_proc'.
* interface.c (dtio_op): New function.
(gfc_match_generic_spec): Match generic DTIO interfaces.
(gfc_match_interface): Treat DTIO interfaces in the same way as
(gfc_current_interface_head): Add INTERFACE_DTIO appropriately.
(check_dtio_arg_TKR_intent): New function.
(check_dtio_interface1): New function.
(gfc_check_dtio_interfaces): New function.
(gfc_find_specific_dtio_proc): New function.
* io.c : Add FMT_DT to format_token.
(format_lex): Handle DTIO formatting.
* match.c (gfc_op2string): Add DTIO operators.
* resolve.c (derived_inaccessible): Ignore pointer components
to enclosing derived type.
(resolve_transfer): Resolve transfers that involve DTIO.
procedures. Find the specific subroutine for the transfer and
use its existence to over-ride some of the constraints on
derived types. If the transfer is recursive, require that the
subroutine be so qualified.
(dtio_procs_present): New function.
(resolve_fl_namelist): Remove inhibition of polymorphic objects
in namelists if DTIO read and write subroutines exist. Likewise
for derived types.
(resolve_types): Invoke 'gfc_verify_dtio_procedures'.
* symbol.c : Set 'dtio_procs' using 'minit'.
* trans-decl.c (gfc_finish_var_decl): If a derived-type/class
object is associated with DTIO procedures, make it TREE_STATIC.
* trans-expr.c (gfc_get_vptr_from_expr): If the expression
drills down to a PARM_DECL, extract the vptr correctly.
(gfc_conv_derived_to_class): Check 'info' in the test for
'useflags'. If the se expression exists and is a pointer, use
it as the class _data.
* trans-io.c : Add IOCALL_X_DERIVED to iocall and the function
prototype. Likewise for IOCALL_SET_NML_DTIO_VAL.
(set_parameter_tree): Renamed from 'set_parameter_const', now
returns void and has new tree argument. Calls modified to match
new interface.
(transfer_namelist_element): Transfer DTIO procedure pointer
and vpointer using the new function IOCALL_SET_NML_DTIO_VAL.
(get_dtio_proc): New function.
(transfer_expr): Add new argument for the vptr field of class
objects. Add the code to call the specific DTIO proc, convert
derived types to class and call IOCALL_X_DERIVED.
(trans_transfer): Add BT_CLASS to structures for treatment by
the scalarizer. Obtain the vptr for the dynamic type, both for
scalar and array transfer.
2016-08-31 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>
PR libgfortran/48298
* gfortran.map : Flag _st_set_nml_dtio_var and
_gfortran_transfer_derived.
* io/format.c (format_lex): Detect DTIO formatting.
(parse_format_list): Parse the DTIO format.
(next_format): Include FMT_DT.
* io/format.h : Likewise. Add structure 'udf' to structure
'fnode' to carry the IOTYPE string and the 'vlist'.
* io/io.h : Add prototypes for the two types of DTIO subroutine
and a typedef for gfc_class. Also, add to 'namelist_type'
fields for the pointer to the DTIO procedure and the vtable.
Add fields to struct st_parameter_dt for pointers to the two
types of DTIO subroutine. Add to gfc_unit DTIO specific fields.
(internal_proto): Add prototype for 'read_user_defined' and
'write_user_defined'.
* io/list_read.c (check_buffers): Use the 'current_unit' field.
(unget_char): Likewise.
(eat_spaces): Likewise.
(list_formatted_read_scalar): For case BT_CLASS, call the DTIO
procedure.
(nml_get_obj_data): Likewise when DTIO procedure is present,.
* io/transfer.c : Export prototypes for 'transfer_derived' and
'transfer_derived_write'.
(unformatted_read): For case BT_CLASS, call the DTIO procedure.
(unformatted_write): Likewise.
(formatted_transfer_scalar_read): Likewise.
(formatted_transfer_scalar_write: Likewise.
(transfer_derived): New function.
(data_transfer_init): Set last_char if no child_dtio.
(finalize_transfer): Return if child_dtio set.
(st_write_done): Add condition for child_dtio not set.
Add extra arguments for st_set_nml_var prototype.
(set_nml_var): New function that contains the contents of the
old version of st_set_nml_var. Also sets the 'dtio_sub' and
'vtable' fields of the 'nml' structure.
(st_set_nml_var): Now just calls set_nml_var with 'dtio_sub'
and 'vtable' NULL.
(st_set_nml_dtio_var): New function that calls set_nml_var.
* io/unit.c (get_external_unit): If the found unit child_dtio
is non zero, don't do any mutex locking/unlocking. Just
return the unit.
* io/unix.c (tempfile_open): Revert to C style comment.
* io/write.c (list_formatted_write_scalar): Do the DTIO call.
(nml_write_obj): Add BT_CLASS and do the DTIO call.
2016-08-31 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>
PR fortran/48298
* gfortran.dg/dtio_1.f90: New test.
* gfortran.dg/dtio_2.f90: New test.
* gfortran.dg/dtio_3.f90: New test.
* gfortran.dg/dtio_4.f90: New test.
* gfortran.dg/dtio_5.f90: New test.
* gfortran.dg/dtio_6.f90: New test.
* gfortran.dg/dtio_7.f90: New test.
* gfortran.dg/dtio_8.f90: New test.
* gfortran.dg/dtio_9.f90: New test.
* gfortran.dg/dtio_10.f90: New test.
From-SVN: r239880
2015-04-21 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/65234
* io/format.c (parse_format_list): Set the seen_dd flag in all
cases where a data descriptor has been seen.
From-SVN: r222274
2015-04-14 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/65089
* io/format.h (free_format): New function to free memory
allocated for building format error messages.
* io/format.c (format_error): Add checks before freeing memory
to avoid potential segfaults and free formatting data when
needed on error conditions. Always allocate and NULL terminate
the string.
* io/transfer.c (st_read_done, st_write_done): Use new
free_format function to clean up memory allocations when done.
From-SVN: r222111
2014-07-20 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/61632
* io/format.c (format_error): Avoid invalid string pointer by
using the fortran string length values to generate error string.
(parse_format): Allocate the null terminator for the format
string.
From-SVN: r212875
2013-03-19 Janne Blomqvist <jb@gcc.gnu.org>
* libgfortran.h: Include stdbool.h.
(enum try): Remove.
(notify_std): Change return type to bool.
* intrinsics/chmod.c: Don't include stdbool.h.
* intrinsics/execute_command_line.c: Likewise.
* io/format.c: Likewise.
* io/list_read.c (nml_parse_qualifier): Change return type to bool.
(nml_read_obj): Likewise.
(nml_get_obj_data): Likewise.
* io/transfer.c (read_block_form): Fix comment.
(write_buf): Change return type to bool.
* io/write.c: Don't include stdbool.h.
* io/write_float.def (output_float): Change return type to bool.
(output_float_FMT_G_ ## x): Change type of result variable.
* runtime/error.c (notify_std): Change return type to bool.
From-SVN: r196791
Change "if (E) free (E);" to "free (E);" everywhere except in the
libgo/, intl/, zlib/ and classpath/ directories.
Also transform equivalent variants like
"if (E != NULL) free (E);" and allow an extra cast on the
argument to free. Otherwise, the tested and freed "E"
expressions must be identical, modulo white space.
From-SVN: r172785
2010-08-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>
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.
From-SVN: r162978
2010-02-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/42742
* io/format.c (reset_fnode_counters): Use the correct pointer to the
head of the fnode list. (parse_format): Remove previous hack that set
limit on size of format string for caching.
From-SVN: r156568
2010-01-15 Jerry DeLisle <jvdelisle@gcc.gnu.org>
* io/format.c (parse_format): Set limit on size of format strings that
will be cached.
From-SVN: r155939
2009-10-12 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/41683
* io/format.c (parse_format_list): Allow a repeat specifier immediately
after a P specifier.
From-SVN: r152695
2009-09-28 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/35862
* io.h (gfc_unit): Add round_status.
(format_token): Add enumerators for rounding format specifiers.
* transfer.c (round_opt): New options table.
(formatted_transfer_scalar_read): Add set round_status for each rounding
format token. (formatted_transfer_scalar_write): Likewise.
* format.c (format_lex): Tokenize the rounding format specifiers.
(parse_format_list): Parse the rounding format specifiers.
* write_float.def (outout_float): Modify rounding code to use new
variable rchar to set the appropriate rounding. Fix some whitespace.
* unit.c (get_internal_unit): Initialize rounding mode for internal
units. (init_units): Likewise.
From-SVN: r152263
2009-08-17 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/41075
* io/io.h (enum format_token): Add FMT_STAR.
* io/format.c (format_lex): Add case for FMT_STAR.
(parse_format_list): Parse FMT_STAR and check for left paren
after. (next_format0): Modify helper function to check for
unimited format and return the repeated format node. Update
comments to clarify.
From-SVN: r150844
2009-07-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/40330
PR libfortran/40662
* io/io.h (st_parameter_dt): Define format_not_saved bit used to signal
whether the parsed format data was previously saved. Used to determine
if the current format data should be freed or not.
* io/transfer.c (st_read_done): Use the format_not_saved bit.
(st_write_done): Likewise.
* io/format.c (parse_format_list): Add boolean pointer to arg list. This
pointer is used to return status to the caller regarding whether it is
safe to cache the parsed format data. Currently, if a FMT_STRING token
is encounetered, it is not safe to cache. Also, added a local boolean
variable to hold this information as recursive calls to
parse_format_list are made. Remove previous save_format logic.
(parse_format): Do not use the format caching facility if the current
unit is an internal unit or if it is not safe to save parsed format
data.
From-SVN: r149398
2009-06-22 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/40508
* io/format.c: Don't save parsed format data for internal units.
From-SVN: r148823
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.
From-SVN: r145571