summaryrefslogtreecommitdiff
path: root/man/mpu_printf.3
blob: 5e206e28bab5ab3e90c9e025ad36dcd3bfa43568 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
.TH MPU_PRINTF 3 "September 2026" "libmpuio" "LIBMPUIO Programmer's Manual"
.SH NAME
mpu_printf, mpu_fprintf, mpu_sprintf, mpu_snprintf, mpu_asprintf,
mpu_dprintf, mpu_vprintf, mpu_vfprintf, mpu_vsprintf, mpu_vsnprintf,
mpu_vasprintf, mpu_vdprintf, mpu_printf_unlocked, mpu_fprintf_unlocked,
mpu_vprintf_unlocked, mpu_vfprintf_unlocked
\- formatted UCS-2 output, including arbitrary precision libmpu numbers
.SH SYNOPSIS
.nf
#include <libmpuio.h>

int       mpu_printf( const __mpu_char16_t *format, ... );
int       mpu_fprintf( mpu_FILE *stream,
                       const __mpu_char16_t *format, ... );
int       mpu_sprintf( __mpu_char16_t *string,
                       const __mpu_char16_t *format, ... );
int       mpu_snprintf( __mpu_char16_t *string, size_t size,
                        const __mpu_char16_t *format, ... );
int       mpu_asprintf( __mpu_char16_t **string,
                        const __mpu_char16_t *format, ... );
int       mpu_dprintf( int fd, const __mpu_char16_t *format, ... );
int       mpu_vprintf( const __mpu_char16_t *format, va_list args );
int       mpu_vfprintf( mpu_FILE *stream,
                        const __mpu_char16_t *format, va_list args );
int       mpu_vsprintf( __mpu_char16_t *string,
                        const __mpu_char16_t *format, va_list args );
int       mpu_vsnprintf( __mpu_char16_t *string, size_t size,
                         const __mpu_char16_t *format, va_list args );
int       mpu_vasprintf( __mpu_char16_t **string,
                         const __mpu_char16_t *format, va_list args );
int       mpu_vdprintf( int fd, const __mpu_char16_t *format,
                        va_list args );
int       mpu_printf_unlocked( const __mpu_char16_t *format, ... );
int       mpu_fprintf_unlocked( mpu_FILE *stream,
                                const __mpu_char16_t *format, ... );
int       mpu_vprintf_unlocked( const __mpu_char16_t *format, va_list args );
int       mpu_vfprintf_unlocked( mpu_FILE *stream,
                                 const __mpu_char16_t *format, va_list args );
.fi
.SH DESCRIPTION
The
.B mpu_printf()
family produces formatted text from a UCS-2 format string.
.B mpu_printf()
and
.B mpu_vprintf()
write to
.BR mpu_stdout .
.B mpu_fprintf()
and
.B mpu_vfprintf()
write to the specified
.BR mpu_FILE .
.B mpu_sprintf()
and
.B mpu_vsprintf()
write to an unbounded UCS-2 memory string supplied by the caller.
.B mpu_snprintf()
and
.B mpu_vsnprintf()
write at most
.I size
UCS-2 code units, including the terminating zero.
.PP
For real file streams the UCS-2 text produced by the formatter is encoded as
UTF-8 by the stream layer.  Memory/string destinations remain UCS-2.
.PP
.B mpu_asprintf()
and
.B mpu_vasprintf()
allocate a sufficiently large NUL-terminated UCS-2 result with
.BR malloc (3).
On success they store that pointer through
.I string;
the caller releases it with
.BR free (3).
If the operation fails,
.I *string
is set to NULL.
.PP
.B mpu_dprintf()
and
.B mpu_vdprintf()
write formatted text to an existing POSIX file descriptor.  The descriptor is
not closed and ownership remains with the caller.  Text is encoded to UTF-8
using the same external representation rules as an ordinary descriptor-backed
LIBMPUIO file stream.
.PP
The ordinary conversion syntax follows printf conventions.  LIBMPUIO extends
that syntax with arbitrary-precision integer, real and complex conversions for
libmpu objects.
.SH FORMAT OF THE FORMAT STRING
Ordinary characters in
.I format
are copied unchanged.  A conversion specification begins with
.B %
and has the form
.PP
.nf
%[flags][width][.precision][.expdigits][length-or-Zbits]conversion
.fi
.PP
The
.B .expdigits
field is a LIBMPUIO extension used by MPU real and complex conversions.  It is
not part of ordinary C printf syntax.
.PP
A literal percent sign is written with
.BR %% .
.SH FLAGS
The following flags are recognized.
.TP
.B -
Left-justify the converted value within the field.  The
.B 0
flag is ignored when
.B -
is present.
.TP
.B +
Always print a sign for signed numeric conversions.
.TP
.B " "
Prefix a positive signed numeric value with a space.  The
.B +
flag takes precedence.
.TP
.B #
Select alternate form.  For octal output this ensures a leading zero.  For
hexadecimal output a nonzero value receives
.B 0x
or
.BR 0X .
For binary
.B b/B
a nonzero value receives
.B 0b
or
.BR 0B .
For ordinary floating conversions the flag has the usual printf alternate-form
meaning.  For MPU general format it also prevents removal of insignificant
trailing fractional zeroes and the decimal point.
.TP
.B 0
Pad numeric fields with zeroes instead of spaces when applicable.  For integer
conversions the flag is ignored when an explicit precision is present.
.SH FIELD WIDTH
A decimal number specifies the minimum field width.  The converted value is
padded if necessary, but is never truncated merely to satisfy the width.
.PP
A width of
.B *
is taken from the next
.B int
argument.  A negative width is treated as a positive width together with the
.B -
flag.
.SH PRECISION
A precision begins with a dot.  It can be a decimal integer or
.BR * .
A negative precision supplied through
.B *
is treated as if no precision had been specified.
.PP
For
.B d, i, u, o, x, X, b
and
.B B,
precision is the minimum number of digits.  An integer value zero printed with
precision zero produces no digits, subject to alternate-form rules.
.PP
For
.B s,
precision is the maximum number of UCS-2 characters written from the string.
Precision has no effect on
.BR c .
.PP
For ordinary floating conversions the precision has the usual printf meaning.
For MPU floating conversions see
.B MPU REAL CONVERSIONS
below.
.SH LENGTH MODIFIERS
For ordinary integer conversions the following length modifiers are supported.
.TP
.B hh
The argument is converted as
.B signed char
or
.BR unsigned char .
.TP
.B h
The argument is converted as
.B short
or
.BR unsigned short .
.TP
.B l
The argument is
.B long
or
.BR unsigned long .
For ordinary floating output, as in C printf,
.B l
does not change the promoted
.B double
argument.
.TP
.B ll
The argument is
.B long long
or
.BR unsigned long long .
.TP
.B j
The argument is
.B intmax_t
or
.BR uintmax_t .
For
.B %n
the argument is an
.B intmax_t *
when
.B j
is used.
.TP
.B t
The argument is
.B ptrdiff_t
or its corresponding unsigned interpretation.
.TP
.B L
For ordinary floating conversions the argument is
.BR "long double" .
.PP
The standard C
.B z
length modifier is intentionally not implemented.  In LIBMPUIO both
.B z
and
.B Z
introduce the LibMPU size modifier described below.
.PP
The letter
.B j
also names the historical MPU complex conversion.  It is interpreted as the
standard
.B intmax_t
length modifier when followed by an ordinary integer conversion or
.BR n ;
otherwise it is an MPU complex conversion.
.SH ORDINARY CONVERSIONS
.TP
.B d, i
Print a signed decimal integer.
.TP
.B u
Print an unsigned decimal integer.
.TP
.B o
Print an unsigned integer in octal.
.TP
.B x, X
Print an unsigned integer in hexadecimal.  Digits and the alternate-form prefix
use lower case for
.B x
and upper case for
.BR X .
.TP
.B b, B
LIBMPUIO extension: print an unsigned integer in binary.  With
.B #,
a nonzero value receives
.B 0b
or
.BR 0B .
.TP
.B c
Write one UCS-2 character.  Because LIBMPUIO character I/O is UCS-2, the
argument is an
.B int
whose value is converted to
.BR __mpu_char16_t .
This is not a libc multibyte/wchar_t conversion.
.TP
.B s
Write a NUL-terminated UCS-2 string of type
.BR "const __mpu_char16_t *" .
A precision limits the number of UCS-2 characters written.  A NULL pointer is
rendered as
.BR (null) .
.TP
.B a
LIBMPUIO extension: write a NUL-terminated current-locale multibyte string of
type
.BR "const __mpu_char8_t *" .
The byte string is decoded according to the active
.B LC_CTYPE
locale and converted to strict UCS-2 before it enters the LIBMPUIO stream.
Field width and precision are measured in converted UCS-2 characters.  A NULL
pointer is rendered as
.BR (null) .
An invalid multibyte sequence, a surrogate, or a character outside the UCS-2
model causes the conversion to fail with
.BR EILSEQ .
Length modifiers and the MPU
.B z/Z<bits>
modifier do not apply to this conversion.
.TP
.B p
Write a pointer value in hexadecimal alternate form.  The argument type is
.BR "void *" .
.TP
.B n
Write the number of UCS-2 characters produced so far through a pointer argument.
No characters are produced by this conversion.  The pointer type is selected by
the length modifier: no modifier gives
.B int *;
.B hh, h, l, ll, j,
and
.B t
select the corresponding integer pointer types.
.TP
.B f, F
Print an ordinary
.B double
(or
.B long double
with
.B L)
in fixed-point notation.
.TP
.B e, E
Print an ordinary floating value in scientific notation.
.TP
.B g, G
Print an ordinary floating value in general format.
.PP
Ordinary
.B f/F/e/E/g/G
output is delegated to the host libc formatting rules and therefore follows
the active
.B LC_NUMERIC
radix character.  LIBMPUIO decodes the resulting libc multibyte field
to strict UCS-2 before it enters an LIBMPUIO stream; invalid sequences,
surrogate output, or characters outside the UCS-2 model are rejected with
.BR EILSEQ .
The corresponding ordinary scanf conversions use the same locale radix
convention.
The MPU
.B z/Z<bits>
formatted-number grammar is separate from this ordinary C locale behavior.
.SH MPU SIZE MODIFIER
The LibMPU arbitrary-precision size modifier is
.B z<bits>
or
.BR Z<bits> .
The lower-case and upper-case forms are equivalent.  The standard C
.B z
length modifier for
.B size_t
is intentionally not part of the LIBMPUIO format language.
.PP
The decimal
.I bits
field is not an arbitrary run-time number.  It must name one of the MPU sizes
compiled into the current LIBMPUIO grammar:
.PP
.nf
8, 16, 32, 64, 128, 256, 512, 1024,
2048, 4096, 8192, 16384, 32768, 65536
.fi
.PP
Only entries not greater than
.B MPU_REAL_IO_LIMIT
from
.B <libmpu.h>
exist in a particular build.  For example, when
.B MPU_REAL_IO_LIMIT
is 16384, the modifiers
.B z32768,
.B Z32768,
.B z65536
and
.B Z65536
do not exist in that LIBMPUIO format grammar and cause a format error.
.PP
If no decimal digits follow
.B z
or
.BR Z ,
128 bits are assumed.  Therefore
.B %zu
is an MPU 128-bit unsigned-integer conversion, exactly equivalent in size to
.BR %z128u ;
it is
.B not
a
.B size_t
conversion.  Likewise
.B %zR,
.B %ZR,
.B %zJ
and
.B %ZJ
use the default 128-bit MPU size.
.PP
The size modifier is parsed before the conversion letter.  Once the size is
accepted, the conversion letter selects the numeric class: integer conversions
use a libmpu integer object, real conversions use a libmpu real object, and
.B j/J
use a libmpu complex object.  Integer conversions accept MPU sizes from 8 bits;
real and complex conversions require at least 32 bits.
.PP
.B MPU_MATH_FN_LIMIT
does not define the formatted-I/O grammar.  It limits transcendental/math
routines only.  The set of available
.B z/Z<bits>
modifiers is controlled by
.BR MPU_REAL_IO_LIMIT .
.SH ARGUMENT TYPE MODEL
Ordinary C conversions and MPU conversions use deliberately different
argument conventions.
.PP
For an ordinary conversion the conversion letter and standard length modifier
describe the C type that
.BR va_arg ()
must fetch.  The argument is passed by value, subject to the usual default
argument promotions.  For example:
.PP
.nf
char  k = 7;
mpu_printf( MPU_UCS2("k = %d\\n"), k );
.fi
.PP
Here
.B k
is promoted to
.B int
before it enters the variadic argument list, and
.B %d
selects an
.B int
value.  The formatter does not discover the argument type at run time; the
format string tells it which C type to fetch.
.PP
An MPU conversion selected by
.B z<bits>
or
.B Z<bits>
has a different contract.  Its argument is a pointer to the storage of an MPU
object, and the size modifier tells the formatter exactly how many bits that
object contains.  For the array typedefs used by libmpu, an object name in a
function-call argument normally undergoes the standard array-to-pointer
conversion, so the natural spelling is:
.PP
.nf
mpu_int128_t   c;
mpu_real128_t  r;

mpu_printf( MPU_UCS2("c = %z128u\\n"), c );
mpu_printf( MPU_UCS2("r = %z128g\\n"), r );
.fi
.PP
The pointer itself carries no object-size metadata.  Consequently a variadic
formatter cannot infer whether a pointer designates, for example, a 32-bit,
128-bit, or 65536-bit MPU object.  The explicit
.B z/Z<bits>
field is therefore part of the type contract of an MPU conversion rather than
redundant decoration.
.PP
It is technically possible to point an MPU conversion at storage belonging to
an ordinary C object when its exact representation and size are deliberately
known, for example:
.PP
.nf
char  k = 7;
mpu_printf( MPU_UCS2("k = %z8d\\n"), &k );
.fi
.PP
This is a low-level interpretation of the byte at
.B &k
as an 8-bit MPU integer object; it is
.B not
the ordinary C
.B char
printing convention and should not be used as a portable substitute for
.BR %d .
For multi-byte C objects such use can additionally depend on representation,
byte order, and compatibility with libmpu storage.  Ordinary C objects should
normally use ordinary C conversions; MPU objects should use
.BR z/Z<bits> .
.PP
Changing libmpu array typedefs to structure typedefs would not make the
variadic function self-describing.  A C
.B va_list
does not carry general run-time type or size metadata, and
.B va_arg()
still requires the expected type to be known from the format contract.

.SH MPU INTEGER CONVERSIONS
With
.BR z/Z<bits> ,
.B d
and
.B i
format a signed arbitrary-precision integer.  The conversions
.B u, o, x, X, b
and
.B B
format an unsigned arbitrary-precision integer.  The argument is a pointer to a
libmpu integer object whose storage size matches the selected bit size.
.PP
Examples:
.PP
.nf
%Z128d
%#Z256x
%#Z1024B
%08.3Z128d
.fi
.PP
The formatter removes libmpu's internal radix prefix before applying printf
alternate-form rules itself.  Thus
.B #
has the same externally visible meaning for ordinary and MPU integer output.
.SH MPU REAL CONVERSIONS
The native MPU real conversions are
.B r
and
.BR R .
If no explicit
.B z/Z<bits>
modifier is present they use 128 bits.
.PP
The conversion letter chooses case, but the exponent marker emitted for a real
number is
.B e
for
.B %r
and
.B E
for
.BR %R .
The letters
.B r/R
are conversion specifiers, not the printed real exponent delimiter.
.PP
Examples:
.PP
.nf
%Z128R
%.28Z128R
%.28.4Z128R
.fi
.PP
The first precision controls mantissa digits.  The optional second
.B .expdigits
field specifies the minimum exponent width.  It may also be supplied with
.BR * .
For example:
.PP
.nf
%.4.3Z128e     -> 1.2346e+004
.fi
.PP
The MPU forms
.B z/Z<bits>e,
.B z/Z<bits>E,
.B z/Z<bits>f,
.B z/Z<bits>F,
.B z/Z<bits>g
and
.B z/Z<bits>G
are also supported.
.PP
All of these real conversions fetch a pointer to a libmpu real object of the
selected size.  In particular, both
.B %Z128R
and
.B %Z128E
expect an
.B mpu_real128_t
object.  Complex output is separate: 
.B %Z128J
expects an
.B mpu_complex128_t
object.  Thus the type mapping is:
.PP
.nf
%Z128R  -> mpu_real128_t
%Z128E  -> mpu_real128_t
%Z128J  -> mpu_complex128_t
.fi
.PP
For historical CODE.LIB compatibility,
.B MPU f/F are scientific aliases of e/E;
they are not fixed-point conversions.  This differs deliberately from ordinary
C
.BR %f/%F .
.PP
For MPU
.B g/G,
a missing precision defaults to 6 and a precision of zero is treated as one
significant digit.  Scientific notation is selected when the decimal exponent
is less than -4 or greater than or equal to the precision.  Otherwise fixed
style is used.  Trailing fractional zeroes and the decimal point are removed
unless
.B #
is specified.
.PP
Lowercase
.B %a
is the LIBMPUIO current-locale multibyte-string conversion.
.SH MPU COMPLEX CONVERSIONS
The native MPU complex conversions are
.B j
and
.BR J .
If no explicit MPU size is supplied they default to 128 bits.  The argument is
a pointer to a libmpu complex object for the selected size.
.PP
The real and imaginary components are concatenated using the historical MPU
complex representation.  For example:
.PP
.nf
%.20.4Z128J
    -> 1.25000000000000000000R+0000-2.50000000000000000000J+0000
.fi
.PP
For
.B %j
the component exponent markers are
.B r
and
.BR j .
For
.B %J
they are
.B R
and
.BR J .
This historical complex syntax is intentional.  It differs from real-only
.B %r/%R,
whose printed exponent marker is
.BR e/E .
.PP
When the
.B 0
flag is used with a field wider than the formatted complex value, the free
field width is divided equally between the real and imaginary components.
Zeroes are inserted after the sign of each component.  If the free width is
odd, the one remaining character is emitted as ordinary leading space
padding.  For example, for a value whose components are 1.25 and 2.5:
.PP
.nf
%+040.6.3Z128J
    -> +0000001.250000R+000+0000002.500000J+000
%+039.6.3Z128J
    ->  +000001.250000R+000+000002.500000J+000
.fi
.SH STRING OUTPUT AND TRUNCATION
.B mpu_sprintf()
and
.B mpu_vsprintf()
do not know the destination capacity.  The caller must provide enough UCS-2
storage for the complete result plus a terminating zero.
.PP
.B mpu_snprintf()
and
.B mpu_vsnprintf()
write at most
.I size
UCS-2 code units including the terminating zero.  If
.I size
is zero, no destination data is written.  The return value is the number of
UCS-2 characters that would have been produced if sufficient space had been
available, excluding the terminating zero.
.SH LOCKING
The normal stream variants lock the
.B mpu_FILE
while formatting.  The
.B *_unlocked
variants do not acquire the stream mutex.  They are intended for code that has
already serialized access, commonly with
.BR mpu_flockfile (3):
.PP
.nf
mpu_flockfile( fp );
mpu_fprintf_unlocked( fp, fmt, ... );
mpu_fflush_unlocked( fp );
mpu_funlockfile( fp );
.fi
.PP
The string-output functions use private memory streams and have no public
unlocked variants.
.SH SNPRINTF SIZING AND TRUNCATION
For
.B mpu_snprintf()
and
.B mpu_vsnprintf(),
the
.I size
argument is the capacity of the UCS-2 destination array, including the final
NUL character.  If
.I size
is zero, no destination characters are stored and
.I string
may be NULL.  The functions still parse the complete format and return the
number of UCS-2 characters that would have been produced, excluding the final
NUL.  This permits the usual two-pass allocation pattern.
.PP
When the output is truncated, the return value and any
.B %n
conversion use the logical character count, not the number of characters that
fit in the destination array.
.PP
If the logical formatted-output count cannot be represented by
.B int,
the operation fails with a negative return value and
.B errno
set to
.B EOVERFLOW.
.SH RETURN VALUE
On success these functions return the number of UCS-2 characters produced,
excluding the terminating zero used by string destinations.  For
.BR mpu_asprintf ()
and
.BR mpu_vasprintf (),
this is the number of allocated UCS-2 code units before the terminating NUL.
For
.BR mpu_dprintf ()
and
.BR mpu_vdprintf (),
the return count is still in UCS-2 characters, not in the number of UTF-8 bytes
written to the descriptor.  A negative value indicates failure.
.PP
.B %n
does not contribute an argument assignment to the return value; it merely
stores the count accumulated at that point.
.SH ERRORS
Errors from the underlying stream and memory allocation are reported through a
negative return value and, where applicable,
.BR errno .
.B mpu_asprintf()
and
.B mpu_vasprintf()
report allocation failure as
.BR ENOMEM ;
a NULL destination pointer is rejected with
.BR EINVAL .
.B mpu_dprintf()
and
.B mpu_vdprintf()
can report descriptor and write errors such as
.BR EBADF .
An invalid configured MPU size causes failure with
.BR EINVAL .
The strict UCS-2 file boundary can report
.B EILSEQ
when a character cannot be represented according to LIBMPUIO's UCS-2/UTF-8
rules.
.SH EXAMPLES
A UCS-2 string and ordinary values:
.PP
.nf
__mpu_char16_t  fmt[]  = MPU_UCS2("name=%s value=%08x");
__mpu_char16_t  name[] = MPU_UCS2("mpu");
mpu_printf( fmt, name, 0x1234U );
.fi
.PP
A current-locale multibyte string:
.PP
.nf
__mpu_char8_t  name8[] = "Andrey";
mpu_printf( MPU_UCS2("name=%a\n"), name8 );
.fi
.PP
An arbitrary-precision integer:
.PP
.nf
__mpu_char16_t  fmt[] = MPU_UCS2("%#Z256x");
mpu_printf( fmt, &integer256 );
.fi
.PP
A 128-bit real with 28 mantissa digits and four exponent digits:
.PP
.nf
__mpu_char16_t  fmt[] = MPU_UCS2("%.28.4Z128E");
mpu_fprintf( fp, fmt, &real128 );
.fi
.SH UCS-2 STRING LITERALS
The public macro
.B MPU_UCS2()
forms a native 16-bit string literal using the
.B u"..."
source-language prefix.  For example:
.PP
.nf
mpu_printf( MPU_UCS2( "value=%d" ), value );
.fi
.PP
Unlike
.B L"...",
which uses the platform
.B wchar_t
type,
.B MPU_UCS2()
is intended for LIBMPUIO interfaces whose text arguments use the LIBMPU
.B __mpu_char16_t
type.
.PP
The public header enables this facility when the translation mode provides
16-bit
.B u"..."
string literals: C11 or later, C++11 or later, or a GNU C mode that supports
the extension.  A build configuration may also define
.B MPU_HAVE_UCS2_STRING_LITERALS
before including
.B <libmpuio.h>
to state explicitly whether the facility is available.  If it is unavailable,
the public header reports a compile-time error.
.PP
The literal prefix is a source-language facility, not a runtime encoding
switch.  LIBMPUIO still applies strict UCS-2 rules and rejects surrogate
code units with
.B EILSEQ.
.SH NOTES
LIBMPUIO uses 16-bit UCS-2 internally rather than the platform
.B wchar_t
type.  Consequently
.B %c
and
.B %s
operate directly on UCS-2 characters and strings and do not have libc
.B %lc/%ls
multibyte semantics.  The LIBMPUIO
.B %a
conversion is the explicit current-locale multibyte-string interface; its
argument type is
.BR "const __mpu_char8_t *" .
.PP
Strict UCS-2 cannot represent Unicode scalar values above U+FFFF.  Such input is
not represented as surrogate pairs by the text layer.
.SH SEE ALSO
.BR mpu_scanf (3),
.BR mpu_flockfile (3),
.BR mpu_unlocked (3),
.BR mpu_fopen (3),
.BR libmpuio (3)
.SH LOCALE
For ordinary floating-point conversions, the decimal-point character follows
the active C locale in the same way as the system
.BR printf (3)
family.  Thus a locale whose
.B LC_NUMERIC
uses a comma may produce, for example,
.B 1,50
for
.BR %.2f .
The LIBMPUIO regression suite selects the C locale after initializing libmpu
so that its expected strings are reproducible.

.SH FORMAT PARSER OVERFLOW
The format parser detects decimal accumulation overflow in field width,
precision, the LIBMPU exponent-width extension, and z/Z<bits> size
fields.  It also rejects INT_MIN supplied as a negative * field width, since
that value cannot be represented as a positive int width.  These cases fail
with a negative return value and set errno to EOVERFLOW.
.SH LOCKED VERSUS UNLOCKED FORMATTED OUTPUT
.BR mpu_fprintf_unlocked (),
.BR mpu_vfprintf_unlocked (),
.BR mpu_printf_unlocked (),
and
.BR mpu_vprintf_unlocked ()
use the exact same formatter as the ordinary stream forms but omit implicit
stream locking.  Format parsing, MPU z/Z<bits> handling, locale behavior, %n,
logical output counts, truncation rules, and errors are unchanged.
.PP
The sprintf/snprintf families write caller-owned UCS-2 memory rather than an
mpu_FILE stream and therefore have no stream-unlocked variants.