RE: ICU4C proposal: Formalizing the ustdio format specifiers

George Rhoten <[email protected]>
Newsgroups gmane.comp.lib.icu.general
Message-ID <OFB9555AC7.403FB675-ON86256D5F.0058435F-88256D5F.005D7299@us.ibm.com>
1) Sadly a long isn't always 4 bytes.  It can also be 8 bytes on a few 
other platforms (Alpha is one of them).  This is why I'm not using long or 
long long in the format specification, and I'm only using int*_t types.  I 
have no plans to support ll or I64.  The reason for this decision was to 
follow a similar philosophy of Java where types always have the same size 
on all platforms.

I figure it would be much easier to say that h means short format, and l 
means long format as opposed to 'h means short int and l means long int.' 
If you don't want l (ell) to mean int64_t, I guess I'll hold off on 
supporting 64-bit types in ustdio.  This topic can be brought up again at 
a later date.

I withdraw the l (ell) format modifier for meaning anything on %d, %i, %o, 
%x, %X or %u.

I agree with you about the optional type specifier.  The type must be 
specified after the l or h in ustdio.

2) I'm not using ints.  %S and %C on several platforms means that wchar_t 
should be used.  On Windows, this is 16-bits, but %S can also mean that 
char * is used instead depending on the API used.  On AIX, it can be 16 or 
32-bits depending on the architecture.  On Linux, it's usually 32-bits, 
but it can also be 16-bits at times.  wchar_t sometimes means that Unicode 
is used, but sometimes it isn't.  I'm trying to stay away from using int, 
long or wchar_t types.  I'd really rather prefer to implement it the way I 
originally suggested.

3) I was planning on explicitly not supporting %ls and %lc for now. Markus 
had a great aversion to adding wchar_t support to ustdio right now 
(http://oss.software.ibm.com/icu/docs/papers/unicode_wchar_t.html), so I'm 
reserving it for possible future implementation when someone has the need 
or time to implement wchar_t.  It's easier to add it in the future, but 
it's very difficult to remove it.

4) I'll let you submit an RFE on it.  I don't want to formalize any 
callbacks yet, but I do see an advantage.  My main goal right now is to 
make a ustdio that works.  Many of the callbacks will be changing 
internally.  Special features like this are beyond what I can do for 2.8.

George Rhoten
IBM Globalization Center of Competency/ICU  San Jose, CA, USA




"Robert Buck" <[email protected]>
07/10/2003 07:22 AM

 
        To:     George Rhoten/San Jose/IBM@IBMUS, <[email protected]>
        cc: 
        Subject:        RE: ICU4C proposal: Formalizing the ustdio format specifiers



Great. I look forward to the changes. Esp support for %ld.

A couple questions though...

############################################################################
##
1.

From what I am reading in the C99 spec before me (Ch 7.19.6.1 article 4 
and
Ch 7.19.6.2 article 11):

, the conversion specifier must be present
, the length modifer is optional
, behavior of a specification using a length modifier by itself is 
undefined

Does your spec suggest that '%l' is equivalent to '%ld' ? If so, please 
no.

Also, the spec says...

", l (ell) Specifies that a following d, i, o, u, x, or X conversion
specifier
applies to a long int or unsigned long int argument; that a following n
conversion specifier applies to a pointer to a long int argument; that a
following c conversion specifier applies to a wint_t argument; that a
following s conversion specifier applies to a pointer to a wchar_t
argument; or has no effect on a following a, A, e, E, f, F, g, or G
conversion
specifier.

", ll (ell-ell) Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a long long int or unsigned long long int argument;
or that a following n conversion specifier applies to a pointer to a long
long int
argument."

It would seem to me that, apart from those outlier compilers that do not
support 'long int' or 'long long int', that the 'l' and 'll' should behave
as though the modifer indicates that the subsequent argument is at most 
the
platform width of 'long int' for 'l', and the platform width of 'long long
int'
for 'll'. Taking a poll on five OSs, this means these would map to:

type / sizeof   windows-ia32-vc7  linux-ia32  solaris-64  macosx  hpux-11
--------------------------------------------------------------------------
'long long int'   unsupported          8         8           8        8
'long int'             4               4         4           4        4

For win32 it would be reasonable to say that 'll' regards 64-bit types.

I think it would be reasonable to say from evidence that %ld is used for
int32_t,
and %lld is used for int64_t. Similarly for corresponding unsigned
quantities as well,
%lu and %llu. In fact, if you use the '%ld' format on hpux for a 64 bit
type,
and a value of INT64_MAX, you get an error, which seems to further support
my
argument.

printf("sizeof long int: %lld\n", INT64_MAX); // yields 
9223372036854775807
printf("sizeof long int: %ld\n", INT64_MAX); // yields 1001; an error of
course

Other platforms that support the spec for 'll' will yield similar errors.

So in summary, %ld is _not_ for int64_t, nor is %lu for uint64_t according
to the spec,
or according to practice. Please do not introduce this error to the ICU 
api.

############################################################################
##
2.

Also, regarding the 'h' modifier and its use with regards to unicode
strings,
another alternative would be:

> %S  UChar32 *  Null terminated UTF-16 string
> %hS UChar *    Null terminated UTF-16 string
> %hhS char *    Null terminated UTF-32 string

and,

> %C UChar32     32-bit Unicode code unit
> %hC  UChar     16-bit Unicode code unit
> %hhC char      8-bit Unicode code unit

The point is that the conversion type for an 'h' modifier is presumed to 
be
promoted to sizeof int. The int type is more naturally associated to
UChar32 than UChar16. So one could argue that the above is more
consistent with the intent of the C99 Spec on the basis that 'h' is
meant to demote a type from an int to a type of short, and 'hh' is meant
to demote an int to a char. Your use of 'h' is inconsistent with the
spec as it demotes a short to a char. See Ch 7.24.2.1 article 7.

############################################################################
##
3.

> %ls N/A         (Unimplemented) Reserved for future implementation

Actually %ls is already taken by the C99 Spec, and refers to a wchar_t *.
So please consider dropping this from your spec, but support it according
to platform/compiler conventions, and the C99 spec.

> %lc N/A         (Unimplemented) Reserved for future implementation

And in the spec this refers to a wint_t. Same as above.

############################################################################
##
4.

A nifty thing we use regularly in MATLAB is function holes. It essentially
does a callback to a function that is allowed to put N characters into
the output buffer. For us it is represented as a naked %U, so leaving out
lots of details:

switch (conversion specifier hole type) {
case FUNCTION_HOLE_TYPE:
{
va_list   hole_ap = msg->hole_infos[holeIdx].hole.hole_ap;
fn_fmtfcn fmtfcn  = va_arg(hole_ap, fn_fmtfcn);
num_chars_written = (fmtfcn)(putsn, dest_buf_or_file_ptr, &hole_ap);
break;
}
}

typedef int (*fn_fmtfcn)(  /* returns the number of chars putsn'd after
processing*/
fn_putsn putsn,
void *x,             /* destination info, e.g., FILE *, or &buffer */
va_list *ap);        /* var args list to custom format specifier, on
return
this is advanced past the custom format varargs */

Would it be possible to augment the icu api to support this sort of
callback?

-Bob

> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]]On Behalf Of George
> Rhoten
> Sent: Wednesday, July 09, 2003 7:05 PM
> To: [email protected]
> Subject: ICU4C proposal: Formalizing the ustdio format specifiers
>
>
> Deadline for comments: July 16, 2003
>
>
> Introduction
>
> For ICU 2.8 we are making ustdio a fully supported library.  Basically,
> this means that I will be fixing many broken things in the ustdio
> library.
>  Part of this fixing process is to formalize how the format 
specification
> string works for fscanf, fprintf and related functions.
>
> As a reminder, the ustdio library has been marked as draft for a while,
> which means that the API may change at any time.  We have also
> stated that
> ustdio is a broken unsupported library for a long time.  I'd like to 
make
> the ustdio library more compatible with the ANSI C stdio format
> specification.  Backwards compatibility with the old ustdio is not a 
goal
> of this proposal, since that would involve keeping many bugs from the 
old
> ustdio around for eternity.
>
> This is only a partial proposal.  A full proposal would be many pages
> long, and most people wouldn't read it.  So I'm only sending out
> a "small"
> proposal for part of my ustdio work at this time so that it is easier to
> read (hopefully).  More proposals will appear later on, like on how some
> of the function APIs will look.
>
>
> Actual Proposal
>
> Here are the format specifications that I plan to use in the new
> supported
> ustdio library.  These formats apply to u_fscanf, u_fprintf, u_sscanf,
> u_sprintf and all related functions in ustdio.h.
>
> printf
> fmt type        Comment
> %E  double      Scientific with an uppercase exponent
> %e  double      Scientific with a lowercase exponent
> %G  double      Use %E or %f for best format
> %g  double      Use %e or %f for best format
> %f  double      Simple floating point without the exponent
> %X  int32_t     ustdio special uppercase hex radix formatting
> %x  int32_t     ustdio special lowercase hex radix formatting
> %d  int32_t     Decimal format
> %i  int32_t     Same as %d
> %n  int32_t     count (write the number of chars written)
> %o  int32_t     octal ustdio special octal radix formatting
> %u  uint32_t    Decimal format
> %p  void *      Prints the pointer value
> %s  char *      Use default converter or specified converter from fopen
> %hs char *      Use invariant converter
> %ls N/A         (Unimplemented) Reserved for future implementation
> %c  char        Use default converter or specified converter from fopen
> %hc char        Use invariant converter
> %lc N/A         (Unimplemented) Reserved for future implementation
> %S  UChar *     Null terminated UTF-16 string
> %hS char *      Null terminated UTF-8 string
> %lS UChar32 *   Null terminated UTF-32 string
> %C  UChar       16-bit Unicode code unit
> %hC char        8-bit Unicode code unit
> %lC UChar32     32-bit Unicode code unit
> %%  N/A         Show a percent sign
>
> scanf differences from printf
> %[] UChar *     Scanset needs to be replaced with ICU UnicodeSet.
>                 Doesn't contain s, S or any other string format.
>
> Format modifiers
> %l    int64_t   long format for %d, %i, %o, %x (usually this means long
> int)
> %h    int16_t   short format for %d, %i, %o, %x (usually this means 
short
> int)
> %l    uint64_t  long format for %u (usually this means long int)
> %h    uint16_t  short format for %u (usually this means short int)
> %-    N/A       Left justify
> %+    N/A       Always show the plus or minus sign. Needs data for plus
> sign.
> %     N/A       Instead of a "+" output a blank character for positive
> numbers.
> %#    N/A       Precede octal value with 0, hex with 0x and show the
> decimal point for floats.
> %num  N/A       Width of input/output. num is an actual number from 0 to
> some large number.
> %.num N/A       Significant digits precision. num is an actual
> number from
> 0
>                 to some large number. Currently can only specify 
precision
>                 before or after decimal, and not total precision.
>
> printf modifier
> %*  int32_t     Next argument after this one specifies the width (need 
to
> implement)
>
> scanf modifier
> %*  N/A         This field is scanned, but not stored (need to 
implement)
>
> Special extensions reserved for future consideration
> %P  double      Percent format
> %V  double      Spellout format
> %b  char *      HP-UX and glibc extension which allows you to unescape a
> string
> %B  UChar *     Similar to %b
> % $ N/A         positional formatting modifier like in MessageFormat 
from
> the "Single Unix Specification".
>
> Formats removed due to other formats or functions.
> %T  UDate       Time. Replaced by strftime/strptime.
> %D  UDate       Date. Replaced by strftime/strptime.
> %K  UChar       Source or target is UChar. Replaced by %C.
> %U  UChar *     Source or target is UChar *. Replaced by %S.
> %M  double      Currency format. Replaced by strfmon. strpmon may be
> implemented in the future.
>
>
>
> Other related changes
>
> Functions removed
> u_getcx()       %b will replace this function in the future
>
> The char * format specification will now be converted with
> u_charsToUChars
> instead of the default converter.  If you want to display non-ASCII
> characters, you need to use the functions that use a const UChar * 
format
> argument.  This is being done because:
>
> 1) It's much faster
> 2) The format specification argument is usually a static char *, but the
> default converter may convert the string differently depending on the
> platform ICU is being run on.  This is generally bad, and that's why the
> UChar * format argument should be used for internationalized text 
instead
> of the API that takes a char * formatting argument.  The %s argument 
will
> still use the default converter since the source of the string is much
> more likely to come from an outside source.
>
>
>
> Thank you for taking time to read this proposal.
>
> George Rhoten
> IBM Globalization Center of Competency/ICU  San Jose, CA, USA
> _______________________________________________
> icu mailing list
> [email protected]
> http://oss.software.ibm.com/developerworks/oss/mailman/listinfo/icu
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.