Received: from malur.postgresql.org ([2a02:16a8:dc51::56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fKAOT-0005sE-Np for pgsql-hackers@arkaria.postgresql.org; Sat, 19 May 2018 22:32:05 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1fKAOR-0006KZ-N5 for pgsql-hackers@arkaria.postgresql.org; Sat, 19 May 2018 22:32:03 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fKAOR-0006KQ-3V for pgsql-hackers@lists.postgresql.org; Sat, 19 May 2018 22:32:03 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fKAOK-00036m-5P for pgsql-hackers@lists.postgresql.org; Sat, 19 May 2018 22:32:01 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.14.4/8.14.4) with ESMTP id w4JMVsb3021671 for ; Sat, 19 May 2018 18:31:54 -0400 From: Tom Lane To: pgsql-hackers@lists.postgresql.org Subject: printf("%lf",...) isn't actually portable MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <21471.1526768868.0@sss.pgh.pa.us> Date: Sat, 19 May 2018 18:31:54 -0400 Message-ID: <21670.1526769114@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <21471.1526768868.1@sss.pgh.pa.us> I noticed while poking at the recent ecpg unpleasantness that some of my older critters were warning about use of %lf conversions in printf. Looking into it, I find that current POSIX says the "l" is a no-op, while SUSv2 says it's undefined. I think this usage got into our code as a result of people making false analogies between scanf and printf conversions. I think we should just switch these to plain %f, as per attached. regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="remove-unportable-lf-format-specs.patch"; charset="us-ascii" Content-ID: <21471.1526768868.2@sss.pgh.pa.us> Content-Description: remove-unportable-lf-format-specs.patch Content-Transfer-Encoding: quoted-printable diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreef= uncs.c index 558a8c4..90acf6a 100644 --- a/contrib/pageinspect/btreefuncs.c +++ b/contrib/pageinspect/btreefuncs.c @@ -563,7 +563,7 @@ bt_metap(PG_FUNCTION_ARGS) if (metad->btm_version =3D=3D BTREE_VERSION) { values[j++] =3D psprintf("%u", metad->btm_oldest_btpo_xact); - values[j++] =3D psprintf("%lf", metad->btm_last_cleanup_num_heap_tuples= ); + values[j++] =3D psprintf("%f", metad->btm_last_cleanup_num_heap_tuples)= ; } else { diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 98b6840..f065477 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -1678,7 +1678,7 @@ while (1) Here is an example using the data type complex from the example in . The external string - representation of that type is (%lf,%lf), + representation of that type is (%f,%f), which is defined in the functions complex_in() and complex_out() functions diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rm= grdesc/nbtdesc.c index 1590d67..5c44571 100644 --- a/src/backend/access/rmgrdesc/nbtdesc.c +++ b/src/backend/access/rmgrdesc/nbtdesc.c @@ -100,7 +100,7 @@ btree_desc(StringInfo buf, XLogReaderState *record) { xl_btree_metadata *xlrec =3D (xl_btree_metadata *) rec; = - appendStringInfo(buf, "oldest_btpo_xact %u; last_cleanup_num_heap_tup= les: %lf", + appendStringInfo(buf, "oldest_btpo_xact %u; last_cleanup_num_heap_tup= les: %f", xlrec->oldest_btpo_xact, xlrec->last_cleanup_num_heap_tuples); break; diff --git a/src/interfaces/ecpg/test/compat_informix/sqlda.pgc b/src/inte= rfaces/ecpg/test/compat_informix/sqlda.pgc index 423ce41..87e0110 100644 --- a/src/interfaces/ecpg/test/compat_informix/sqlda.pgc +++ b/src/interfaces/ecpg/test/compat_informix/sqlda.pgc @@ -37,7 +37,7 @@ dump_sqlda(sqlda_t *sqlda) printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqln= ame, *(int *)sqlda->sqlvar[i].sqldata); break; case SQLFLOAT: - printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sql= name, *(double *)sqlda->sqlvar[i].sqldata); + printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqln= ame, *(double *)sqlda->sqlvar[i].sqldata); break; case SQLDECIMAL: { diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/s= rc/interfaces/ecpg/test/expected/compat_informix-sqlda.c index fa2e569..ad3188d 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c +++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c @@ -142,7 +142,7 @@ dump_sqlda(sqlda_t *sqlda) printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqln= ame, *(int *)sqlda->sqlvar[i].sqldata); break; case SQLFLOAT: - printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sql= name, *(double *)sqlda->sqlvar[i].sqldata); + printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqln= ame, *(double *)sqlda->sqlvar[i].sqldata); break; case SQLDECIMAL: { diff --git a/src/interfaces/ecpg/test/expected/preproc-outofscope.c b/src/= interfaces/ecpg/test/expected/preproc-outofscope.c index f4676a0..ef4dada 100644 --- a/src/interfaces/ecpg/test/expected/preproc-outofscope.c +++ b/src/interfaces/ecpg/test/expected/preproc-outofscope.c @@ -337,7 +337,7 @@ if (sqlca.sqlcode < 0) exit (1);} get_record1(); if (sqlca.sqlcode =3D=3D ECPG_NOT_FOUND) break; - printf("id=3D%d%s t=3D'%s'%s d1=3D%lf%s d2=3D%lf%s c =3D '%s'%s\n", + printf("id=3D%d%s t=3D'%s'%s d1=3D%f%s d2=3D%f%s c =3D '%s'%s\n", myvar->id, mynullvar->id ? " (NULL)" : "", myvar->t, mynullvar->t ? " (NULL)" : "", myvar->d1, mynullvar->d1 ? " (NULL)" : "", diff --git a/src/interfaces/ecpg/test/expected/sql-sqlda.c b/src/interface= s/ecpg/test/expected/sql-sqlda.c index 81d26b3..090aaf1 100644 --- a/src/interfaces/ecpg/test/expected/sql-sqlda.c +++ b/src/interfaces/ecpg/test/expected/sql-sqlda.c @@ -158,7 +158,7 @@ dump_sqlda(sqlda_t *sqlda) break; #endif case ECPGt_double: - printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sql= name.data, *(double *)sqlda->sqlvar[i].sqldata); + printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqln= ame.data, *(double *)sqlda->sqlvar[i].sqldata); break; case ECPGt_numeric: { diff --git a/src/interfaces/ecpg/test/preproc/outofscope.pgc b/src/interfa= ces/ecpg/test/preproc/outofscope.pgc index aae5325..b03743c 100644 --- a/src/interfaces/ecpg/test/preproc/outofscope.pgc +++ b/src/interfaces/ecpg/test/preproc/outofscope.pgc @@ -101,7 +101,7 @@ main (void) get_record1(); if (sqlca.sqlcode =3D=3D ECPG_NOT_FOUND) break; - printf("id=3D%d%s t=3D'%s'%s d1=3D%lf%s d2=3D%lf%s c =3D '%s'%s\n", + printf("id=3D%d%s t=3D'%s'%s d1=3D%f%s d2=3D%f%s c =3D '%s'%s\n", myvar->id, mynullvar->id ? " (NULL)" : "", myvar->t, mynullvar->t ? " (NULL)" : "", myvar->d1, mynullvar->d1 ? " (NULL)" : "", diff --git a/src/interfaces/ecpg/test/sql/sqlda.pgc b/src/interfaces/ecpg/= test/sql/sqlda.pgc index 0f2059f..2ea5121 100644 --- a/src/interfaces/ecpg/test/sql/sqlda.pgc +++ b/src/interfaces/ecpg/test/sql/sqlda.pgc @@ -45,7 +45,7 @@ dump_sqlda(sqlda_t *sqlda) break; #endif case ECPGt_double: - printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sql= name.data, *(double *)sqlda->sqlvar[i].sqldata); + printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqln= ame.data, *(double *)sqlda->sqlvar[i].sqldata); break; case ECPGt_numeric: { ------- =_aaaaaaaaaa0--