From patchwork Wed Aug 31 03:04:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerry DeLisle X-Patchwork-Id: 664348 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sP9Gf5vzRz9s8x for ; Wed, 31 Aug 2016 13:04:40 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=EGiGVCA9; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=ci2JMdzuosx2BatXR6EZ7iJ6jF05GpaFjU7cINWJ9q7JhEU2gG nRScW+BuVdQxhuhYTidZp2Tiog1EPEfDVghwkfaFlMFp7A47y02Sb+7q2OJ2KENx FydGwobsrwIttmFbWiCz6crqxmYuod1r88mRqcWurxK6H4/5xQDdkgu1c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=rHYlnx58CF6UoTiwo4Pchn+Yqq8=; b=EGiGVCA95nkmpsN7tJOt kbW3KBcDmihewe0prsYFKelJ2t4zL+OFhtT3Zmr/8qdRh3cqBWKbWMwUaBwJml1M zvkLEzP94IFTVJQm7ahfkNkUxzhMuVcBlLwn+wKZCy8zaMwTwwB7EPNExW3YVnVi a3u+sDSgr/DdvfyGifPp5E4= Received: (qmail 113529 invoked by alias); 31 Aug 2016 03:04:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 113466 invoked by uid 89); 31 Aug 2016 03:04:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_20, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=2016-08-31, UD:write.c, write.c, writec X-Spam-User: qpsmtpd, 2 recipients X-HELO: mtaout001-public.msg.strl.va.charter.net Received: from mtaout001-public.msg.strl.va.charter.net (HELO mtaout001-public.msg.strl.va.charter.net) (68.114.190.26) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 31 Aug 2016 03:04:20 +0000 Received: from impout005 ([68.114.189.20]) by mtaout001.msg.strl.va.charter.net (InterMail vM.9.00.023.01 201-2473-194) with ESMTP id <20160831030418.VTMU7355.mtaout001.msg.strl.va.charter.net@impout005>; Tue, 30 Aug 2016 22:04:18 -0500 Received: from quattro.localdomain ([96.41.215.23]) by impout005 with charter.net id df4H1t00A0Wrkg001f4H04; Tue, 30 Aug 2016 22:04:18 -0500 X-Authority-Analysis: v=2.1 cv=N8unFgNB c=1 sm=1 tr=0 a=salB9WdMPIDduBH7JsZfrA==:117 a=salB9WdMPIDduBH7JsZfrA==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=r77TgQKjGQsHNAKrUKIA:9 a=mDV3o1hIAAAA:8 a=6pF6a2IwzZ3hRa5GE6MA:9 a=QEXdDO2ut3YA:10 a=tLwzKS4-BhTzpugiVJUA:9 a=ZpOvkZYwA2DRhsgH2SoA:9 a=_FVE-zBwftR9WsbkzFJk:22 X-Auth-id: anZkZWxpc2xlQGNoYXJ0ZXIubmV0 To: gfortran Cc: gcc patches From: Jerry DeLisle Subject: [patch, libgfortran] PR77393 [7 Regression] Revision r237735 changed the behavior of F0.0 Message-ID: Date: Tue, 30 Aug 2016 20:04:17 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 Hi all, The attached patch fixes the problem by adding a new helper function to determine the buffer size needed for F0 editing depending on the kind. In this new function there are some constants presented which document the limits needed for each kind type. As can be seen, the required buffers are fixed on stack at 256 bytes which will handle almost all cases unless a user is doing something with unusually wide formats. The buffer is malloc'ed if a larger size is needed. I have not changed the buffering mechanism, only the method of determining the needed size. Regression tested on x86-linux. New test case provided. OK for trunk? Regards, Jerry 2016-08-31 Jerry DeLisle PR libgfortran/77393 * io/write.c (kind_from_size): New function to calculate required buffer size based on kind type. (select_buffer, select_string): Use new function. (write_float_0, write_real, write_real_g0, write_complex): Adjust calls to pass parameters needed by new function. diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index db27f2d..0e4ce0b 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -1357,11 +1357,52 @@ get_precision (st_parameter_dt *dtp, const fnode *f, const char *source, int kin return determine_en_precision (dtp, f, source, kind); } +/* 4932 is the maximum exponent of long double and quad precision, 3 + extra characters for the sign, the decimal point, and the + trailing null. Extra digits are added by the calling functions for + requested precision. Likewise for float and double. F0 editing produces + full precision output. */ +static int +size_from_kind (st_parameter_dt *dtp, const fnode *f, int kind) +{ + int size; + + if (f->format == FMT_F && f->u.real.w == 0) + { + switch (kind) + { + case 4: + size = 38 + 3; /* These constants shown for clarity. */ + break; + case 8: + size = 308 + 3; + break; + case 10: + size = 4932 + 3; + break; + case 16: + size = 4932 + 3; + break; + default: + internal_error (&dtp->common, "bad real kind"); + break; + } + } + else + size = f->u.real.w + 1; /* One byte for a NULL character. */ + + return size; +} + static char * -select_buffer (int precision, char *buf, size_t *size) +select_buffer (st_parameter_dt *dtp, const fnode *f, int precision, + char *buf, size_t *size, int kind) { char *result; - *size = BUF_STACK_SZ / 2 + precision; + + /* The buffer needs at least one more byte to allow room for normalizing. */ + *size = size_from_kind (dtp, f, kind) + precision + 1; + if (*size > BUF_STACK_SZ) result = xmalloc (*size); else @@ -1370,10 +1411,11 @@ select_buffer (int precision, char *buf, size_t *size) } static char * -select_string (const fnode *f, char *buf, size_t *size) +select_string (st_parameter_dt *dtp, const fnode *f, char *buf, size_t *size, + int kind) { char *result; - *size = f->u.real.w + 1; + *size = size_from_kind (dtp, f, kind) + f->u.real.d; if (*size > BUF_STACK_SZ) result = xmalloc (*size); else @@ -1397,6 +1439,7 @@ write_float_string (st_parameter_dt *dtp, char *fstr, size_t len) memcpy (p, fstr, len); } + static void write_float_0 (st_parameter_dt *dtp, const fnode *f, const char *source, int kind) { @@ -1409,9 +1452,9 @@ write_float_0 (st_parameter_dt *dtp, const fnode *f, const char *source, int kin int precision = get_precision (dtp, f, source, kind); /* String buffer to hold final result. */ - result = select_string (f, str_buf, &res_len); + result = select_string (dtp, f, str_buf, &res_len, kind); - buffer = select_buffer (precision, buf_stack, &buf_size); + buffer = select_buffer (dtp, f, precision, buf_stack, &buf_size, kind); get_float_string (dtp, f, source , kind, 0, buffer, precision, buf_size, result, &res_len); @@ -1527,10 +1570,10 @@ write_real (st_parameter_dt *dtp, const char *source, int kind) int precision = get_precision (dtp, &f, source, kind); /* String buffer to hold final result. */ - result = select_string (&f, str_buf, &res_len); + result = select_string (dtp, &f, str_buf, &res_len, kind); - /* scratch buffer to hold final result. */ - buffer = select_buffer (precision, buf_stack, &buf_size); + /* Scratch buffer to hold final result. */ + buffer = select_buffer (dtp, &f, precision, buf_stack, &buf_size, kind); get_float_string (dtp, &f, source , kind, 1, buffer, precision, buf_size, result, &res_len); @@ -1572,9 +1615,9 @@ write_real_g0 (st_parameter_dt *dtp, const char *source, int kind, int d) int precision = get_precision (dtp, &f, source, kind); /* String buffer to hold final result. */ - result = select_string (&f, str_buf, &res_len); + result = select_string (dtp, &f, str_buf, &res_len, kind); - buffer = select_buffer (precision, buf_stack, &buf_size); + buffer = select_buffer (dtp, &f, precision, buf_stack, &buf_size, kind); get_float_string (dtp, &f, source , kind, comp_d, buffer, precision, buf_size, result, &res_len); @@ -1620,10 +1663,10 @@ write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size) int precision = get_precision (dtp, &f, source, kind); /* String buffers to hold final result. */ - result1 = select_string (&f, str1_buf, &res_len1); - result2 = select_string (&f, str2_buf, &res_len2); + result1 = select_string (dtp, &f, str1_buf, &res_len1, kind); + result2 = select_string (dtp, &f, str2_buf, &res_len2, kind); - buffer = select_buffer (precision, buf_stack, &buf_size); + buffer = select_buffer (dtp, &f, precision, buf_stack, &buf_size, kind); get_float_string (dtp, &f, source , kind, 0, buffer, precision, buf_size, result1, &res_len1);