TIP 476: Scan/Printf format consistancy

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2017 Conference, Houston/TX, US, Oct 16-20
Send your abstracts to tclconference@googlegroups.com
by Aug 21.
Author: Jan Nijtmans (jan.nijtmans@gmail.com)
State: Draft
Type: Project
Vote: Pending
Created: 27-Sep-2017
Post-history: PM
Tcl-Version: 8.7
Keywords: scan printf

Abstract

The Scan/Printf format handlers are originally derived from the C-equivalent scan() and printf() functions. Since ISO C99 there is the inttypes.h header file, which defines useful macros. But since the Tcl implementation was older than that, those macros don't play well together with Tcl. This TIP proposes a solution for that.

In addition, this TIP proposes to adapt the %#o modifier such that it produces the "0o" prefix in stead of "o". This is a small step in the direction of phasing out octal (TIP #114). Finally this TIP modifiers the %#d modifier, such that it only produces a "0d" prefix if that is needed for correct interpretation of the number when parsing it.

Rationale

For an example program containing all situations mentioned here, see main.c

First of all, when compiling the example program on 64-bit linux (with -DTCL_WIDE_INT_IS_LONG=1), gcc outputs 5 warnings, 4 of them are unnecessary:

main.c: In function 'main':
main.c:61:9: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'long long unsigned int' [-Wformat=]
  printf("%" TCL_LL_MODIFIER "u\n", ll);
         ^~~
main.c:62:22: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'long long unsigned int' [-Wformat=]
  obj = Tcl_ObjPrintf("%" TCL_LL_MODIFIER "u", ll);
                      ^~~
main.c:64:13: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 2 has type 'Tcl_WideUInt {aka long unsigned int}' [-Wformat=]
  printf("%llu\n", w);
             ^
main.c:65:26: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 2 has type 'Tcl_WideUInt {aka long unsigned int}' [-Wformat=]
  obj = Tcl_ObjPrintf("%llu", w);
                          ^
main.c:99:25: warning: format '%Ld' expects argument of type 'long long int', but argument 2 has type 'mp_int * {aka struct mp_int *}' [-Wformat=]
  obj = Tcl_ObjPrintf("%Ld", &mp);
                         ^~~

The last warning arises because the C printf formatter doesn't handle mp_int types, this warning can be safely ignored.

The other 4 warnings arise because Tcl_WideInt is defined as being the same as long on this sytem. Making it the same as long long fully eliminates those warnings.

Specification

This TIP proposes serveral things:

Considerations regarding the incompatibility

This change is almost fully upwards compatible. As long as Tcl extensions use the Tcl_WideInt/Tcl_WideUInt data types (in stead of long long or __int64), everything works as before.

In some situations, "format" doesn't produce the exact same output as Tcl 8.6 any more, but only rarely used corner cases are affected. As the "main.c" example shows, the result is more similar to ISO C99 than before.

Reference Implementation

https://core.tcl.tk/tcl/timeline?r=z_modifier

Copyright

This document is placed in public domain.

History