summaryrefslogtreecommitdiff
path: root/source/ap/ghostscript
diff options
context:
space:
mode:
Diffstat (limited to 'source/ap/ghostscript')
-rw-r--r--source/ap/ghostscript/cidfmap12
-rwxr-xr-xsource/ap/ghostscript/ghostscript.SlackBuild37
-rw-r--r--source/ap/ghostscript/ghostscript.gs_sprintf.diff28431
-rw-r--r--source/ap/ghostscript/slack-desc4
4 files changed, 28461 insertions, 23 deletions
diff --git a/source/ap/ghostscript/cidfmap b/source/ap/ghostscript/cidfmap
index 0303f66f..28d69ad8 100644
--- a/source/ap/ghostscript/cidfmap
+++ b/source/ap/ghostscript/cidfmap
@@ -29,17 +29,17 @@
%% cidfmap.zh_CN (simplified Chinese ; zh_CN)
-%% This font will produce better results than the wqy-zenhei.ttf that we use
+%% This font will produce better results than the wqy-zenhei.ttc that we use
%% to get out-of-the-box output.
%% If you install it, uncomment the line below and comment the one below that.
%/BousungEG-Light-GB << /FileType /TrueType /Path (uming.ttf) /CSI [(GB1) 4] >> ;
-/BousungEG-Light-GB << /FileType /TrueType /Path (wqy-zenhei.ttf) /CSI [(GB1) 4] >> ;
-%% This font will produce better results than the wqy-zenhei.ttf that we use
+/BousungEG-Light-GB << /FileType /TrueType /Path (wqy-zenhei.ttc) /CSI [(GB1) 4] >> ;
+%% This font will produce better results than the wqy-zenhei.ttc that we use
%% to get out-of-the-box output.
%% If you install it, uncomment the line below and comment the one below that.
%/GBZenKai-Medium << /FileType /TrueType /Path (ukai.ttf) /CSI [(GB1) 4] >> ;
-/GBZenKai-Medium << /FileType /TrueType /Path (wqy-zenhei.ttf) /CSI [(GB1) 4] >> ;
-/MSungGBK-Light << /FileType /TrueType /Path (wqy-zenhei.ttf) /CSI [(GB1) 4] >> ;
+/GBZenKai-Medium << /FileType /TrueType /Path (wqy-zenhei.ttc) /CSI [(GB1) 4] >> ;
+/MSungGBK-Light << /FileType /TrueType /Path (wqy-zenhei.ttc) /CSI [(GB1) 4] >> ;
/MSung-Light /MSungGBK-Light ;
/MSung-Medium /GBZenKai-Medium ;
/MHei-Medium /BousungEG-Light-GB ;
@@ -57,7 +57,7 @@
%% interference (or comment the whole block out).
%/BousungEG-Light-GB << /FileType /TrueType /Path (uming.ttf) /CSI [(CNS1) 4] >> ;
%/ZenKai-Medium << /FileType /TrueType /Path (ukai.ttf) /CSI [(CNS1) 4] >> ;
-%/ShanHeiSun-Light << /FileType /TrueType /Path (wqy-zenhei.ttf) /CSI [(CNS1) 4] >> ;
+%/ShanHeiSun-Light << /FileType /TrueType /Path (wqy-zenhei.ttc) /CSI [(CNS1) 4] >> ;
%/STSong-Light /BousungEG-Light-GB ;
%/STKaiti-Regular /ZenKai-Medium-GB ;
%/STFangsong-Light /BousungEG-Light ;
diff --git a/source/ap/ghostscript/ghostscript.SlackBuild b/source/ap/ghostscript/ghostscript.SlackBuild
index 4afef964..4ce0d69e 100755
--- a/source/ap/ghostscript/ghostscript.SlackBuild
+++ b/source/ap/ghostscript/ghostscript.SlackBuild
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 Patrick J. Volkerding, Sebeka, MN, USA
+# Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
@@ -22,8 +22,11 @@
PKGNAM=ghostscript
-VERSION=${VERSION:-$(echo $PKGNAM-*.tar.xz | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-3}
+if [ -r gnu-ghostscript-*.tar.xz ]; then
+ SRCPREFIX="gnu-"
+fi
+VERSION=${VERSION:-$(echo $SRCPREFIX$PKGNAM-*.tar.xz | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
@@ -56,12 +59,18 @@ else
fi
cd $TMP
-rm -rf ${PKGNAM}-${VERSION}
-tar xvf $CWD/${PKGNAM}-$VERSION.tar.xz || exit 1
-cd ${PKGNAM}-$VERSION
+rm -rf ${SRCPREFIX}${PKGNAM}-${VERSION}
+tar xvf $CWD/${SRCPREFIX}${PKGNAM}-$VERSION.tar.xz || exit 1
+cd ${SRCPREFIX}${PKGNAM}-$VERSION
+
+# Use sprintf from Trio library as gs_printf to fix problems with
+# documents using locales where commas are used as decimals:
+zcat $CWD/ghostscript.gs_sprintf.diff.gz | patch -p1 --verbose || exit 1
-## Regenerate ./configure (if patched):
-#sh autogen.sh
+# Regenerate ./configure. Needed if patched, or to prevent libtool mismatch.
+autoreconf --force --install
+( cd jbig2dec ; autoreconf --force --install )
+( cd ijs ; autoreconf --force --install )
# Make sure ownerships and permissions are sane:
chown -R root:root .
@@ -73,9 +82,6 @@ find . \
# Build/install IJS:
( cd ijs
- if [ ! -r configure ]; then
- sh autogen.sh
- fi
CFLAGS="$SLKCFLAGS" \
./configure \
--prefix=/usr \
@@ -118,9 +124,10 @@ make soinstall DESTDIR=$PKG || exit 1
# Replace the default cidfmap with one containing additional
# support for CJK printing:
-if [ -r $PKG/usr/share/ghostscript/${VERSION}/Resource/Init/cidfmap ]; then
- mv $PKG/usr/share/ghostscript/${VERSION}/Resource/Init/cidfmap $PKG/usr/share/ghostscript/${VERSION}/Resource/Init/cidfmap.default.ghostscript-${VERSION}
- zcat $CWD/cidfmap.gz > $PKG/usr/share/ghostscript/${VERSION}/Resource/Init/cidfmap.new
+if [ -r $PKG/usr/share/ghostscript/*.*/Resource/Init/cidfmap ]; then
+ SHARE_VERSION=$(echo $PKG/usr/share/ghostscript/*.*/Resource/Init/cidfmap | rev | cut -f 4 -d / | rev)
+ mv $PKG/usr/share/ghostscript/${SHARE_VERSION}/Resource/Init/cidfmap $PKG/usr/share/ghostscript/${SHARE_VERSION}/Resource/Init/cidfmap.default.ghostscript-${VERSION}
+ zcat $CWD/cidfmap.gz > $PKG/usr/share/ghostscript/${SHARE_VERSION}/Resource/Init/cidfmap.new
fi
# Many programs expect to find this filter with the old name:
@@ -163,7 +170,7 @@ fi
mkdir -p $PKG/usr/doc/${PKGNAM}-$VERSION
( cd doc
cp -a \
- COPYING ../LICENSE README \
+ AUTHORS COPYING* ../LICENSE* README* \
$PKG/usr/doc/${PKGNAM}-$VERSION
)
( cd $PKG/usr/doc/${PKGNAM}-$VERSION
diff --git a/source/ap/ghostscript/ghostscript.gs_sprintf.diff b/source/ap/ghostscript/ghostscript.gs_sprintf.diff
new file mode 100644
index 00000000..5e123e13
--- /dev/null
+++ b/source/ap/ghostscript/ghostscript.gs_sprintf.diff
@@ -0,0 +1,28431 @@
+diff -up ghostscript-9.07/base/fapiufst.c.gs_sprintf ghostscript-9.07/base/fapiufst.c
+--- ghostscript-9.07/base/fapiufst.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/fapiufst.c 2013-05-09 17:02:39.056447042 +0100
+@@ -699,7 +699,7 @@ pack_long(LPUB8 * p, UL32 v)
+ static inline void
+ pack_float(LPUB8 * p, float v)
+ {
+- sprintf((char *)(*p), "%f", v);
++ gs_sprintf((char *)(*p), "%f", v);
+ *p += strlen((const char *)*p) + 1;
+ }
+
+diff -up ghostscript-9.07/base/gdev3b1.c.gs_sprintf ghostscript-9.07/base/gdev3b1.c
+--- ghostscript-9.07/base/gdev3b1.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdev3b1.c 2013-05-09 17:02:39.057447046 +0100
+@@ -538,7 +538,7 @@ att3b1_do_output_page(gx_device *dev, in
+ }
+
+ ut.ut_num = WTXTSLK1;
+- sprintf(ut.ut_text,
++ gs_sprintf(ut.ut_text,
+ "%s %d, top right (%d,%d), size (%d,%d), press '?' for help.",
+ flush ? "Showpage" : "Copypage", att3b1dev->page_num, xorigin, yorigin,
+ att3b1dev->width, att3b1dev->height);
+diff -up ghostscript-9.07/base/gdev8510.c.gs_sprintf ghostscript-9.07/base/gdev8510.c
+--- ghostscript-9.07/base/gdev8510.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdev8510.c 2013-05-09 17:02:39.058447051 +0100
+@@ -129,7 +129,7 @@ m8510_output_run(gx_device_printer *pdev
+ /* Transfer the line of data. */
+ count = out_end - out;
+ if (count) {
+- sprintf(tmp, "\033g%03d", count/8);
++ gs_sprintf(tmp, "\033g%03d", count/8);
+ fwrite(tmp, 1, 5, prn_stream);
+ fwrite(out, 1, count, prn_stream);
+ fwrite("\r", 1, 1, prn_stream);
+diff -up ghostscript-9.07/base/gdevccr.c.gs_sprintf ghostscript-9.07/base/gdevccr.c
+--- ghostscript-9.07/base/gdevccr.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevccr.c 2013-05-09 17:02:39.059447055 +0100
+@@ -207,9 +207,9 @@ static int alloc_rb( gs_memory_t *mem, c
+ int r;
+ for(r=0; r<rows; r++)
+ {
+- sprintf((*rb)[r].cname, "C%02x", r);
+- sprintf((*rb)[r].mname, "M%02x", r);
+- sprintf((*rb)[r].yname, "Y%02x", r);
++ gs_sprintf((*rb)[r].cname, "C%02x", r);
++ gs_sprintf((*rb)[r].mname, "M%02x", r);
++ gs_sprintf((*rb)[r].yname, "Y%02x", r);
+ (*rb)[r].is_used=0;
+ }
+ return 0;
+diff -up ghostscript-9.07/base/gdevdevn.c.gs_sprintf ghostscript-9.07/base/gdevdevn.c
+--- ghostscript-9.07/base/gdevdevn.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevdevn.c 2013-05-09 17:02:39.060447059 +0100
+@@ -2078,7 +2078,7 @@ spotcmyk_print_page(gx_device_printer *
+
+ /* Open the output files for the spot colors */
+ for(i = 0; i < nspot; i++) {
+- sprintf(spotname, "%ss%d", pdevn->fname, i);
++ gs_sprintf(spotname, "%ss%d", pdevn->fname, i);
+ spot_file[i] = gp_fopen(spotname, "wb");
+ if (spot_file[i] == NULL) {
+ code = gs_error_VMerror;
+@@ -2117,7 +2117,7 @@ spotcmyk_print_page(gx_device_printer *
+ return code;
+ }
+ for(i = 0; i < nspot; i++) {
+- sprintf(spotname, "%ss%d", pdevn->fname, i);
++ gs_sprintf(spotname, "%ss%d", pdevn->fname, i);
+ code = devn_write_pcx_file(pdev, spotname, 1, bpc, linelength[i]);
+ if (code < 0)
+ return code;
+@@ -2451,7 +2451,7 @@ devn_write_pcx_file(gx_device_printer *
+ in = gp_fopen(filename, "rb");
+ if (!in)
+ return_error(gs_error_invalidfileaccess);
+- sprintf(outname, "%s.pcx", filename);
++ gs_sprintf(outname, "%s.pcx", filename);
+ out = gp_fopen(outname, "wb");
+ if (!out) {
+ fclose(in);
+diff -up ghostscript-9.07/base/gdevdjet.c.gs_sprintf ghostscript-9.07/base/gdevdjet.c
+--- ghostscript-9.07/base/gdevdjet.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevdjet.c 2013-05-09 17:02:39.061447064 +0100
+@@ -323,9 +323,9 @@ hpjet_make_init(gx_device_printer *pdev,
+ else if (dev->MediaPosition_set && dev->MediaPosition >= 0)
+ paper_source = dev->MediaPosition;
+ if (paper_source >= 0)
+- sprintf(buf, "%s\033&l%dH", str, paper_source);
++ gs_sprintf(buf, "%s\033&l%dH", str, paper_source);
+ else
+- sprintf(buf, "%s", str);
++ gs_sprintf(buf, "%s", str);
+ }
+
+ /* The DeskJet can compress (mode 2) */
+@@ -361,7 +361,7 @@ fs600_print_page_copies(gx_device_printe
+ char base_init[60];
+ char init[80];
+
+- sprintf(base_init, "\033*r0F\033&u%dD", dots_per_inch);
++ gs_sprintf(base_init, "\033*r0F\033&u%dD", dots_per_inch);
+ hpjet_make_init(pdev, init, base_init);
+ return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
+ dots_per_inch, PCL_FS600_FEATURES,
+@@ -425,7 +425,7 @@ ljet3d_print_page_copies(gx_device_print
+ bool tumble=dev->Tumble;
+
+ hpjet_make_init(pdev, init, "\033&l-180u36Z\033*r0F");
+- sprintf(even_init, "\033&l180u36Z\033*r0F");
++ gs_sprintf(even_init, "\033&l180u36Z\033*r0F");
+ return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
+ 300, PCL_LJ3D_FEATURES, init, even_init, tumble);
+ }
+@@ -440,7 +440,7 @@ ljet4_print_page_copies(gx_device_printe
+ char base_init[60];
+ char init[80];
+
+- sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
++ gs_sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
+ hpjet_make_init(pdev, init, base_init);
+
+ return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
+@@ -472,9 +472,9 @@ ljet4d_print_page_copies(gx_device_print
+ in duplex mode we set this parameters for each odd page
+ (paper tray is set by "hpjet_make_init")
+ */
+- sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
++ gs_sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
+ hpjet_make_init(pdev, init, base_init);
+- sprintf(even_init, "\033&l180u36Z\033*r0F\033&u%dD", dots_per_inch);
++ gs_sprintf(even_init, "\033&l180u36Z\033*r0F\033&u%dD", dots_per_inch);
+ return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
+ dots_per_inch, PCL_LJ4D_FEATURES,
+ init,even_init,tumble);
+@@ -489,7 +489,7 @@ ljet4pjl_print_page_copies(gx_device_pri
+ { int dots_per_inch = (int)pdev->y_pixels_per_inch;
+ char real_init[60];
+
+- sprintf(real_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
++ gs_sprintf(real_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch);
+ return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
+ dots_per_inch, PCL_LJ4PJL_FEATURES,
+ real_init, real_init, false);
+diff -up ghostscript-9.07/base/gdevijs.c.gs_sprintf ghostscript-9.07/base/gdevijs.c
+--- ghostscript-9.07/base/gdevijs.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevijs.c 2013-05-09 17:02:39.063447072 +0100
+@@ -674,7 +674,7 @@ gsijs_set_margin_params(gx_device_ijs *i
+ }
+
+ if (code == 0) {
+- sprintf (buf, "%gx%g", ijsdev->MediaSize[0] * (1.0 / 72),
++ gs_sprintf (buf, "%gx%g", ijsdev->MediaSize[0] * (1.0 / 72),
+ ijsdev->MediaSize[1] * (1.0 / 72));
+ code = ijs_client_set_param(ijsdev->ctx, 0, "PaperSize",
+ buf, strlen(buf));
+@@ -715,7 +715,7 @@ gsijs_set_margin_params(gx_device_ijs *i
+ m[1] = ijsdev->MediaSize[1] * (1.0 / 72) -
+ printable_top - printable_height;
+ gx_device_set_margins((gx_device *)ijsdev, m, true);
+- sprintf (buf, "%gx%g", printable_left, printable_top);
++ gs_sprintf (buf, "%gx%g", printable_left, printable_top);
+ code = ijs_client_set_param(ijsdev->ctx, 0, "TopLeft",
+ buf, strlen(buf));
+ }
+@@ -864,7 +864,7 @@ gsijs_open(gx_device *dev)
+ /* Note: dup() may not be portable to all interesting IJS
+ platforms. In that case, this branch should be #ifdef'ed out.
+ */
+- sprintf(buf, "%d", fd);
++ gs_sprintf(buf, "%d", fd);
+ ijs_client_set_param(ijsdev->ctx, 0, "OutputFD", buf, strlen(buf));
+ close(fd);
+ } else {
+@@ -1021,9 +1021,9 @@ gsijs_output_page(gx_device *dev, int nu
+ }
+
+ /* Required page parameters */
+- sprintf(buf, "%d", n_chan);
++ gs_sprintf(buf, "%d", n_chan);
+ gsijs_client_set_param(ijsdev, "NumChan", buf);
+- sprintf(buf, "%d", ijsdev->BitsPerSample);
++ gs_sprintf(buf, "%d", ijsdev->BitsPerSample);
+ gsijs_client_set_param(ijsdev, "BitsPerSample", buf);
+
+ /* This needs to become more sophisticated for DeviceN. */
+@@ -1031,12 +1031,12 @@ gsijs_output_page(gx_device *dev, int nu
+ ((n_chan == 3) ? (krgb_mode ? ((k_bits == 1) ? "KRGB" : "KxRGB") : "DeviceRGB") : "DeviceGray"));
+ gsijs_client_set_param(ijsdev, "ColorSpace", buf);
+
+- sprintf(buf, "%d", ijs_width);
++ gs_sprintf(buf, "%d", ijs_width);
+ gsijs_client_set_param(ijsdev, "Width", buf);
+- sprintf(buf, "%d", ijs_height);
++ gs_sprintf(buf, "%d", ijs_height);
+ gsijs_client_set_param(ijsdev, "Height", buf);
+
+- sprintf(buf, "%gx%g", xres, yres);
++ gs_sprintf(buf, "%gx%g", xres, yres);
+ gsijs_client_set_param(ijsdev, "Dpi", buf);
+
+ #ifdef KRGB_DEBUG
+diff -up ghostscript-9.07/base/gdevl31s.c.gs_sprintf ghostscript-9.07/base/gdevl31s.c
+--- ghostscript-9.07/base/gdevl31s.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevl31s.c 2013-05-09 17:02:39.063447072 +0100
+@@ -184,9 +184,9 @@ lj3100sw_print_page_copies(gx_device_pri
+ if (gdev_prn_file_is_new(pdev)) {
+ lj3100sw_output_section_header(prn_stream, 1, 0, 0);
+ lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0x1b, 12);
+- ptr += sprintf(ptr, "\r\nBD");
++ ptr += gs_sprintf(ptr, "\r\nBD");
+ lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0, 5520);
+- ptr += sprintf(ptr, "%s\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n",
++ ptr += gs_sprintf(ptr, "%s\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n",
+ "NJ",
+ "PQ", -1,
+ "RE", high_resolution ? 6 : 2,
+@@ -198,7 +198,7 @@ lj3100sw_print_page_copies(gx_device_pri
+ }
+
+ lj3100sw_output_section_header(prn_stream, 3, ppdev->NumCopies, 0);
+- ptr += sprintf(ptr, "%s %d\r\n%s\r\n",
++ ptr += gs_sprintf(ptr, "%s %d\r\n%s\r\n",
+ "CM", 1,
+ "PD");
+ *ptr++ = 0;
+diff -up ghostscript-9.07/base/gdevp14.c.gs_sprintf ghostscript-9.07/base/gdevp14.c
+--- ghostscript-9.07/base/gdevp14.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevp14.c 2013-05-09 17:02:39.065447081 +0100
+@@ -6427,7 +6427,7 @@ get_param_compressed_color_list_elem(pdf
+ pkeyname_list_elem->next = *pkeyname_list;
+ pkeyname_list_elem->key_name = keyname_buf;
+ *pkeyname_list = pkeyname_list_elem;
+- sprintf(keyname_buf, "%s_%d", keyname, i);
++ gs_sprintf(keyname_buf, "%s_%d", keyname, i);
+ get_param_compressed_color_list_elem(pdev, plist,
+ pcomp_list->u.sub_level_ptrs[i], keyname_buf,
+ pkeyname_list);
+@@ -6498,7 +6498,7 @@ put_param_compressed_color_list_elem(gx_
+ char buff[50];
+ compressed_color_list_t * sub_list_ptr;
+
+- sprintf(buff, "%s_%d", keyname, i);
++ gs_sprintf(buff, "%s_%d", keyname, i);
+ put_param_compressed_color_list_elem(pdev, plist,
+ &sub_list_ptr, buff, num_comps - 1);
+ pcomp_list->u.sub_level_ptrs[i] = sub_list_ptr;
+@@ -6560,7 +6560,7 @@ get_param_spot_color_names(pdf14_clist_d
+ pkeyname_list_elem->next = *pkeyname_list;
+ pkeyname_list_elem->key_name = keyname_buf;
+ *pkeyname_list = pkeyname_list_elem;
+- sprintf(keyname_buf, "PDF14SpotName_%d", i);
++ gs_sprintf(keyname_buf, "PDF14SpotName_%d", i);
+ str.size = separations->names[i].size;
+ str.data = separations->names[i].data;
+ str.persistent = false;
+@@ -6596,7 +6596,7 @@ put_param_pdf14_spot_names(gx_device * p
+ char buff[20];
+ byte * sep_name;
+
+- sprintf(buff, "PDF14SpotName_%d", i);
++ gs_sprintf(buff, "PDF14SpotName_%d", i);
+ code = param_read_string(plist, buff, &str);
+ switch (code) {
+ default:
+diff -up ghostscript-9.07/base/gdevpdfb.c.gs_sprintf ghostscript-9.07/base/gdevpdfb.c
+--- ghostscript-9.07/base/gdevpdfb.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfb.c 2013-05-09 17:02:39.066447085 +0100
+@@ -588,7 +588,7 @@ gdev_pdf_strip_tile_rectangle(gx_device
+ if (image_id) {
+ char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */
+
+- sprintf(buf, "/R%ld Do\n", image_id);
++ gs_sprintf(buf, "/R%ld Do\n", image_id);
+ pprintd1(s, "%d>>stream\n", strlen(buf));
+ if (pdev->PDFA != 0)
+ pprints1(s, "%s\nendstream\n", buf);
+diff -up ghostscript-9.07/base/gdevpdf.c.gs_sprintf ghostscript-9.07/base/gdevpdf.c
+--- ghostscript-9.07/base/gdevpdf.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdf.c 2013-05-09 17:02:39.067447089 +0100
+@@ -301,7 +301,7 @@ pdf_initialize_ids(gx_device_pdf * pdev)
+ timeoffset = any_abs(timeoffset) / 60;
+ tms = *localtime(&t);
+
+- sprintf(buf, "(D:%04d%02d%02d%02d%02d%02d%c%02d\'%02d\')",
++ gs_sprintf(buf, "(D:%04d%02d%02d%02d%02d%02d%c%02d\'%02d\')",
+ tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
+ tms.tm_hour, tms.tm_min, tms.tm_sec,
+ timesign, timeoffset / 60, timeoffset % 60);
+@@ -1277,7 +1277,7 @@ static int write_xref_section(gx_device_
+ * chances of needing to write white space to pad the file out.
+ */
+ if (!pdev->Linearise) {
+- sprintf(str, "%010"PRId64" 00000 n \n", pos);
++ gs_sprintf(str, "%010"PRId64" 00000 n \n", pos);
+ stream_puts(pdev->strm, str);
+ }
+ if (Offsets)
+@@ -1310,7 +1310,7 @@ rewrite_object(gx_device_pdf *const pdev
+ code = fread(&c, 1, 1, linear_params->sfile);
+ read++;
+ } while (c != '\n' && code > 0);
+- sprintf(Scratch, "%d 0 obj\n", pdev->ResourceUsage[object].NewObjectNumber);
++ gs_sprintf(Scratch, "%d 0 obj\n", pdev->ResourceUsage[object].NewObjectNumber);
+ fwrite(Scratch, strlen(Scratch), 1, linear_params->Lin_File.file);
+
+ code = fread(&c, 1, 1, linear_params->sfile);
+@@ -1359,7 +1359,7 @@ rewrite_object(gx_device_pdf *const pdev
+ target++;
+ sscanf(target, "%d 0 R", &ID);
+ fwrite(source, target - source, 1, linear_params->Lin_File.file);
+- sprintf(Buf, "%d 0 R", pdev->ResourceUsage[ID].NewObjectNumber);
++ gs_sprintf(Buf, "%d 0 R", pdev->ResourceUsage[ID].NewObjectNumber);
+ fwrite(Buf, strlen(Buf), 1, linear_params->Lin_File.file);
+ source = next;
+ } else {
+@@ -1544,7 +1544,7 @@ static int pdf_linearise(gx_device_pdf *
+ }
+ #endif
+ /* Linearisation. Part 1, file header */
+- sprintf(Header, "%%PDF-%d.%d\n", level / 10, level % 10);
++ gs_sprintf(Header, "%%PDF-%d.%d\n", level / 10, level % 10);
+ fwrite(Header, strlen(Header), 1, linear_params->Lin_File.file);
+ if (pdev->binary_ok)
+ fwrite(Binary, strlen(Binary), 1, linear_params->Lin_File.file);
+@@ -1556,16 +1556,16 @@ static int pdf_linearise(gx_device_pdf *
+
+ /* Linearisation. Part 2, the Linearisation dictioanry */
+ linear_params->LDictOffset = gp_ftell_64(linear_params->Lin_File.file);
+- sprintf(LDict, "%d 0 obj\n<< \n",
++ gs_sprintf(LDict, "%d 0 obj\n<< \n",
+ LDictObj);
+ fwrite(LDict, strlen(LDict), 1, linear_params->Lin_File.file);
+
+ /* First page cross-reference table here (Part 3) */
+ linear_params->FirstxrefOffset = gp_ftell_64(linear_params->Lin_File.file);
+- sprintf(Header, "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */
++ gs_sprintf(Header, "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */
+ fwrite(Header, strlen(Header), 1, linear_params->Lin_File.file);
+
+- sprintf(Header, "0000000000 00000 n \n");
++ gs_sprintf(Header, "0000000000 00000 n \n");
+
+ for (i = LDictObj;i <= linear_params->LastResource + 2; i++) {
+ fwrite(Header, 20, 1, linear_params->Lin_File.file);
+@@ -1575,7 +1575,7 @@ static int pdf_linearise(gx_device_pdf *
+ * +1 for the linearisation dict and +1 for the primary hint stream.
+ */
+ linear_params->FirsttrailerOffset = gp_ftell_64(linear_params->Lin_File.file);
+- sprintf(LDict, "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %d>>\nstartxref\r\n0\n%%%%EOF\n \n",
++ gs_sprintf(LDict, "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %d>>\nstartxref\r\n0\n%%%%EOF\n \n",
+ linear_params->LastResource + 3, pdev->ResourceUsage[linear_params->Info_id].NewObjectNumber, pdev->ResourceUsage[linear_params->Catalog_id].NewObjectNumber, fileID, fileID, 0);
+ fwrite(LDict, strlen(LDict), 1, linear_params->Lin_File.file);
+
+@@ -1685,7 +1685,7 @@ static int pdf_linearise(gx_device_pdf *
+ }
+ }
+ /* insert the primary hint stream */
+- sprintf(LDict, "%d 0 obj\n<</Length \n/S >>\nstream\n", HintStreamObj);
++ gs_sprintf(LDict, "%d 0 obj\n<</Length \n/S >>\nstream\n", HintStreamObj);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+
+ HintStreamStart = gp_ftell_64(linear_params->sfile);
+@@ -1999,7 +1999,7 @@ static int pdf_linearise(gx_device_pdf *
+ flush_hint_stream(linear_params);
+ HintLength = gp_ftell_64(linear_params->sfile) - HintStreamStart;
+
+- sprintf(LDict, "\nendstream\nendobj\n");
++ gs_sprintf(LDict, "\nendstream\nendobj\n");
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+ /* Calculate the length of the primary hint stream */
+ HintStreamLen = gp_ftell_64(linear_params->sfile) - pdev->ResourceUsage[HintStreamObj].LinearisedOffset;
+@@ -2032,23 +2032,23 @@ static int pdf_linearise(gx_device_pdf *
+
+ /* Now the file is long enough, write the xref */
+ mainxref = gp_ftell_64(linear_params->sfile);
+- sprintf(Header, "xref\n0 %d\n", LDictObj);
++ gs_sprintf(Header, "xref\n0 %d\n", LDictObj);
+ fwrite(Header, strlen(Header), 1, linear_params->sfile);
+
+ linear_params->T = gp_ftell_64(linear_params->sfile) - 1;
+- sprintf(Header, "0000000000 65535 f \n");
++ gs_sprintf(Header, "0000000000 65535 f \n");
+ fwrite(Header, strlen(Header), 1, linear_params->sfile);
+
+ for (i = 1;i < LDictObj; i++) {
+ for (j = 0; j < pdev->ResourceUsageSize;j++) {
+ if (pdev->ResourceUsage[j].NewObjectNumber == i) {
+- sprintf(Header, "%010ld 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset + HintStreamLen);
++ gs_sprintf(Header, "%010ld 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset + HintStreamLen);
+ fwrite(Header, 20, 1, linear_params->sfile);
+ }
+ }
+ }
+
+- sprintf(LDict, "trailer\n<</Size %d>>\nstartxref\n%ld\n%%%%EOF\n",
++ gs_sprintf(LDict, "trailer\n<</Size %d>>\nstartxref\n%ld\n%%%%EOF\n",
+ LDictObj, linear_params->FirstxrefOffset);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+
+@@ -2062,32 +2062,32 @@ static int pdf_linearise(gx_device_pdf *
+ * versions.
+ */
+ gp_fseek_64(linear_params->sfile, linear_params->LDictOffset, SEEK_SET);
+- sprintf(LDict, "%d 0 obj\n<</Linearized 1/L %ld/H[ ", LDictObj, linear_params->FileLength);
++ gs_sprintf(LDict, "%d 0 obj\n<</Linearized 1/L %ld/H[ ", LDictObj, linear_params->FileLength);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+
+- sprintf(LDict, "%ld", pdev->ResourceUsage[HintStreamObj].LinearisedOffset);
++ gs_sprintf(LDict, "%ld", pdev->ResourceUsage[HintStreamObj].LinearisedOffset);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+- sprintf(LDict, " %ld]", HintStreamLen);
++ gs_sprintf(LDict, " %ld]", HintStreamLen);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+ /* Implementation Note 180 in hte PDF Reference 1.7 says that Acrobat
+ * gets the 'E' value wrong. So its probably not important....
+ */
+- sprintf(LDict, "/O %d/E %ld",pdev->ResourceUsage[pdev->pages[0].Page->id].NewObjectNumber, linear_params->E);
++ gs_sprintf(LDict, "/O %d/E %ld",pdev->ResourceUsage[pdev->pages[0].Page->id].NewObjectNumber, linear_params->E);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+- sprintf(LDict, "/N %d/T %ld>>\nendobj\n", pdev->next_page, linear_params->T);
++ gs_sprintf(LDict, "/N %d/T %ld>>\nendobj\n", pdev->next_page, linear_params->T);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+
+ /* Return to the secondary xref and write it again filling
+ * in the missing offsets.
+ */
+ gp_fseek_64(linear_params->sfile, linear_params->FirstxrefOffset, SEEK_SET);
+- sprintf(Header, "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */
++ gs_sprintf(Header, "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */
+ fwrite(Header, strlen(Header), 1, linear_params->sfile);
+
+ for (i = LDictObj;i <= linear_params->LastResource + 2; i++) {
+ for (j = 0; j < pdev->ResourceUsageSize;j++) {
+ if (pdev->ResourceUsage[j].NewObjectNumber == i) {
+- sprintf(Header, "%010ld 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset);
++ gs_sprintf(Header, "%010ld 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset);
+ fwrite(Header, 20, 1, linear_params->sfile);
+ }
+ }
+@@ -2097,14 +2097,14 @@ static int pdf_linearise(gx_device_pdf *
+ * in the missing values.
+ */
+ code = gp_fseek_64(linear_params->sfile, linear_params->FirsttrailerOffset, SEEK_SET);
+- sprintf(LDict, "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %ld>>\nstartxref\r\n0\n%%%%EOF\n",
++ gs_sprintf(LDict, "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %ld>>\nstartxref\r\n0\n%%%%EOF\n",
+ linear_params->LastResource + 3, pdev->ResourceUsage[linear_params->Info_id].NewObjectNumber, pdev->ResourceUsage[linear_params->Catalog_id].NewObjectNumber, fileID, fileID, (unsigned long)mainxref);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+
+ code = gp_fseek_64(linear_params->sfile, pdev->ResourceUsage[HintStreamObj].LinearisedOffset, SEEK_SET);
+- sprintf(LDict, "%d 0 obj\n<</Length %10ld", HintStreamObj, HintLength);
++ gs_sprintf(LDict, "%d 0 obj\n<</Length %10ld", HintStreamObj, HintLength);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+- sprintf(LDict, "\n/S %10ld>>\nstream\n", SharedHintOffset);
++ gs_sprintf(LDict, "\n/S %10ld>>\nstream\n", SharedHintOffset);
+ fwrite(LDict, strlen(LDict), 1, linear_params->sfile);
+
+ error:
+@@ -2605,7 +2605,7 @@ pdf_close(gx_device * dev)
+ pprintld1(s, "/Encrypt %ld 0 R ", Encrypt_id);
+ }
+ stream_puts(s, ">>\n");
+- sprintf(xref_str, "startxref\n%"PRId64"\n%%%%EOF\n", xref);
++ gs_sprintf(xref_str, "startxref\n%"PRId64"\n%%%%EOF\n", xref);
+ stream_puts(s, xref_str);
+ }
+ }
+diff -up ghostscript-9.07/base/gdevpdfe.c.gs_sprintf ghostscript-9.07/base/gdevpdfe.c
+--- ghostscript-9.07/base/gdevpdfe.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfe.c 2013-05-09 17:02:39.067447089 +0100
+@@ -205,7 +205,7 @@ pdf_xmp_time(char *buf, int buf_length)
+
+ time(&t);
+ tms = *localtime(&t);
+- sprintf(buf1,
++ gs_sprintf(buf1,
+ "%04d-%02d-%02d",
+ tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday);
+ strncpy(buf, buf1, buf_length);
+@@ -860,7 +860,7 @@ pdf_document_metadata(gx_device_pdf *pde
+ code = COS_WRITE_OBJECT(pres->object, pdev, resourceNone);
+ if (code < 0)
+ return code;
+- sprintf(buf, "%ld 0 R", pres->object->id);
++ gs_sprintf(buf, "%ld 0 R", pres->object->id);
+ pdf_record_usage(pdev, pres->object->id, resource_usage_part9_structure);
+
+ code = cos_dict_put_c_key_object(pdev->Catalog, "/Metadata", pres->object);
+diff -up ghostscript-9.07/base/gdevpdfg.c.gs_sprintf ghostscript-9.07/base/gdevpdfg.c
+--- ghostscript-9.07/base/gdevpdfg.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfg.c 2013-05-09 17:02:39.068447094 +0100
+@@ -674,7 +674,7 @@ pdf_write_transfer_map(gx_device_pdf *pd
+ gs_function_free(pfn, false, mem);
+ if (code < 0)
+ return code;
+- sprintf(ids, "%s%s%ld 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
++ gs_sprintf(ids, "%s%s%ld 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
+ return 0;
+ }
+ static int
+@@ -1255,7 +1255,7 @@ pdf_update_halftone(gx_device_pdf *pdev,
+ }
+ if (code < 0)
+ return code;
+- sprintf(hts, "%ld 0 R", id);
++ gs_sprintf(hts, "%ld 0 R", id);
+ pdev->halftone_id = pis->dev_ht->id;
+ return code;
+ }
+@@ -1392,7 +1392,7 @@ pdf_update_alpha(gx_device_pdf *pdev, co
+ if (pis->soft_mask_id == 0)
+ strcpy(buf, "/None");
+ else
+- sprintf(buf, "%ld 0 R", pis->soft_mask_id);
++ gs_sprintf(buf, "%ld 0 R", pis->soft_mask_id);
+ code = pdf_open_gstate(pdev, ppres);
+ if (code < 0)
+ return code;
+@@ -1548,7 +1548,7 @@ pdf_prepare_drawing(gx_device_pdf *pdev,
+ code = pdf_open_gstate(pdev, ppres);
+ if (code < 0)
+ return code;
+- sprintf(buf, "[%d %d]", phase.x, phase.y);
++ gs_sprintf(buf, "[%d %d]", phase.x, phase.y);
+ code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTP", buf);
+ if (code < 0)
+ return code;
+diff -up ghostscript-9.07/base/gdevpdfi.c.gs_sprintf ghostscript-9.07/base/gdevpdfi.c
+--- ghostscript-9.07/base/gdevpdfi.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfi.c 2013-05-09 17:02:39.068447094 +0100
+@@ -1122,7 +1122,7 @@ pdf_end_and_do_image(gx_device_pdf *pdev
+ if (pdev->image_mask_id != gs_no_id) {
+ char buf[20];
+
+- sprintf(buf, "%ld 0 R", pdev->image_mask_id);
++ gs_sprintf(buf, "%ld 0 R", pdev->image_mask_id);
+ code = cos_dict_put_string_copy((cos_dict_t *)pres->object,
+ pdev->image_mask_is_SMask ? "/SMask" : "/Mask", buf);
+ if (code < 0)
+diff -up ghostscript-9.07/base/gdevpdfm.c.gs_sprintf ghostscript-9.07/base/gdevpdfm.c
+--- ghostscript-9.07/base/gdevpdfm.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfm.c 2013-05-09 17:02:39.069447098 +0100
+@@ -153,9 +153,9 @@ pdfmark_make_dest(char dstr[MAX_DEST_STR
+ else if (pdfmark_find_key("/Action", pairs, count, &action) &&
+ pdf_key_eq(&action, "/GoToR")
+ )
+- sprintf(dstr, "[%d ", page - 1);
++ gs_sprintf(dstr, "[%d ", page - 1);
+ else
+- sprintf(dstr, "[%ld 0 R ", pdf_page_id(pdev, page));
++ gs_sprintf(dstr, "[%ld 0 R ", pdf_page_id(pdev, page));
+ len = strlen(dstr);
+ if (len + view_string.size > MAX_DEST_STRING)
+ return_error(gs_error_limitcheck);
+@@ -697,7 +697,7 @@ pdfmark_put_ao_pairs(gx_device_pdf * pde
+ char dstr[1 + (sizeof(long) * 8 / 3 + 1) + 25 + 1];
+ long page_id = pdf_page_id(pdev, pdev->next_page + 1);
+
+- sprintf(dstr, "[%ld 0 R /XYZ null null null]", page_id);
++ gs_sprintf(dstr, "[%ld 0 R /XYZ null null null]", page_id);
+ cos_dict_put_c_key_string(pcd, "/Dest", (const unsigned char*) dstr,
+ strlen(dstr));
+ }
+@@ -1470,7 +1470,7 @@ pdfmark_PS(gx_device_pdf * pdev, gs_para
+ if (level1_id != gs_no_id) {
+ char r[MAX_DEST_STRING];
+
+- sprintf(r, "%ld 0 R", level1_id);
++ gs_sprintf(r, "%ld 0 R", level1_id);
+ code = cos_dict_put_c_key_string(cos_stream_dict(pcs), "/Level1",
+ (byte *)r, strlen(r));
+ if (code < 0)
+diff -up ghostscript-9.07/base/gdevpdfo.c.gs_sprintf ghostscript-9.07/base/gdevpdfo.c
+--- ghostscript-9.07/base/gdevpdfo.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfo.c 2013-05-09 17:02:39.069447098 +0100
+@@ -700,7 +700,7 @@ cos_array_add_int(cos_array_t *pca, int
+ char str[sizeof(int) * 8 / 3 + 3]; /* sign, rounding, 0 terminator */
+ cos_value_t v;
+
+- sprintf(str, "%d", i);
++ gs_sprintf(str, "%d", i);
+ return cos_array_add(pca, cos_string_value(&v, (byte *)str, strlen(str)));
+ }
+ int
+@@ -1081,7 +1081,7 @@ cos_dict_put_c_key_int(cos_dict_t *pcd,
+ {
+ char str[sizeof(int) * 8 / 3 + 3]; /* sign, rounding, 0 terminator */
+
+- sprintf(str, "%d", value);
++ gs_sprintf(str, "%d", value);
+ return cos_dict_put_c_key_string(pcd, key, (byte *)str, strlen(str));
+ }
+ int
+diff -up ghostscript-9.07/base/gdevpdfr.c.gs_sprintf ghostscript-9.07/base/gdevpdfr.c
+--- ghostscript-9.07/base/gdevpdfr.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfr.c 2013-05-09 17:02:39.070447102 +0100
+@@ -140,7 +140,7 @@ pdf_refer_named(gx_device_pdf * pdev, co
+ }
+ if (page_number <= 0)
+ return code;
+- sprintf(page_name_chars, "{Page%d}", page_number);
++ gs_sprintf(page_name_chars, "{Page%d}", page_number);
+ param_string_from_string(pnstr, page_name_chars);
+ pname = &pnstr;
+ code = pdf_find_named(pdev, pname, ppco);
+@@ -452,7 +452,7 @@ pdf_replace_names(gx_device_pdf * pdev,
+
+ size += sname - scan;
+ if (pco) {
+- sprintf(ref, " %ld 0 R ", pco->id);
++ gs_sprintf(ref, " %ld 0 R ", pco->id);
+ size += strlen(ref);
+ }
+ scan = next;
+@@ -480,7 +480,7 @@ pdf_replace_names(gx_device_pdf * pdev,
+ memcpy(sto, scan, copy);
+ sto += copy;
+ if (pco) {
+- sprintf(ref, " %ld 0 R ", pco->id);
++ gs_sprintf(ref, " %ld 0 R ", pco->id);
+ rlen = strlen(ref);
+ memcpy(sto, ref, rlen);
+ sto += rlen;
+diff -up ghostscript-9.07/base/gdevpdft.c.gs_sprintf ghostscript-9.07/base/gdevpdft.c
+--- ghostscript-9.07/base/gdevpdft.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdft.c 2013-05-09 17:02:39.070447102 +0100
+@@ -63,7 +63,7 @@ pdf_make_soft_mask_dict(gx_device_pdf *
+ code = pdf_write_function(pdev, pparams->transfer_function, &id);
+ if (code < 0)
+ return code;
+- sprintf(buf, " %ld 0 R", id);
++ gs_sprintf(buf, " %ld 0 R", id);
+ code = cos_dict_put_c_key_string(soft_mask_dict, "/TR", (const byte *)buf, strlen(buf));
+ if (code < 0)
+ return code;
+@@ -317,7 +317,7 @@ pdf_end_transparency_mask(gs_imager_stat
+ return 0;
+ /* We need to update the 'where_used' field, in case we substituted a resource */
+ pres->where_used |= pdev->used_mask;
+- sprintf(buf, "%ld 0 R", pdf_resource_id(pres));
++ gs_sprintf(buf, "%ld 0 R", pdf_resource_id(pres));
+ code = cos_dict_put_c_key_string((cos_dict_t *)pdev->pres_soft_mask_dict->object,
+ "/G", (const byte *)buf, strlen(buf));
+ if (code < 0)
+diff -up ghostscript-9.07/base/gdevpdfu.c.gs_sprintf ghostscript-9.07/base/gdevpdfu.c
+--- ghostscript-9.07/base/gdevpdfu.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfu.c 2013-05-09 17:02:39.071447106 +0100
+@@ -341,14 +341,14 @@ static int write_tt_encodings(stream *s,
+ char Buffer[256];
+ single_glyph_list_t *entry = (single_glyph_list_t *)&SingleGlyphList;
+
+- sprintf(Buffer, "/AdobeGlyphList mark\n");
++ gs_sprintf(Buffer, "/AdobeGlyphList mark\n");
+ stream_write(s, Buffer, strlen(Buffer));
+ while (entry->Glyph) {
+- sprintf(Buffer, "/%s 16#%04x\n", entry->Glyph, entry->Unicode);
++ gs_sprintf(Buffer, "/%s 16#%04x\n", entry->Glyph, entry->Unicode);
+ stream_write(s, Buffer, strlen(Buffer));
+ entry++;
+ };
+- sprintf(Buffer, ".dicttomark readonly def\n");
++ gs_sprintf(Buffer, ".dicttomark readonly def\n");
+ stream_write(s, Buffer, strlen(Buffer));
+
+ index = 0;
+@@ -425,24 +425,24 @@ int ps2write_dsc_header(gx_device_pdf *
+ pagecount++;
+ }
+ }
+- sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\n", (int)urx, (int)ury);
++ gs_sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\n", (int)urx, (int)ury);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+- sprintf(BBox, "%%%%HiResBoundingBox: 0 0 %.2f %.2f\n", urx, ury);
++ gs_sprintf(BBox, "%%%%HiResBoundingBox: 0 0 %.2f %.2f\n", urx, ury);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+ }
+ cre_date_time_len = pdf_get_docinfo_item(pdev, "/CreationDate", cre_date_time, sizeof(cre_date_time) - 1);
+ cre_date_time[cre_date_time_len] = 0;
+- sprintf(BBox, "%%%%Creator: %s %d (%s)\n", gs_product, (int)gs_revision,
++ gs_sprintf(BBox, "%%%%Creator: %s %d (%s)\n", gs_product, (int)gs_revision,
+ pdev->dname);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+ stream_puts(s, "%%LanguageLevel: 2\n");
+- sprintf(BBox, "%%%%CreationDate: %s\n", cre_date_time);
++ gs_sprintf(BBox, "%%%%CreationDate: %s\n", cre_date_time);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+- sprintf(BBox, "%%%%Pages: %d\n", pages);
++ gs_sprintf(BBox, "%%%%Pages: %d\n", pages);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+- sprintf(BBox, "%%%%EndComments\n");
++ gs_sprintf(BBox, "%%%%EndComments\n");
+ stream_write(s, (byte *)BBox, strlen(BBox));
+- sprintf(BBox, "%%%%BeginProlog\n");
++ gs_sprintf(BBox, "%%%%BeginProlog\n");
+ stream_write(s, (byte *)BBox, strlen(BBox));
+ if (pdev->params.CompressPages) {
+ /* When CompressEntireFile is true and ASCII85EncodePages is false,
+@@ -493,7 +493,7 @@ pdfwrite_pdf_open_document(gx_device_pdf
+ pdev->CompressEntireFile = 0;
+ else {
+ stream_write(s, (byte *)"%!\r", 3);
+- sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
++ gs_sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
+ stream_write(s, (byte *)BBox, strlen(BBox));
+ if (pdev->params.CompressPages || pdev->CompressEntireFile) {
+ /* When CompressEntireFile is true and ASCII85EncodePages is false,
+@@ -1340,7 +1340,7 @@ void
+ pdf_reserve_object_id(gx_device_pdf * pdev, pdf_resource_t *pres, long id)
+ {
+ pres->object->id = (id == 0 ? pdf_obj_ref(pdev) : id);
+- sprintf(pres->rname, "R%ld", pres->object->id);
++ gs_sprintf(pres->rname, "R%ld", pres->object->id);
+ }
+
+ /* Begin an aside (resource, annotation, ...). */
+@@ -1802,9 +1802,9 @@ void
+ pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER])
+ {
+ if ((gs_revision % 100) == 0)
+- sprintf(buf, "(%s %1.1f)", gs_product, gs_revision / 100.0);
++ gs_sprintf(buf, "(%s %1.1f)", gs_product, gs_revision / 100.0);
+ else
+- sprintf(buf, "(%s %1.2f)", gs_product, gs_revision / 100.0);
++ gs_sprintf(buf, "(%s %1.2f)", gs_product, gs_revision / 100.0);
+ }
+
+ /* Write matrix values. */
+@@ -1851,7 +1851,7 @@ pdf_put_name_chars_1_2(stream *s, const
+ case '[': case ']':
+ case '{': case '}':
+ case '/':
+- sprintf(hex, "#%02x", c);
++ gs_sprintf(hex, "#%02x", c);
+ stream_puts(s, hex);
+ break;
+ case 0:
+diff -up ghostscript-9.07/base/gdevpdfv.c.gs_sprintf ghostscript-9.07/base/gdevpdfv.c
+--- ghostscript-9.07/base/gdevpdfv.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdfv.c 2013-05-09 17:02:39.071447106 +0100
+@@ -157,7 +157,7 @@ pdf_pattern(gx_device_pdf *pdev, const g
+
+ if (pcd_XObject == 0)
+ return_error(gs_error_VMerror);
+- sprintf(key, "/R%ld", pcs_image->id);
++ gs_sprintf(key, "/R%ld", pcs_image->id);
+ /* This is non-obvious code. Previously we would put the image object (pcs_image)
+ * into the Resources dit. When we come to write out the Resources dict
+ * that code writes a reference (index 0 R) using the ID from the object.
+@@ -201,7 +201,7 @@ pdf_pattern(gx_device_pdf *pdev, const g
+ {
+ char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */
+
+- sprintf(buf, "/R%ld Do\n", pcs_image->id);
++ gs_sprintf(buf, "/R%ld Do\n", pcs_image->id);
+ cos_stream_add_bytes(pcos, (const byte *)buf, strlen(buf));
+ }
+
+@@ -596,7 +596,7 @@ pdf_put_linear_shading(cos_dict_t *pscd,
+ if (Extend[0] | Extend[1]) {
+ char extend_str[1 + 5 + 1 + 5 + 1 + 1]; /* [bool bool] */
+
+- sprintf(extend_str, "[%s %s]",
++ gs_sprintf(extend_str, "[%s %s]",
+ (Extend[0] ? "true" : "false"),
+ (Extend[1] ? "true" : "false"));
+ code = cos_dict_put_c_key_string(pscd, "/Extend",
+diff -up ghostscript-9.07/base/gdevpdtb.c.gs_sprintf ghostscript-9.07/base/gdevpdtb.c
+--- ghostscript-9.07/base/gdevpdtb.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdtb.c 2013-05-09 17:02:39.072447111 +0100
+@@ -345,7 +345,7 @@ pdf_base_font_alloc(gx_device_pdf *pdev,
+ font_name.size -= SUBSET_PREFIX_SIZE;
+ }
+ } else {
+- sprintf(fnbuf, ".F%lx", (ulong)copied);
++ gs_sprintf(fnbuf, ".F%lx", (ulong)copied);
+ font_name.data = (byte *)fnbuf;
+ font_name.size = strlen(fnbuf);
+ }
+@@ -530,7 +530,7 @@ pdf_adjust_font_name(gx_device_pdf *pdev
+ size = i + 1;
+ }
+ /* Create a unique name. */
+- sprintf(suffix, "%c%lx", SUFFIX_CHAR, id);
++ gs_sprintf(suffix, "%c%lx", SUFFIX_CHAR, id);
+ suffix_size = strlen(suffix);
+ data = gs_resize_string(pdev->pdf_memory, chars, size,
+ size + suffix_size,
+diff -up ghostscript-9.07/base/gdevpdtc.c.gs_sprintf ghostscript-9.07/base/gdevpdtc.c
+--- ghostscript-9.07/base/gdevpdtc.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdtc.c 2013-05-09 17:02:39.072447111 +0100
+@@ -338,7 +338,7 @@ attach_cmap_resource(gx_device_pdf *pdev
+ strcpy(pdfont->u.type0.Encoding_name,
+ (pcmap->WMode ? "/Identity-V" : "/Identity-H"));
+ else
+- sprintf(pdfont->u.type0.Encoding_name, "%ld 0 R",
++ gs_sprintf(pdfont->u.type0.Encoding_name, "%ld 0 R",
+ pdf_resource_id(pcmres));
+ pdfont->u.type0.CMapName.data = chars;
+ pdfont->u.type0.CMapName.size = size;
+@@ -349,7 +349,7 @@ attach_cmap_resource(gx_device_pdf *pdev
+ */
+ return_error(gs_error_invalidfont);
+
+- sprintf(pdfont->u.type0.Encoding_name, "/%s", *pcmn);
++ gs_sprintf(pdfont->u.type0.Encoding_name, "/%s", *pcmn);
+ pdfont->u.type0.CMapName.data = (const byte *)*pcmn;
+ pdfont->u.type0.CMapName.size = strlen(*pcmn);
+ pdfont->u.type0.cmap_is_standard = true;
+diff -up ghostscript-9.07/base/gdevpdtf.c.gs_sprintf ghostscript-9.07/base/gdevpdtf.c
+--- ghostscript-9.07/base/gdevpdtf.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdtf.c 2013-05-09 17:02:39.072447111 +0100
+@@ -1152,7 +1152,7 @@ pdf_convert_truetype_font(gx_device_pdf
+ if (code < 0)
+ return 0;
+ pdfont->u.cidfont.CIDSystemInfo_id = pdev->IdentityCIDSystemInfo_id;
+- sprintf(pdfont0->u.type0.Encoding_name, "%ld 0 R", pdf_resource_id(pdev->OneByteIdentityH));
++ gs_sprintf(pdfont0->u.type0.Encoding_name, "%ld 0 R", pdf_resource_id(pdev->OneByteIdentityH));
+ /* Move ToUnicode : */
+ pdfont0->res_ToUnicode = pdfont->res_ToUnicode; pdfont->res_ToUnicode = 0;
+ pdfont0->cmap_ToUnicode = pdfont->cmap_ToUnicode; pdfont->cmap_ToUnicode = 0;
+diff -up ghostscript-9.07/base/gdevpdti.c.gs_sprintf ghostscript-9.07/base/gdevpdti.c
+--- ghostscript-9.07/base/gdevpdti.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdti.c 2013-05-09 17:02:39.073447115 +0100
+@@ -1178,7 +1178,7 @@ pdf_add_resource(gx_device_pdf *pdev, co
+ if (code < 0)
+ return code;
+ }
+- sprintf(buf, "%ld 0 R\n", pres->object->id);
++ gs_sprintf(buf, "%ld 0 R\n", pres->object->id);
+ if (v != NULL) {
+ if (v->value_type != COS_VALUE_OBJECT &&
+ v->value_type != COS_VALUE_RESOURCE)
+diff -up ghostscript-9.07/base/gdevpdtt.c.gs_sprintf ghostscript-9.07/base/gdevpdtt.c
+--- ghostscript-9.07/base/gdevpdtt.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdtt.c 2013-05-09 17:02:39.074447119 +0100
+@@ -2752,7 +2752,7 @@ pdf_choose_output_glyph_hame(gx_device_p
+ p = (byte *)gs_alloc_string(pdev->pdf_memory, gnstr->size, "pdf_text_set_cache");
+ if (p == NULL)
+ return_error(gs_error_VMerror);
+- sprintf(buf, "g%04x", (unsigned int)(glyph & 0xFFFF));
++ gs_sprintf(buf, "g%04x", (unsigned int)(glyph & 0xFFFF));
+ memcpy(p, buf, 5);
+ gnstr->data = p;
+ }
+diff -up ghostscript-9.07/base/gdevpdtw.c.gs_sprintf ghostscript-9.07/base/gdevpdtw.c
+--- ghostscript-9.07/base/gdevpdtw.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpdtw.c 2013-05-09 17:02:39.074447119 +0100
+@@ -925,7 +925,7 @@ pdf_write_OneByteIdentityH(gx_device_pdf
+ code = cos_dict_put_string_copy(pcd, "/CMapName", "/OneByteIdentityH");
+ if (code < 0)
+ return code;
+- sprintf(buf, "%ld 0 R", pdev->IdentityCIDSystemInfo_id);
++ gs_sprintf(buf, "%ld 0 R", pdev->IdentityCIDSystemInfo_id);
+ code = cos_dict_put_string_copy(pcd, "/CIDSystemInfo", buf);
+ if (code < 0)
+ return code;
+diff -up ghostscript-9.07/base/gdevpng.c.gs_sprintf ghostscript-9.07/base/gdevpng.c
+--- ghostscript-9.07/base/gdevpng.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpng.c 2013-05-09 17:02:39.074447119 +0100
+@@ -564,7 +564,7 @@ do_png_print_page(gx_device_png * pdev,
+ }
+ /* add comment */
+ strncpy(software_key, "Software", sizeof(software_key));
+- sprintf(software_text, "%s %d.%02d", gs_product,
++ gs_sprintf(software_text, "%s %d.%02d", gs_product,
+ (int)(gs_revision / 100), (int)(gs_revision % 100));
+ text_png.compression = -1; /* uncompressed */
+ text_png.key = software_key;
+diff -up ghostscript-9.07/base/gdevps.c.gs_sprintf ghostscript-9.07/base/gdevps.c
+--- ghostscript-9.07/base/gdevps.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevps.c 2013-05-09 17:02:39.075447124 +0100
+@@ -526,7 +526,7 @@ psw_image_write(gx_device_pswrite * pdev
+ const char *op;
+
+ if (index >= 0) {
+- sprintf(str, "%d%c", index / 26, index % 26 + 'A');
++ gs_sprintf(str, "%d%c", index / 26, index % 26 + 'A');
+ pprintd2(s, "%d %d ", x, y);
+ pprints2(s, "%s %s\n", str, imagestr);
+ if (s->end_status == ERRC)
+@@ -556,12 +556,12 @@ psw_image_write(gx_device_pswrite * pdev
+ };
+
+ index = image_cache_lookup(pdev, id, width_bits, height, true);
+- sprintf(str, "/%d%c", index / 26, index % 26 + 'A');
++ gs_sprintf(str, "/%d%c", index / 26, index % 26 + 'A');
+ stream_puts(s, str);
+ if (depth != 1)
+ pprintld1(s, " %ld", ((width_bits + 7) >> 3) * (ulong) height);
+ op = cached[encode];
+- sprintf(endstr, "\n%s\n", imagestr);
++ gs_sprintf(endstr, "\n%s\n", imagestr);
+ }
+ if (s->end_status == ERRC)
+ return_error(gs_error_ioerror);
+@@ -1261,7 +1261,7 @@ psw_copy_color(gx_device * dev,
+ return (*dev_proc(dev, fill_rectangle))
+ (dev, x, y, w, h, (bits[0] << 16) + (bits[1] << 8) + bits[2]);
+ }
+- sprintf(op, "%d Ic", depth / 3); /* RGB */
++ gs_sprintf(op, "%d Ic", depth / 3); /* RGB */
+ code = gdev_vector_update_clip_path(vdev, NULL);
+ if (code < 0)
+ return code;
+diff -up ghostscript-9.07/base/gdevpsf1.c.gs_sprintf ghostscript-9.07/base/gdevpsf1.c
+--- ghostscript-9.07/base/gdevpsf1.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpsf1.c 2013-05-09 17:02:39.075447124 +0100
+@@ -646,12 +646,12 @@ write_Private(stream *s, gs_font_type1 *
+ gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record");
+ return code;
+ }
+- sprintf(buf, "dup %d %u -| ", i, code);
++ gs_sprintf(buf, "dup %d %u -| ", i, code);
+ stream_puts(s, buf);
+ write_CharString(s, stripped, code);
+ gs_free_object(pfont->memory, stripped, "free Subrs copy for OtherSubrs");
+ } else {
+- sprintf(buf, "dup %d %u -| ", i, gdata.bits.size);
++ gs_sprintf(buf, "dup %d %u -| ", i, gdata.bits.size);
+ stream_puts(s, buf);
+ write_CharString(s, gdata.bits.data, gdata.bits.size);
+ }
+diff -up ghostscript-9.07/base/gdevpsf2.c.gs_sprintf ghostscript-9.07/base/gdevpsf2.c
+--- ghostscript-9.07/base/gdevpsf2.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevpsf2.c 2013-05-09 17:02:39.076447128 +0100
+@@ -274,7 +274,7 @@ cff_put_real(cff_writer_t *pcw, floatp f
+ byte b = 0xff;
+ const char *p;
+
+- sprintf(str, "%g", f);
++ gs_sprintf(str, "%g", f);
+ sputc(pcw->strm, CD_REAL);
+ for (p = str; ; ++p) {
+ int digit;
+diff -up ghostscript-9.07/base/gdevsppr.c.gs_sprintf ghostscript-9.07/base/gdevsppr.c
+--- ghostscript-9.07/base/gdevsppr.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevsppr.c 2013-05-09 17:02:39.076447128 +0100
+@@ -100,7 +100,7 @@ err_code_string(int err_code)
+ {
+ if ((err_code<EMOTOR)||(err_code>ESERIAL))
+ {
+- sprintf(err_buffer,"err_code out of range: %d",err_code);
++ gs_sprintf(err_buffer,"err_code out of range: %d",err_code);
+ return err_buffer;
+ }
+ return errmsg[err_code];
+diff -up ghostscript-9.07/base/gdevsun.c.gs_sprintf ghostscript-9.07/base/gdevsun.c
+--- ghostscript-9.07/base/gdevsun.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevsun.c 2013-05-09 17:02:39.076447128 +0100
+@@ -392,7 +392,7 @@ if ( gs_debug['X'] )
+ /*
+ * Install the colormap.
+ */
+- sprintf(xdev->cmsname, "%s-%d", CMSNAME, getpid());
++ gs_sprintf(xdev->cmsname, "%s-%d", CMSNAME, getpid());
+ pw_setcmsname(xdev->pw, xdev->cmsname);
+ pw_putcolormap(xdev->pw, 0, CMS_SIZE,
+ xdev->red, xdev->green, xdev->blue);
+diff -up ghostscript-9.07/base/gdevsvg.c.gs_sprintf ghostscript-9.07/base/gdevsvg.c
+--- ghostscript-9.07/base/gdevsvg.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevsvg.c 2013-05-09 17:02:39.076447128 +0100
+@@ -374,22 +374,22 @@ svg_write_header(gx_device_svg *svg)
+ return 1;
+
+ /* write the initial boilerplate */
+- sprintf(line, "%s\n", XML_DECL);
++ gs_sprintf(line, "%s\n", XML_DECL);
+ /* svg_write(svg, line); */
+ sputs(s, (byte *)line, strlen(line), &used);
+- sprintf(line, "%s\n", SVG_DOCTYPE);
++ gs_sprintf(line, "%s\n", SVG_DOCTYPE);
+ /* svg_write(svg, line); */
+ sputs(s, (byte *)line, strlen(line), &used);
+- sprintf(line, "<svg xmlns='%s' version='%s'",
++ gs_sprintf(line, "<svg xmlns='%s' version='%s'",
+ SVG_XMLNS, SVG_VERSION);
+ /* svg_write(svg, line); */
+ sputs(s, (byte *)line, strlen(line), &used);
+- sprintf(line, "\n\twidth='%dpt' height='%dpt'>\n",
++ gs_sprintf(line, "\n\twidth='%dpt' height='%dpt'>\n",
+ (int)svg->MediaSize[0], (int)svg->MediaSize[1]);
+ sputs(s, (byte *)line, strlen(line), &used);
+
+ /* Scale drawing so our coordinates are in pixels */
+- sprintf(line, "<g transform='scale(%lf,%lf)'>\n",
++ gs_sprintf(line, "<g transform='scale(%lf,%lf)'>\n",
+ 72.0 / svg->HWResolution[0],
+ 72.0 / svg->HWResolution[1]);
+ /* svg_write(svg, line); */
+@@ -430,19 +430,19 @@ svg_write_state(gx_device_svg *svg)
+ /* write out the new current state */
+ svg_write(svg, "<g ");
+ if (svg->strokecolor != gx_no_color_index) {
+- sprintf(line, " stroke='#%06x'", svg->strokecolor & 0xffffffL);
++ gs_sprintf(line, " stroke='#%06x'", svg->strokecolor & 0xffffffL);
+ svg_write(svg, line);
+ } else {
+ svg_write(svg, " stroke='none'");
+ }
+ if (svg->fillcolor != gx_no_color_index) {
+- sprintf(line, "#%06x", svg->fillcolor & 0xffffffL);
++ gs_sprintf(line, "#%06x", svg->fillcolor & 0xffffffL);
+ svg_write(svg, line);
+ } else {
+ svg_write(svg, " fill='none'");
+ }
+ if (svg->linewidth != 1.0) {
+- sprintf(line, " stroke-width='%lf'", svg->linewidth);
++ gs_sprintf(line, " stroke-width='%lf'", svg->linewidth);
+ svg_write(svg, line);
+ }
+ if (svg->linecap != SVG_DEFAULT_LINECAP) {
+@@ -476,7 +476,7 @@ svg_write_state(gx_device_svg *svg)
+ }
+ }
+ if (svg->miterlimit != SVG_DEFAULT_MITERLIMIT) {
+- sprintf(line, " stroke-miterlimit='%lf'", svg->miterlimit);
++ gs_sprintf(line, " stroke-miterlimit='%lf'", svg->miterlimit);
+ svg_write(svg, line);
+ }
+ svg_write(svg, ">\n");
+@@ -653,7 +653,7 @@ svg_dorect(gx_device_vector *vdev, fixed
+ svg_write(svg, "<clipPath>\n");
+ }
+
+- sprintf(line, "<rect x='%lf' y='%lf' width='%lf' height='%lf'",
++ gs_sprintf(line, "<rect x='%lf' y='%lf' width='%lf' height='%lf'",
+ fixed2float(x0), fixed2float(y0),
+ fixed2float(x1 - x0), fixed2float(y1 - y0));
+ svg_write(svg, line);
+@@ -714,7 +714,7 @@ svg_moveto(gx_device_vector *vdev, float
+ svg_print_path_type(svg, type);
+ if_debug0m('_', svg->memory, "\n");
+
+- sprintf(line, " M%lf,%lf", x, y);
++ gs_sprintf(line, " M%lf,%lf", x, y);
+ svg_write(svg, line);
+
+ return 0;
+@@ -739,7 +739,7 @@ svg_lineto(gx_device_vector *vdev, float
+ svg_print_path_type(svg, type);
+ if_debug0m('_', svg->memory, "\n");
+
+- sprintf(line, " L%lf,%lf", x, y);
++ gs_sprintf(line, " L%lf,%lf", x, y);
+ svg_write(svg, line);
+
+ return 0;
+@@ -766,7 +766,7 @@ svg_curveto(gx_device_vector *vdev, floa
+ svg_print_path_type(svg, type);
+ if_debug0m('_', svg->memory, "\n");
+
+- sprintf(line, " C%lf,%lf %lf,%lf %lf,%lf", x1,y1, x2,y2, x3,y3);
++ gs_sprintf(line, " C%lf,%lf %lf,%lf %lf,%lf", x1,y1, x2,y2, x3,y3);
+ svg_write(svg, line);
+
+ return 0;
+diff -up ghostscript-9.07/base/gdevtifs.c.gs_sprintf ghostscript-9.07/base/gdevtifs.c
+--- ghostscript-9.07/base/gdevtifs.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevtifs.c 2013-05-09 17:02:39.077447132 +0100
+@@ -500,7 +500,7 @@ int tiff_set_fields_for_printer(gx_devic
+
+ strncpy(softwareValue, gs_product, maxSoftware);
+ softwareValue[maxSoftware - 1] = 0;
+- sprintf(revs, " %1.2f", gs_revision / 100.0);
++ gs_sprintf(revs, " %1.2f", gs_revision / 100.0);
+ strncat(softwareValue, revs,
+ maxSoftware - strlen(softwareValue) - 1);
+
+@@ -513,7 +513,7 @@ int tiff_set_fields_for_printer(gx_devic
+
+ time(&t);
+ tms = *localtime(&t);
+- sprintf(dateTimeValue, "%04d:%02d:%02d %02d:%02d:%02d",
++ gs_sprintf(dateTimeValue, "%04d:%02d:%02d %02d:%02d:%02d",
+ tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
+ tms.tm_hour, tms.tm_min, tms.tm_sec);
+
+diff -up ghostscript-9.07/base/gdevtsep.c.gs_sprintf ghostscript-9.07/base/gdevtsep.c
+--- ghostscript-9.07/base/gdevtsep.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevtsep.c 2013-05-09 17:02:39.077447132 +0100
+@@ -1182,9 +1182,9 @@ tiffsep1_prn_close(gx_device * pdev)
+ while (*fmt != 'l' && *fmt != '%')
+ --fmt;
+ if (*fmt == 'l')
+- sprintf(compname, parsed.fname, count1);
++ gs_sprintf(compname, parsed.fname, count1);
+ else
+- sprintf(compname, parsed.fname, (int)count1);
++ gs_sprintf(compname, parsed.fname, (int)count1);
+ parsed.iodev->procs.delete_file(parsed.iodev, compname);
+ } else {
+ parsed.iodev->procs.delete_file(parsed.iodev, tfdev->fname);
+@@ -1370,7 +1370,7 @@ create_separation_file_name(tiffsep_devi
+ /* Max of 10 chars in %d format */
+ if (max_size < base_filename_length + 11)
+ return_error(gs_error_rangecheck);
+- sprintf(buffer + base_filename_length, "s%d", sep_num);
++ gs_sprintf(buffer + base_filename_length, "s%d", sep_num);
+ }
+ }
+ if (use_sep_name)
+@@ -2385,9 +2385,9 @@ tiffsep1_print_page(gx_device_printer *
+ while (*fmt != 'l' && *fmt != '%')
+ --fmt;
+ if (*fmt == 'l')
+- sprintf(compname, parsed.fname, count1);
++ gs_sprintf(compname, parsed.fname, count1);
+ else
+- sprintf(compname, parsed.fname, (int)count1);
++ gs_sprintf(compname, parsed.fname, (int)count1);
+ parsed.iodev->procs.delete_file(parsed.iodev, compname);
+ /* we always need an open printer (it will get deleted in tiffsep1_prn_close */
+ if ((code = gdev_prn_open_printer((gx_device *)pdev, 1)) < 0)
+diff -up ghostscript-9.07/base/gdevtxtw.c.gs_sprintf ghostscript-9.07/base/gdevtxtw.c
+--- ghostscript-9.07/base/gdevtxtw.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevtxtw.c 2013-05-09 17:02:39.078447137 +0100
+@@ -633,16 +633,16 @@ static int escaped_Unicode (unsigned sho
+ {
+ switch (Unicode)
+ {
+- case 0x3C: sprintf(Buf, "&lt;"); break;
+- case 0x3E: sprintf(Buf, "&gt;"); break;
+- case 0x26: sprintf(Buf, "&amp;"); break;
+- case 0x22: sprintf(Buf, "&quot;"); break;
+- case 0x27: sprintf(Buf, "&apos;"); break;
++ case 0x3C: gs_sprintf(Buf, "&lt;"); break;
++ case 0x3E: gs_sprintf(Buf, "&gt;"); break;
++ case 0x26: gs_sprintf(Buf, "&amp;"); break;
++ case 0x22: gs_sprintf(Buf, "&quot;"); break;
++ case 0x27: gs_sprintf(Buf, "&apos;"); break;
+ default:
+ if (Unicode >= 32 && Unicode <= 127)
+- sprintf(Buf, "%c", Unicode);
++ gs_sprintf(Buf, "%c", Unicode);
+ else
+- sprintf(Buf, "&#x%x;", Unicode);
++ gs_sprintf(Buf, "&#x%x;", Unicode);
+ break;
+ }
+
+@@ -665,13 +665,13 @@ static int decorated_text_output(gx_devi
+ x_entry = tdev->PageData.unsorted_text_list;
+ while (x_entry) {
+ next_x = x_entry->next;
+- sprintf(TextBuffer, "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y,
++ gs_sprintf(TextBuffer, "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y,
+ x_entry->end.x, x_entry->end.y, x_entry->FontName,x_entry->size);
+ fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file);
+ xpos = x_entry->start.x;
+ for (i=0;i<x_entry->Unicode_Text_Size;i++) {
+ escaped_Unicode(x_entry->Unicode_Text[i], (char *)&Escaped);
+- sprintf(TextBuffer, "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\">\n", xpos,
++ gs_sprintf(TextBuffer, "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\">\n", xpos,
+ x_entry->start.y, xpos + x_entry->Widths[i], x_entry->end.y, Escaped);
+ fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file);
+ xpos += x_entry->Widths[i];
+@@ -788,13 +788,13 @@ static int decorated_text_output(gx_devi
+ fwrite("<line>\n", sizeof(unsigned char), 7, tdev->file);
+ x_entry = block_line->x_ordered_list;
+ while(x_entry) {
+- sprintf(TextBuffer, "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y,
++ gs_sprintf(TextBuffer, "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y,
+ x_entry->end.x, x_entry->end.y, x_entry->FontName,x_entry->size);
+ fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file);
+ xpos = x_entry->start.x;
+ for (i=0;i<x_entry->Unicode_Text_Size;i++) {
+ escaped_Unicode(x_entry->Unicode_Text[i], (char *)&Escaped);
+- sprintf(TextBuffer, "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\">\n", xpos,
++ gs_sprintf(TextBuffer, "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\">\n", xpos,
+ x_entry->start.y, xpos + x_entry->Widths[i], x_entry->end.y, Escaped);
+ fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file);
+ xpos += x_entry->Widths[i];
+diff -up ghostscript-9.07/base/gdevupd.c.gs_sprintf ghostscript-9.07/base/gdevupd.c
+--- ghostscript-9.07/base/gdevupd.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevupd.c 2013-05-09 17:02:39.079447141 +0100
+@@ -6476,7 +6476,7 @@ upd_open_wrtrtl(upd_device *udev)
+ if( (B_PAGEWIDTH & upd->flags) &&
+ ((c == 0x73) || (c == 0x53)) ) { /* esc * r # S */
+
+- sprintf(cv,"%d",upd->pwidth);
++ gs_sprintf(cv,"%d",upd->pwidth);
+ ncv = strlen(cv);
+
+ nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
+@@ -6494,7 +6494,7 @@ upd_open_wrtrtl(upd_device *udev)
+ } else if((B_PAGELENGTH & upd->flags) &&
+ ((c == 0x74) || (c == 0x54)) ) { /* esc * r # T */
+
+- sprintf(cv,"%d",upd->pheight);
++ gs_sprintf(cv,"%d",upd->pheight);
+ ncv = strlen(cv);
+
+ nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
+@@ -6523,7 +6523,7 @@ upd_open_wrtrtl(upd_device *udev)
+ if( (B_RESOLUTION & upd->flags) &&
+ ((c == 0x72) || (c == 0x52)) ) { /* esc * t # R */
+
+- sprintf(cv,"%d",(int)
++ gs_sprintf(cv,"%d",(int)
+ ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
+ udev->x_pixels_per_inch : udev->y_pixels_per_inch)
+ +0.5));
+@@ -6730,7 +6730,7 @@ upd_open_wrtrtl(upd_device *udev)
+
+ if(B_PAGELENGTH & upd->flags) { /* insert new number */
+
+- sprintf(cv,"%d",(int)
++ gs_sprintf(cv,"%d",(int)
+ (720.0 * udev->height / udev->y_pixels_per_inch + 0.5));
+ ncv = strlen(cv);
+
+@@ -6795,7 +6795,7 @@ upd_open_wrtrtl(upd_device *udev)
+
+ if(B_PAGEWIDTH & upd->flags) { /* insert new number */
+
+- sprintf(cv,"%d",(int)
++ gs_sprintf(cv,"%d",(int)
+ (720.0 * udev->width / udev->x_pixels_per_inch + 0.5));
+ ncv = strlen(cv);
+
+@@ -6890,7 +6890,7 @@ upd_open_wrtrtl(upd_device *udev)
+
+ if(B_RESOLUTION & upd->flags) { /* insert new number */
+
+- sprintf(cv,"%d",(int)
++ gs_sprintf(cv,"%d",(int)
+ ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
+ udev->x_pixels_per_inch : udev->y_pixels_per_inch)
+ +0.5));
+@@ -6945,7 +6945,7 @@ It must hold:
+ char tmp[16];
+
+ if(0 < upd->strings[S_YMOVE].size) {
+- sprintf(tmp,"%d",upd->pheight);
++ gs_sprintf(tmp,"%d",upd->pheight);
+ ny = upd->strings[S_YMOVE].size + strlen(tmp);
+ } else {
+ ny = 1 + upd->string_a[SA_WRITECOMP].data[upd->ocomp-1].size;
+@@ -7006,14 +7006,14 @@ upd_wrtrtl(upd_p upd, FILE *out)
+ */
+ if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
+ if(1 < upd->strings[S_YMOVE].size) {
+- sprintf((char *)upd->outbuf+ioutbuf,
++ gs_sprintf((char *)upd->outbuf+ioutbuf,
+ (const char *) upd->strings[S_YMOVE].data,
+ upd->yscan - upd->yprinter);
+ ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
+ } else {
+ while(upd->yscan > upd->yprinter) {
+ for(icomp = 0; icomp < upd->ocomp; ++icomp) {
+- sprintf((char *)upd->outbuf+ioutbuf,
++ gs_sprintf((char *)upd->outbuf+ioutbuf,
+ (const char *) upd->string_a[SA_WRITECOMP].data[icomp].data,0);
+ ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
+ }
+diff -up ghostscript-9.07/base/gdevwpr2.c.gs_sprintf ghostscript-9.07/base/gdevwpr2.c
+--- ghostscript-9.07/base/gdevwpr2.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevwpr2.c 2013-05-09 17:02:39.080447145 +0100
+@@ -548,7 +548,7 @@ win_pr2_print_page(gx_device_printer * p
+ }
+
+ if (!wdev->nocancel) {
+- sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1);
++ gs_sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1);
+ SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext);
+ ShowWindow(wdev->hDlgModeless, SW_SHOW);
+ }
+@@ -577,7 +577,7 @@ win_pr2_print_page(gx_device_printer * p
+
+ if (!wdev->nocancel) {
+ /* inform user of progress */
+- sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines));
++ gs_sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines));
+ SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext);
+ }
+ /* process message loop */
+@@ -1488,9 +1488,9 @@ win_pr2_print_setup_interaction(gx_devic
+
+ wdev->user_changed_settings = TRUE;
+ if (wdev->use_old_spool_name) {
+- sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
++ gs_sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
+ } else {
+- sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
++ gs_sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
+ }
+
+ if (mode == 3) {
+diff -up ghostscript-9.07/base/gdevxini.c.gs_sprintf ghostscript-9.07/base/gdevxini.c
+--- ghostscript-9.07/base/gdevxini.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gdevxini.c 2013-05-09 17:02:39.080447145 +0100
+@@ -377,7 +377,7 @@ gdev_x_open(gx_device_X * xdev)
+ char gstr[40];
+ int bitmask;
+
+- sprintf(gstr, "%dx%d+%d+%d", sizehints.width,
++ gs_sprintf(gstr, "%dx%d+%d+%d", sizehints.width,
+ sizehints.height, sizehints.x, sizehints.y);
+ bitmask = XWMGeometry(xdev->dpy, DefaultScreen(xdev->dpy),
+ xdev->geometry, gstr, xdev->borderWidth,
+diff -up ghostscript-9.07/base/gp_macio.c.gs_sprintf ghostscript-9.07/base/gp_macio.c
+--- ghostscript-9.07/base/gp_macio.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gp_macio.c 2013-05-09 17:02:39.080447145 +0100
+@@ -162,7 +162,7 @@ getenv(const char * env) {
+ convertSpecToPath(&pFile, fpath, 256);
+ // sprintf(fpath,"%s",fpath);
+ p = (char*)malloc((size_t) ( 4*strlen(fpath) + 40));
+- sprintf(p,"%s,%sGhostscript:lib,%sGhostscript:fonts",
++ gs_sprintf(p,"%s,%sGhostscript:lib,%sGhostscript:fonts",
+ (char *)&fpath[0],(char *)&fpath[0],
+ (char *)&fpath[0] );
+
+@@ -402,9 +402,9 @@ gp_open_scratch_file (const gs_memory_t
+ }
+ FSMakeFSSpec(foundVRefNum, foundDirID,thepfname, &fSpec);
+ convertSpecToPath(&fSpec, thefname, sizeof(thefname) - 1);
+- sprintf(fname,"%s",thefname);
++ gs_sprintf(fname,"%s",thefname);
+ } else {
+- sprintf((char*)&thefname[0],"%s\0",fname);
++ gs_sprintf((char*)&thefname[0],"%s\0",fname);
+ memmove((char*)&thepfname[1],(char *)&thefname[0],strlen(thefname));
+ thepfname[0]=strlen(thefname);
+ }
+@@ -535,9 +535,9 @@ gp_fopen (const char * fname, const char
+ //(*pgsdll_callback) (GSDLL_STDOUT, thefname, strlen(fname));
+ if ( strrchr(fname,':') == NULL )
+ // sprintf((char *)&thefname[0],"%s%s\0",g_homeDir,fname);
+- sprintf((char *)&thefname[0],"%s%s\0","",fname);
++ gs_sprintf((char *)&thefname[0],"%s%s\0","",fname);
+ else
+- sprintf((char*)&thefname[0],"%s\0",fname);
++ gs_sprintf((char*)&thefname[0],"%s\0",fname);
+
+ fid = fopen(thefname,mode);
+
+diff -up ghostscript-9.07/base/gp_mswin.c.gs_sprintf ghostscript-9.07/base/gp_mswin.c
+--- ghostscript-9.07/base/gp_mswin.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gp_mswin.c 2013-05-09 17:02:39.081447150 +0100
+@@ -316,7 +316,7 @@ get_queues(void)
+ char buf[256];
+
+ free(enumbuffer);
+- sprintf(buf, "EnumPrinters() failed, error code = %d", GetLastError());
++ gs_sprintf(buf, "EnumPrinters() failed, error code = %d", GetLastError());
+ MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
+ return NULL;
+ }
+@@ -423,7 +423,7 @@ gp_printfile_win32(const char *filename,
+ if (!gp_OpenPrinter(port, &printer)) {
+ char buf[256];
+
+- sprintf(buf, "OpenPrinter() failed for \042%s\042, error code = %d", port, GetLastError());
++ gs_sprintf(buf, "OpenPrinter() failed for \042%s\042, error code = %d", port, GetLastError());
+ MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
+ free(buffer);
+ return FALSE;
+@@ -436,7 +436,7 @@ gp_printfile_win32(const char *filename,
+ if (!StartDocPrinter(printer, 1, (LPBYTE) & di)) {
+ char buf[256];
+
+- sprintf(buf, "StartDocPrinter() failed, error code = %d", GetLastError());
++ gs_sprintf(buf, "StartDocPrinter() failed, error code = %d", GetLastError());
+ MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
+ AbortPrinter(printer);
+ free(buffer);
+@@ -457,7 +457,7 @@ gp_printfile_win32(const char *filename,
+ if (!EndDocPrinter(printer)) {
+ char buf[256];
+
+- sprintf(buf, "EndDocPrinter() failed, error code = %d", GetLastError());
++ gs_sprintf(buf, "EndDocPrinter() failed, error code = %d", GetLastError());
+ MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
+ AbortPrinter(printer);
+ return FALSE;
+@@ -465,7 +465,7 @@ gp_printfile_win32(const char *filename,
+ if (!ClosePrinter(printer)) {
+ char buf[256];
+
+- sprintf(buf, "ClosePrinter() failed, error code = %d", GetLastError());
++ gs_sprintf(buf, "ClosePrinter() failed, error code = %d", GetLastError());
+ MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
+ return FALSE;
+ }
+diff -up ghostscript-9.07/base/gp_wgetv.c.gs_sprintf ghostscript-9.07/base/gp_wgetv.c
+--- ghostscript-9.07/base/gp_wgetv.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gp_wgetv.c 2013-05-09 17:02:39.081447150 +0100
+@@ -181,9 +181,9 @@ gp_getenv(const char *name, char *ptr, i
+ char key[256];
+ char dotversion[16];
+
+- sprintf(dotversion, "%d.%02d", (int)(gs_revision / 100),
++ gs_sprintf(dotversion, "%d.%02d", (int)(gs_revision / 100),
+ (int)(gs_revision % 100));
+- sprintf(key, "Software\\%s\\%s", gs_productfamily, dotversion);
++ gs_sprintf(key, "Software\\%s\\%s", gs_productfamily, dotversion);
+ #else
+ wchar_t key[256];
+ wchar_t dotversion[16];
+@@ -224,7 +224,7 @@ gp_serialnumber(void)
+ #ifdef WINDOWS_NO_UNICODE
+ char key[256];
+
+- sprintf(key, "Software\\Microsoft\\MSLicensing\\HardwareID");
++ gs_sprintf(key, "Software\\Microsoft\\MSLicensing\\HardwareID");
+ #else /* WINDOWS_NO_UNICODE */
+ wchar_t key[256];
+
+diff -up ghostscript-9.07/base/gsalloc.c.gs_sprintf ghostscript-9.07/base/gsalloc.c
+--- ghostscript-9.07/base/gsalloc.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gsalloc.c 2013-05-09 17:02:39.081447150 +0100
+@@ -2045,7 +2045,7 @@ debug_dump_contents(const gs_memory_t *m
+ }
+ continue;
+ }
+- sprintf(label, "0x%lx:", (ulong) block);
++ gs_sprintf(label, "0x%lx:", (ulong) block);
+ debug_indent(mem, indent);
+ dmputs(mem, label);
+ for (i = 0; i < block_size; ++i) {
+diff -up ghostscript-9.07/base/gsdevice.c.gs_sprintf ghostscript-9.07/base/gsdevice.c
+--- ghostscript-9.07/base/gsdevice.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gsdevice.c 2013-05-09 17:02:39.082447154 +0100
+@@ -1011,11 +1011,11 @@ gx_device_open_output_file(const gx_devi
+ while (*fmt != 'l' && *fmt != '%')
+ --fmt;
+ if (*fmt == 'l')
+- sprintf(pfname, parsed.fname, count1);
++ gs_sprintf(pfname, parsed.fname, count1);
+ else
+- sprintf(pfname, parsed.fname, (int)count1);
++ gs_sprintf(pfname, parsed.fname, (int)count1);
+ } else if (parsed.len && strchr(parsed.fname, '%')) /* filename with "%%" but no "%nnd" */
+- sprintf(pfname, parsed.fname);
++ gs_sprintf(pfname, parsed.fname);
+ else
+ pfname[0] = 0; /* 0 to use "fname", not "pfname" */
+ if (pfname[0]) {
+diff -up ghostscript-9.07/base/gsdparam.c.gs_sprintf ghostscript-9.07/base/gsdparam.c
+--- ghostscript-9.07/base/gsdparam.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gsdparam.c 2013-05-09 17:02:39.082447154 +0100
+@@ -377,7 +377,7 @@ gdev_write_input_media(int index, gs_par
+ int code;
+ gs_param_string as;
+
+- sprintf(key, "%d", index);
++ gs_sprintf(key, "%d", index);
+ mdict.size = 4;
+ code = param_begin_write_dict(pdict->list, key, &mdict, false);
+ if (code < 0)
+@@ -465,7 +465,7 @@ gdev_write_output_media(int index, gs_pa
+ gs_param_dict mdict;
+ int code;
+
+- sprintf(key, "%d", index);
++ gs_sprintf(key, "%d", index);
+ mdict.size = 4;
+ code = param_begin_write_dict(pdict->list, key, &mdict, false);
+ if (code < 0)
+diff -up ghostscript-9.07/base/gsfcmap.c.gs_sprintf ghostscript-9.07/base/gsfcmap.c
+--- ghostscript-9.07/base/gsfcmap.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gsfcmap.c 2013-05-09 17:02:39.082447154 +0100
+@@ -567,7 +567,7 @@ gs_cmap_ToUnicode_alloc(gs_memory_t *mem
+ char sid[10], *pref = "aux-";
+ int sid_len, pref_len = strlen(pref);
+
+- sprintf(sid, "%d", id);
++ gs_sprintf(sid, "%d", id);
+ sid_len = strlen(sid);
+ name_len = pref_len + sid_len;
+ cmap_name = gs_alloc_string(mem, name_len, "gs_cmap_ToUnicode_alloc");
+diff -up ghostscript-9.07/base/gsicc_create.c.gs_sprintf ghostscript-9.07/base/gsicc_create.c
+--- ghostscript-9.07/base/gsicc_create.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gsicc_create.c 2013-05-09 17:02:39.083447158 +0100
+@@ -451,7 +451,7 @@ save_profile(unsigned char *buffer, char
+ char full_file_name[50];
+ FILE *fid;
+
+- sprintf(full_file_name,"%d)Profile_%s.icc",icc_debug_index,filename);
++ gs_sprintf(full_file_name,"%d)Profile_%s.icc",icc_debug_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fwrite(buffer,sizeof(unsigned char),buffer_size,fid);
+ fclose(fid);
+diff -up ghostscript-9.07/base/gsicc_manage.c.gs_sprintf ghostscript-9.07/base/gsicc_manage.c
+--- ghostscript-9.07/base/gsicc_manage.c.gs_sprintf 2013-05-09 17:02:39.043446986 +0100
++++ ghostscript-9.07/base/gsicc_manage.c 2013-05-09 17:02:39.083447158 +0100
+@@ -550,8 +550,8 @@ gsicc_set_srcgtag_struct(gsicc_manager_t
+ srcgtag = gsicc_new_srcgtag_profile(mem);
+ /* Now parse through the data opening the profiles that are needed */
+ /* First create the format that we should read for the key */
+- sprintf(str_format_key, "%%%ds", GSICC_SRCGTAG_MAX_KEY);
+- sprintf(str_format_file, "%%%ds", FILENAME_MAX);
++ gs_sprintf(str_format_key, "%%%ds", GSICC_SRCGTAG_MAX_KEY);
++ gs_sprintf(str_format_file, "%%%ds", FILENAME_MAX);
+ curr_ptr = buffer_ptr;
+ /* Initialize that we want color management. Then if profile is not
+ present we know we did not want anything special done with that
+@@ -1296,13 +1296,13 @@ gsicc_set_device_profile_colorants(gx_de
+ DEFAULT_ICC_PROCESS_LENGTH - 1; /* -1 due to no comma at end */
+ name_str = (char*) gs_alloc_bytes(dev->memory, total_len+1,
+ "gsicc_set_device_profile_colorants");
+- sprintf(name_str, DEFAULT_ICC_PROCESS);
++ gs_sprintf(name_str, DEFAULT_ICC_PROCESS);
+ for (kk = 0; kk < num_comps-5; kk++) {
+- sprintf(temp_str,"ICC_COLOR_%d,",kk);
++ gs_sprintf(temp_str,"ICC_COLOR_%d,",kk);
+ strcat(name_str,temp_str);
+ }
+ /* Last one no comma */
+- sprintf(temp_str,"ICC_COLOR_%d",kk);
++ gs_sprintf(temp_str,"ICC_COLOR_%d",kk);
+ strcat(name_str,temp_str);
+ }
+ str_len = strlen(name_str);
+@@ -2344,7 +2344,7 @@ dump_icc_buffer(int buffersize, char fil
+ char full_file_name[50];
+ FILE *fid;
+
+- sprintf(full_file_name,"%d)%s_debug.icc",global_icc_index,filename);
++ gs_sprintf(full_file_name,"%d)%s_debug.icc",global_icc_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fwrite(Buffer,sizeof(unsigned char),buffersize,fid);
+ fclose(fid);
+diff -up ghostscript-9.07/base/gsiodisk.c.gs_sprintf ghostscript-9.07/base/gsiodisk.c
+--- ghostscript-9.07/base/gsiodisk.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gsiodisk.c 2013-05-09 17:02:39.084447162 +0100
+@@ -415,7 +415,7 @@ MapFileOpen(const char * rootpath, const
+
+ if (strlen(rootpath) + strlen(filename) >= BUFFER_LENGTH)
+ return NULL;
+- sprintf(fullname, "%s%s", rootpath, filename);
++ gs_sprintf(fullname, "%s%s", rootpath, filename);
+ return gp_fopen(fullname, attributes);
+ }
+
+@@ -516,7 +516,7 @@ MapFileUnlink(const char * rootpath, con
+
+ if (strlen(rootpath) + strlen(filename) >= BUFFER_LENGTH)
+ return;
+- sprintf(fullname, "%s%s", rootpath, filename);
++ gs_sprintf(fullname, "%s%s", rootpath, filename);
+ unlink(fullname);
+ }
+
+@@ -537,8 +537,8 @@ MapFileRename(const char * rootpath, con
+ return;
+ if (strlen(rootpath) + strlen(newfilename) >= BUFFER_LENGTH)
+ return;
+- sprintf(oldfullname, "%s%s", rootpath, oldfilename);
+- sprintf(newfullname, "%s%s", rootpath, newfilename);
++ gs_sprintf(oldfullname, "%s%s", rootpath, oldfilename);
++ gs_sprintf(newfullname, "%s%s", rootpath, newfilename);
+ rename(oldfullname, newfullname);
+ }
+
+@@ -711,7 +711,7 @@ map_file_name_get(const char * root_name
+ if (d != -1) {
+ /* 20 characters are enough for even a 64 bit integer */
+ if ((strlen(root_name) + 20) < BUFFER_LENGTH) {
+- sprintf(osname, "%s%d", root_name, d);
++ gs_sprintf(osname, "%s%d", root_name, d);
+ return true;
+ }
+ }
+diff -up ghostscript-9.07/base/gs.mak.gs_sprintf ghostscript-9.07/base/gs.mak
+--- ghostscript-9.07/base/gs.mak.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gs.mak 2013-05-09 17:02:39.084447162 +0100
+@@ -239,6 +239,8 @@ LCUPSGENDIR=$(GLGENDIR)
+ LCUPSOBJDIR=$(GLOBJDIR)
+ LCUPSIGENDIR=$(GLGENDIR)
+ LCUPSIOBJDIR=$(GLOBJDIR)
++
++TRIOOBJDIR=$(GLOBJDIR)
+ #**************** END PATCHES
+
+ GSGEN=$(GLGENDIR)$(D)
+diff -up ghostscript-9.07/base/gspmdrv.c.gs_sprintf ghostscript-9.07/base/gspmdrv.c
+--- ghostscript-9.07/base/gspmdrv.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gspmdrv.c 2013-05-09 17:02:39.084447162 +0100
+@@ -345,11 +345,11 @@ write_profile(void)
+ {
+ char profile[64];
+
+- sprintf(profile, "%d %d", option.img_origin.x, option.img_origin.y);
++ gs_sprintf(profile, "%d %d", option.img_origin.x, option.img_origin.y);
+ PrfWriteProfileString(HINI_USERPROFILE, section, "Origin", profile);
+- sprintf(profile, "%d %d", option.img_size.x, option.img_size.y);
++ gs_sprintf(profile, "%d %d", option.img_size.x, option.img_size.y);
+ PrfWriteProfileString(HINI_USERPROFILE, section, "Size", profile);
+- sprintf(profile, "%d", option.img_max);
++ gs_sprintf(profile, "%d", option.img_max);
+ PrfWriteProfileString(HINI_USERPROFILE, section, "Maximized", profile);
+ }
+
+@@ -489,26 +489,26 @@ init_display(int argc, char *argv[])
+ find_hwnd_gs(argv[2]);
+
+ if (!rc) {
+- sprintf(name, SHARED_NAME, argv[2]);
++ gs_sprintf(name, SHARED_NAME, argv[2]);
+ rc = DosGetNamedSharedMem((PVOID *) & bitmap.pbmi, name, PAG_READ | PAG_WRITE);
+ if (rc) {
+- sprintf(buf, "Failed to open: bmp shared memory \"%s\" rc = %d", argv[0], rc);
++ gs_sprintf(buf, "Failed to open: bmp shared memory \"%s\" rc = %d", argv[0], rc);
+ error_message(buf);
+ }
+ }
+ if (!rc) {
+- sprintf(name, SYNC_NAME, argv[2]);
++ gs_sprintf(name, SYNC_NAME, argv[2]);
+ rc = DosOpenEventSem(name, &update_event_sem);
+ if (rc) {
+- sprintf(buf, "Failed to open: update event semaphore \"%s\" rc = %d", argv[1], rc);
++ gs_sprintf(buf, "Failed to open: update event semaphore \"%s\" rc = %d", argv[1], rc);
+ error_message(buf);
+ }
+ }
+ if (!rc) {
+- sprintf(name, MUTEX_NAME, argv[2]);
++ gs_sprintf(name, MUTEX_NAME, argv[2]);
+ rc = DosOpenMutexSem(name, &bmp_mutex_sem);
+ if (rc) {
+- sprintf(buf, "Failed to open: bmp mutex semaphore \"%s\" rc = %d", argv[1], rc);
++ gs_sprintf(buf, "Failed to open: bmp mutex semaphore \"%s\" rc = %d", argv[1], rc);
+ error_message(buf);
+ }
+ }
+@@ -535,19 +535,19 @@ init_bitmap(int argc, char *argv[])
+ if ((rc = DosOpen(argv[2], &hf, &action, 0, FILE_NORMAL, FILE_OPEN,
+ OPEN_ACCESS_READONLY | OPEN_SHARE_DENYREADWRITE, 0))
+ != (APIRET) 0) {
+- sprintf(buf, "Error opening: %s", argv[2]);
++ gs_sprintf(buf, "Error opening: %s", argv[2]);
+ error_message(buf);
+ return rc;
+ }
+ rc = DosSetFilePtr(hf, 0, FILE_END, &length);
+ if (rc) {
+- sprintf(buf, "failed seeking to EOF: error = %d", rc);
++ gs_sprintf(buf, "failed seeking to EOF: error = %d", rc);
+ error_message(buf);
+ return rc;
+ }
+ rc = DosSetFilePtr(hf, 0, FILE_BEGIN, &count);
+ if (rc) {
+- sprintf(buf, "failed seeking to BOF: error = %d", rc);
++ gs_sprintf(buf, "failed seeking to BOF: error = %d", rc);
+ error_message(buf);
+ return rc;
+ };
+@@ -555,14 +555,14 @@ init_bitmap(int argc, char *argv[])
+ /* allocate memory for bitmap */
+ if ((rc = DosAllocMem((PPVOID) & bbuffer, length, PAG_READ | PAG_WRITE | PAG_COMMIT))
+ != (APIRET) 0) {
+- sprintf(buf, "failed allocating memory");
++ gs_sprintf(buf, "failed allocating memory");
+ error_message(buf);
+ return rc;
+ }
+ rc = DosRead(hf, bbuffer, length, &count);
+ DosClose(hf);
+ if (rc) {
+- sprintf(buf, "failed reading bitmap, error = %u, count = %u", rc, count);
++ gs_sprintf(buf, "failed reading bitmap, error = %u, count = %u", rc, count);
+ error_message(buf);
+ return rc;
+ }
+@@ -573,7 +573,7 @@ init_bitmap(int argc, char *argv[])
+ scan_bitmap(&bitmap);
+ bitmap.valid = TRUE;
+
+- sprintf(buf, "bitmap width = %d, height = %d", bitmap.width, bitmap.height);
++ gs_sprintf(buf, "bitmap width = %d, height = %d", bitmap.width, bitmap.height);
+ message_box(buf, 0);
+ return rc;
+ }
+@@ -805,7 +805,7 @@ make_bitmap(BMAP * pbm, ULONG left, ULON
+ char buf[256];
+
+ eid = WinGetLastError(hab);
+- sprintf(buf, "make_bitmap: GpiDrawBits rc = %08x, eid = %08x", rc, eid);
++ gs_sprintf(buf, "make_bitmap: GpiDrawBits rc = %08x, eid = %08x", rc, eid);
+ message_box(buf, 0);
+ }
+ }
+diff -up ghostscript-9.07/base/gssprintf.c.gs_sprintf ghostscript-9.07/base/gssprintf.c
+--- ghostscript-9.07/base/gssprintf.c.gs_sprintf 2013-05-09 17:02:39.085447167 +0100
++++ ghostscript-9.07/base/gssprintf.c 2013-05-09 17:02:39.084447162 +0100
+@@ -0,0 +1,60 @@
++/* Copyright (C) 2001-2012 Artifex Software, Inc.
++ All Rights Reserved.
++
++ This software is provided AS-IS with no warranty, either express or
++ implied.
++
++ This software is distributed under license and may not be copied,
++ modified or distributed except as expressly authorized under the terms
++ of the license contained in the file LICENSE in this distribution.
++
++ Refer to licensing information at http://www.artifex.com or contact
++ Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
++ CA 94903, U.S.A., +1(415)492-9861, for further information.
++*/
++
++
++/* Simple interface to a sprintf/sscanf without locale */
++#include "gssprintf.h"
++#include "trio.h"
++#include "triop.h"
++#include "triodef.h"
++#include "trionan.h"
++#include "triostr.h"
++
++int
++gs_vsnprintf(char *buf, int n, const char *format, va_list ap)
++{
++ return(trio_vsnprintf(buf, n, format, ap));
++}
++
++int
++gs_snprintf(char *buf, int n, const char *format, ...)
++{
++ int len;
++ va_list ap;
++
++ va_start(ap, format);
++ len = trio_vsnprintf(buf, n, format, ap);
++ va_end(ap);
++ return len;
++}
++
++int
++gs_vsprintf(char *buf, const char *format, va_list ap)
++{
++ return(trio_vsprintf(buf, format, ap));
++}
++
++int
++gs_sprintf(char *buf, const char *format, ...)
++{
++ int len;
++ va_list ap;
++
++ va_start(ap, format);
++ len = trio_vsprintf(buf, format, ap);
++ va_end(ap);
++
++ return(len);
++}
+diff -up ghostscript-9.07/base/gssprintf.h.gs_sprintf ghostscript-9.07/base/gssprintf.h
+--- ghostscript-9.07/base/gssprintf.h.gs_sprintf 2013-05-09 17:02:39.085447167 +0100
++++ ghostscript-9.07/base/gssprintf.h 2013-05-09 17:02:39.085447167 +0100
+@@ -0,0 +1,33 @@
++/* Copyright (C) 2001-2012 Artifex Software, Inc.
++ All Rights Reserved.
++
++ This software is provided AS-IS with no warranty, either express or
++ implied.
++
++ This software is distributed under license and may not be copied,
++ modified or distributed except as expressly authorized under the terms
++ of the license contained in the file LICENSE in this distribution.
++
++ Refer to licensing information at http://www.artifex.com or contact
++ Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
++ CA 94903, U.S.A., +1(415)492-9861, for further information.
++*/
++
++#ifndef gssprintf_INCLUDED
++# define gssprintf_INCLUDED
++
++#include <stdarg.h>
++
++int
++gs_vsnprintf(char *zBuf, int n, const char *zFormat, va_list ap);
++
++int
++gs_snprintf(char *zBuf, int n, const char *zFormat, ...);
++
++int
++gs_vsprintf(char *zBuf, const char *zFormat, va_list ap);
++
++int
++gs_sprintf(char *zBuf, const char *zFormat, ...);
++
++#endif
+diff -up ghostscript-9.07/base/gxblend1.c.gs_sprintf ghostscript-9.07/base/gxblend1.c
+--- ghostscript-9.07/base/gxblend1.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gxblend1.c 2013-05-09 17:02:39.085447167 +0100
+@@ -643,7 +643,7 @@ dump_planar_rgba(gs_memory_t *mem, const
+ info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+
+ /* add comment */
+- sprintf(software_text, "%s %d.%02d", gs_product,
++ gs_sprintf(software_text, "%s %d.%02d", gs_product,
+ (int)(gs_revision / 100), (int)(gs_revision % 100));
+ text_png.compression = -1; /* uncompressed */
+ text_png.key = (char *)software_key; /* not const, unfortunately */
+diff -up ghostscript-9.07/base/gxblend.c.gs_sprintf ghostscript-9.07/base/gxblend.c
+--- ghostscript-9.07/base/gxblend.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gxblend.c 2013-05-09 17:02:39.085447167 +0100
+@@ -1573,7 +1573,7 @@ dump_raw_buffer(int num_rows, int width,
+ /* FIXME: GRAY + ALPHA + SHAPE + TAGS will be interpreted as RGB + ALPHA */
+ if ((n_chan == 2) || (n_chan == 3)) {
+ int x;
+- sprintf(full_file_name,"%02d)%s.pam",global_index,filename);
++ gs_sprintf(full_file_name,"%02d)%s.pam",global_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fprintf(fid, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE GRAYSCALE_ALPHA\nENDHDR\n",
+ width, num_rows);
+@@ -1583,7 +1583,7 @@ dump_raw_buffer(int num_rows, int width,
+ fputc(Buffer[z*plane_stride + y*rowstride + x], fid);
+ fclose(fid);
+ if (n_chan == 3) {
+- sprintf(full_file_name,"%02d)%s_shape.pam",global_index,filename);
++ gs_sprintf(full_file_name,"%02d)%s_shape.pam",global_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fprintf(fid, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 1\nMAXVAL 255\nTUPLTYPE GRAYSCALE\nENDHDR\n",
+ width, num_rows);
+@@ -1595,7 +1595,7 @@ dump_raw_buffer(int num_rows, int width,
+ }
+ if ((n_chan == 4) || (n_chan == 5) || (n_chan == 6)) {
+ int x;
+- sprintf(full_file_name,"%02d)%s.pam",global_index,filename);
++ gs_sprintf(full_file_name,"%02d)%s.pam",global_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fprintf(fid, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
+ width, num_rows);
+@@ -1605,7 +1605,7 @@ dump_raw_buffer(int num_rows, int width,
+ fputc(Buffer[z*plane_stride + y*rowstride + x], fid);
+ fclose(fid);
+ if (n_chan > 4) {
+- sprintf(full_file_name,"%02d)%s_shape.pam",global_index,filename);
++ gs_sprintf(full_file_name,"%02d)%s_shape.pam",global_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fprintf(fid, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 1\nMAXVAL 255\nTUPLTYPE GRAYSCALE\nENDHDR\n",
+ width, num_rows);
+@@ -1615,7 +1615,7 @@ dump_raw_buffer(int num_rows, int width,
+ fclose(fid);
+ }
+ if (n_chan == 6) {
+- sprintf(full_file_name,"%02d)%s_tags.pam",global_index,filename);
++ gs_sprintf(full_file_name,"%02d)%s_tags.pam",global_index,filename);
+ fid = fopen(full_file_name,"wb");
+ fprintf(fid, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 1\nMAXVAL 255\nTUPLTYPE GRAYSCALE\nENDHDR\n",
+ width, num_rows);
+@@ -1628,7 +1628,7 @@ dump_raw_buffer(int num_rows, int width,
+ }
+ #endif
+ max_bands = ( n_chan < 57 ? n_chan : 56); /* Photoshop handles at most 56 bands */
+- sprintf(full_file_name,"%02d)%s_%dx%dx%d.raw",global_index,filename,width,num_rows,max_bands);
++ gs_sprintf(full_file_name,"%02d)%s_%dx%dx%d.raw",global_index,filename,width,num_rows,max_bands);
+ fid = fopen(full_file_name,"wb");
+
+ for (z = 0; z < max_bands; ++z) {
+diff -up ghostscript-9.07/base/gxclmem.c.gs_sprintf ghostscript-9.07/base/gxclmem.c
+--- ghostscript-9.07/base/gxclmem.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gxclmem.c 2013-05-09 17:02:39.086447171 +0100
+@@ -401,7 +401,7 @@ memfile_fopen(char fname[gp_file_name_si
+
+ /* Return the address of this memfile as a string for use in future clist_fopen calls */
+ fname[0] = 0xff; /* a flag that this is a memfile name */
+- sprintf(fname+1, "%p", f);
++ gs_sprintf(fname+1, "%p", f);
+
+ #ifdef DEBUG
+ tot_compressed = 0;
+diff -up ghostscript-9.07/base/gxhintn.c.gs_sprintf ghostscript-9.07/base/gxhintn.c
+--- ghostscript-9.07/base/gxhintn.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gxhintn.c 2013-05-09 17:02:39.086447171 +0100
+@@ -387,7 +387,7 @@ static void t1_hinter__paint_glyph(t1_hi
+
+ for(j = beg_pole; j <= end_pole; j++) {
+ vd_circle(X(j), Y(j), 3, RGB(0,0,255));
+- sprintf(buf, "%d", j);
++ gs_sprintf(buf, "%d", j);
+ vd_text(self->pole[j].gx, self->pole[j].gy, buf, RGB(0,0,0));
+ if (self->pole[j + 1].type == offcurve)
+ j+=2;
+diff -up ghostscript-9.07/base/gxpath.c.gs_sprintf ghostscript-9.07/base/gxpath.c
+--- ghostscript-9.07/base/gxpath.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gxpath.c 2013-05-09 17:02:39.086447171 +0100
+@@ -1035,7 +1035,7 @@ gx_print_segment(const gs_memory_t *mem,
+ double py = fixed2float(pseg->pt.y);
+ char out[80];
+
+- sprintf(out, "0x%lx<0x%lx,0x%lx>:%u",
++ gs_sprintf(out, "0x%lx<0x%lx,0x%lx>:%u",
+ (ulong) pseg, (ulong) pseg->prev, (ulong) pseg->next, pseg->notes);
+ switch (pseg->type) {
+ case s_start:{
+diff -up ghostscript-9.07/base/gxpcmap.c.gs_sprintf ghostscript-9.07/base/gxpcmap.c
+--- ghostscript-9.07/base/gxpcmap.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/gxpcmap.c 2013-05-09 17:02:39.087447175 +0100
+@@ -1147,10 +1147,10 @@ dump_raw_pattern(int height, int width,
+ is_planar = dev_proc(mdev, dev_spec_op)(mdev, gxdso_is_native_planar, NULL, 0) > 0;
+ max_bands = ( n_chan < 57 ? n_chan : 56); /* Photoshop handles at most 56 bands */
+ if (is_planar) {
+- sprintf(full_file_name,"%d)PATTERN_PLANE_%dx%dx%d.raw",global_pat_index,
++ gs_sprintf(full_file_name,"%d)PATTERN_PLANE_%dx%dx%d.raw",global_pat_index,
+ width,height,max_bands);
+ } else {
+- sprintf(full_file_name,"%d)PATTERN_CHUNK_%dx%dx%d.raw",global_pat_index,
++ gs_sprintf(full_file_name,"%d)PATTERN_CHUNK_%dx%dx%d.raw",global_pat_index,
+ width,height,max_bands);
+ }
+ fid = fopen(full_file_name,"wb");
+diff -up ghostscript-9.07/base/lib.mak.gs_sprintf ghostscript-9.07/base/lib.mak
+--- ghostscript-9.07/base/lib.mak.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/lib.mak 2013-05-09 17:02:39.088447180 +0100
+@@ -98,6 +98,9 @@ std_h=$(GLSRC)std.h $(arch_h) $(stdpre_h
+
+ vmsmath_h=$(GLSRC)vmsmath.h
+
++# declare here for use by string__h
++gssprintf_h=$(GLSRC)gssprintf.h
++
+ dos__h=$(GLSRC)dos_.h
+ ctype__h=$(GLSRC)ctype_.h $(std_h)
+ dirent__h=$(GLSRC)dirent_.h $(std_h) $(gconfig__h)
+@@ -110,7 +113,7 @@ math__h=$(GLSRC)math_.h $(std_h) $(vmsma
+ memory__h=$(GLSRC)memory_.h $(std_h)
+ setjmp__h=$(GLSRC)setjmp_.h
+ stat__h=$(GLSRC)stat_.h $(std_h)
+-stdio__h=$(GLSRC)stdio_.h $(std_h)
++stdio__h=$(GLSRC)stdio_.h $(std_h) $(gssprintf_h)
+ string__h=$(GLSRC)string_.h $(std_h)
+ time__h=$(GLSRC)time_.h $(std_h) $(gconfig__h)
+ unistd__h=$(GLSRC)unistd_.h $(std_h)
+@@ -151,6 +154,7 @@ gx_h=$(GLSRC)gx.h $(stdio__h) $(gdebug_h
+ $(gsio_h) $(gsmemory_h) $(gstypes_h) $(gserrors_h)
+ gxsync_h=$(GLSRC)gxsync.h $(gpsync_h) $(gsmemory_h)
+ gxclthrd_h=$(GLSRC)gxclthrd.h $(gxsync_h)
++
+ # Out of order
+ gsmemlok_h=$(GLSRC)gsmemlok.h $(gsmemory_h) $(gxsync_h)
+ gsnotify_h=$(GLSRC)gsnotify.h $(gsstype_h)
+@@ -320,6 +324,10 @@ $(AUX)gsutil.$(OBJ) : $(GLSRC)gsutil.c $
+ $(gsrect_h) $(gsuid_h) $(gsutil_h) $(gzstate_h) $(gxdcolor_h) $(MAKEDIRS)
+ $(GLCCAUX) $(AUXO_)gsutil.$(OBJ) $(C_) $(GLSRC)gsutil.c
+
++$(GLOBJ)gssprintf.$(OBJ) : $(GLSRC)gssprintf.c $(gssprintf_h) $(triodef_h) $(trio_h) \
++$(triop_h) $(triostr_h) $(trionan_h)
++ $(GLCC) $(I_)$(TRIOSRCDIR)$(_I) $(GLO_)gssprintf.$(OBJ) $(C_) $(GLSRC)gssprintf.c
++
+ # MD5 digest
+ md5_h=$(GLSRC)md5.h
+ # We have to use a slightly different compilation approach in order to
+@@ -1309,7 +1317,7 @@ LIB10s=$(GLOBJ)gsmalloc.$(OBJ) $(GLOBJ)m
+ LIB11s=$(GLOBJ)gsmemory.$(OBJ) $(GLOBJ)gsmemret.$(OBJ) $(GLOBJ)gsmisc.$(OBJ) $(GLOBJ)gsnotify.$(OBJ) $(GLOBJ)gslibctx.$(OBJ)
+ LIB12s=$(GLOBJ)gspaint.$(OBJ) $(GLOBJ)gsparam.$(OBJ) $(GLOBJ)gspath.$(OBJ)
+ LIB13s=$(GLOBJ)gsserial.$(OBJ) $(GLOBJ)gsstate.$(OBJ) $(GLOBJ)gstext.$(OBJ)\
+- $(GLOBJ)gsutil.$(OBJ)
++ $(GLOBJ)gsutil.$(OBJ) $(TRIOOBJS) $(GLOBJ)gssprintf.$(OBJ)
+ LIB1x=$(GLOBJ)gxacpath.$(OBJ) $(GLOBJ)gxbcache.$(OBJ) $(GLOBJ)gxccache.$(OBJ)
+ LIB2x=$(GLOBJ)gxccman.$(OBJ) $(GLOBJ)gxchar.$(OBJ) $(GLOBJ)gxcht.$(OBJ)
+ LIB3x=$(GLOBJ)gxclip.$(OBJ) $(GLOBJ)gxcmap.$(OBJ) $(GLOBJ)gxcpath.$(OBJ)
+diff -up ghostscript-9.07/base/md5main.c.gs_sprintf ghostscript-9.07/base/md5main.c
+--- ghostscript-9.07/base/md5main.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/md5main.c 2013-05-09 17:02:39.088447180 +0100
+@@ -87,7 +87,7 @@ do_test(void)
+ gs_md5_append(&state, (const gs_md5_byte_t *)test[i], strlen(test[i]));
+ gs_md5_finish(&state, digest);
+ for (di = 0; di < 16; ++di)
+- sprintf(hex_output + di * 2, "%02x", digest[di]);
++ gs_sprintf(hex_output + di * 2, "%02x", digest[di]);
+ if (strcmp(hex_output, test[i + 1])) {
+ printf("MD5 (\"%s\") = ", test[i]);
+ puts(hex_output);
+diff -up ghostscript-9.07/base/mkromfs.c.gs_sprintf ghostscript-9.07/base/mkromfs.c
+--- ghostscript-9.07/base/mkromfs.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/mkromfs.c 2013-05-09 17:02:39.088447180 +0100
+@@ -64,6 +64,8 @@
+ *
+ */
+
++/* prevent gp.h redefining sprintf */
++#define sprintf sprintf
+ #include "stdpre.h"
+ #include "stdint_.h"
+ #include "time_.h"
+diff -up ghostscript-9.07/base/sdcparam.c.gs_sprintf ghostscript-9.07/base/sdcparam.c
+--- ghostscript-9.07/base/sdcparam.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/sdcparam.c 2013-05-09 17:02:39.088447180 +0100
+@@ -200,7 +200,7 @@ s_DCT_get_quantization_tables(gs_param_l
+ gs_param_string str;
+ gs_param_float_array fa;
+
+- sprintf(key, "%d", i);
++ gs_sprintf(key, "%d", i);
+ if (QFactor == 1.0) {
+ code = quant_param_string(&str, DCTSIZE2,
+ table_ptrs[comp_info[i].quant_tbl_no]->quantval,
+@@ -474,7 +474,7 @@ s_DCT_put_quantization_tables(gs_param_l
+ char istr[5]; /* i converted to string key */
+ UINT16 values[DCTSIZE2];
+
+- sprintf(istr, "%d", i);
++ gs_sprintf(istr, "%d", i);
+ code = quant_params(quant_tables.list, istr, DCTSIZE2, values,
+ pdct->QFactor);
+ if (code < 0)
+@@ -566,7 +566,7 @@ s_DCT_put_huffman_tables(gs_param_list *
+ UINT8 counts[16], values[256];
+
+ /* Collect the Huffman parameters. */
+- sprintf(istr, "%d", i);
++ gs_sprintf(istr, "%d", i);
+ code = s_DCT_byte_params(huff_tables.list, istr, 0, 16, counts);
+ if (code < 0)
+ return code;
+diff -up ghostscript-9.07/base/sjbig2.c.gs_sprintf ghostscript-9.07/base/sjbig2.c
+--- ghostscript-9.07/base/sjbig2.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/sjbig2.c 2013-05-09 17:02:39.089447184 +0100
+@@ -65,7 +65,7 @@ s_jbig2decode_error(void *error_callback
+ default: type = "unknown message:"; break;;
+ }
+ if (seg_idx == -1) segment[0] = '\0';
+- else sprintf(segment, "(segment 0x%02x)", seg_idx);
++ else gs_sprintf(segment, "(segment 0x%02x)", seg_idx);
+
+ if (state)
+ {
+diff -up ghostscript-9.07/base/spprint.c.gs_sprintf ghostscript-9.07/base/spprint.c
+--- ghostscript-9.07/base/spprint.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/spprint.c 2013-05-09 17:02:39.089447184 +0100
+@@ -83,7 +83,7 @@ pprintd1(stream * s, const char *format,
+ if (*fp == 0 || fp[1] != 'd') /* shouldn't happen! */
+ lprintf1("Bad format in pprintd1: %s\n", format);
+ #endif
+- sprintf(str, "%d", v);
++ gs_sprintf(str, "%d", v);
+ pputs_short(s, str);
+ return pprintf_scan(s, fp + 2);
+ }
+@@ -115,12 +115,12 @@ pprintg1(stream * s, const char *format,
+ if (*fp == 0 || fp[1] != 'g') /* shouldn't happen! */
+ lprintf1("Bad format in pprintg: %s\n", format);
+ #endif
+- sprintf(str, "%f", 1.5);
++ gs_sprintf(str, "%f", 1.5);
+ dot = str[1]; /* locale-dependent */
+- sprintf(str, "%g", v);
++ gs_sprintf(str, "%g", v);
+ if (strchr(str, 'e')) {
+ /* Bad news. Try again using f-format. */
+- sprintf(str, (fabs(v) > 1 ? "%1.1f" : "%1.8f"), v);
++ gs_sprintf(str, (fabs(v) > 1 ? "%1.1f" : "%1.8f"), v);
+ }
+ /* Juggling locales isn't thread-safe. Posix me harder. */
+ if (dot != '.') {
+@@ -165,7 +165,7 @@ pprintld1(stream * s, const char *format
+ if (*fp == 0 || fp[1] != 'l' || fp[2] != 'd') /* shouldn't happen! */
+ lprintf1("Bad format in pprintld: %s\n", format);
+ #endif
+- sprintf(str, "%ld", v);
++ gs_sprintf(str, "%ld", v);
+ pputs_short(s, str);
+ return pprintf_scan(s, fp + 3);
+ }
+diff -up ghostscript-9.07/base/trio.mak.gs_sprintf ghostscript-9.07/base/trio.mak
+--- ghostscript-9.07/base/trio.mak.gs_sprintf 2013-05-09 17:02:39.089447184 +0100
++++ ghostscript-9.07/base/trio.mak 2013-05-09 17:02:39.089447184 +0100
+@@ -0,0 +1,57 @@
++# Copyright (C) 2001-2012 Artifex Software, Inc.
++# All Rights Reserved.
++#
++# This software is provided AS-IS with no warranty, either express or
++# implied.
++#
++# This software is distributed under license and may not be copied,
++# modified or distributed except as expressly authorized under the terms
++# of the license contained in the file LICENSE in this distribution.
++#
++# Refer to licensing information at http://www.artifex.com or contact
++# Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
++# CA 94903, U.S.A., +1(415)492-9861, for further information.
++#
++# makefile for trio - locale-less s(n)printf/s(n)canf
++#
++# Users of this makefile must define the following:
++# TRIO_CFLAGS - Compiler flags for building the source,
++# TRIOSRCDIR - the expat source top-level directory,
++# TIOOBJDIR - directory for object files.
++
++# Define the name of this makefile
++TRIO_MAK=$(GLSRCDIR)$(D)trio.mak
++
++# local aliases
++TRIOSRC=$(TRIOSRCDIR)$(D)
++TRIOOBJ=$(TRIOOBJDIR)$(D)
++TRIOO_=$(O_)$(TRIOOBJ)
++
++TRIOCFLAGS=$(CFLAGS) $(TRIO_CFLAGS) $(D_)TRIO_EMBED_STRING$(_D) $(D_)TRIO_FEATURE_CLOSURE=0$(_D) \
++$(D_)TRIO_FEATURE_DYNAMICSTRING=0$(_D) $(D_)TRIO_MINIMAL=0$(_D) \
++$(D_)TRIO_FEATURE_USER_DEFINED=0$(_D) $(D_)TRIO_EXTENSION=0$(_D)\
++$(D_)TRIO_FUNC_TO_FLOAT$(_D) $(I_)$(TRIOSRCDIR)$(_I) \
++$(D_)TRIO_MALLOC=no_malloc$(_D) $(D_)TRIO_REALLOC=no_realloc$(_D) $(D_)TRIO_FREE=no_free$(_D)
++
++
++# NB: we can't use the normal $(CC_) here because msvccmd.mak
++# adds /Za which conflicts with the trio source.
++TRIOCC=$(CC) $(TRIOCFLAGS)
++
++TRIOOBJS=$(TRIOOBJ)triostr.$(OBJ) $(TRIOOBJ)trio.$(OBJ) $(TRIOOBJ)trionan.$(OBJ)
++
++triodef_h=$(TRIOSRC)triodef.h
++trio_h=$(TRIOSRC)trio.h
++triop_h=$(TRIOSRC)triop.h
++triostr_h=$(TRIOSRC)triostr.h
++
++TRIOHDRS=$(triodef_h) $(trio_h) $(triop_h) $(triostr_h)
++
++$(TRIOOBJ)triostr.$(OBJ) : $(TRIOSRC)triostr.c $(TRIOHDRS) $(TRIO_MAK)
++ $(TRIOCC) $(TRIOO_)triostr.$(OBJ) $(C_) $(TRIOSRC)triostr.c
++
++$(TRIOOBJ)trio.$(OBJ) : $(TRIOSRC)trio.c $(TRIOHDRS) $(TRIO_MAK)
++ $(TRIOCC) $(TRIOO_)trio.$(OBJ) $(C_) $(TRIOSRC)trio.c
++
++$(TRIOOBJ)trionan.$(OBJ) : $(TRIOSRC)trionan.c $(TRIOHDRS) $(TRIO_MAK)
++ $(TRIOCC) $(TRIOO_)trionan.$(OBJ) $(C_) $(TRIOSRC)trionan.c
+diff -up ghostscript-9.07/base/unixansi.mak.gs_sprintf ghostscript-9.07/base/unixansi.mak
+--- ghostscript-9.07/base/unixansi.mak.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/unixansi.mak 2013-05-09 17:02:39.089447184 +0100
+@@ -152,6 +152,8 @@ TIFFPLATFORM=unix
+ TIFFCONFIG_SUFFIX=.unix
+ LIBTIFF_NAME=tiff
+
++TRIOSRCDIR=trio
++
+ # Define the directory where the zlib sources are stored.
+ # See zlib.mak for more information.
+
+@@ -392,6 +394,7 @@ CC_SHARED=$(CC_)
+
+ include $(GLSRCDIR)/unixhead.mak
+ include $(GLSRCDIR)/gs.mak
++include $(GLSRCDIR)/trio.mak
+ # psromfs.mak must precede lib.mak
+ include $(PSSRCDIR)/psromfs.mak
+ include $(GLSRCDIR)/lib.mak
+diff -up ghostscript-9.07/base/unix-gcc.mak.gs_sprintf ghostscript-9.07/base/unix-gcc.mak
+--- ghostscript-9.07/base/unix-gcc.mak.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/unix-gcc.mak 2013-05-09 17:02:39.089447184 +0100
+@@ -165,6 +165,8 @@ TIFFPLATFORM=unix
+ TIFFCONFIG_SUFFIX=.unix
+ LIBTIFF_NAME=tiff
+
++TRIOSRCDIR=trio
++
+ # Define the directory where the zlib sources are stored.
+ # See zlib.mak for more information.
+
+@@ -461,6 +463,7 @@ MAKEDIRSTOP=directories
+
+ include $(GLSRCDIR)/unixhead.mak
+ include $(GLSRCDIR)/gs.mak
++include $(GLSRCDIR)/trio.mak
+ # psromfs.mak must precede lib.mak
+ include $(PSSRCDIR)/psromfs.mak
+ include $(GLSRCDIR)/lib.mak
+diff -up ghostscript-9.07/base/winlib.mak.gs_sprintf ghostscript-9.07/base/winlib.mak
+--- ghostscript-9.07/base/winlib.mak.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/winlib.mak 2013-05-09 17:02:39.090447188 +0100
+@@ -133,6 +133,7 @@ BEGINFILES=$(GLGENDIR)\ccf32.tr\
+ #!include $(COMMONDIR)/pcdefs.mak
+ #!include $(COMMONDIR)/generic.mak
+ !include $(GLSRCDIR)\gs.mak
++!include $(GLSRCDIR)\trio.mak
+ !include $(GLSRCDIR)\lib.mak
+ !include $(GLSRCDIR)\freetype.mak
+ !if "$(UFST_BRIDGE)"=="1"
+diff -up ghostscript-9.07/base/wrfont.c.gs_sprintf ghostscript-9.07/base/wrfont.c
+--- ghostscript-9.07/base/wrfont.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/wrfont.c 2013-05-09 17:02:39.090447188 +0100
+@@ -72,7 +72,7 @@ WRF_wfloat(WRF_output * a_output, double
+ {
+ char buffer[32];
+
+- sprintf(buffer, "%f", a_float);
++ gs_sprintf(buffer, "%f", a_float);
+ WRF_wstring(a_output, buffer);
+ }
+
+@@ -81,6 +81,6 @@ WRF_wint(WRF_output * a_output, long a_i
+ {
+ char buffer[32];
+
+- sprintf(buffer, "%ld", a_int);
++ gs_sprintf(buffer, "%ld", a_int);
+ WRF_wstring(a_output, buffer);
+ }
+diff -up ghostscript-9.07/base/write_t1.c.gs_sprintf ghostscript-9.07/base/write_t1.c
+--- ghostscript-9.07/base/write_t1.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/write_t1.c 2013-05-09 17:02:39.090447188 +0100
+@@ -300,7 +300,7 @@ write_main_dictionary(gs_fapi_font * a_f
+ if (x)
+ entries++;
+
+- sprintf(Buffer, "/FontInfo %d dict dup begin\n", entries);
++ gs_sprintf(Buffer, "/FontInfo %d dict dup begin\n", entries);
+ WRF_wstring(a_output, Buffer);
+ x = a_fapi_font->get_word(a_fapi_font,
+ gs_fapi_font_feature_BlendAxisTypes_count,
+@@ -330,7 +330,7 @@ write_main_dictionary(gs_fapi_font * a_f
+ x1 = a_fapi_font->get_float(a_fapi_font,
+ gs_fapi_font_feature_BlendDesignPositionsArrayValue,
+ i * 8 + j);
+- sprintf(Buffer, "%f ", x1);
++ gs_sprintf(Buffer, "%f ", x1);
+ WRF_wstring(a_output, Buffer);
+ }
+ WRF_wstring(a_output, "]");
+@@ -352,12 +352,12 @@ write_main_dictionary(gs_fapi_font * a_f
+ x1 = a_fapi_font->get_float(a_fapi_font,
+ gs_fapi_font_feature_BlendDesignPositionsArrayValue,
+ i * 64 + j * 64);
+- sprintf(Buffer, "%f ", x1);
++ gs_sprintf(Buffer, "%f ", x1);
+ WRF_wstring(a_output, Buffer);
+ x1 = a_fapi_font->get_float(a_fapi_font,
+ gs_fapi_font_feature_BlendDesignPositionsArrayValue,
+ i * 64 + j * 64 + 1);
+- sprintf(Buffer, "%f ", x1);
++ gs_sprintf(Buffer, "%f ", x1);
+ WRF_wstring(a_output, Buffer);
+ WRF_wstring(a_output, "]");
+ }
+@@ -397,7 +397,7 @@ write_main_dictionary(gs_fapi_font * a_f
+ for (i = 0; i < x; i++) {
+ x1 = a_fapi_font->get_float(a_fapi_font,
+ gs_fapi_font_feature_WeightVector, i);
+- sprintf(Buffer, "%f ", x1);
++ gs_sprintf(Buffer, "%f ", x1);
+ WRF_wstring(a_output, Buffer);
+ }
+ WRF_wstring(a_output, "] def\n");
+diff -up ghostscript-9.07/base/write_t2.c.gs_sprintf ghostscript-9.07/base/write_t2.c
+--- ghostscript-9.07/base/write_t2.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/base/write_t2.c 2013-05-09 17:02:39.090447188 +0100
+@@ -70,7 +70,7 @@ write_type2_float(WRF_output * a_output,
+ int high = true;
+ char c = 0;
+
+- sprintf(buffer, "%f", a_float);
++ gs_sprintf(buffer, "%f", a_float);
+ WRF_wbyte(a_output, 30);
+ for (;;) {
+ char n = 0;
+diff -up ghostscript-9.07/contrib/eplaser/gdevescv.c.gs_sprintf ghostscript-9.07/contrib/eplaser/gdevescv.c
+--- ghostscript-9.07/contrib/eplaser/gdevescv.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/eplaser/gdevescv.c 2013-05-09 17:02:39.091447193 +0100
+@@ -545,7 +545,7 @@ escv_vector_dopath(gx_device_vector * vd
+ y = fixed2float(vs[1]) / scale.y;
+
+ /* ¥µ¥Ö¥Ñ¥¹³«»ÏÌ¿Îá p1 */
+- (void)sprintf(obuf, ESC_GS "0;%d;%dmvpG", (int)x, (int)y);
++ (void)gs_sprintf(obuf, ESC_GS "0;%d;%dmvpG", (int)x, (int)y);
+ lputs(s, obuf);
+
+ if (first)
+@@ -556,11 +556,11 @@ escv_vector_dopath(gx_device_vector * vd
+ cnt = 1;
+ for (pseg = cenum.pseg; pseg != 0 && pseg->type == s_line; cnt++, pseg = pseg->next);
+
+- (void)sprintf(obuf, ESC_GS "0;%d", cnt);
++ (void)gs_sprintf(obuf, ESC_GS "0;%d", cnt);
+ lputs(s, obuf);
+
+ do {
+- (void)sprintf(obuf, ";%d;%d",
++ (void)gs_sprintf(obuf, ";%d;%d",
+ (int)(fixed2float(vs[0]) / scale.x),
+ (int)(fixed2float(vs[1]) / scale.y));
+ lputs(s, obuf);
+@@ -577,11 +577,11 @@ escv_vector_dopath(gx_device_vector * vd
+ case gs_pe_curveto:
+ cnt = 1;
+ for (pseg = cenum.pseg; pseg != 0 && pseg->type == s_curve; cnt++, pseg = pseg->next);
+- (void)sprintf(obuf, ESC_GS "0;%d", cnt * 3);
++ (void)gs_sprintf(obuf, ESC_GS "0;%d", cnt * 3);
+ lputs(s, obuf);
+
+ do {
+- (void)sprintf(obuf, ";%d;%d;%d;%d;%d;%d",
++ (void)gs_sprintf(obuf, ";%d;%d;%d;%d;%d;%d",
+ (int)(fixed2float(vs[0]) / scale.x), (int)(fixed2float(vs[1]) / scale.y),
+ (int)(fixed2float(vs[2]) / scale.x), (int)(fixed2float(vs[3]) / scale.y),
+ (int)(fixed2float(vs[4]) / scale.x), (int)(fixed2float(vs[5]) / scale.y));
+@@ -637,7 +637,7 @@ escv_vector_dorect(gx_device_vector * vd
+
+ scale = vdev->scale;
+
+- (void)sprintf(obuf, ESC_GS "0;%d;%d;%d;%d;0;0rrpG",
++ (void)gs_sprintf(obuf, ESC_GS "0;%d;%d;%d;%d;0;0rrpG",
+ (int)(fixed2float(x0) / scale.x),
+ (int)(fixed2float(y0) / scale.y),
+ (int)(fixed2float(x1) / scale.x),
+@@ -1116,7 +1116,7 @@ escv_beginpage(gx_device_vector * vdev)
+ lputs(s, " PU=15");
+ }
+ } else if (pdev->cassetFeed) {
+- (void)sprintf(ebuf, " PU=%d", pdev->cassetFeed);
++ (void)gs_sprintf(ebuf, " PU=%d", pdev->cassetFeed);
+ lputs(s, ebuf);
+ } else {
+ lputs(s, " PU=AU");
+@@ -1146,14 +1146,14 @@ escv_beginpage(gx_device_vector * vdev)
+
+ /* lp8000c not have QT */
+ if (strcmp(pdev->dname, "lp8000c") == 0) {
+- (void)sprintf(ebuf, " QT=1 CO=%d", pdev->NumCopies);
++ (void)gs_sprintf(ebuf, " QT=1 CO=%d", pdev->NumCopies);
+ } else {
+ if (pdev->Collate) {
+ /* CO is 1, when set QT */
+- (void)sprintf(ebuf, " QT=%d CO=1", pdev->NumCopies);
++ (void)gs_sprintf(ebuf, " QT=%d CO=1", pdev->NumCopies);
+ } else {
+ /* QT is 1, when not specified QT */
+- (void)sprintf(ebuf, " QT=1 CO=%d", pdev->NumCopies);
++ (void)gs_sprintf(ebuf, " QT=1 CO=%d", pdev->NumCopies);
+ }
+ }
+ lputs(s, ebuf);
+@@ -1162,7 +1162,7 @@ escv_beginpage(gx_device_vector * vdev)
+ }
+
+ if (pdev->toner_density) {
+- (void)sprintf(ebuf, " DL=%d", pdev->toner_density);
++ (void)gs_sprintf(ebuf, " DL=%d", pdev->toner_density);
+ lputs(s, ebuf);
+ }
+
+@@ -1320,7 +1320,7 @@ escv_setlinewidth(gx_device_vector * vde
+ /* ESC/Page ¤Ç¤ÏÀþÉý¡¿½ªÃ¼¡¿ÀܹçÉô¤ÎÀßÄê¤Ï£±¤Ä¤Î¥³¥Þ¥ó¥É¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¿¤áÊÝ»ý¤·¤Æ¤ª¤¯¡£ */
+ pdev -> lwidth = width;
+
+- (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG",
++ (void)gs_sprintf(obuf, ESC_GS "%d;%d;%dlwG",
+ (int)(pdev -> lwidth),
+ (int)(pdev -> cap),
+ (int)(pdev -> join));
+@@ -1341,7 +1341,7 @@ escv_setlinecap(gx_device_vector * vdev,
+
+ if (pdev -> cap >= 3) return -1;
+
+- (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG",
++ (void)gs_sprintf(obuf, ESC_GS "%d;%d;%dlwG",
+ (int)(pdev -> lwidth),
+ (int)(pdev -> cap),
+ (int)(pdev -> join));
+@@ -1372,7 +1372,7 @@ escv_setlinejoin(gx_device_vector * vdev
+ return -1;
+ }
+
+- (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG",
++ (void)gs_sprintf(obuf, ESC_GS "%d;%d;%dlwG",
+ (int)(pdev -> lwidth),
+ (int)(pdev -> cap),
+ (int)(pdev -> join));
+@@ -1394,14 +1394,14 @@ escv_setmiterlimit(gx_device_vector * vd
+ if (pdev -> join != 3) {
+ /* ¶¯À©Åª¤ËÀܹçÉô»ØÄê¤ò¹Ô¤¦ */
+ pdev -> join = 3;
+- (void)sprintf(obuf, ESC_GS "%d;%d;%dlwG",
++ (void)gs_sprintf(obuf, ESC_GS "%d;%d;%dlwG",
+ (int)(pdev -> lwidth),
+ (int)(pdev -> cap),
+ (int)(pdev -> join));
+ lputs(s, obuf);
+ }
+
+- (void)sprintf(obuf, ESC_GS "1;%dmlG", (int)limit);
++ (void)gs_sprintf(obuf, ESC_GS "1;%dmlG", (int)limit);
+ lputs(s, obuf);
+
+ return 0;
+@@ -1433,7 +1433,7 @@ escv_setfillcolor(gx_device_vector * vde
+
+ if( 0 == pdev->colormode ) { /* ESC/Page (Monochrome) */
+
+- (void)sprintf(obuf, /*ESC_GS "1owE"*/ ESC_GS "0;0;100spE" ESC_GS "1;0;%ldccE" ,color);
++ (void)gs_sprintf(obuf, /*ESC_GS "1owE"*/ ESC_GS "0;0;100spE" ESC_GS "1;0;%ldccE" ,color);
+ lputs(s, obuf);
+
+ if (vdev->x_pixels_per_inch == 1200) {
+@@ -1447,7 +1447,7 @@ escv_setfillcolor(gx_device_vector * vde
+ } else { /* ESC/Page-Color */
+
+ /* ¥Ñ¥¿¡¼¥ó£Ï£Î»ØÄê¡¿¥½¥ê¥Ã¥É¥Ñ¥¿¡¼¥ó»ØÄê */
+- (void)sprintf(obuf, ESC_GS "1;2;3;%d;%d;%dfpE",
++ (void)gs_sprintf(obuf, ESC_GS "1;2;3;%d;%d;%dfpE",
+ (unsigned char)(color >> 16 & 0xff),
+ (unsigned char)(color >> 8 & 0xff),
+ (unsigned char)(color & 0xff));
+@@ -1477,7 +1477,7 @@ escv_setstrokecolor(gx_device_vector * v
+
+ pdev->current_color = color;
+
+- (void)sprintf(obuf, /*ESC_GS "1owE"*/ ESC_GS "0;0;100spE" ESC_GS "1;1;%ldccE" , color);
++ (void)gs_sprintf(obuf, /*ESC_GS "1owE"*/ ESC_GS "0;0;100spE" ESC_GS "1;1;%ldccE" , color);
+ lputs(s, obuf);
+
+ if (vdev->x_pixels_per_inch == 1200) {
+@@ -1494,7 +1494,7 @@ escv_setstrokecolor(gx_device_vector * v
+
+ pdev->current_color = color;
+ /* ¥Ñ¥¿¡¼¥ó£Ï£Î¿§»ØÄê¡¿¥½¥ê¥Ã¥É¥Ñ¥¿¡¼¥ó»ØÄê */
+- (void)sprintf(obuf, ESC_GS "1;2;3;%d;%d;%dfpE" ESC_GS "2;2;1;0;0cpE",
++ (void)gs_sprintf(obuf, ESC_GS "1;2;3;%d;%d;%dfpE" ESC_GS "2;2;1;0;0cpE",
+ (unsigned char)(color >> 16 & 0xff),
+ (unsigned char)(color >> 8 & 0xff),
+ (unsigned char)(color & 0xff));
+@@ -1538,11 +1538,11 @@ escv_setdash(gx_device_vector * vdev, co
+ if (count) {
+ if (count == 1) {
+ #if GS_VERSION_MAJOR == 5
+- (void)sprintf(obuf, ESC_GS "1;%d;%ddlG",
++ (void)gs_sprintf(obuf, ESC_GS "1;%d;%ddlG",
+ (int)(pattern[0] * scale / vdev->x_pixels_per_inch + 0.5),
+ (int)(pattern[0] * scale / vdev->x_pixels_per_inch + 0.5));
+ #else
+- (void)sprintf(obuf, ESC_GS "1;%d;%ddlG", (int) pattern[0], (int) pattern[0]);
++ (void)gs_sprintf(obuf, ESC_GS "1;%d;%ddlG", (int) pattern[0], (int) pattern[0]);
+ #endif
+ lputs(s, obuf);
+ } else {
+@@ -1554,10 +1554,10 @@ escv_setdash(gx_device_vector * vdev, co
+ lputs(s, ESC_GS "1");
+ for (i = 0; i < count; ++i) {
+ #if GS_VERSION_MAJOR == 5
+- (void)sprintf(obuf, ";%d", (int)(pattern[i] * scale / vdev->x_pixels_per_inch + 0.5));
++ (void)gs_sprintf(obuf, ";%d", (int)(pattern[i] * scale / vdev->x_pixels_per_inch + 0.5));
+
+ #else
+- (void)sprintf(obuf, ";%d", (int) pattern[i]);
++ (void)gs_sprintf(obuf, ";%d", (int) pattern[i]);
+ #endif
+ lputs(s, obuf);
+ }
+@@ -1608,7 +1608,7 @@ escv_moveto(gx_device_vector * vdev,
+ char obuf[64];
+
+ /* ¥µ¥Ö¥Ñ¥¹³«»ÏÌ¿Îá */
+- (void)sprintf(obuf, ESC_GS "0;%d;%dmvpG", (int)x1, (int)y1);
++ (void)gs_sprintf(obuf, ESC_GS "0;%d;%dmvpG", (int)x1, (int)y1);
+ lputs(s, obuf);
+
+ return 0;
+@@ -1622,7 +1622,7 @@ escv_lineto(gx_device_vector * vdev,
+ gx_device_escv *pdev = (gx_device_escv *) vdev;
+ char obuf[64];
+
+- (void)sprintf(obuf, ESC_GS "0;1;%d;%dlnpG", (int)x1, (int)y1);
++ (void)gs_sprintf(obuf, ESC_GS "0;1;%d;%dlnpG", (int)x1, (int)y1);
+ lputs(s, obuf);
+ pdev->ispath = 1;
+
+@@ -1639,7 +1639,7 @@ escv_curveto(gx_device_vector * vdev, fl
+ char obuf[128];
+
+ /* ¥Ù¥¸¥§¶ÊÀþ */
+- (void)sprintf(obuf, ESC_GS "0;3;%d;%d;%d;%d;%d;%dbzpG",
++ (void)gs_sprintf(obuf, ESC_GS "0;3;%d;%d;%d;%d;%d;%dbzpG",
+ (int)x1, (int)y1, (int)x2, (int)y2, (int)x3, (int)y3);
+ lputs(s, obuf);
+ pdev->ispath = 1;
+@@ -2176,7 +2176,7 @@ escv_copy_mono(gx_device * dev, const by
+ if( 0 == pdev->colormode ) { /* ESC/Page (Monochrome) */
+
+ /* lputs(s, ESC_GS "1owE");*/
+- (void)sprintf(obuf, ESC_GS "1;1;%ldccE", c_color);
++ (void)gs_sprintf(obuf, ESC_GS "1;1;%ldccE", c_color);
+ lputs(s, obuf);
+
+ if (vdev->x_pixels_per_inch == 1200) {
+@@ -2263,7 +2263,7 @@ escv_copy_mono(gx_device * dev, const by
+ } else { /* ESC/Page-Color */
+
+ /* ¥Ñ¥¿¡¼¥ó£Ï£Î»ØÄê¡¿¥½¥ê¥Ã¥É¥Ñ¥¿¡¼¥ó»ØÄê */
+- (void)sprintf(obuf, ESC_GS "1;2;3;%d;%d;%dfpE",
++ (void)gs_sprintf(obuf, ESC_GS "1;2;3;%d;%d;%dfpE",
+ (unsigned char)(c_color >> 16 & 0xff),
+ (unsigned char)(c_color >> 8 & 0xff),
+ (unsigned char)(c_color & 0xff));
+@@ -2388,7 +2388,7 @@ escv_fill_mask(gx_device * dev,
+ if (!gx_dc_is_pure(pdcolor)) return_error(gs_error_rangecheck);
+ pdev->current_color = color;
+
+- (void)sprintf(obuf, ESC_GS "0;0;100spE" ESC_GS "1;1;%ldccE" ,color);
++ (void)gs_sprintf(obuf, ESC_GS "0;0;100spE" ESC_GS "1;1;%ldccE" ,color);
+ lputs(s, obuf);
+
+ if (vdev->x_pixels_per_inch == 1200) {
+@@ -2428,7 +2428,7 @@ escv_fill_mask(gx_device * dev,
+ memcpy(buf + i * width_bytes, data + (data_x >> 3) + i * raster, width_bytes);
+ }
+
+- (void)sprintf(obuf, ESC_GS "%d;%d;%d;%d;0db{F", num_bytes, (int)(id & VCACHE), w, h);
++ (void)gs_sprintf(obuf, ESC_GS "%d;%d;%d;%d;0db{F", num_bytes, (int)(id & VCACHE), w, h);
+ lputs(s, obuf);
+ put_bytes(s, buf, num_bytes);
+
+@@ -2436,9 +2436,9 @@ escv_fill_mask(gx_device * dev,
+ pdev -> id_cache[id & VCACHE] = id;
+ }
+
+- (void)sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y);
++ (void)gs_sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y);
+ lputs(s, obuf);
+- (void)sprintf(obuf, ESC_GS "%lddbF", id & VCACHE);
++ (void)gs_sprintf(obuf, ESC_GS "%lddbF", id & VCACHE);
+ lputs(s, obuf);
+
+ return 0;
+@@ -2603,7 +2603,7 @@ escv_begin_image(gx_device * dev,
+ if( 0 == pdev->colormode ) { /* ESC/Page (Monochrome) */
+
+ /* lputs(s, ESC_GS "1owE");*/
+- (void)sprintf(obuf, ESC_GS "1;1;%ldccE", color);
++ (void)gs_sprintf(obuf, ESC_GS "1;1;%ldccE", color);
+ lputs(s, obuf);
+
+ if (vdev->x_pixels_per_inch == 1200) {
+@@ -2908,7 +2908,7 @@ static void escv_write_begin(gx_device *
+
+ if( 0 == pdev->colormode ) { /* ESC/Page (Monochrome) */
+
+- (void)sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y);
++ (void)gs_sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y);
+ lputs(s, obuf);
+
+ comp = 10;
+@@ -2916,34 +2916,34 @@ static void escv_write_begin(gx_device *
+ if (bits == 1) {
+ if (strcmp(pdev->dname, "lp1800") == 0 ||
+ strcmp(pdev->dname, "lp9600") == 0) {
+- (void)sprintf(obuf, ESC_GS "0bcI");
++ (void)gs_sprintf(obuf, ESC_GS "0bcI");
+ }else{
+- (void)sprintf(obuf, ESC_GS "5;%d;%d;%d;%d;%dsrI", sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "5;%d;%d;%d;%d;%dsrI", sw, sh, dw, dh, roll);
+ }
+ } else if (bits == 4) {
+ if (pdev -> c4map) {
+ pdev -> c4map = FALSE;
+ }
+- (void)sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ } else if (bits == 8) {
+ if (pdev -> c8map) {
+ pdev -> c8map = FALSE;
+ }
+- (void)sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ } else {
+ /* 24 bit */
+- (void)sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "1;1;1;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ }
+
+ } else { /* ESC/Page-Color */
+
+- (void)sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y);
++ (void)gs_sprintf(obuf, ESC_GS "%dX" ESC_GS "%dY", x, y);
+ lputs(s, obuf);
+
+ comp = 0;
+
+ if (bits == 1) {
+- (void)sprintf(obuf, ESC_GS "2;201;1;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "2;201;1;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ } else if (bits == 4) {
+ if (pdev -> c4map) {
+ /* ¥«¥é¡¼¥Þ¥Ã¥×ÅÐÏ¿ */
+@@ -2959,7 +2959,7 @@ static void escv_write_begin(gx_device *
+ gs_free_object(vdev->memory, tmp, "escv_write_begin(tmp4)");
+ pdev -> c4map = FALSE;
+ }
+- (void)sprintf(obuf, ESC_GS "2;203;2;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "2;203;2;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ } else if (bits == 8) {
+ if (pdev -> c8map) {
+ /* ¥«¥é¡¼¥Þ¥Ã¥×ÅÐÏ¿ */
+@@ -2975,10 +2975,10 @@ static void escv_write_begin(gx_device *
+ gs_free_object(vdev->memory, tmp, "escv_write_begin(tmp)");
+ pdev -> c8map = FALSE;
+ }
+- (void)sprintf(obuf, ESC_GS "2;204;4;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "2;204;4;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ } else {
+ /* 24 bit */
+- (void)sprintf(obuf, ESC_GS "2;102;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
++ (void)gs_sprintf(obuf, ESC_GS "2;102;0;%d;%d;%d;%d;%d;%dscrI", comp, sw, sh, dw, dh, roll);
+ }
+
+ } /* ESC/Page-Color */
+@@ -3045,12 +3045,12 @@ static void escv_write_data(gx_device *d
+ if(bits == 1){
+ if (strcmp(pdev->dname, "lp1800") == 0 || \
+ strcmp(pdev->dname, "lp9600") == 0) {
+- (void)sprintf(obuf, ESC_GS "%d;1;%d;%d;0db{I", bsize, w, ras);
++ (void)gs_sprintf(obuf, ESC_GS "%d;1;%d;%d;0db{I", bsize, w, ras);
+ }else{
+- (void)sprintf(obuf, ESC_GS "%d;%du{I", bsize, ras);
++ (void)gs_sprintf(obuf, ESC_GS "%d;%du{I", bsize, ras);
+ }
+ }else{
+- (void)sprintf(obuf, ESC_GS "%d;%dcu{I", bsize, ras);
++ (void)gs_sprintf(obuf, ESC_GS "%d;%dcu{I", bsize, ras);
+ }
+ lputs(s, obuf);
+
+@@ -3077,7 +3077,7 @@ static void escv_write_data(gx_device *d
+ buf = tmps;
+ }
+
+- (void)sprintf(obuf, ESC_GS "%d;%dcu{I", bsize, ras);
++ (void)gs_sprintf(obuf, ESC_GS "%d;%dcu{I", bsize, ras);
+ lputs(s, obuf);
+ put_bytes(s, buf, bsize);
+
+diff -up ghostscript-9.07/contrib/gdevcd8.c.gs_sprintf ghostscript-9.07/contrib/gdevcd8.c
+--- ghostscript-9.07/contrib/gdevcd8.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/gdevcd8.c 2013-05-09 17:02:39.092447197 +0100
+@@ -2439,7 +2439,7 @@ do_gcr(int bytecount, byte * inbyte, con
+ #if 0
+ if ((*cyan > 0) && (*magenta > 0) && (*yellow > 0))
+ {
+- sprintf(output, "%3d %3d %3d %3d - ", *cyan, *magenta, *yellow, *black);
++ gs_sprintf(output, "%3d %3d %3d %3d - ", *cyan, *magenta, *yellow, *black);
+ debug_print_string(output, strlen(output));
+ }
+ #endif /* 0 */
+@@ -2486,7 +2486,7 @@ do_gcr(int bytecount, byte * inbyte, con
+ #if 0
+ if (ucr > 0)
+ {
+- sprintf(output, "%3d %3d %3d %3d - %5d\n", *cyan, *magenta, *yellow, *black, ucr);
++ gs_sprintf(output, "%3d %3d %3d %3d - %5d\n", *cyan, *magenta, *yellow, *black, ucr);
+ debug_print_string(output, strlen(output));
+ }
+ #endif /* 0 */
+diff -up ghostscript-9.07/contrib/gdevdj9.c.gs_sprintf ghostscript-9.07/contrib/gdevdj9.c
+--- ghostscript-9.07/contrib/gdevdj9.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/gdevdj9.c 2013-05-09 17:02:39.092447197 +0100
+@@ -2563,7 +2563,7 @@ static int cdj970_write_header (gx_devic
+
+ memset (startbuffer, 0, 1260);
+
+- sprintf (&(startbuffer[600]), "\033E\033%%-12345X@PJL JOB NAME = \"GHOST BY RENE HARSCH\"\n@PJL ENTER LANGUAGE=PCL3GUI\n");
++ gs_sprintf (&(startbuffer[600]), "\033E\033%%-12345X@PJL JOB NAME = \"GHOST BY RENE HARSCH\"\n@PJL ENTER LANGUAGE=PCL3GUI\n");
+
+ fwrite (startbuffer, sizeof(char), 678, prn_stream);
+
+diff -up ghostscript-9.07/contrib/gdevhl12.c.gs_sprintf ghostscript-9.07/contrib/gdevhl12.c
+--- ghostscript-9.07/contrib/gdevhl12.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/gdevhl12.c 2013-05-09 17:02:39.092447197 +0100
+@@ -662,7 +662,7 @@ hl1250_print_page_copies(gx_device_print
+ (-120, 0) compared to the one in the ljet4 driver (-180, 36)
+ (X, Y coordinates here are specified in 1/720-inch units). */
+
+- sprintf(page_init, "\033&l-120U\033*r0F\033&u%dD%s", y_dpi, tray_pcl);
++ gs_sprintf(page_init, "\033&l-120U\033*r0F\033&u%dD%s", y_dpi, tray_pcl);
+ return dljet_mono_print_page_copies(pdev, prn_stream, num_copies,
+ y_dpi, PCL_LJ4_FEATURES,
+ page_init, page_init, false);
+diff -up ghostscript-9.07/contrib/gdevxes.c.gs_sprintf ghostscript-9.07/contrib/gdevxes.c
+--- ghostscript-9.07/contrib/gdevxes.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/gdevxes.c 2013-05-09 17:02:39.092447197 +0100
+@@ -173,7 +173,7 @@ sixel_print_page(gx_device_printer *pdev
+ if ( tmp[l] == last ) {
+ count++;
+ if (count==32767) {
+- run[sprintf(run, "%d", count)]='\0';
++ run[gs_sprintf(run, "%d", count)]='\0';
+ for (t=run; *t; t++)fputc( *t, prn_stream );
+ fputc( last, prn_stream );
+ last = '\0';
+@@ -186,7 +186,7 @@ sixel_print_page(gx_device_printer *pdev
+ case 0: break;
+ case 1: fputc( last, prn_stream );
+ break;
+- default:run[sprintf(run, "%d", count)]='\0';
++ default:run[gs_sprintf(run, "%d", count)]='\0';
+ for (t=run; *t; t++) fputc( *t, prn_stream );
+ fputc( last, prn_stream );
+ break;
+@@ -203,7 +203,7 @@ sixel_print_page(gx_device_printer *pdev
+ case 0: break;
+ case 1: fputc( last, prn_stream );
+ break;
+- default:run[sprintf(run, "%d", count)]='\0';
++ default:run[gs_sprintf(run, "%d", count)]='\0';
+ for (t=run; *t; t++) fputc( *t, prn_stream );
+ fputc( last, prn_stream );
+ break;
+diff -up ghostscript-9.07/contrib/gomni.c.gs_sprintf ghostscript-9.07/contrib/gomni.c
+--- ghostscript-9.07/contrib/gomni.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/gomni.c 2013-05-09 17:02:39.093447201 +0100
+@@ -790,7 +790,7 @@ SetupDevice (gx_device *pgxdev, gs_param
+ "Devicestring");
+ if (pszDeviceLib)
+ {
+- sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cOmnilib);
++ gs_sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cOmnilib);
+
+ pDev->hmodOmni = g_module_open (pszDeviceLib, (GModuleFlags)0);
+
+@@ -817,7 +817,7 @@ SetupDevice (gx_device *pgxdev, gs_param
+ "Devicestring");
+ if (pszDeviceLib)
+ {
+- sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cOmnilib);
++ gs_sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cOmnilib);
+
+ pModule = g_module_open (pszDeviceLib, (GModuleFlags)0);
+
+@@ -1053,7 +1053,7 @@ SetupDevice (gx_device *pgxdev, gs_param
+
+ if (pszDeviceLib)
+ {
+- sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cDialogName);
++ gs_sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cDialogName);
+
+ if (fDebugOutput) dprintf1 ("attempting to load - %s\n", pszDeviceLib);
+
+@@ -1079,7 +1079,7 @@ SetupDevice (gx_device *pgxdev, gs_param
+
+ if (pszDeviceLib)
+ {
+- sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cDialogName);
++ gs_sprintf (pszDeviceLib, "%s%s", apszLibraryPaths[i], cDialogName);
+
+ pModule = g_module_open (pszDeviceLib, (GModuleFlags)0);
+
+diff -up ghostscript-9.07/contrib/japanese/dviprlib.c.gs_sprintf ghostscript-9.07/contrib/japanese/dviprlib.c
+--- ghostscript-9.07/contrib/japanese/dviprlib.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/dviprlib.c 2013-05-09 17:02:39.093447201 +0100
+@@ -106,7 +106,7 @@ dviprt_read_S_cfg(dviprt_cfg_t *pcfg,dvi
+ goto not_cfg;
+ pcfg->version = rbuf[2] | ((uint)rbuf[3] << 8);
+ if (pcfg->version > CFG_VERSION) {
+- sprintf(dviprt_message_buffer,
++ gs_sprintf(dviprt_message_buffer,
+ "This *.CFG file is too new version(ver.%u).\n",pcfg->version);
+ dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
+ return CFG_ERROR_OTHER;
+@@ -129,7 +129,7 @@ dviprt_read_S_cfg(dviprt_cfg_t *pcfg,dvi
+ if (n >= CFG_INTEGER_TYPE_COUNT) {
+ ptype = "integer";
+ unknown_no:
+- sprintf(dviprt_message_buffer,
++ gs_sprintf(dviprt_message_buffer,
+ "Unknown %s type value No.%d is found.\n",ptype,n);
+ dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
+ return CFG_ERROR_OTHER;
+@@ -346,7 +346,7 @@ dviprt_read_QR_cfg(dviprt_cfg_t *pcfg,dv
+ ptr++;
+ break;
+ default:
+- sprintf(dviprt_message_buffer,"Unknown format %02X",type);
++ gs_sprintf(dviprt_message_buffer,"Unknown format %02X",type);
+ dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
+ goto ex_func;
+ }
+@@ -587,7 +587,7 @@ dviprt_readsrc(char *fname,dviprt_cfg_t
+ while (*pbuf && isspace(*pbuf)) pbuf++;
+ if (pitem->spec_f) {
+ dviprt_printcfgerror(&info,NULL,0);
+- sprintf(dviprt_message_buffer,
++ gs_sprintf(dviprt_message_buffer,
+ "Item `%s' is specified twice.\n",pitem->name);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ code = CFG_ERROR_SYNTAX;
+@@ -691,7 +691,7 @@ dviprt_readsrc(char *fname,dviprt_cfg_t
+ code = 0;
+ for (pitem = dviprt_items;pitem->name;pitem++) {
+ if (!pitem->spec_f && pitem->req_f) {
+- sprintf(dviprt_message_buffer,"%s not found.\n",pitem->name);
++ gs_sprintf(dviprt_message_buffer,"%s not found.\n",pitem->name);
+ dviprt_printcfgerror(&info,dviprt_message_buffer,-1);
+ code++;
+ }
+@@ -749,14 +749,14 @@ dviprt_readsrc(char *fname,dviprt_cfg_t
+
+ for (pitem = dviprt_items;pitem->type>=0;pitem++) {
+ if (pitem->spec_f == 0) {
+- sprintf(dviprt_message_buffer,": %s:",pitem->name);
++ gs_sprintf(dviprt_message_buffer,": %s:",pitem->name);
+ switch (pitem->type) {
+ case T_INTEGER:
+ if (pcfg->integer[pitem->no] >= 0) {
+ uint v = pcfg->integer[pitem->no];
+ dviprt_printmessage(fname,-1);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+- sprintf(dviprt_message_buffer," %d\n",v);
++ gs_sprintf(dviprt_message_buffer," %d\n",v);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ }
+ break;
+@@ -802,7 +802,7 @@ dviprt_set_integer(dviprt_cfg_item_t *pi
+ out_of_range:
+ dviprt_printtokenerror(pinfo,buf,strlen(buf),ERROR_OUTOFRANGE);
+ dviprt_printcfgerror(pinfo,"",-1);
+- sprintf(dviprt_message_buffer,
++ gs_sprintf(dviprt_message_buffer,
+ "(%u <= value <= %u).\n",(uint)min,(uint)max);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ return CFG_ERROR_RANGE;
+@@ -1108,10 +1108,10 @@ dviprt_set_rpexpr(dviprt_cfg_item_t *pit
+ pitem->no != CFG_AFTER_BIT_IMAGE) {
+ unavailable_value:
+ dviprt_printcfgerror(pinfo,"",-1);
+- sprintf(dviprt_message_buffer,"Variable `%c' in ",(int)*pbuf);
++ gs_sprintf(dviprt_message_buffer,"Variable `%c' in ",(int)*pbuf);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ dviprt_printmessage(pbuf,(int)(pend-pbuf));
+- sprintf(dviprt_message_buffer," cannot be used in %s.\n",pitem->name);
++ gs_sprintf(dviprt_message_buffer," cannot be used in %s.\n",pitem->name);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ return CFG_ERROR_RANGE;
+ }
+@@ -1144,7 +1144,7 @@ dviprt_set_rpexpr(dviprt_cfg_item_t *pit
+ case '^': op = CFG_OP_XOR; break;
+ default:
+ dviprt_printcfgerror(pinfo,NULL,0);
+- sprintf(dviprt_message_buffer,"Unknown operator %c in ",(int)*pbuf);
++ gs_sprintf(dviprt_message_buffer,"Unknown operator %c in ",(int)*pbuf);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ dviprt_printmessage(pbuf,(int)(pend-pbuf));
+ dviprt_printmessage(".\n",-1);
+@@ -1520,7 +1520,7 @@ dviprt_printcfgerrorheader(dviprt_cfg_i
+ dviprt_printmessage(fn,-1);
+ dviprt_printmessage(": ",-1);
+ if (pinfo->line_no>0) {
+- sprintf(dviprt_message_buffer,"%d: ",pinfo->line_no);
++ gs_sprintf(dviprt_message_buffer,"%d: ",pinfo->line_no);
+ dviprt_printmessage(dviprt_message_buffer,-1);
+ }
+ }
+@@ -2210,9 +2210,9 @@ dviprt_output_expr(dviprt_print *pprint,
+ if (cols == 0)
+ strcpy(fmtbuf,"%");
+ else
+- sprintf(fmtbuf,"%%0%d",cols);
++ gs_sprintf(fmtbuf,"%%0%d",cols);
+ strcat(fmtbuf,f);
+- sprintf(valbuf,fmtbuf,stack[stack_p]);
++ gs_sprintf(valbuf,fmtbuf,stack[stack_p]);
+ cols = strlen(valbuf);
+ if (fmt & CFG_FMT_ISO_BIT)
+ valbuf[cols-1] |= 0x10;
+diff -up ghostscript-9.07/contrib/japanese/gdevfmlbp.c.gs_sprintf ghostscript-9.07/contrib/japanese/gdevfmlbp.c
+--- ghostscript-9.07/contrib/japanese/gdevfmlbp.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/gdevfmlbp.c 2013-05-09 17:02:39.094447206 +0100
+@@ -112,7 +112,7 @@ gdev_fmlbp_paper_size(gx_device_printer
+ height_inches = t;
+ landscape = 1;
+ }
+- sprintf(paper, "%s;%d",
++ gs_sprintf(paper, "%s;%d",
+ (height_inches >= 15.9 ? PAPER_SIZE_A3 :
+ height_inches >= 11.8 ?
+ (width_inches >= 9.2 ? PAPER_SIZE_B4 : PAPER_SIZE_LEGAL) :
+@@ -136,7 +136,7 @@ static void goto_xy(FILE *prn_stream,int
+
+ fputc(CEX,prn_stream);
+ fputc('"',prn_stream);
+- sprintf(buff,"%d",x);
++ gs_sprintf((char *)buff,"%d",x);
+ while (*p)
+ {
+ if (!*(p+1)) fputc((*p)+0x30,prn_stream);
+@@ -146,7 +146,7 @@ static void goto_xy(FILE *prn_stream,int
+ }
+
+ p=buff;
+- sprintf(buff,"%d",y);
++ gs_sprintf((char *)buff,"%d",y);
+ while (*p)
+ {
+ if (!*(p+1)) fputc((*p)+0x40,prn_stream);
+diff -up ghostscript-9.07/contrib/japanese/gdevfmpr.c.gs_sprintf ghostscript-9.07/contrib/japanese/gdevfmpr.c
+--- ghostscript-9.07/contrib/japanese/gdevfmpr.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/gdevfmpr.c 2013-05-09 17:02:39.094447206 +0100
+@@ -184,13 +184,13 @@ fmpr_print_page(gx_device_printer *pdev,
+ }
+ out_beg -= (out_beg - out) % bytes_per_column;
+
+- sprintf(prn_buf, "\033[%da",
++ gs_sprintf(prn_buf, "\033[%da",
+ (out_beg - out) / bytes_per_column);
+ prn_puts(pdev, prn_buf);
+
+ /* Dot graphics */
+ size = out_end - out_beg + 1;
+- sprintf(prn_buf, "\033Q%d W", size / bytes_per_column);
++ gs_sprintf(prn_buf, "\033Q%d W", size / bytes_per_column);
+ prn_puts(pdev, prn_buf);
+ prn_write(pdev, out_beg, size);
+
+diff -up ghostscript-9.07/contrib/japanese/gdevj100.c.gs_sprintf ghostscript-9.07/contrib/japanese/gdevj100.c
+--- ghostscript-9.07/contrib/japanese/gdevj100.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/gdevj100.c 2013-05-09 17:02:39.094447206 +0100
+@@ -128,12 +128,12 @@ jj100_print_page(gx_device_printer *pdev
+
+ /* Vertical tab to the appropriate position. */
+ while(skip > 15) {
+- sprintf(prn_buf, "\037%c", 16 + 15);
++ gs_sprintf(prn_buf, "\037%c", 16 + 15);
+ fputs(prn_buf, pdev->file);
+ skip -= 15;
+ }
+ if(skip > 0) {
+- sprintf(prn_buf, "\037%c", 16 + skip);
++ gs_sprintf(prn_buf, "\037%c", 16 + skip);
+ fputs(prn_buf, pdev->file);
+ }
+
+@@ -170,13 +170,13 @@ jj100_print_page(gx_device_printer *pdev
+ out_beg -= (out_beg - out) % (bytes_per_column * 2);
+
+ /* Dot addressing */
+- sprintf(prn_buf, "\033F%04d",
++ gs_sprintf(prn_buf, "\033F%04d",
+ (out_beg - out) / bytes_per_column / 2);
+ fputs(prn_buf, pdev->file);
+
+ /* Dot graphics */
+ size = out_end - out_beg + 1;
+- sprintf(prn_buf, "\034bP,48,%04d.", size / bytes_per_column);
++ gs_sprintf(prn_buf, "\034bP,48,%04d.", size / bytes_per_column);
+ fputs(prn_buf, pdev->file);
+ fwrite(out_beg, 1, size, pdev->file);
+
+diff -up ghostscript-9.07/contrib/japanese/gdevlbp3.c.gs_sprintf ghostscript-9.07/contrib/japanese/gdevlbp3.c
+--- ghostscript-9.07/contrib/japanese/gdevlbp3.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/gdevlbp3.c 2013-05-09 17:02:39.094447206 +0100
+@@ -81,7 +81,7 @@ lbp310PrintPage(gx_device_printer *pDev,
+ DataSize = CompressImage(pDev, &Box, fp, "\x1b[1;%d;%d;11;%d;.r");
+
+ /* ----==== Set size ====---- */
+- sprintf(Buf, "0%ld", DataSize);
++ gs_sprintf((char *)Buf, "0%ld", DataSize);
+ i = (DataSize+strlen(Buf)+1)&1;
+ /* ----==== escape to LIPS ====---- */
+ fprintf(fp, "\x80%s\x80\x80\x80\x80\x0c",Buf+i);
+@@ -110,7 +110,7 @@ lbp320PrintPage(gx_device_printer *pDev,
+ DataSize = CompressImage(pDev, &Box, fp, "\x1b[1;%d;%d;11;%d;.&r");
+
+ /* ----==== Set size ====---- */
+- sprintf(Buf, "000%ld", DataSize);
++ gs_sprintf((char *)Buf, "000%ld", DataSize);
+ i = (DataSize+strlen(Buf)+1)&3;
+ /* ----==== escape to LIPS ====---- */
+ fprintf(fp, "\x80%s\x80\x80\x80\x80\x0c",Buf+i);
+diff -up ghostscript-9.07/contrib/japanese/gdevmag.c.gs_sprintf ghostscript-9.07/contrib/japanese/gdevmag.c
+--- ghostscript-9.07/contrib/japanese/gdevmag.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/gdevmag.c 2013-05-09 17:02:39.094447206 +0100
+@@ -137,8 +137,8 @@ mag_print_page(gx_device_printer *pdev,
+
+ if (user == 0) user = "Unknown";
+ strcpy(check,magic);
+- sprintf(check+strlen(check),"%-18s",user);
+- sprintf(check+31," Ghostscript with %s driver\x1a", pdev->dname);
++ gs_sprintf(check+strlen(check),"%-18s",user);
++ gs_sprintf(check+31," Ghostscript with %s driver\x1a", pdev->dname);
+
+ /* check sizes of flag and pixel data. */
+ pixel_bytes = 0;
+diff -up ghostscript-9.07/contrib/japanese/gdevnpdl.c.gs_sprintf ghostscript-9.07/contrib/japanese/gdevnpdl.c
+--- ghostscript-9.07/contrib/japanese/gdevnpdl.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/japanese/gdevnpdl.c 2013-05-09 17:02:39.094447206 +0100
+@@ -592,31 +592,31 @@ npdl_print_page_copies(gx_device_printer
+ /* Check paper size */
+ switch (npdl_get_paper_size((gx_device *) pdev)) {
+ case PAPER_SIZE_POSTCARD:
+- sprintf(paper_command, "PC");
++ gs_sprintf(paper_command, "PC");
+ break;
+ case PAPER_SIZE_A5:
+- sprintf(paper_command, "A5");
++ gs_sprintf(paper_command, "A5");
+ break;
+ case PAPER_SIZE_A4:
+- sprintf(paper_command, "A4");
++ gs_sprintf(paper_command, "A4");
+ break;
+ case PAPER_SIZE_A3:
+- sprintf(paper_command, "A3");
++ gs_sprintf(paper_command, "A3");
+ break;
+ case PAPER_SIZE_B5:
+- sprintf(paper_command, "B5");
++ gs_sprintf(paper_command, "B5");
+ break;
+ case PAPER_SIZE_B4:
+- sprintf(paper_command, "B4");
++ gs_sprintf(paper_command, "B4");
+ break;
+ case PAPER_SIZE_LETTER:
+- sprintf(paper_command, "LT");
++ gs_sprintf(paper_command, "LT");
+ break;
+ case PAPER_SIZE_ENV4:
+- sprintf(paper_command, "ENV4");
++ gs_sprintf(paper_command, "ENV4");
+ break;
+ case PAPER_SIZE_BPOSTCARD:
+- sprintf(paper_command, "UPPC");
++ gs_sprintf(paper_command, "UPPC");
+ break;
+ }
+
+diff -up ghostscript-9.07/contrib/lips4/gdevl4r.c.gs_sprintf ghostscript-9.07/contrib/lips4/gdevl4r.c
+--- ghostscript-9.07/contrib/lips4/gdevl4r.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/lips4/gdevl4r.c 2013-05-09 17:02:39.095447210 +0100
+@@ -775,9 +775,9 @@ lips2p_image_out(gx_device_printer * pde
+ move_cap(pdev, prn_stream, x, y);
+
+ Len = lips_mode3format_encode(lprn->TmpBuf, lprn->CompBuf, width / 8 * height);
+- sprintf(raw_str, "%c%d;%d;%d.r", LIPS_CSI,
++ gs_sprintf(raw_str, "%c%d;%d;%d.r", LIPS_CSI,
+ width / 8 * height, width / 8, (int)pdev->x_pixels_per_inch);
+- sprintf(comp_str, "%c%d;%d;%d;9;%d.r", LIPS_CSI,
++ gs_sprintf(comp_str, "%c%d;%d;%d;9;%d.r", LIPS_CSI,
+ Len, width / 8, (int)pdev->x_pixels_per_inch, height);
+
+ if (Len < width / 8 * height - strlen(comp_str) + strlen(raw_str)) {
+@@ -806,11 +806,11 @@ lips4_image_out(gx_device_printer * pdev
+ Len = lips_packbits_encode(lprn->TmpBuf, lprn->CompBuf, width / 8 * height);
+ Len_rle = lips_rle_encode(lprn->TmpBuf, lprn->CompBuf2, width / 8 * height);
+
+- sprintf(raw_str, "%c%d;%d;%d.r", LIPS_CSI,
++ gs_sprintf(raw_str, "%c%d;%d;%d.r", LIPS_CSI,
+ width / 8 * height, width / 8, (int)pdev->x_pixels_per_inch);
+
+ if (Len < Len_rle) {
+- sprintf(comp_str, "%c%d;%d;%d;11;%d.r", LIPS_CSI,
++ gs_sprintf(comp_str, "%c%d;%d;%d;11;%d.r", LIPS_CSI,
+ Len, width / 8, (int)pdev->x_pixels_per_inch, height);
+ if (Len < width / 8 * height - strlen(comp_str) + strlen(raw_str)) {
+ fprintf(prn_stream, "%s", comp_str);
+@@ -821,7 +821,7 @@ lips4_image_out(gx_device_printer * pdev
+ fwrite(lprn->TmpBuf, 1, width / 8 * height, prn_stream);
+ }
+ } else {
+- sprintf(comp_str, "%c%d;%d;%d;10;%d.r", LIPS_CSI,
++ gs_sprintf(comp_str, "%c%d;%d;%d;10;%d.r", LIPS_CSI,
+ Len, width / 8, (int)pdev->x_pixels_per_inch, height);
+ if (Len_rle < width / 8 * height - strlen(comp_str) + strlen(raw_str)) {
+ fprintf(prn_stream, "%s", comp_str);
+diff -up ghostscript-9.07/contrib/lips4/gdevl4v.c.gs_sprintf ghostscript-9.07/contrib/lips4/gdevl4v.c
+--- ghostscript-9.07/contrib/lips4/gdevl4v.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/lips4/gdevl4v.c 2013-05-09 17:02:39.095447210 +0100
+@@ -459,17 +459,17 @@ lips4v_set_cap(gx_device * dev, int x, i
+ int dy = y - pdev->prev_y;
+
+ if (dx > 0) {
+- sprintf(cap, "%c%da", LIPS_CSI, dx);
++ gs_sprintf(cap, "%c%da", LIPS_CSI, dx);
+ lputs(s, cap);
+ } else if (dx < 0) {
+- sprintf(cap, "%c%dj", LIPS_CSI, -dx);
++ gs_sprintf(cap, "%c%dj", LIPS_CSI, -dx);
+ lputs(s, cap);
+ }
+ if (dy > 0) {
+- sprintf(cap, "%c%dk", LIPS_CSI, dy);
++ gs_sprintf(cap, "%c%dk", LIPS_CSI, dy);
+ lputs(s, cap);
+ } else if (dy < 0) {
+- sprintf(cap, "%c%de", LIPS_CSI, -dy);
++ gs_sprintf(cap, "%c%de", LIPS_CSI, -dy);
+ lputs(s, cap);
+ }
+ pdev->prev_x = x;
+@@ -544,10 +544,10 @@ lips4v_copy_text_char(gx_device * dev, c
+ if (download) {
+ if (ccode % 128 == 0 && ccode == pdev->count) {
+ /* ʸ»ú¥»¥Ã¥ÈÅÐÏ¿Êä½õÌ¿Îá */
+- sprintf(cset_sub, "%c%dx%c", LIPS_DCS, ccode / 128, LIPS_ST);
++ gs_sprintf(cset_sub, "%c%dx%c", LIPS_DCS, ccode / 128, LIPS_ST);
+ lputs(s, cset_sub);
+ /* ʸ»ú¥»¥Ã¥ÈÅÐÏ¿Ì¿Îá */
+- sprintf(cset,
++ gs_sprintf(cset,
+ "%c%d;1;0;0;3840;8;400;100;0;0;200;%d;%d;0;0;;;;;%d.p",
+ LIPS_CSI,
+ size + 9, cell_length, /* Cell Width */
+@@ -556,7 +556,7 @@ lips4v_copy_text_char(gx_device * dev, c
+ lputs(s, cset);
+ } else {
+ /* 1ʸ»úÅÐÏ¿Ì¿Îá */
+- sprintf(cset,
++ gs_sprintf(cset,
+ "%c%d;%d;8;%d.q", LIPS_CSI,
+ size + 9, ccode / 128, (int)dev->x_pixels_per_inch);
+ lputs(s, cset);
+@@ -575,13 +575,13 @@ lips4v_copy_text_char(gx_device * dev, c
+ /* ʸ»ú¥»¥Ã¥È¡¦¥¢¥µ¥¤¥óÈÖ¹æÁªÂòÌ¿Îá2 */
+ if (download) {
+ if (pdev->current_font != ccode / 128) {
+- sprintf(cset_number, "%c%d%%v", LIPS_CSI, ccode / 128);
++ gs_sprintf(cset_number, "%c%d%%v", LIPS_CSI, ccode / 128);
+ lputs(s, cset_number);
+ pdev->current_font = ccode / 128;
+ }
+ } else {
+ if (pdev->current_font != ccode / 128) {
+- sprintf(cset_number, "%c%d%%v", LIPS_CSI, ccode / 128);
++ gs_sprintf(cset_number, "%c%d%%v", LIPS_CSI, ccode / 128);
+ lputs(s, cset_number);
+ pdev->current_font = ccode / 128;
+ }
+@@ -592,7 +592,7 @@ lips4v_copy_text_char(gx_device * dev, c
+ if (pdev->color_info.depth == 8) {
+ sputc(s, LIPS_CSI);
+ lputs(s, "?10;2;");
+- sprintf(text_color, "%d",
++ gs_sprintf(text_color, "%d",
+ (int)(pdev->color_info.max_gray - pdev->current_color));
+ } else {
+ int r = (pdev->current_color >> 16) * 1000.0 / 255.0;
+@@ -601,7 +601,7 @@ lips4v_copy_text_char(gx_device * dev, c
+
+ sputc(s, LIPS_CSI);
+ lputs(s, "?10;;");
+- sprintf(text_color, "%d;%d;%d", r, g, b);
++ gs_sprintf(text_color, "%d;%d;%d", r, g, b);
+ }
+ lputs(s, text_color);
+ lputs(s, "%p");
+@@ -717,16 +717,16 @@ lips4v_beginpage(gx_device_vector * vdev
+ lputs(s, "@PJL SET RESOLUTION = QUICK\n");
+ lputs(s, l4v_file_header2);
+ if (pdev->toner_density) {
+- sprintf(toner_d, "@PJL SET TONER-DENSITY=%d\n",
++ gs_sprintf(toner_d, "@PJL SET TONER-DENSITY=%d\n",
+ pdev->toner_density);
+ lputs(s, toner_d);
+ }
+ if (pdev->toner_saving_set) {
+ lputs(s, "@PJL SET TONER-SAVING=");
+ if (pdev->toner_saving)
+- sprintf(toner_s, "ON\n");
++ gs_sprintf(toner_s, "ON\n");
+ else
+- sprintf(toner_s, "OFF\n");
++ gs_sprintf(toner_s, "OFF\n");
+ lputs(s, toner_s);
+ }
+ lputs(s, l4v_file_header3);
+@@ -737,7 +737,7 @@ lips4v_beginpage(gx_device_vector * vdev
+ return_error(gs_error_rangecheck);
+
+ /* set reaolution (dpi) */
+- sprintf(dpi_char, "%d", dpi);
++ gs_sprintf(dpi_char, "%d", dpi);
+ lputs(s, dpi_char);
+
+ if (pdev->color_info.depth == 8)
+@@ -746,7 +746,7 @@ lips4v_beginpage(gx_device_vector * vdev
+ lputs(s, l4vcolor_file_header);
+
+ /* username */
+- sprintf(username, "%c2y%s%c", LIPS_DCS, pdev->Username, LIPS_ST);
++ gs_sprintf(username, "%c2y%s%c", LIPS_DCS, pdev->Username, LIPS_ST);
+ lputs(s, username);
+ }
+ if (strcmp(pdev->mediaType, "PlainPaper") == 0) {
+@@ -773,13 +773,13 @@ lips4v_beginpage(gx_device_vector * vdev
+ && strcmp(pdev->mediaType, LIPS_MEDIATYPE_DEFAULT) != 0)) {
+ /* Use ManualFeed */
+ if (pdev->prev_feed_mode != 10) {
+- sprintf(feedmode, "%c10q", LIPS_CSI);
++ gs_sprintf(feedmode, "%c10q", LIPS_CSI);
+ lputs(s, feedmode);
+ pdev->prev_feed_mode = 10;
+ }
+ } else {
+ if (pdev->prev_feed_mode != pdev->cassetFeed) {
+- sprintf(feedmode, "%c%dq", LIPS_CSI, pdev->cassetFeed);
++ gs_sprintf(feedmode, "%c%dq", LIPS_CSI, pdev->cassetFeed);
+ lputs(s, feedmode);
+ pdev->prev_feed_mode = pdev->cassetFeed;
+ }
+@@ -791,10 +791,10 @@ lips4v_beginpage(gx_device_vector * vdev
+ if (pdev->prev_paper_size != paper_size) {
+ if (paper_size == USER_SIZE) {
+ /* modified by shige 06/27 2003
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI, width * 10, height * 10); */
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI, width * 10, height * 10); */
+ /* modified by shige 11/09 2003
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI, height * 10, width * 10); */
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI, height * 10, width * 10); */
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
+ (height * 10 > LIPS_HEIGHT_MAX_720)?
+ LIPS_HEIGHT_MAX_720 : (height * 10),
+ (width * 10 > LIPS_WIDTH_MAX_720)?
+@@ -802,27 +802,27 @@ lips4v_beginpage(gx_device_vector * vdev
+ lputs(s, paper);
+ } else if (paper_size == USER_SIZE + LANDSCAPE) {
+ /* modified by shige 06/27 2003
+- sprintf(paper, "%c81;%d;%dp", LIPS_CSI, height * 10, width * 10); */
++ gs_sprintf(paper, "%c81;%d;%dp", LIPS_CSI, height * 10, width * 10); */
+ /* modified by shige 11/09 2003
+- sprintf(paper, "%c81;%d;%dp", LIPS_CSI, width * 10, height * 10); */
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
++ gs_sprintf(paper, "%c81;%d;%dp", LIPS_CSI, width * 10, height * 10); */
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
+ (width * 10 > LIPS_HEIGHT_MAX_720)?
+ LIPS_HEIGHT_MAX_720 : (width * 10),
+ (height * 10 > LIPS_WIDTH_MAX_720)?
+ LIPS_WIDTH_MAX_720 : (height * 10));
+ lputs(s, paper);
+ } else {
+- sprintf(paper, "%c%dp", LIPS_CSI, paper_size);
++ gs_sprintf(paper, "%c%dp", LIPS_CSI, paper_size);
+ lputs(s, paper);
+ }
+ } else if (paper_size == USER_SIZE) {
+ if (pdev->prev_paper_width != width ||
+ pdev->prev_paper_height != height)
+ /* modified by shige 06/27 2003
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI, width * 10, height * 10); */
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI, width * 10, height * 10); */
+ /* modified by shige 11/09 2003
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI, height * 10, width * 10); */
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI, height * 10, width * 10); */
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
+ (height * 10 > LIPS_HEIGHT_MAX_720)?
+ LIPS_HEIGHT_MAX_720 : (height * 10),
+ (width * 10 > LIPS_WIDTH_MAX_720)?
+@@ -832,10 +832,10 @@ lips4v_beginpage(gx_device_vector * vdev
+ if (pdev->prev_paper_width != width ||
+ pdev->prev_paper_height != height)
+ /* modified by shige 06/27 2003
+- sprintf(paper, "%c81;%d;%dp", LIPS_CSI, height * 10, width * 10); */
++ gs_sprintf(paper, "%c81;%d;%dp", LIPS_CSI, height * 10, width * 10); */
+ /* modified by shige 11/09 2003
+- sprintf(paper, "%c81;%d;%dp", LIPS_CSI, width * 10, height * 10); */
+- sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
++ gs_sprintf(paper, "%c81;%d;%dp", LIPS_CSI, width * 10, height * 10); */
++ gs_sprintf(paper, "%c80;%d;%dp", LIPS_CSI,
+ (width * 10 > LIPS_HEIGHT_MAX_720)?
+ LIPS_HEIGHT_MAX_720 : (width * 10),
+ (height * 10 > LIPS_WIDTH_MAX_720)?
+@@ -847,32 +847,32 @@ lips4v_beginpage(gx_device_vector * vdev
+ pdev->prev_paper_height = height;
+
+ if (pdev->faceup) {
+- sprintf(faceup_char, "%c11;12;12~", LIPS_CSI);
++ gs_sprintf(faceup_char, "%c11;12;12~", LIPS_CSI);
+ lputs(s, faceup_char);
+ }
+ /* N-up Printing Setting */
+ if (pdev->first_page) {
+ if (pdev->nup != 1) {
+- sprintf(nup_char, "%c%d1;;%do", LIPS_CSI, pdev->nup, paper_size);
++ gs_sprintf(nup_char, "%c%d1;;%do", LIPS_CSI, pdev->nup, paper_size);
+ lputs(s, nup_char);
+ }
+ }
+ /* Duplex Setting */
+ if (dupset && dup) {
+ if (pdev->prev_duplex_mode == 0 || pdev->prev_duplex_mode == 1) {
+- sprintf(duplex_char, "%c2;#x", LIPS_CSI); /* duplex */
++ gs_sprintf(duplex_char, "%c2;#x", LIPS_CSI); /* duplex */
+ lputs(s, duplex_char);
+ if (!tum) {
+ /* long edge binding */
+ if (pdev->prev_duplex_mode != 2) {
+- sprintf(tumble_char, "%c0;#w", LIPS_CSI);
++ gs_sprintf(tumble_char, "%c0;#w", LIPS_CSI);
+ lputs(s, tumble_char);
+ }
+ pdev->prev_duplex_mode = 2;
+ } else {
+ /* short edge binding */
+ if (pdev->prev_duplex_mode != 3) {
+- sprintf(tumble_char, "%c2;#w", LIPS_CSI);
++ gs_sprintf(tumble_char, "%c2;#w", LIPS_CSI);
+ lputs(s, tumble_char);
+ }
+ pdev->prev_duplex_mode = 3;
+@@ -880,7 +880,7 @@ lips4v_beginpage(gx_device_vector * vdev
+ }
+ } else if (dupset && !dup) {
+ if (pdev->prev_duplex_mode != 1) {
+- sprintf(duplex_char, "%c0;#x", LIPS_CSI); /* simplex */
++ gs_sprintf(duplex_char, "%c0;#x", LIPS_CSI); /* simplex */
+ lputs(s, duplex_char);
+ }
+ pdev->prev_duplex_mode = 1;
+@@ -893,9 +893,9 @@ lips4v_beginpage(gx_device_vector * vdev
+ /* size unit (dpi) */
+ sputc(s, LIPS_CSI);
+ lputs(s, "11h");
+- sprintf(unit, "%c?7;%d I", LIPS_CSI, (int)pdev->x_pixels_per_inch);
++ gs_sprintf(unit, "%c?7;%d I", LIPS_CSI, (int)pdev->x_pixels_per_inch);
+ lputs(s, unit);
+- sprintf(page_header, "%c[0&}#%c", LIPS_ESC, LIPS_IS2);
++ gs_sprintf(page_header, "%c[0&}#%c", LIPS_ESC, LIPS_IS2);
+ lputs(s, page_header); /* vector mode */
+
+ lputs(s, "!0"); /* size unit (dpi) */
+@@ -904,10 +904,10 @@ lips4v_beginpage(gx_device_vector * vdev
+ sputc(s, LIPS_IS2);
+
+ if (pdev->color_info.depth == 8) {
+- sprintf(l4vmono_page_header, "!13%c$%c", LIPS_IS2, LIPS_IS2);
++ gs_sprintf(l4vmono_page_header, "!13%c$%c", LIPS_IS2, LIPS_IS2);
+ lputs(s, l4vmono_page_header);
+ } else {
+- sprintf(l4vcolor_page_header, "!11%c$%c", LIPS_IS2, LIPS_IS2);
++ gs_sprintf(l4vcolor_page_header, "!11%c$%c", LIPS_IS2, LIPS_IS2);
+ lputs(s, l4vcolor_page_header);
+ }
+
+@@ -1010,7 +1010,7 @@ lips4v_setlinecap(gx_device_vector * vde
+ break;
+ }
+ /* Àþü·Á¾õ»ØÄêÌ¿Îá */
+- sprintf(c, "}E%d%c", line_cap, LIPS_IS2);
++ gs_sprintf(c, "}E%d%c", line_cap, LIPS_IS2);
+ lputs(s, c);
+
+ pdev->linecap = cap;
+@@ -1050,7 +1050,7 @@ lips4v_setlinejoin(gx_device_vector * vd
+ break;
+ }
+
+- sprintf(c, "}F%d%c", lips_join, LIPS_IS2);
++ gs_sprintf(c, "}F%d%c", lips_join, LIPS_IS2);
+ lputs(s, c);
+
+ return 0;
+@@ -1486,7 +1486,7 @@ lips4v_output_page(gx_device * dev, int
+ if (num_copies > 255)
+ num_copies = 255;
+ if (pdev->prev_num_copies != num_copies) {
+- sprintf(str, "%c%dv", LIPS_CSI, num_copies);
++ gs_sprintf(str, "%c%dv", LIPS_CSI, num_copies);
+ lputs(s, str);
+ pdev->prev_num_copies = num_copies;
+ }
+diff -up ghostscript-9.07/contrib/pcl3/src/gdevpcl3.c.gs_sprintf ghostscript-9.07/contrib/pcl3/src/gdevpcl3.c
+--- ghostscript-9.07/contrib/pcl3/src/gdevpcl3.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/contrib/pcl3/src/gdevpcl3.c 2013-05-09 17:02:39.095447210 +0100
+@@ -302,7 +302,7 @@ static void get_string_for_int(int in_va
+ else {
+ static char buffer[22]; /* Must be sufficient for an 'int' */
+
+- sprintf(buffer, "%d", in_value);
++ gs_sprintf(buffer, "%d", in_value);
+ assert(strlen(buffer) < sizeof(buffer));
+ out_value->data = (const byte *)buffer;
+ out_value->size = strlen(buffer);
+diff -up ghostscript-9.07/cups/gdevcups.c.gs_sprintf ghostscript-9.07/cups/gdevcups.c
+--- ghostscript-9.07/cups/gdevcups.c.gs_sprintf 2013-05-09 17:02:39.048447008 +0100
++++ ghostscript-9.07/cups/gdevcups.c 2013-05-09 17:02:39.096447214 +0100
+@@ -60,6 +60,9 @@
+ * cups_print_planar() - Print a page of planar pixels.
+ */
+
++/* prevent gp.h redefining fopen */
++#define sprintf sprintf
++
+ /*
+ * Include necessary headers...
+ */
+diff -up ghostscript-9.07/base/Makefile.in.gs_sprintf ghostscript-9.07/base/Makefile.in
+--- ghostscript-9.07/base/Makefile.in.gs_sprintf 2013-05-09 17:02:46.190477741 +0100
++++ ghostscript-9.07/base/Makefile.in 2013-05-09 17:03:22.377633508 +0100
+@@ -302,6 +302,8 @@ LCUPSISRCDIR=cups
+ CUPS_CC=$(CC)
+
+
++TRIOSRCDIR=trio
++
+ # Define how to build the library archives. (These are not used in any
+ # standard configuration.)
+
+@@ -583,6 +585,7 @@ MAKEDIRSTOP=
+ INSTALL_CONTRIB=@INSTALL_CONTRIB@
+ include $(GLSRCDIR)/unixhead.mak
+ include $(GLSRCDIR)/gs.mak
++include $(GLSRCDIR)/trio.mak
+ # psromfs.mak must precede lib.mak
+ include $(PSSRCDIR)/psromfs.mak
+ include $(GLSRCDIR)/lib.mak
+diff -up ghostscript-9.07/psi/dmmain.c.gs_sprintf ghostscript-9.07/psi/dmmain.c
+--- ghostscript-9.07/psi/dmmain.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/dmmain.c 2013-05-09 17:02:39.096447214 +0100
+@@ -644,8 +644,8 @@ void main(void)
+ argv[1] = ddevice;
+ argv[2] = dformat;
+
+- sprintf(ddevice, "-sDEVICE=display");
+- sprintf(dformat, "-dDisplayFormat=%d", display_format);
++ gs_sprintf(ddevice, "-sDEVICE=display");
++ gs_sprintf(dformat, "-dDisplayFormat=%d", display_format);
+
+ /* Run Ghostscript */
+ if (gsapi_new_instance(&instance, NULL) < 0)
+diff -up ghostscript-9.07/psi/dpmain.c.gs_sprintf ghostscript-9.07/psi/dpmain.c
+--- ghostscript-9.07/psi/dpmain.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/dpmain.c 2013-05-09 17:02:39.097447219 +0100
+@@ -100,9 +100,9 @@ gs_free_dll(void)
+ return TRUE;
+ rc = DosFreeModule(gsdll.hmodule);
+ if (rc) {
+- sprintf(buf, "DosFreeModule returns %d\n", rc);
++ gs_sprintf(buf, "DosFreeModule returns %d\n", rc);
+ gs_addmess(buf);
+- sprintf(buf, "Unloaded GSDLL\n\n");
++ gs_sprintf(buf, "Unloaded GSDLL\n\n");
+ gs_addmess(buf);
+ }
+ return !rc;
+@@ -150,7 +150,7 @@ gs_load_dll(void)
+ dllname = szDllName;
+ #ifdef DEBUG
+ if (debug) {
+- sprintf(buf, "Trying to load %s\n", dllname);
++ gs_sprintf(buf, "Trying to load %s\n", dllname);
+ gs_addmess(buf);
+ }
+ #endif
+@@ -172,7 +172,7 @@ gs_load_dll(void)
+ dllname = fullname;
+ #ifdef DEBUG
+ if (debug) {
+- sprintf(buf, "Trying to load %s\n", dllname);
++ gs_sprintf(buf, "Trying to load %s\n", dllname);
+ gs_addmess(buf);
+ }
+ #endif
+@@ -183,7 +183,7 @@ gs_load_dll(void)
+ dllname = shortname;
+ #ifdef DEBUG
+ if (debug) {
+- sprintf(buf, "Trying to load %s\n", dllname);
++ gs_sprintf(buf, "Trying to load %s\n", dllname);
+ gs_addmess(buf);
+ }
+ #endif
+@@ -197,21 +197,21 @@ gs_load_dll(void)
+ #endif
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_REVISION",
+ (PFN *) (&gsdll.revision))) != 0) {
+- sprintf(buf, "Can't find GSAPI_REVISION, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_REVISION, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ /* check DLL version */
+ if (gsdll.revision(&rv, sizeof(rv)) != 0) {
+- sprintf(buf, "Unable to identify Ghostscript DLL revision - it must be newer than needed.\n");
++ gs_sprintf(buf, "Unable to identify Ghostscript DLL revision - it must be newer than needed.\n");
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+
+ if (rv.revision != GS_REVISION) {
+- sprintf(buf, "Wrong version of DLL found.\n Found version %ld\n Need version %ld\n", rv.revision, (long)GS_REVISION);
++ gs_sprintf(buf, "Wrong version of DLL found.\n Found version %ld\n Need version %ld\n", rv.revision, (long)GS_REVISION);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+@@ -219,35 +219,35 @@ gs_load_dll(void)
+
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_NEW_INSTANCE",
+ (PFN *) (&gsdll.new_instance))) != 0) {
+- sprintf(buf, "Can't find GSAPI_NEW_INSTANCE, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_NEW_INSTANCE, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_DELETE_INSTANCE",
+ (PFN *) (&gsdll.delete_instance))) != 0) {
+- sprintf(buf, "Can't find GSAPI_DELETE_INSTANCE, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_DELETE_INSTANCE, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_SET_STDIO",
+ (PFN *) (&gsdll.set_stdio))) != 0) {
+- sprintf(buf, "Can't find GSAPI_SET_STDIO, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_SET_STDIO, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_SET_DISPLAY_CALLBACK",
+ (PFN *) (&gsdll.set_display_callback))) != 0) {
+- sprintf(buf, "Can't find GSAPI_SET_DISPLAY_CALLBACK, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_SET_DISPLAY_CALLBACK, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_SET_POLL",
+ (PFN *) (&gsdll.set_poll))) != 0) {
+- sprintf(buf, "Can't find GSAPI_SET_POLL, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_SET_POLL, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+@@ -255,27 +255,27 @@ gs_load_dll(void)
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0,
+ "GSAPI_INIT_WITH_ARGS",
+ (PFN *) (&gsdll.init_with_args))) != 0) {
+- sprintf(buf, "Can't find GSAPI_INIT_WITH_ARGS, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_INIT_WITH_ARGS, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_RUN_STRING",
+ (PFN *) (&gsdll.run_string))) != 0) {
+- sprintf(buf, "Can't find GSAPI_RUN_STRING, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_RUN_STRING, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_EXIT",
+ (PFN *) (&gsdll.exit))) != 0) {
+- sprintf(buf, "Can't find GSAPI_EXIT, rc = %d\n", rc);
++ gs_sprintf(buf, "Can't find GSAPI_EXIT, rc = %d\n", rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+ return FALSE;
+ }
+ } else {
+- sprintf(buf, "Can't load Ghostscript DLL %s \nDosLoadModule rc = %d\n",
++ gs_sprintf(buf, "Can't load Ghostscript DLL %s \nDosLoadModule rc = %d\n",
+ szDllName, rc);
+ gs_addmess(buf);
+ gs_load_dll_cleanup();
+@@ -373,10 +373,10 @@ static int run_gspmdrv(IMAGE *img)
+ if (debug)
+ fprintf(stdout, "run_gspmdrv: starting\n");
+ #endif
+- sprintf(id, ID_NAME, img->pid, (ULONG)img->device);
++ gs_sprintf(id, ID_NAME, img->pid, (ULONG)img->device);
+
+ /* Create termination queue - used to find out when gspmdrv terminates */
+- sprintf(term_queue_name, "\\QUEUES\\TERMQ_%s", id);
++ gs_sprintf(term_queue_name, "\\QUEUES\\TERMQ_%s", id);
+ if (DosCreateQueue(&(img->term_queue), QUE_FIFO, term_queue_name)) {
+ fprintf(stdout, "run_gspmdrv: failed to create termination queue\n");
+ return e_limitcheck;
+@@ -404,7 +404,7 @@ static int run_gspmdrv(IMAGE *img)
+ /* arguments are: */
+ /* (1) -d (display) option */
+ /* (2) id string */
+- sprintf(arg, "-d %s", id);
++ gs_sprintf(arg, "-d %s", id);
+
+ /* because gspmdrv.exe is a different EXE type to gs.exe,
+ * we must use start session not DosExecPgm() */
+@@ -592,17 +592,17 @@ int display_open(void *handle, void *dev
+ return e_limitcheck;
+ }
+ img->pid = pppib->pib_ulppid; /* use parent (CMD.EXE) pid */
+- sprintf(id, ID_NAME, img->pid, (ULONG) img->device);
++ gs_sprintf(id, ID_NAME, img->pid, (ULONG) img->device);
+
+ /* Create update event semaphore */
+- sprintf(name, SYNC_NAME, id);
++ gs_sprintf(name, SYNC_NAME, id);
+ if (DosCreateEventSem(name, &(img->sync_event), 0, FALSE)) {
+ fprintf(stdout, "display_open: failed to create event semaphore %s\n", name);
+ return e_limitcheck;
+ }
+ /* Create mutex - used for preventing gspmdrv from accessing */
+ /* bitmap while we are changing the bitmap size. Initially unowned. */
+- sprintf(name, MUTEX_NAME, id);
++ gs_sprintf(name, MUTEX_NAME, id);
+ if (DosCreateMutexSem(name, &(img->bmp_mutex), 0, FALSE)) {
+ DosCloseEventSem(img->sync_event);
+ fprintf(stdout, "display_open: failed to create mutex semaphore %s\n", name);
+@@ -612,7 +612,7 @@ int display_open(void *handle, void *dev
+ /* Shared memory is common to all processes so we don't want to
+ * allocate too much.
+ */
+- sprintf(name, SHARED_NAME, id);
++ gs_sprintf(name, SHARED_NAME, id);
+ if (DosAllocSharedMem((PPVOID) & img->bitmap, name,
+ 13 * 1024 * 1024, PAG_READ | PAG_WRITE)) {
+ fprintf(stdout, "display_open: failed allocating shared BMP memory %s\n", name);
+@@ -1020,7 +1020,7 @@ main(int argc, char *argv[])
+ else if (depth >= 4)
+ format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
+ DISPLAY_DEPTH_4 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
+- sprintf(dformat, "-dDisplayFormat=%d", format);
++ gs_sprintf(dformat, "-dDisplayFormat=%d", format);
+ }
+ nargc = argc + 1;
+
+diff -up ghostscript-9.07/psi/dscparse.c.gs_sprintf ghostscript-9.07/psi/dscparse.c
+--- ghostscript-9.07/psi/dscparse.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/dscparse.c 2013-05-09 17:02:39.097447219 +0100
+@@ -38,7 +38,7 @@
+ % %%ViewingOrientation: xx xy yx yy
+ */
+
+-#include <stdio.h> /* for sprintf(), not file I/O */
++#include <stdio_.h> /* for sprintf(), not file I/O */
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+@@ -584,7 +584,7 @@ dsc_fixup(CDSC *dsc)
+ /* make sure all pages have a label */
+ for (i=0; i<dsc->page_count; i++) {
+ if (strlen(dsc->page[i].label) == 0) {
+- sprintf(buf, "%d", i+1);
++ gs_sprintf(buf, "%d", i+1);
+ if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf)))
+ == (char *)NULL)
+ return CDSC_ERROR; /* no memory */
+@@ -1178,7 +1178,7 @@ dsc_unknown(CDSC *dsc)
+ if (dsc->debug_print_fn) {
+ char line[DSC_LINE_LENGTH];
+ unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
+- sprintf(line, "Unknown in %s section at line %d:\n ",
++ gs_sprintf(line, "Unknown in %s section at line %d:\n ",
+ dsc_scan_section_name[dsc->scan_section], dsc->line_count);
+ dsc_debug_print(dsc, line);
+ strncpy(line, dsc->line, length);
+@@ -2669,7 +2669,7 @@ dsc_check_match_prompt(CDSC *dsc, const
+ strncpy(buf, dsc->line, dsc->line_length);
+ buf[dsc->line_length] = '\0';
+ }
+- sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
++ gs_sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
+ return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, (int)strlen(buf));
+ }
+ return CDSC_RESPONSE_CANCEL;
+diff -up ghostscript-9.07/psi/dwimg.c.gs_sprintf ghostscript-9.07/psi/dwimg.c
+--- ghostscript-9.07/psi/dwimg.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/dwimg.c 2013-05-09 17:02:39.098447223 +0100
+@@ -36,6 +36,11 @@
+
+ #define STRICT
+ #include <windows.h>
++
++
++/* prevent gp.h redefining sprintf */
++#define sprintf sprintf
++
+ #include "stdio_.h"
+
+ #include "dwres.h"
+diff -up ghostscript-9.07/psi/dwmainc.c.gs_sprintf ghostscript-9.07/psi/dwmainc.c
+--- ghostscript-9.07/psi/dwmainc.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/dwmainc.c 2013-05-09 17:02:39.098447223 +0100
+@@ -13,6 +13,8 @@
+ CA 94903, U.S.A., +1(415)492-9861, for further information.
+ */
+
++/* prevent gp.h redefining sprintf */
++#define sprintf sprintf
+
+ /* dwmainc.c */
+
+diff -up ghostscript-9.07/psi/dxmain.c.gs_sprintf ghostscript-9.07/psi/dxmain.c
+--- ghostscript-9.07/psi/dxmain.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/dxmain.c 2013-05-09 17:02:39.098447223 +0100
+@@ -1160,7 +1160,7 @@ int main(int argc, char *argv[])
+ use_gui = gtk_init_check(&argc, &argv);
+
+ /* insert display device parameters as first arguments */
+- sprintf(dformat, "-dDisplayFormat=%d",
++ gs_sprintf(dformat, "-dDisplayFormat=%d",
+ DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
+ DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST);
+ nargc = argc + 1;
+diff -up ghostscript-9.07/psi/int.mak.gs_sprintf ghostscript-9.07/psi/int.mak
+--- ghostscript-9.07/psi/int.mak.gs_sprintf 2013-05-09 17:02:39.018446879 +0100
++++ ghostscript-9.07/psi/int.mak 2013-05-09 17:02:39.098447223 +0100
+@@ -651,7 +651,7 @@ $(PSOBJ)zdscpars.$(OBJ) : $(PSSRC)zdscpa
+ $(gsstruct_h)
+ $(PSCC) $(PSO_)zdscpars.$(OBJ) $(C_) $(PSSRC)zdscpars.c
+
+-$(PSOBJ)dscparse.$(OBJ) : $(PSSRC)dscparse.c $(dscparse_h)
++$(PSOBJ)dscparse.$(OBJ) : $(PSSRC)dscparse.c $(dscparse_h) $(stdio__h)
+ $(PSCC) $(PSO_)dscparse.$(OBJ) $(C_) $(PSSRC)dscparse.c
+
+ dscparse_=$(PSOBJ)zdscpars.$(OBJ) $(PSOBJ)dscparse.$(OBJ)
+diff -up ghostscript-9.07/psi/iparam.c.gs_sprintf ghostscript-9.07/psi/iparam.c
+--- ghostscript-9.07/psi/iparam.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/iparam.c 2013-05-09 17:02:39.099447227 +0100
+@@ -65,7 +65,7 @@ ref_to_key(const ref * pref, gs_param_ke
+ int len;
+ byte *buf;
+
+- sprintf(istr, "%"PRIpsint, pref->value.intval);
++ gs_sprintf(istr, "%"PRIpsint, pref->value.intval);
+ len = strlen(istr);
+ /* GC will take care of freeing this: */
+ buf = gs_alloc_string(plist->memory, len, "ref_to_key");
+diff -up ghostscript-9.07/psi/iutil2.c.gs_sprintf ghostscript-9.07/psi/iutil2.c
+--- ghostscript-9.07/psi/iutil2.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/iutil2.c 2013-05-09 17:02:39.099447227 +0100
+@@ -56,7 +56,7 @@ param_read_password(gs_param_list * plis
+ code = param_read_long(plist, kstr, &ipass);
+ if (code != 0) /* error or missing */
+ return code;
+- sprintf((char *)ppass->data, "%ld", ipass);
++ gs_sprintf((char *)ppass->data, "%ld", ipass);
+ ppass->size = strlen((char *)ppass->data);
+ return 0;
+ }
+diff -up ghostscript-9.07/psi/iutil.c.gs_sprintf ghostscript-9.07/psi/iutil.c
+--- ghostscript-9.07/psi/iutil.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/iutil.c 2013-05-09 17:02:39.099447227 +0100
+@@ -340,10 +340,10 @@ obj_cvp(const ref * op, byte * str, uint
+ float value = op->value.realval;
+ float scanned;
+
+- sprintf(buf, "%g", value);
++ gs_sprintf(buf, "%g", value);
+ sscanf(buf, "%f", &scanned);
+ if (scanned != value)
+- sprintf(buf, "%.9g", value);
++ gs_sprintf(buf, "%.9g", value);
+ ensure_dot(buf);
+ goto rs;
+ }
+@@ -494,7 +494,7 @@ other:
+ data = (const byte *)(op->value.boolval ? "true" : "false");
+ break;
+ case t_integer:
+- sprintf(buf, "%"PRIpsint, op->value.intval);
++ gs_sprintf(buf, "%"PRIpsint, op->value.intval);
+ break;
+ case t_string:
+ check_read(*op);
+@@ -529,7 +529,7 @@ other:
+ break;
+ }
+ /* Internal operator, no name. */
+- sprintf(buf, "@0x%lx", (ulong) op->value.opproc);
++ gs_sprintf(buf, "@0x%lx", (ulong) op->value.opproc);
+ break;
+ }
+ case t_real:
+@@ -542,7 +542,7 @@ other:
+ if (op->value.realval == (float)0.0001) {
+ strcpy(buf, "0.0001");
+ } else {
+- sprintf(buf, "%g", op->value.realval);
++ gs_sprintf(buf, "%g", op->value.realval);
+ }
+ ensure_dot(buf);
+ break;
+@@ -573,9 +573,9 @@ ensure_dot(char *buf)
+ sscanf(pe + 1, "%d", &i);
+ /* MSVC .net 2005 express doesn't support "%+02d" */
+ if (i >= 0)
+- sprintf(pe + 1, "+%02d", i);
++ gs_sprintf(pe + 1, "+%02d", i);
+ else
+- sprintf(pe + 1, "-%02d", -i);
++ gs_sprintf(pe + 1, "-%02d", -i);
+ } else if (strchr(buf, '.') == NULL) {
+ strcat(buf, ".0");
+ }
+diff -up ghostscript-9.07/psi/msvc.mak.gs_sprintf ghostscript-9.07/psi/msvc.mak
+--- ghostscript-9.07/psi/msvc.mak.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/msvc.mak 2013-05-09 17:02:39.099447227 +0100
+@@ -332,6 +332,10 @@ TIFFCONFIG_SUFFIX=.vc
+ TIFFPLATFORM=win32
+ !endif
+
++!ifndef TRIOSRCDIR
++TRIOSRCDIR=trio
++!endif
++
+ # Define the directory where the zlib sources are stored.
+ # See zlib.mak for more information.
+
+diff -up ghostscript-9.07/psi/zbfont.c.gs_sprintf ghostscript-9.07/psi/zbfont.c
+--- ghostscript-9.07/psi/zbfont.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/zbfont.c 2013-05-09 17:02:39.099447227 +0100
+@@ -109,7 +109,7 @@ zfont_encode_char(gs_font *pfont, gs_cha
+
+ if (gspace == GLYPH_SPACE_NOGEN)
+ return gs_no_glyph;
+- sprintf(buf, "j%ld", chr); /* 'j' is arbutrary. */
++ gs_sprintf(buf, "j%ld", chr); /* 'j' is arbutrary. */
+ code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
+ if (code < 0) {
+ /* Can't propagate the error due to interface limitation,
+@@ -131,7 +131,7 @@ zfont_glyph_name(gs_font *font, gs_glyph
+ char cid_name[sizeof(gs_glyph) * 3 + 1];
+ int code;
+
+- sprintf(cid_name, "%lu", (ulong) index);
++ gs_sprintf(cid_name, "%lu", (ulong) index);
+ code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
+ &nref, 1);
+ if (code < 0)
+diff -up ghostscript-9.07/psi/zdouble.c.gs_sprintf ghostscript-9.07/psi/zdouble.c
+--- ghostscript-9.07/psi/zdouble.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/zdouble.c 2013-05-09 17:02:39.100447231 +0100
+@@ -323,7 +323,7 @@ zcvsd(i_ctx_t *i_ctx_p)
+ len = r_size(op - 1);
+ if (len > MAX_CHARS)
+ return_error(e_limitcheck);
+- sprintf(buf, "%f", 1.5);
++ gs_sprintf(buf, "%f", 1.5);
+ dot = buf[1]; /* locale-dependent */
+ memcpy(str, op[-1].value.bytes, len);
+ /*
+@@ -406,7 +406,7 @@ zdcvs(i_ctx_t *i_ctx_p)
+ if (code < 0)
+ return code;
+ check_write_type(*op, t_string);
+- sprintf(str, "%f", 1.5);
++ gs_sprintf(str, "%f", 1.5);
+ dot = str[1]; /* locale-dependent */
+ /*
+ * To get fully accurate output results for IEEE double-
+@@ -420,10 +420,10 @@ zdcvs(i_ctx_t *i_ctx_p)
+ {
+ double scanned;
+
+- sprintf(str, "%g", num);
++ gs_sprintf(str, "%g", num);
+ sscanf(str, "%lf", &scanned);
+ if (scanned != num)
+- sprintf(str, "%.16g", num);
++ gs_sprintf(str, "%.16g", num);
+ }
+ len = strlen(str);
+ if (len > r_size(op))
+diff -up ghostscript-9.07/psi/zfapi.c.gs_sprintf ghostscript-9.07/psi/zfapi.c
+--- ghostscript-9.07/psi/zfapi.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/zfapi.c 2013-05-09 17:02:39.100447231 +0100
+@@ -583,11 +583,11 @@ FAPI_FF_get_word(gs_fapi_font *ff, gs_fa
+ length += r_size(&string) + 1;
+ break;
+ case t_real:
+- sprintf(Buffer, "%f", Element.value.realval);
++ gs_sprintf(Buffer, "%f", Element.value.realval);
+ length += strlen(Buffer) + 1;
+ break;
+ case t_integer:
+- sprintf(Buffer, "%"PRIpsint, Element.value.intval);
++ gs_sprintf(Buffer, "%"PRIpsint, Element.value.intval);
+ length += strlen(Buffer) + 1;
+ break;
+ case t_operator:
+@@ -823,12 +823,12 @@ FAPI_FF_get_proc(gs_fapi_font *ff, gs_fa
+ ptr += r_size(&string);
+ break;
+ case t_real:
+- sprintf(Buf, "%f", Element.value.realval);
++ gs_sprintf(Buf, "%f", Element.value.realval);
+ strcpy(ptr, Buf);
+ ptr += strlen(Buf);
+ break;
+ case t_integer:
+- sprintf(Buf, "%"PRIpsint, Element.value.intval);
++ gs_sprintf(Buf, "%"PRIpsint, Element.value.intval);
+ strcpy(ptr, Buf);
+ ptr += strlen(Buf);
+ break;
+diff -up ghostscript-9.07/psi/zfont2.c.gs_sprintf ghostscript-9.07/psi/zfont2.c
+--- ghostscript-9.07/psi/zfont2.c.gs_sprintf 2013-02-14 07:58:13.000000000 +0000
++++ ghostscript-9.07/psi/zfont2.c 2013-05-09 17:02:39.101447236 +0100
+@@ -2666,7 +2666,7 @@ parse_font(i_ctx_t *i_ctx_p, ref *topdi
+ return sid;
+ if ((code = make_name_from_sid(i_ctx_p, &name, strings, data, sid)) < 0) {
+ char buf[40];
+- int len = sprintf(buf, "sid-%d", sid);
++ int len = gs_sprintf(buf, "sid-%d", sid);
+
+ if ((code = name_ref(imemory, (unsigned char *)buf, len, &name, 1)) < 0)
+ return code;
+diff -up ghostscript-9.07/trio/autogen.sh.gs_sprintf ghostscript-9.07/trio/autogen.sh
+--- ghostscript-9.07/trio/autogen.sh.gs_sprintf 2013-05-09 17:02:39.101447236 +0100
++++ ghostscript-9.07/trio/autogen.sh 2013-05-09 17:02:39.101447236 +0100
+@@ -0,0 +1,3 @@
++#!/bin/sh
++autoconf
++rm -rf autom4te.cache
+diff -up ghostscript-9.07/trio/CHANGES.gs_sprintf ghostscript-9.07/trio/CHANGES
+--- ghostscript-9.07/trio/CHANGES.gs_sprintf 2013-05-09 17:02:39.101447236 +0100
++++ ghostscript-9.07/trio/CHANGES 2013-05-09 17:02:39.101447236 +0100
+@@ -0,0 +1,785 @@
++CHANGES -- trio
++
++
++The changes listed without a name attributed to them were most likely done by
++Bjorn Reese and/or Daniel Stenberg.
++
++Version 1.14 - 2010/01/26
++-------------------------
++* David Byron
++ Added trio_xstring_append_max.
++
++* Fixed compilation problem on Cygwin due to lack of long double math
++ (reported by Matthias Andree).
++
++* David Boyce
++ Added #undef of standard stdio function names before assigning trio functions
++ to them.
++
++* Matthias Andree
++ Upgraded configure.in to use new macros instead of obsoleted macros.
++
++* Matthias Andree
++ Added VPATH to Makefile.in
++
++* Tom Honermann
++ Fixed problem with subnormal numbers which caused an infinite loop outputting
++ leading spaces.
++
++* Adam McLaurin
++ Improved parsing performance by avoiding memset() and memcpy() on character
++ arrays.
++
++* Gideon Smeding
++ Fixed %u scanning of signed numbers.
++
++* Gideon Smeding
++ Fixed group scanning for non-matching input.
++
++* Fixed missing undo of look-ahead reading for scanf functions. This does only
++ work for the scanf* and fscanf* functions, not dscanf* and cscanf* functions
++ (reported by Gideon Smeding).
++
++* If the format string is empty, scanf does not attempt to read any input.
++
++* Ralf Junker
++ Fixed Borland compilation for user-defined specifiers.
++
++
++Version 1.13 - 2008/11/09
++-------------------------
++* Ives Aerts
++ Added the $<format|skip> format for user-defined specifiers, which is
++ compatible with compiler warnings about mismatches between specifiers and
++ arguments.
++
++* Added TRIO_DEPRECATED flag (reported by David Boyce)
++
++* Fixed rounding adjustment for long double (reported as bug item #2136686).
++
++* Added Makefile dependency for test target (reported as bug item #2136636).
++
++* David Boyce
++ Fixed long long support for MSVC.
++
++* Fixed potential problem with read after buffer end for non-zero terminated
++ strings (reported as bug item #1828465).
++
++* Andreas Stricker
++ Added WinCE support.
++
++* Fixed number of significant digits for %g.
++
++
++Version 1.12 - 2006/10/22
++-------------------------
++* Fixed scanning of floats (reported by Bernd Ahlers).
++
++* Fixed configure.in for GCC on Tru64 and MIPSpro on IRIX (reported by Andreas
++ Maus).
++
++* Olli Savia
++ Added support for LynxOS.
++
++
++Version 1.11 - 2006/04/08
++-------------------------
++* Mark Pickelmann
++ Fixed trio_unregister. If the first element was removed, the remaining
++ list would be removed as well.
++
++* Fixed unintended formatting of %e that would result in non-zero numbers
++ starting with zero (reported by Mark Pickelmann and Gisli Ottarsson).
++
++* Fixed compilation with Sun Workshop 6 (reported by Matthias Andree).
++
++* Fixed accuracy for denormalized numbers (bug item #758327).
++
++* Glen Davidson
++ Fixed scanning of floating-point numbers without a decimal-point (bug item
++ #1370427).
++
++* David Byron
++ Fixed more compiler warnings.
++
++* Fixed compilation of trio_to_long_double and TRIO_FEATURE_FLOAT (reported by
++ David Byron).
++
++* Fixed precision of large floating-point numbers (bug item #1314524).
++
++* Karl Bochert
++ Fixed trio_fpclassify_and_signbit to only restore the floating-point
++ precision.
++
++* Fixed detection of need for ieee option on FreeBSD/Alpha.
++
++* Added TRIO_SNPRINTF_ONLY compilation.
++
++* Fixed trio_to_double by not using strtod() on Tru64/DECC because it does not
++ support hex-floats.
++
++* Fixed crash on 64 bits machines related to a previous workaround in version
++ 1.9 for uninitialized va_list (reported by Nicolai Tufar, suggestion by
++ Douglas Gwyn).
++
++* Patrick Jessee
++ Fixed width calculation for %g.
++
++* Added macros for internal features.
++
++* Jon Foster
++ Added macros for conditional compilation of many features. Documented all
++ the features.
++
++* Karl Bochert
++ Fixed problem with Borland C++, which changes the floating-point precision
++ for certain math functions (log10() and _fpclass()).
++
++* Karl Bochert
++ Fixed compilation warnings on Borland C++.
++
++* Removed any occurrence of #elif because Borland C++ reports wrong line
++ numbers when they are present (reported by Karl Bochert).
++
++* David Byron
++ Added trio_asprintfv.
++
++* Brian Chapman
++ Fixed Mac OS X compilation.
++
++* David Byron
++ Fixed several compiler warnings.
++
++* Fixed printing of out-of-range arguments for %hhd and %hd. These arguments
++ can be out of range because of default integer promotion.
++
++* Bob Friesenhahn
++ Fixed installation of header files.
++
++* Joe Orton
++ Added SHELL to Makefile.in to avoid problems with CShells.
++
++* Shaun Tancheff
++ Fixed regresion tests for MSVC.
++
++* Craig Berry
++ Fixed the VMS C99 workaround.
++
++
++Version 1.10 - 2003/03/06
++-------------------------
++* Rearranged some include files to accommodate large file support (reported by
++ Albert Chin-A-Young).
++
++* Added support for SunOS 4.1.x lack of strerror, tolower, and toupper
++ (reported by Peter McCluskey).
++
++* Fixed pedantic compilation with TRIO_MINIMAL.
++
++* Jose Kahan
++ Moved <limits.h> to avoid redefinition problems.
++
++* Fixed hex-float exponents (reported by Matthias Clasen).
++
++* Fixed handling of negative width and precision via paramters (reported by
++ Jacob Navia).
++
++* Nigel Hall
++ Fixed TRIO_VA_START for VMS.
++
++* Rune Enggaard Lausen
++ Fixed compilation for Borland C++ Builder.
++
++* Fixed precision of hex-float numbers (reported by James Antill).
++
++* Fixed plus sign only to be added for signed numbers.
++
++* Fixed printing of integers with value and precision of zero (reported by
++ James Antill).
++
++* Fixed %#.o to only print one zero if the value is zero (reported by James
++ Antill).
++
++* Rewrote check for IEEE compilation option to remove dependency on additional
++ scripts.
++
++* Mehdi Lavasani
++ Makefile install target fixed to work with older install programs.
++
++* Collapsed the DECC, MSVC, HP-UX, and AIX code for trio_fpclassify_and_sign()
++ with further preprocessing.
++
++
++Version 1.9 - 2002/10/13
++------------------------
++* Fixed trio_fpclassify_and_signbit on AIX 3.2
++
++* Added configure check for -ieee/-mieee compilation option for Alpha machines.
++
++* Craig Berry
++ Fixed compilation on VMS.
++
++* Albert Chin-A-Young
++ Fixed incorrect conditional expression in trio_isinf.
++
++* Fixed the warnings about uninitialized va_list in the printfv and scanfv
++ family without the use of compiler specific pragmas (suggested by Ian
++ Pilcher).
++
++* Fixed space flag for floating-point numbers (reported by Ian Main).
++
++
++Version 1.8 - 2002/07/10
++------------------------
++* Fixed infinite loop in multibyte handling (reported by Gisli Ottarsson).
++
++* Added the customizable cprintf/cscanf family which enables to user to specify
++ input and output stream functions (suggested by Florian Schulze).
++
++* Fixed trio_isinf by removing the HP-UX workaround, and instead making sure
++ that the C99 macro will adhere to the trio return values (reported by Luke
++ Dunstan).
++
++* Alexander Lukyanov
++ Fixed boundary case for scanning and EOF.
++
++* Jacob Navia
++ Enabled the L modifier for formatting.
++
++* Added TRIO_MINIMAL to build trio without the string functions.
++
++* Added the R modifier to print rounded floating-point numbers.
++
++* Added trio_to_long_double and long double scanning (the L modifier).
++
++* Added trio_locale_decimal_point, trio_locale_thousand_separator,
++ trio_locale_grouping to overwrite locale settings.
++
++* Rewrote TrioWriteDouble to avoid temporary buffers and thus the danger of
++ buffer overflows (for instance %.5000f).
++
++* Improved floating-point formatting accuracy.
++
++* Fixed formatting of non-decimal exponents.
++
++* Fixed thousand separator checking.
++
++* Fixed %f scanning to get a float and %lf to get a double.
++
++* Fixed WIN32 compilation (reported by Emmanuel Mogenet)
++
++* Fixed regression test cases to exclude disabled features.
++
++
++Version 1.7 - 2002/05/07
++------------------------
++* Fixed trio_to_double to handle hex-floats properly.
++
++* Fixed printing of %a-format to be like %e, not like %g.
++
++* Fixed floating-point printing of values beyond the machine accuracy.
++
++* Fixed %f for printing with large precision.
++
++* Fixed the usage of C99 nan(), which caused a crash on OSF/1 (reported by
++ Georg Bolz)
++
++* Joe Orton
++ Fixed %p on 64-bit platforms.
++
++* Made trio compile with K&R compilers.
++
++* Emmanuel Mogenet
++ Fixed bug in trio_asprintf.
++
++* Emmanuel Mogenet
++ Various WIN32 fixes.
++
++* Joe Orton
++ Fixed trio_isinf() on HP-UX, and added test cases.
++
++* Joe Orton
++ Fixed non-portable use of $^ in Makefile.
++
++* Joe Orton
++ Added autoconf.
++
++* Alexander Lukyanov
++ Fixed a number of bugs in the scanning of EOF and the count specifier.
++
++* Richard Jinks
++ Added trio_nzero
++
++* Fixed incorrect handling of return code from TrioReadChar (reported by
++ Henrik Löf)
++
++* Fixed parsing of character class expressions.
++
++* Fixed trio_to_double which did not work with long fractions.
++
++* Fixed %f for printing of large numbers.
++
++* Fixed %#s to handle whitespaces as non-printable characters.
++
++* Added trio_isfinite, trio_signbit, and trio_fpclassify.
++
++* Added new test cases.
++
++
++Version 1.6 - 2002/01/13
++------------------------
++* Added dynamic string functions.
++
++* Rewrote and extended documentation in JavaDoc (using Doxygen).
++
++* Moved and renamed strio functions to triostr.
++
++* Robert Collins
++ Added definition for Cygwin.
++
++* Markus Henke
++ Added long double workaround for the HP C/iX compiler.
++
++* Marc Verwerft
++ Improved error handling for dynamically allocated strings.
++
++* John Fotheringham
++ Made trionan compile on OpenVMS.
++
++* Added 'd' and 'D' as exponent letters when using TRIO_MICROSOFT.
++
++* Fixed uninitial memory read for the parameter modifiers.
++
++
++Version 1.5 - 2001/09/08
++------------------------
++* Merged with libxml changes.
++
++* Moved NaN and Inf handling to separate file to enable reuse in other
++ projects.
++
++* Igor Zlatkovic
++ Fixed TrioGenerateNan for MSVC.
++
++* Fixed lots of preprocessor macros and internal data structure names.
++
++
++Version 1.4 - 2001/06/03
++------------------------
++* Added hex-float (%a and %A) for scanning.
++
++* Added wide character arguments (%ls, %ws, %S, %lc, %wc, and %C) for both
++ printf and scanf.
++
++* Added mutex callbacks for user-specified specifiers to enable applications to
++ add thread-safety. These are registered with trio_register, where the
++ namespace is set to either ":enter" to lock a mutex, or ":leave" to unlock a
++ mutex.
++
++* Added equivalence class expressions for scanning. For example, %[[=a=]] scans
++ for all letters in the same equivalence class as the letter 'a' as defined
++ by the locale.
++
++* Changed character class expressions for scanning. The expressions must now
++ be embedded withing an extra set of brackets, e.g. %[[:alpha:]]. This was
++ done to adhere to the syntax of UNIX98 regular expressions.
++
++* Added the possibility to specify standard support (TRIO_C99 etc.) as compiler
++ options.
++
++* Fixed conversion of hex-float in StrToDouble.
++
++* Fixed formatting of hex-float numbers.
++
++* Stan Boehm
++ Fixed crash on QNX, which happend because some buffers on the stack were too
++ big.
++
++* Fixed default precision for %f and %g (reported by Jose Ortiz)
++
++* Howard Kapustein
++ Added the I8, I16, I32, and I64 modifiers.
++
++* Jose Ortiz
++ Fixed rounding problem for %e.
++
++* Jose Ortiz
++ Fixed various problems with the xlC and Sun C++ compilers.
++
++
++Version 1.3 - 2001/05/16
++------------------------
++* trio's treatment of the field width when the %e code was used was not
++ correct (reported by Gisli Ottarsson). It turns out the fraction part should
++ be zero-padded by default and the exponent part should be zero-prefixed if
++ it is only one digit. At least that's how the GNU and Sun libc's work. The
++ trio floating point output looks identical to them now.
++
++* Fixed group scanning with modifiers.
++
++* Fixed compilation for 64-bit Digital Unix.
++
++* Igor Zlatkovic
++ Fixed compilation of dprintf, which uses read/write, for MSVC.
++
++* Fixed various compilation problems on Digital Unix (mainly associated with
++ va_list).
++
++
++Version 1.2 - 2001/04/11
++------------------------
++* Added autoconf integration. If compiled with HAVE_CONFIG_H the following
++ happens. Firstly, <config.h> is included. Secondly, trio will only be
++ compiled if WITH_TRIO is defined herein. Thirdly, if TRIO_REPLACE_STDIO is
++ defined, only stdio functions that have not been detected by autoconf, i.e.
++ those not defined by HAVE_PRINTF or similar, will be replaced by trio
++ functions (suggested by Daniel Veillard).
++
++* Fixed '%m.nf' output. Previously trio did not treat the width properly
++ in all cases (reported by Gisli Ottarsson).
++
++* Added explicit promotion for the scanfv family.
++
++* Fixed more C++ compilation warnings.
++
++
++Version 1.1 - 2001/02/25
++------------------------
++* Added explicit promotion for the printfv familiy. A float must be specified
++ by %hf.
++
++* Fixed positionals for printfv (reported by Gisli Ottarsson).
++
++* Fixed an integer to pointer conversion problem on the SGI MIPS C compiler
++ (reported by Gisli Ottarsson).
++
++* Fixed ANSI C++ warnings (type casting, and namespace is a reserved keyword).
++
++* Added \n to all examples in the documentation to prevent confusion.
++
++* Fixed StrSubstringMax
++
++
++Version 1.0 - 2000/12/10
++------------------------
++* Bumped Version number.
++
++
++Version 0.25 - 2000/12/09
++-------------------------
++* Wrote more documentation.
++
++* Improved NaN support and added NaN to regression test.
++
++* Fixed C99 support.
++
++* Added missing getter/setter functions.
++
++
++Version 0.24 - 2000/12/02
++-------------------------
++* Added callback functionality for the user-defined specifier (<>). All
++ the necessary functions are defined in triop.h header file. See the
++ documentation for trio_register for further detail.
++
++* Wrote initial documentation on the callback functionality.
++
++* Added the printfv and scanfv family of functions, which takes a pointer
++ array rather than variadic arguments. Each pointer in the array must point
++ to the associated data (requested by Bruce Korb).
++
++* As indicated in version 0.21 the extension modifiers (<>) have now been
++ completely removed.
++
++* Added skipping of thousand-separators in floating-point number scanning.
++
++
++Version 0.23 - 2000/10/21
++-------------------------
++* Added width to scanning of floating-point numbers.
++
++* Wrote more documentation on trio_printf.
++
++* Fixed problem with trailing zeroes after decimal-point.
++
++
++Version 0.22 - 2000/08/06
++-------------------------
++* Added LC_CTYPE locale dependent character class expressions to scan lists.
++ Included are [:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:],
++ [:lower:], [:print:], [:punct:], [:space:], [:upper:], [:xdigit:]
++
++* Added C escapes to alternative string formatting and scanning.
++
++* Added StrSubstringMax.
++
++* Wrote a little more documentation.
++
++* Fixed scanf return values.
++
++* Fixed a sign error for non-ascii characters.
++
++
++Version 0.21 - 2000/07/19
++-------------------------
++* Converted the documentation to TeX. With latex2man the documentation can
++ automatically be converted into man pages.
++
++* Added trio_scanf, trio_vscanf, trio_fscanf, and trio_vfscanf.
++
++* Added trio_dprintf, trio_vdprintf, trio_dscanf, and trio_vdscanf. These
++ functions can be used to write and read directly to pipes and sockets (the
++ assume blocking sockets). Stdio buffering is surpassed, so the functions are
++ async-safe. However, reading from stdin (STDIN_FILENO) or writing to stdout
++ (STDOUT_FILENO) reintroduces the buffering.
++
++* Paul Janzen
++ Added trio_asprintf and trio_vasprintf, which are compatible with the GNU
++ and BSD interfaces.
++
++* Added scanlist ranges for group scanning (%[]).
++
++* Added width for scanning (missing for floating-point numbers though).
++
++* Added variable size modifier (&) to handle system defined types of unknown
++ size. This modifier makes certain assumptions about the integer sizes, which
++ may not be valid on any machine. Consequently, the modifier will remain
++ undocumented, as it may be removed later.
++
++* Added \777 and \xFF to alternative string scanning (%#s)
++
++* Added the TRIO_REPLACE_STDIO check in the header.
++
++* Improved performance of the multibyte character parsing.
++
++* Fixed positionals (%n$) which had stopped working.
++
++* Fixed hh and ll modifiers to allow exactly two letters and no more.
++
++* Fixed ANSI C++ warnings. Also fixed the compiler warning about casting
++ between integer and pointer (this has been annoying me for ages).
++
++* Fixed snprintf and vsnprintf with zero buffer size.
++
++* Fixed NAN problems (reported by Keith Briggs).
++
++* Fixed parsing of multibyte characters. The format string was not correctly
++ advanced in case of a multibyte character.
++
++* Renamed many of the internal functions to have more consistant names.
++
++* Removed the <quote=c> and <fill=c> modifiers. They are not really worth
++ including. The other <> modifiers may disappear as well.
++
++
++Version 0.20 - 2000/06/05
++-------------------------
++* Added intmax_t and ptrdiff_t support.
++
++* Added support for LC_NUMERIC grouping.
++
++* Added double-dot notation for the conversion base. The style is now
++ %width.precision.base, where any argument can be a number, an asterix
++ indicating a parameter, or be omitted entirely. For example, %*..2i is
++ to specify binary numbers without precision, and with width as a parameter
++ on the va_list.
++
++* Added sticky modifier (!), which makes subsequent specifiers of the same
++ type reuse the current modifiers. Inspired by a suggestion from Gary Porter.
++
++* Added group scanning (%[]). Scanlist ranges and multibyte sequences are not
++ supported yet.
++
++* Added count scanning (%n).
++
++* Changed the number scanning to accept thousand separators and any base.
++
++* Fixed positional for parameters. It is possible to write something like
++ %3$*1$.*2$d (which happens to be the same as %*.*d).
++
++* Fixed precision of integers.
++
++* Fixed parameter flags. Before trio could only handle one parameter flag per
++ specifier, although two (three with double-dot base) were possible.
++
++* Fixed isinf() for those platforms where it is unimplemented.
++
++
++Version 0.18 - 2000/05/27
++-------------------------
++* Rewrote the entire floating-point formatting function (Danny Dulai had
++ reported several errors and even supplied some patches, which unfortunately
++ were lost due to the refactoring).
++
++* Removed the use of strlen() in the declaration of a stack array. This
++ caused problems on some compilers (besides it isn't really ANSI C compliant
++ anyways). Using some arbitrarily chosen maximum value; should examine if
++ some standard defines an upper limit on the length of decimal-point and
++ thousands-separator (sizeof(wchar_t) perhaps?)
++
++* Changed the parsing of the format string to be multibyte aware.
++
++
++Version 0.17 - 2000/05/19
++-------------------------
++* Added INF, -INF, and NAN for floating-point numbers.
++
++* Fixed %#.9g -- alternative with precision.
++
++* Ken Gibson
++ Fixed printing of negative hex numbers
++
++* Joerg (last name unknown)
++ Fixed convertion of non-ASCII characters
++
++
++Version 0.16 - 1999/08/06
++-------------------------
++* Changed the constness of the second argument of StrFloat and StrDouble. The
++ lack of parameter overloading in C is the reason for the strange use of
++ constness in strtof and strtod.
++
++* Cleaned up constness.
++
++
++Version 0.15 - 1999/07/23
++-------------------------
++* Fixed the internal representation of numbers from signed to unsigned. Signed
++ numbers posed a problem for large unsigned numbers (reported by Tero)
++
++* Fixed a tiny bug in trio_vsprintfcat
++
++* Changed the meaning of the max argument of StrAppendMax to be consistant
++ with StrFormatAppendMax. Now it is the maximal size of the entire target
++ buffer, not just the appended size. This makes it easier to avoid buffer
++ overflows (requested by Tero)
++
++
++Version 0.14 - 1999/05/16
++-------------------------
++* Added size_t support (just waiting for a C99 compliant compiler to add
++ ptrdiff_t and intmax_t)
++
++* Rewrote TrioOutStreamDouble so it does not use the libc sprintf to emulate
++ floating-point anylonger.
++
++* Fixed width, precision, and adjustment for numbers and doubles.
++
++
++Version 0.13 - 1999/05/06
++-------------------------
++* Fixed zero padding for %d. Now %d will only zero pad if explicitly requested
++ to do so with the 0 flag (reported by Tero).
++
++* Fixed an incorrect while() condition in TrioGetString (reported by Tero).
++
++
++Version 0.12 - 1999/04/19
++-------------------------
++* Fixed incorrect zero padding of pointers
++
++* Added StrHash with STRIO_HASH_PLAIN
++
++* Added StrFormatDateMax
++
++
++Version 0.11 - 1999/03/25
++-------------------------
++* Made it compile under cygwin
++
++* Fixed a bug were TrioPreprocess would return an error if no formatting chars
++ were found (reported by Tero).
++
++
++Version - 1999/03/19
++--------------------
++* Added trio_strerror and TRIO_ERROR_NAME.
++
++* Changed the error codes to be positive (as errno)
++
++* Fixed two reads of uninitialized memory reported by Purify
++
++* Added binary specifiers 'b' and 'B' (like SCO.) ThousandSeparator can be
++ used to separate nibbles (4 bit)
++
++* Renamed all Internal* functions to Trio*, which seems like a better
++ namespace (even though it is of no practical interest because these
++ functions are not visible beyond the scope of this file.)
++
++
++Version - 1999/03/12
++--------------------
++* Added hex-float format for StrToDouble
++
++* Double references and gaps in the arguments are not allowed (for the %n$
++ format) and in both cases an error code is returned.
++
++* Added StrToDouble (and StrToFloat)
++
++
++Version - 1999/03/08
++--------------------
++* Added InStream and OutStream to the trio_T structure.
++
++* Started work on TrioScan.
++
++* Return values for errors changed. Two macros to unpack the error code has
++ been added to the header.
++
++* Shortshort (hh) flag added.
++
++* %#s also quotes the quote-char now.
++
++* Removed the 'errorInFormat' boolean, which isn't used anymore after the
++ functions bail out with an error instead.
++
++
++Version - 1999/03/04
++--------------------
++* More than MAX_PARAMETERS parametes will now cause the TrioPreprocess()
++ function to return error.
++
++* Unknown flags and/or specifiers cause errors too.
++
++* Added trio_snprintfcat and trio_vsnprintfcat and the defined name
++ StrFormatAppendMax. They append a formatted string to the end of a string.
++
++* Define MAX_PARAMETERS to 128 at all times instead of using NL_ARGMAX when
++ that exists.
++
++* Added platform fixes for Amiga as suggested by Tero Jänkä <tesaja@utu.fi>
++
++
++Version - 1999/01/31
++--------------------
++* vaprintf did add a zero byte even when it had failed.
++
++* Cleaned up the code for locale handling and thousand separator
++
++* Added trio_aprintf() and trio_vaprintf(). They return an allocated string.
++
++* Added thousands separator for numbers
++
++* Added floating point support for *printf
++
++
++Version - 1998/10/20
++--------------------
++* StrMatchCase() called StrMatch() instead of itself recursively
++
++* Rewrote the implementation of *printf and *scanf and put all the code in
++ this file. Extended qualifiers and qualifiers from other standards were
++ added.
++
++* Added StrSpanFunction, StrToLong, and StrToUnsignedLong
++
++
++Version - 1998/05/23
++--------------------
++* Made the StrEqual* functions resistant to NULL pointers
++
++* Turns out strdup() is no standard at all, and some platforms (I seem to
++ recall HP-UX) has problems with it. Made our own StrDuplicate() instead.
++
++* Added StrFormat() and StrFormatMax() to serve as sprintf() and snprintf()
++ respectively.
+diff -up ghostscript-9.07/trio/compare.c.gs_sprintf ghostscript-9.07/trio/compare.c
+--- ghostscript-9.07/trio/compare.c.gs_sprintf 2013-05-09 17:02:39.101447236 +0100
++++ ghostscript-9.07/trio/compare.c 2013-05-09 17:02:39.101447236 +0100
+@@ -0,0 +1,53 @@
++#include "trio.h"
++
++#define compare(format, value) printf("FORMAT: %s\n", format); printf("TRIO: "); trio_printf(format,value); printf("\nLIBC: "); \
++printf(format,value); printf("\n\n");
++
++int main()
++{
++ compare("\"%e\"",2.342E+02);
++ compare("\"%10.4e\"",-2.342E-02);
++ compare("\"%11.4e\"",-2.342E-02);
++ compare("\"%12.4e\"",-2.342E-02);
++ compare("\"%13.4e\"",-2.342E-02);
++ compare("\"%14.4e\"",-2.342E-02);
++ compare("\"%15.4e\"",-2.342E-02);
++ compare("\"%16.4e\"",-2.342E-02);
++ compare("\"%16.4e\"",-2.342E-22);
++ compare("\"%G\"",-2.342E-02);
++ compare("\"%G\"",3.1415e-6);
++ compare("%016e", 3141.5);
++ compare("%16e", 3141.5);
++ compare("%-16e", 3141.5);
++ compare("%010.3e", 3141.5);
++
++ compare("*%5f*", 3.3);
++ compare("*%5f*", 3.0);
++ compare("*%5f*", .999999E-4);
++ compare("*%5f*", .99E-3);
++ compare("*%5f*", 3333.0);
++
++ compare("*%5g*", 3.3);
++ compare("*%5g*", 3.0);
++ compare("*%5g*", .999999E-4);
++ compare("*%5g*", .99E-3);
++ compare("*%5g*", 3333.0);
++ compare("*%5g*", 0.01);
++
++ compare("*%5.g*", 3.3);
++ compare("*%5.g*", 3.0);
++ compare("*%5.g*", .999999E-4);
++ compare("*%5.g*", 1.0E-4);
++ compare("*%5.g*", .99E-3);
++ compare("*%5.g*", 3333.0);
++ compare("*%5.g*", 0.01);
++
++ compare("*%5.2g*", 3.3);
++ compare("*%5.2g*", 3.0);
++ compare("*%5.2g*", .999999E-4);
++ compare("*%5.2g*", .99E-3);
++ compare("*%5.2g*", 3333.0);
++ compare("*%5.2g*", 0.01);
++
++ return 0;
++}
+diff -up ghostscript-9.07/trio/configure.in.gs_sprintf ghostscript-9.07/trio/configure.in
+--- ghostscript-9.07/trio/configure.in.gs_sprintf 2013-05-09 17:02:39.101447236 +0100
++++ ghostscript-9.07/trio/configure.in 2013-05-09 17:02:39.101447236 +0100
+@@ -0,0 +1,54 @@
++dnl
++dnl Configuration for trio
++dnl
++
++AC_INIT
++AC_CONFIG_SRCDIR([triodef.h])
++AC_PREREQ(2.55) dnl autoconf 2.55 was released in 2002
++
++AC_PROG_CC
++ifdef([AC_PROG_CC_STDC], [AC_PROG_CC_STDC])
++AC_LANG([C])
++
++AC_PROG_INSTALL
++AC_PROG_RANLIB
++
++dnl
++dnl Alpha floating-point compiler option.
++dnl
++
++AC_MSG_CHECKING(for IEEE compilation options)
++AC_CACHE_VAL(ac_cv_ieee_option, [
++ AC_COMPILE_IFELSE(AC_LANG_PROGRAM(,[[[
++ #if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS)))
++ # error "Option needed"
++ typedef int option_needed[-1];
++ #endif
++ ]]]),
++ ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE",
++ AC_COMPILE_IFELSE(AC_LANG_PROGRAM(,[[[
++ #if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
++ # error "Option needed"
++ typedef int option_needed[-1];
++ #endif
++ ]]]),
++ ac_cv_ieee_option="-ieee",
++ AC_COMPILE_IFELSE(AC_LANG_PROGRAM(,[[[
++ #if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__))))
++ # error "Option needed"
++ typedef int option_needed[-1];
++ #endif
++ ]]]),
++ ac_cv_ieee_option="-mieee",
++ ac_cv_ieee_option="none"
++ )
++ )
++ )
++])
++AC_MSG_RESULT($ac_cv_ieee_option)
++if test $ac_cv_ieee_option != none; then
++ CFLAGS="${CFLAGS} ${ac_cv_ieee_option}"
++fi
++
++AC_CONFIG_FILES([Makefile])
++AC_OUTPUT
+diff -up ghostscript-9.07/trio/doc/doc_dynamic.h.gs_sprintf ghostscript-9.07/trio/doc/doc_dynamic.h
+--- ghostscript-9.07/trio/doc/doc_dynamic.h.gs_sprintf 2013-05-09 17:02:39.102447240 +0100
++++ ghostscript-9.07/trio/doc/doc_dynamic.h 2013-05-09 17:02:39.102447240 +0100
+@@ -0,0 +1,31 @@
++/*************************************************************************
++ *
++ * $Id: doc_dynamic.h,v 1.1 2001/12/27 17:29:20 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/** @addtogroup DynamicStrings Dynamic String Functions.
++Dynamic string functions.
++
++@b SYNOPSIS
++
++@verbatim
++cc ... -ltrio -lm
++
++#include <triostr.h>
++@endverbatim
++
++@b DESCRIPTION
++
++*/
+diff -up ghostscript-9.07/trio/doc/doc.h.gs_sprintf ghostscript-9.07/trio/doc/doc.h
+--- ghostscript-9.07/trio/doc/doc.h.gs_sprintf 2013-05-09 17:02:39.102447240 +0100
++++ ghostscript-9.07/trio/doc/doc.h 2013-05-09 17:02:39.102447240 +0100
+@@ -0,0 +1,172 @@
++/*************************************************************************
++ *
++ * $Id: doc.h,v 1.20 2006/08/18 11:32:08 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/**
++@mainpage
++
++@author Bjørn Reese
++@author Daniel Stenberg
++
++@section intro Introduction
++
++Trio is a fully matured and stable set of printf and string functions
++designed be used by applications with focus on portability or with the
++need for additional features that are not supported by standard stdio
++implementation.
++
++There are several cases where you may want to consider using trio:
++
++@li Portability across heterogeneous platforms.
++@li Embedded systems without stdio support.
++@li Extendability of unsupported features.
++@li Your native version does not do everything you need.
++
++When you write applications that must be portable to a wide range of
++platforms you often have to deal with inadequate implementations of the
++stdio library functions. Most notably is the lack of secure formatting
++functions, such as snprintf, or the lack of parameter reordering commonly
++used for the internationalization of applications, such as the <num>$
++modifier. Sometimes the feature you need is simply not present in stdio.
++So you end up spending much effort on determining which platforms supports
++what, and to write your own versions of various features. This is where
++trio can help you. Trio is a platform-independent implementation of the
++stdio printf and scanf functions and the string library functions.
++
++The functionality described in the stdio standards is a compromise, and
++does unfortunately not include a mechanism to extend the functionality for
++an individual application. Oftentimes an application has the need for an
++extra feature, and the application code can become much more clear and
++readable by using an extension mechanism. Trio supports a range of useful
++extensions such as user-defined specifiers, passing of arguments in arrays,
++localized string scanning, thousand-separators, and arbitrary integer bases.
++
++Trio fully implements the C99 (ISO/IEC 9899:1999) and UNIX98 (the Single
++Unix Specification, Version 2) standards, as well as many features from
++other implemenations, e.g. the GNU libc and BSD4.
++
++@section examples Examples
++
++@subsection ex1 Binary Numbers
++Output an integer as a binary number using a trio extension.
++@verbatim
++ trio_printf("%..2i\n", number);
++@endverbatim
++
++@subsection ex2 Thousand-separator
++Output a number with thousand-separator using a trio extension.
++@verbatim
++ trio_printf("%'f\n", 12345.6);
++@endverbatim
++The thousand-separator described by the locale is used.
++
++@subsection ex3 Fixed Length Array and Sticky Modifier
++Output an fixed length array of floating-point numbers.
++@verbatim
++ double array[] = {1.0, 2.0, 3.0};
++ printf("%.2f %.2f %.2f\n", array[0], array[1], array[2]);
++@endverbatim
++The same with two trio extensions (arguments are passed in an array, and
++the first formatting specifier sets the sticky option so we do not have
++to type all the formatting modifiers for the remaining formatting specifiers)
++@verbatim
++ trio_printfv("%!.2f %f %f\n", array);
++@endverbatim
++Another, and more powerful, application of being able to pass arguments in
++an array is the creation of the printf/scanf statement at run-time, where
++the formatting string, and thus the argument list, is based on an external
++configuration file.
++
++@subsection ex4 Localized scanning
++Parse a string consisting of one or more upper-case alphabetic characters
++followed by one or more numeric characters.
++@verbatim
++ sscanf(buffer, "%[A-Z]%[0-9]", alphabetic, numeric);
++@endverbatim
++The same but with locale using a trio extension.
++@verbatim
++ trio_sscanf(buffer, "%[[:upper:]]%[[:digit:]]", alphabetic, numeric);
++@endverbatim
++
++@section legal Legal Issues
++Trio is distributed under the following license, which allows practically
++anybody to use it in almost any kind of software, including proprietary
++software, without difficulty.
++
++"Copyright (C) 1998-2001 Bjorn Reese and Daniel Stenberg.
++
++Permission to use, copy, modify, and distribute this software for any
++purpose with or without fee is hereby granted, provided that the above
++copyright notice and this permission notice appear in all copies.
++
++THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER."
++
++@section contribution Contribution
++
++@subsection contribute Contribute
++We appreciate any type of contribution, from ideas over improvements to
++error corrections.
++
++The project space contains references to bug and feature tracking,
++mailing-list, and the CVS repository. We prefer communication via the
++mailing-list, but do not require you to be subscribed, because trio is a
++small project.
++
++The project space is located at http://sourceforge.net/projects/ctrio/
++
++@subsection contributors Contributors
++We have received contributions from the following persons (in alphabetic
++order sorted by surname)
++
++@li Craig Berry
++@li Karl Bochert
++@li Stan Boehm
++@li David Byron
++@li Brian Chapman
++@li Robert Collins
++@li Danny Dulai
++@li Bob Friesenhahn
++@li Jon Foster
++@li John Fotheringham
++@li Markus Henke
++@li Ken Gibson
++@li Paul Janzen
++@li Patrick Jessee
++@li Richard Jinks
++@li Tero Jänkä
++@li Howard Kapustein
++@li Rune Enggaard Lausen
++@li Mehdi Lavasani
++@li Alexander Lukyanov
++@li Andreas Maus
++@li Mikey Menezes
++@li Emmanuel Mogenet
++@li Jacob Navia
++@li Jose Ortiz
++@li Joe Orton
++@li Gisli Ottarsson
++@li Mark Pickelmann
++@li Olli Savia
++@li Shaun Tancheff
++@li Marc Werwerft
++@li Igor Zlatkovic
++
++Please let us know, and accept our apology, if we have omitted anybody.
++
++*/
+diff -up ghostscript-9.07/trio/doc/doc_printf.h.gs_sprintf ghostscript-9.07/trio/doc/doc_printf.h
+--- ghostscript-9.07/trio/doc/doc_printf.h.gs_sprintf 2013-05-09 17:02:39.102447240 +0100
++++ ghostscript-9.07/trio/doc/doc_printf.h 2013-05-09 17:02:39.102447240 +0100
+@@ -0,0 +1,532 @@
++/*************************************************************************
++ *
++ * $Id: doc_printf.h,v 1.5 2008/10/12 12:09:51 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/** @addtogroup Printf Formatted Printing Functions.
++Variations of formatted printing functions.
++
++@b SYNOPSIS
++
++@verbatim
++cc ... -ltrio -lm
++
++#include <trio.h>
++@endverbatim
++
++@b DESCRIPTION
++
++This documentation is incomplete.
++The documentation of the printf family in [C99] and [UNIX98] also applies
++to the trio counterparts.
++
++All these functions outputs a string which is formatted according to the
++@p format string and the consecutive arguments. The @p format string is
++described in the Formatting section below.
++
++@ref trio_printf, @ref trio_vprintf, and @ref trio_printfv writes the
++output to the standard output stream (stdout).
++
++@ref trio_fprintf, @ref trio_vfprintf, and @ref trio_fprintfv writes the
++output to a given output stream.
++
++@ref trio_dprintf, @ref trio_vdprintf, and @ref trio_dprintfv writes the
++output to a file descriptor (this includes, for example, sockets).
++
++@ref trio_sprintf, @ref trio_vsprintf, and @ref trio_sprintfv writes the
++output into @p buffer.
++
++@ref trio_snprintf, @ref trio_vsnprintf, and @ref trio_snprintfv writes @p
++max - 1 characters into @p buffer followed by a terminating zero character.
++If @p max is 1, then @p buffer will be an empty string. If @p max is 0,
++then @p buffer is left untouched, and can consequently be NULL. The number
++of characters that would have been written to @p buffer, had there been
++sufficient space, is returned.
++
++@ref trio_snprintfcat appends the formatted text at the end of @p buffer.
++
++@ref trio_asprintf, @ref trio_vasprintf, and @ref trio_asprintfv allocates
++and returns an allocated string in @p buffer containing the formatted text.
++
++@b FORMATTING
++
++The @p format string can contain normal text and conversion indicators.
++The normal text can be any character except the nil character (\000 =
++'\0') and the percent character (\045 = '%'). Conversion indicators
++consists of an indication character (%), followed by zero or more conversion
++modifiers, and exactly one conversion specifier.
++
++@b Modifiers
++
++Some modifiers exhibit the same behaviour for all specifiers, other modifiers
++indicate different behaviours for different specifiers, and other modifiers
++are only applicable to certain specifiers. The relationship is described for
++each modifier. The number 9 is used to denotes an arbitrary integer.
++
++@em Positional ( @c 9$ ) [UNIX98]
++
++Normally the arguments supplied to these functions are interpreted
++incrementially from left to right. Arguments can be referenced specifically in
++the format string. The modifier n$ selects the nth argument. The first
++argument is referred as 1$. If this modifier is used, it must be the first
++modifier after the indication character. n$ can also be used for argument
++width, precision, and base.
++
++The performance penalty of using positionals is almost neglible (contrary to
++most other printf implementations).
++
++@li @em Reference @em Mix.
++Mixing normal and positional specifiers is allowed [TRIO]. For example,
++@verbatim
++ trio_printf("%d %3$d %2$d\n", 1, 2, 3);
++@endverbatim
++results in
++@verbatim
++ 1 3 2
++@endverbatim
++Arguments for the printf family are passed on the stack. On most platforms it
++is not possible to determine the size of individual stack elements, so it is
++essential that the format string corresponds exactly to the passed arguments.
++If this is not the case, incorrect values may be put into the result.
++
++@li @em Reference @em Gap.
++For the same reason it is also essential that the format string does not
++contain any &quot;gaps&quot; in the positional arguments. For example,
++@verbatim
++ trio_printf("%1$d %3$d\n", 1, 2, 3);
++@endverbatim
++is NOT allowed. The format string parser has no knowledge about whether the
++second argument is, say, an integer or a long double (which have different
++sizes).
++@verbatim
++@endverbatim
++[UNIX98] describes this as unspecified behaviour. [TRIO] will detect reference
++gaps and return an error.
++
++@li @em Double @em Reference.
++It is also not allowed to reference an argument twice or more. For example,
++@verbatim
++ trio_printf("%1$d %1$lf\n", 1);
++@endverbatim
++is NOT allowed, because it references the first argument as two differently
++sized objects.
++@verbatim
++@endverbatim
++[UNIX98] describes this as unspecified behaviour. [TRIO] will detect double
++references and return an error.
++
++The following two statements are equivalent
++@verbatim
++ trio_printf("|%d %s\n|", 42, "meanings");
++ |42 meanings|
++
++ trio_printf("|%1$d %2$s|\n", 42, "meanings");
++ |42 meanings|
++@endverbatim
++
++@em Width ( @c 9 )
++
++Specifies the minimum width of a field. If the fields has less characters than
++specified by the width, the field will be left adjusted and padded by spaces.
++The adjustment and padding can be changed by the Alignment ( @c - ) and
++Padding ( @c 0 ) modifiers.
++
++The width is specified as a number. If an asterix ( @c * ) is used instead, the
++width will be read from the argument list.
++
++Prefixes, such as 0x for hexadecimal integers, are part of width.
++@verbatim
++ trio_printf("|%10i|\n", 42);
++ | 42|
++@endverbatim
++
++@em Precision ( @c .9 )
++
++The precision has different semantics for the various data types.
++The precision specifies the maximum number of printed characters for strings,
++the number of digits after the decimal-point for floating-point numbers,
++the number of significant digits for the @c g (and @c G) representation of
++floating-point numbers, the minimum number of printed digits for integers.
++@verbatim
++ trio_printf("|%10.8i|%.8i|\n", 42, 42);
++ | 00000042|00000042|
++@endverbatim
++
++@em Base ( @c ..9 ) [TRIO]
++
++Sets the base that the associated integer must be converted to. The base can
++be between 2 and 36 (both included).
++@verbatim
++ trio_printf("|%10.8.2i|%10..2i|%..2i|\n", 42, 42, 42);
++ | 00101010| 101010|101010|
++
++ trio_printf("|%*.8.*i|\n", 10, 2, 42);
++ | 00101010|
++@endverbatim
++
++@em Padding ( @c 0 )
++
++Integer and floating point numbers are prepended by zeros. The number of
++leading zeros are determined by the precision. If precision is not present,
++width is used instead.
++
++@em Short ( @c h )
++
++Integer arguments are read as an ( @c unsigned ) @c short @c int. String
++and character arguments are read as @c char @c * and @c char respectively.
++
++@em Short @em short ( @c hh ) [C99, GNU]
++
++The argument is read as an ( @c unsigned ) @c char.
++
++@em Fixed @em Size ( @c I ) [MSVC]
++
++The argument is read as a fixed sized integer. The modifier is followed by
++a number, which specifies the number of bits in the integer, and can be one
++of the following
++
++@li @c I8
++@li @c I16
++@li @c I32
++@li @c I64 (if 64-bits integers are supported)
++
++Works only for integers (i, u, d, o, x, X)
++
++@em Largest ( @c j ) [C99]
++
++The argument is read as an @c intmax_t / @c uintmax_t, which is defined to
++be the largest signed/unsigned integer.
++
++@em Long ( @c l )
++
++An integral argument is read as an ( @c unsigned ) @c long @c int. A string
++argument is read as a @c wchar_t @c *, and output as a multi-byte character
++sequence.
++
++@em Long @em long ( @c ll ) [C99, UNIX98, GNU]
++
++The argument is read as an ( @c unsigned ) @c long @c long @c int.
++
++@em Long @em double ( @c L ) [C99, UNIX98, GNU]
++
++The argument is read as a @c long @c double.
++
++@em ptrdiff_t ( @c t ) [C99]
++
++The argument is read as a @c ptrdiff_t, which is defined to be the signed
++integer type of the result of subtracting two pointers.
++
++@em Quad ( @c q ) [BSD, GNU]
++
++Corresponds to the long long modifier ( @c ll ).
++
++@em Wide ( @c w ) [MISC]
++
++For a string argument this is equivalent to using the long modifier ( @c l ).
++
++@em size_t ( @c z ) [C99]
++
++The argument is read as a @c size_t, which is defined to be the type
++returned by the @c sizeof operator.
++
++@em size_t ( @c Z ) [GNU]
++
++Corresponds to the size_t modifier ( @c z ).
++
++@em Alternative ( @c # )
++
++Prepend radix indicator for hexadecimal, octal, and binary integer numbers
++and for pointers.
++Always add a decimal-point for floating-point numbers.
++Escape non-printable characters for strings.
++
++@em Spacing ( )
++
++Prepend leading spaces when necessary.
++
++@em Sign ( @c + )
++
++Always prepend a sign to numbers. Normally only the negative sign is prepended
++to a number. With this modifier the positive sign may also be prepended.
++
++@em Alignment ( @c - )
++
++The output will be left-justified in the field specified by the width.
++
++@em Argument ( @c * )
++
++Width, precision, or base is read from the argument list, rather than from
++the formatting string.
++
++@em Quote / @em Grouping ( @c ' ) [MISC]
++
++Groups integers and the integer-part of floating-point numbers according to
++the locale. Quote strings and characters.
++
++@em Sticky ( @c ! ) [TRIO]
++
++The modifiers listed for the current specifier will be reused by subsequent
++specifiers of the same group.
++The following specifier groups exists
++@li Integer ( @c i, @c u, @c d, @c o, @c x, @c X )
++@li Floating-point ( @c f, @c F, @c e, @c E, @c g, @c G, @c a, @c A )
++@li Character ( @c c )
++@li String ( @c s )
++@li Pointer ( @c p )
++@li Count ( @c n )
++@li Errno ( @c m )
++@li Group ( @c [] )
++
++The sticky modifiers are active until superseeded by other sticky modifiers,
++or the end of the format string is reached.
++Local modifiers overrides sticky modifiers for the given specifier only.
++@verbatim
++ trio_printf("|%!08#x|%04x|%x|\n", 42, 42, 42);
++ |0x00002a|0x2a|0x00002a|
++@endverbatim
++
++@b Specifiers
++
++@em Percent ( @c % )
++
++Produce a percent ( @c % ) character. This is used to quote the indication
++character. No modifiers are allowed.
++The full syntax is @c %%.
++@verbatim
++ trio_printf("Percent is %%\n");
++ Percent is %
++@endverbatim
++
++@em Hex @em floats ( @c a, @c A ) [C99]
++
++Output a hexadecimal (base 16) representation of a floating point number. The
++number is automatically preceeded by @c 0x ( or @c 0X ). The exponent is
++@c p ( or @c P ).
++@verbatim
++ trio_printf("|%a|%A|\n", 3.1415, 3.1415e20);
++ |0x3.228bc|0X3.228BCP+14|
++@endverbatim
++
++@em Binary @em numbers ( @c b, @c B ) [MISC - SCO UnixWare 7]
++
++DEPRECATED: Use Base modifier @c %..2i instead.
++
++@em Character ( @c c )
++
++Output a single character.
++
++@li Quote ( @c ' ) [TRIO].
++Quote the character.
++
++@em Decimal ( @c d )
++
++Output a decimal (base 10) representation of a number.
++
++@li Grouping ( @c ' ) [TRIO].
++The number is separated by the locale thousand separator.
++@verbatim
++ trio_printf("|%'ld|\n", 1234567);
++ |1,234,567|
++@endverbatim
++
++@em Floating-point ( @c e, @c E)
++
++Output a decimal floating-point number.
++The style is @c [-]9.99e[-]9, where
++@li @c [-]9.99 is the mantissa (as described for the @c f, @c F specifier), and
++@li @c e[-]9 is the exponent indicator (either @c e or @c E, depending on the
++floating-point specifier), followed by an optional sign and the exponent
++
++If the precision is wider than the maximum number of digits that can be
++represented by the floating-point unit, then the number will be adequately
++rounded. For example, assuming DBL_DIG is 15
++@verbatim
++ trio_printf("|%.18e|\n", (1.0 / 3.0));
++ |3.333333333333333000e-01|
++@endverbatim
++
++@em Floating-point ( @c f, @c F )
++
++Output a decimal floating-point number.
++The style is @c [-]9.99, where
++@li @c [-] is an optional sign (either @c + or @c -),
++@li @c 9 is the integer-part (possibly interspersed with thousand-separators),
++@li @c . is the decimal-point (depending on the locale), and
++@li @c 99 is the fractional-part.
++
++If more digits are needed to output the number, than can be represented with
++the accuracy of the floating-point unit, then the number will be adequately
++rounded. For example, assuming that DBL_DIG is 15
++@verbatim
++ trio_printf("|%f|\n", (2.0 / 3.0) * 1E18);
++ |666666666666666700.000000|
++@endverbatim
++
++The following modifiers holds a special meaning for this specifier
++@li Alternative ( @c # ) [C99].
++Add decimal point.
++@li Grouping ( @c ' ) [TRIO].
++Group integer part of number into thousands (according to locale).
++
++@em Floating-point ( @c g, @c G)
++
++Output a decimal floating-point representation of a number. The format of
++either the @c f, @c F specifier or the @c e, @c E specifier is used, whatever
++produces the shortest result.
++
++@em Integer ( @c i )
++
++Output a signed integer. Default base is 10.
++
++@em Errno ( @c m ) [GNU]
++
++@em Count ( @c n )
++
++Insert into the location pointed to by the argument, the number of octets
++written to the output so far.
++
++@em Octal ( @c o )
++
++Output an octal (base 8) representation of a number.
++
++@em Pointer ( @c p )
++
++Ouput the address of the argument. The address is printed as a hexadecimal
++number. If the argument is the NULL pointer the text @c (nil) will be used
++instead.
++@li Alternative ( @c # ) [TRIO].
++Prepend 0x
++
++@em String ( @c s, @c S )
++
++Output a string. The argument must point to a zero terminated string. If the
++argument is the NULL pointer the text @c (nil) will be used instead.
++@c S is equivalent to @c ls.
++@li Alternative ( @c # ) [TRIO].
++Escape non-printable characters.
++
++Non-printable characters are converted into C escapes, or hexadecimal numbers
++where no C escapes exists for the character. The C escapes, the hexadecimal
++number, and all backslashes are prepended by a backslash ( @c \ ).
++The supported C escapes are
++@li @c \a (\007) = alert
++@li @c \b (\010) = backspace
++@li @c \f (\014) = formfeed
++@li @c \n (\012) = newline
++@li @c \r (\015) = carriage return
++@li @c \t (\011) = horizontal tab
++@li @c \v (\013) = vertical tab
++
++@verbatim
++ trio_printf("|One %s Three|One %'s Three|\n", "Two", "Two");
++ |One Two Three|One "Two" Three|
++
++ trio_printf("|Argument missing %s|\n", NULL);
++ |Argument missing (nil)|
++
++ trio_printf("|%#s|\n", "\007 \a.");
++ |\a \a.|
++@endverbatim
++
++@em Unsigned ( @c u )
++
++Output an unsigned integer. Default base is 10.
++
++@em Hex ( @c x, @c X )
++
++Output a hexadecimal (base 16) representation of a number.
++
++@li Alternative ( @c # ).
++Preceed the number by @c 0x ( or @c 0X ). The two characters are counted
++as part of the width.
++
++@em User-defined ( @c <> )
++
++Invoke user-defined formatting.
++See @ref trio_register for further information.
++
++@b RETURN @b VALUES
++
++All functions returns the number of outputted characters. If an error occured
++then a negative error code is returned [TRIO]. Note that this is a deviation
++from the standard, which simply returns -1 (or EOF) and errno set
++appropriately.
++The error condition can be detected by checking whether the function returns
++a negative number or not, and the number can be parsed with the following
++macros. The error codes are primarily intended as debugging aide for the
++developer.
++
++@li TRIO_EINVAL: Invalid argument.
++@li TRIO_ETOOMANY: Too many arguments.
++@li TRIO_EDBLREF: Double argument reference.
++@li TRIO_EGAP: Argument reference gap.
++@li TRIO_ENOMEM: Out of memory.
++@li TRIO_ERANGE: Invalid range.
++@li TRIO_ERRNO: The error is specified by the errno variable.
++
++Example:
++@verbatim
++ int rc;
++
++ rc = trio_printf("%r\n", 42);
++ if (rc < 0) {
++ if (TRIO_ERROR_CODE(rc) != TRIO_EOF) {
++ trio_printf("Error: %s at position %d\n",
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ }
++ }
++@endverbatim
++
++@b SEE @b ALSO
++
++@e trio_scanf, @e trio_register.
++
++@b NOTES
++
++The printfv family uses an array rather than the stack to pass arguments.
++This means that @c short @c int and @c float values will not be handled by
++the default argument promotion in C. Instead, these values must be explicitly
++converted with the Short (h) modifier in both cases.
++
++Example:
++@verbatim
++ void *array[2];
++ float float_number = 42.0;
++ short short_number = 42;
++
++ array[0] = &float_number;
++ array[1] = &short_number;
++
++ trio_printfv("%hf %hd\n", array); /* CORRECT */
++ trio_printfv("%f %d\n", array); /* WRONG */
++@endverbatim
++
++@b CONFORMING @b TO
++
++Throughout this document the following abbreviations have been used to
++indicate what standard a feature conforms to. If nothing else is indicated
++ANSI C (C89) is assumed.
++
++@li [C89] ANSI X3.159-1989
++@li [C99] ISO/IEC 9899:1999
++@li [UNIX98] The Single UNIX Specification, Version 2
++@li [BSD] 4.4BSD
++@li [GNU] GNU libc
++@li [MSVC] Microsoft Visual C
++@li [MISC] Other non-standard sources
++@li [TRIO] Extensions specific for this package
++
++*/
+diff -up ghostscript-9.07/trio/doc/doc_register.h.gs_sprintf ghostscript-9.07/trio/doc/doc_register.h
+--- ghostscript-9.07/trio/doc/doc_register.h.gs_sprintf 2013-05-09 17:02:39.102447240 +0100
++++ ghostscript-9.07/trio/doc/doc_register.h 2013-05-09 17:02:39.102447240 +0100
+@@ -0,0 +1,384 @@
++/*************************************************************************
++ *
++ * $Id: doc_register.h,v 1.3 2008/10/12 12:09:51 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/** @addtogroup UserDefined User-defined Formatted Printing Functions.
++Functions for using customized formatting specifiers.
++
++@b SYNOPSIS
++
++@verbatim
++cc ... -ltrio -lm
++
++#include <trio.h>
++#include <triop.h>
++@endverbatim
++
++@b DESCRIPTION
++
++This documentation is incomplete.
++
++@b User-defined @b Specifier
++
++The user-defined specifier consists of a start character (\074 = '<'), an
++optional namespace string followed by a namespace separator (\072 = ':'),
++a format string, an optional skipping separator (\174 = '|'), and an end
++character (\076 = '>').
++
++The namespace string can consist of alphanumeric characters, and is used to
++define a named reference (see below). The namespace is case-sensitive. If no
++namespace is specified, then we use an unnamed reference (see below).
++
++The format can consist of any character except the end character ('>'), the
++namespace separator (':'), the skipping separator ('|'), and the nil character
++(\000).
++
++Any modifier can be used together with the user-defined specifier.
++
++There are two formats for invoking a user-defined specifier. The first format
++is an extension of the normal printf/scanf formatting. It uses the percent
++character (\045 = '%') followed by optional qualifiers and a specifier. For
++example:
++
++@verbatim
++ trio_printf("%<format>\n", my_handle, my_data);
++@endverbatim
++
++Some C compilers can issue a warning if there is a mismatch between specifiers
++and arguments. Unfortunately, these warnings does not work with the first
++format for user-defined specifiers. Therefore the second format has been
++introduced. The second format can only be applied to user-defined specifiers.
++
++The second format starts with a dollar character (\044 = '$') instead of the
++percent character, and is followed by optional qualifiers and the user-defined
++specifier. If the specifier contains a pipe character (\174 = '|'), then
++everything between the pipe character and the end character ('>') is ignored.
++The ignored part can be used to list the normal specifiers that the C compiler
++uses to determine mismatches. For example:
++
++@verbatim
++ trio_printf("$<format|%p%p>\n", my_handle, my_data);
++@endverbatim
++
++@b Registering
++
++A user-defined specifier must be registered before it can be used.
++Unregistered user-defined specifiers are ignored. The @ref trio_register
++function is used to register a user-defined specifier. It takes two argument,
++a callback function and a namespace, and it returns a handle. The handle must
++be used to unregister the specifier later.
++
++The following example registers a user-define specifier with the "my_namespace"
++namespace:
++
++@verbatim
++ my_handle = trio_register(my_callback, "my_namespace");
++@endverbatim
++
++There can only be one user-defined specifier with a given namespace. There
++can be an unlimited number (subject to maximum length of the namespace) of
++different user-defined specifiers.
++
++Passing NULL as the namespace argument results in an anonymous reference.
++There can be an unlimited number of anonymous references.
++
++@b REFERENCES
++
++There are two ways that a registered callback can be called. Either the
++user-defined specifier must contain the registered namespace in the format
++string, or the handle is passed as an argument to the formatted printing
++function.
++
++If the namespace is used, then a user-defined pointer must be passed as an
++argument:
++
++@verbatim
++ trio_printf("%<my_namespace:format>\n", my_data);
++@endverbatim
++
++If the handle is used, then the user-defined specifier must not contain a
++namespace. Instead the handle must be passed as an argument, followed by a
++user-defined pointer:
++
++@verbatim
++ trio_printf("%<format>\n", my_handle, my_data);
++@endverbatim
++
++The two examples above are equivalent.
++
++There must be exactly one user-defined pointer per user-defined specifier.
++This pointer can be used within the callback function with the
++@ref trio_get_argument getter function (see below).
++
++The format string is optional. It can be used within the callback function
++with the @ref trio_get_format getter function.
++
++@b Anonymous @b References
++Anonymous references are specified by passing NULL as the namespace.
++
++The handle must be passed as an argument followed by a user-defined pointer.
++No namespace can be specified.
++
++@verbatim
++ anon_handle = trio_register(callback, NULL);
++ trio_printf("%<format>\n", anon_handle, my_data);
++@endverbatim
++
++@b Restrictions
++
++@li The length of the namespace string cannot exceed 63 characters.
++@li The length of the user-defined format string cannot exceed 255 characters.
++@li User-defined formatting cannot re-define existing specifiers.
++This restriction was imposed because the existing formatting specifiers have
++a well-defined behaviour, and any re-definition would apply globally to an
++application (imagine a third-party library changing the behaviour of a
++specifier that is crusial to your application).
++
++@b CALLBACK @b FUNCTION
++
++The callback function will be called if a matching user-defined specifier
++is found within the formatting string. The callback function takes one input
++parameter, an opaque reference which is needed by the private functions. It
++returns an @c int, which is currently ignored. The prototype is
++
++@verbatim
++ int (*trio_callback_t)(void *ref);
++@endverbatim
++
++See the Example section for full examples.
++
++@b PRINTING @b FUNCTIONS
++
++The following printing functions must only be used inside a callback function.
++These functions will print to the same output medium as the printf function
++which invoked the callback function. For example, if the user-defined
++specifier is used in an sprintf function, then these print functions will
++output their result to the same string.
++
++@b Elementary @b Printing
++
++There are a number of function to print elementary data types.
++
++@li @ref trio_print_int Print a signed integer. For example:
++@verbatim
++ trio_print_int(42);
++@endverbatim
++@li @ref trio_print_uint Print an unsigned integer.
++@li @ref trio_print_double Print a floating-point number.
++@li @ref trio_print_string Print a string. For example:
++@verbatim
++ trio_print_string("Hello World");
++ trio_print_string(trio_get_format());
++@endverbatim
++@li @ref trio_print_pointer Print a pointer.
++
++@b Formatted @b Printing
++
++The functions @ref trio_print_ref, @ref trio_vprint_ref, and
++@ref trio_printv_ref outputs a formatted string just like its printf
++equivalents.
++
++@verbatim
++ trio_print_ref(ref, "There are %d towels\n", 42);
++ trio_print_ref(ref, "%<recursive>\n", recursive_writer, trio_get_argument(ref));
++@endverbatim
++
++@b GETTER @b AND @b SETTER @b FUNCTIONS
++
++The following getter and setter functions must only be used inside a callback
++function. They can either operate on the modifiers or on special data.
++
++@b Modifiers
++
++The value of a modifier, or a boolean indication of its presence or absence,
++can be found or set with the getter and setter functions.
++The generic prototypes of the these getter and setter functions are
++
++@verbatim
++ int trio_get_???(void *ref);
++ void trio_set_???(void *ref, int);
++@endverbatim
++
++where @c ??? refers to a modifier. For example, to get the width of the
++user-defined specifier use
++
++@verbatim
++ int width = trio_get_width(ref);
++@endverbatim
++
++@b Special @b Data
++
++Consider the following user-defined specifier, in its two possible referencing
++presentations.
++
++@verbatim
++ trio_printf("%<format>\n", namespace_writer, argument);
++ trio_printf("%<namespace:format>\n", argument);
++@endverbatim
++
++@ref trio_get_format will get the @p format string, and
++@ref trio_get_argument} will get the @p argument parameter.
++There are no associated setter functions.
++
++@b EXAMPLES
++
++The following examples show various types of user-defined specifiers. Although
++each specifier is demonstrated in isolation, they can all co-exist within the
++same application.
++
++@b Time @b Example
++
++Print the time in the format "HOUR:MINUTE:SECOND" if "time" is specified inside
++the user-defined specifier.
++
++@verbatim
++ static int time_print(void *ref)
++ {
++ const char *format;
++ time_t *data;
++ char buffer[256];
++
++ format = trio_get_format(ref);
++ if ((format) && (strcmp(format, "time") == 0)) {
++ data = trio_get_argument(ref);
++ if (data == NULL)
++ return -1;
++ strftime(buffer, sizeof(buffer), "%H:%M:%S", localtime(data));
++ trio_print_string(ref, buffer);
++ }
++ return 0;
++ }
++@endverbatim
++
++@verbatim
++ int main(void)
++ {
++ void *handle;
++ time_t now = time(NULL);
++
++ handle = trio_register(time_print, "my_time");
++
++ trio_printf("%<time>\n", handle, &now);
++ trio_printf("%<my_time:time>\n", &now);
++
++ trio_unregister(handle);
++ return 0;
++ }
++@endverbatim
++
++@b Complex @b Numbers @b Example
++
++Consider a complex number consisting of a real part, re, and an imaginary part,
++im.
++
++@verbatim
++ struct Complex {
++ double re;
++ double im;
++ };
++@endverbatim
++
++This example can print such a complex number in one of two formats.
++The default format is "re + i im". If the alternative modifier is used, then
++the format is "r exp(i theta)", where r is the length of the complex vector
++(re, im) and theta is its angle.
++
++@verbatim
++ static int complex_print(void *ref)
++ {
++ struct Complex *data;
++ const char *format;
++
++ data = (struct Complex *)trio_get_argument(ref);
++ if (data) {
++ format = trio_get_format(ref);
++
++ if (trio_get_alternative(ref)) {
++ double r, theta;
++
++ r = sqrt(pow(data->re, 2) + pow(data->im, 2));
++ theta = acos(data->re / r);
++ trio_print_ref(ref, "%#f exp(i %#f)", r, theta);
++
++ } else {
++ trio_print_ref(ref, "%#f + i %#f", data->re, data->im);
++ }
++ }
++ return 0;
++ }
++@endverbatim
++
++@verbatim
++ int main(void)
++ {
++ void *handle;
++
++ handle = trio_register(complex_print, "complex");
++
++ /* Normal format. With handle and the with namespace */
++ trio_printf("%<>\n", handle, &complex);
++ trio_printf("%<complex:>\n", &complex);
++ /* In exponential notation */
++ trio_printf("%#<>\n", handle, &complex);
++ trio_printf("%#<complex:unused data>\n", &complex);
++
++ trio_unregister(handle);
++ return 0;
++ }
++@endverbatim
++
++@b RETURN @b VALUES
++
++@ref trio_register returns a handle, or NULL if an error occured.
++
++@b SEE @b ALSO
++
++@ref trio_printf
++
++@b NOTES
++
++User-defined specifiers, @ref trio_register, and @ref trio_unregister are
++not thread-safe. In multi-threaded applications they must be guarded by
++mutexes. Trio provides two special callback functions, called ":enter" and
++":leave", which are invoked every time a thread-unsafe operation is attempted.
++As the thread model is determined by the application, these callback functions
++must be implemented by the application.
++
++The following callback functions are for demonstration-purposes only.
++Replace their bodies with locking and unlocking of a mutex to achieve
++thread-safety.
++@verbatim
++ static int enter_region(void *ref)
++ {
++ fprintf(stderr, "Enter Region\n");
++ return 1;
++ }
++
++ static int leave_region(void *ref)
++ {
++ fprintf(stderr, "Leave Region\n");
++ return 1;
++ }
++@endverbatim
++These two callbacks must be registered before other callbacks are registered.
++@verbatim
++ trio_register(enter_region, ":enter");
++ trio_register(leave_region, ":leave");
++
++ another_handle = trio_register(another_callback, NULL);
++@endverbatim
++
++*/
+diff -up ghostscript-9.07/trio/doc/doc_scanf.h.gs_sprintf ghostscript-9.07/trio/doc/doc_scanf.h
+--- ghostscript-9.07/trio/doc/doc_scanf.h.gs_sprintf 2013-05-09 17:02:39.102447240 +0100
++++ ghostscript-9.07/trio/doc/doc_scanf.h 2013-05-09 17:02:39.102447240 +0100
+@@ -0,0 +1,120 @@
++/*************************************************************************
++ *
++ * $Id: doc_scanf.h,v 1.1 2001/12/27 17:29:20 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/** @addtogroup Scanf Formatted Scanning Functions.
++Variations of formatted scanning functions.
++
++@b SYNOPSIS
++
++@verbatim
++cc ... -ltrio -lm
++
++#include <trio.h>
++@endverbatim
++
++@b DESCRIPTION
++
++This documentation is incomplete.
++The documentation of the scanf family in [C99] and [UNIX98] also applies
++to the trio counterparts.
++
++@b SCANNING
++
++The scanning is controlled by the format string.
++The format string can contain normal text and conversion indicators.
++The normal text can be any character except the nil character
++(\000) and the percent character (\045 = '\%').
++Conversion indicators consists of an indication character (%), followed by
++zero or more conversion modifiers, and exactly one conversion specifier.
++
++@b Modifiers
++
++@em Positional ( @c 9$ ) [UNIX98]
++
++See @ref trio_printf.
++
++@b Specifiers
++
++@em Percent ( @c % )
++
++@em Character ( @c c )
++
++@em Decimal ( @c d )
++
++@em Floating-point ( @c a, @c A, @c e, @c E, @c f, @c F, @c g, @c G )
++
++@em Integer ( @c i )
++
++@em Count ( @c n )
++
++@em Octal ( @c o )
++
++@em Pointer ( @c p )
++
++@em String ( @c s )
++
++@em Unsigned ( @c u )
++
++@em Hex ( @c x, @c X )
++
++@em Scanlist ( @c [] )
++
++Scanlist Exclusion (@c ^ )
++
++Scanlist Range ( @c - ) [TRIO]
++
++@li Only increasing ranges, i.e. @c [a-b], but not @c [b-a].
++@li Transitive ranges, ie. @c [a-b-c] equals @c [a-c].
++@li Trailing minus, ie. @c [a-] is interpreted as an @c a and a @c -.
++@li Duplicates are ignored.
++
++Scanlist Equivalence Class Expression ( @c [= @c =] ) [TRIO]
++
++Locale dependent (LC_COLLATE).
++Only one expression can appear inside the delimiters.
++@li @c [=a=] All letters in the same equivalence class as the letter @c a.
++@verbatim
++ trio_scanf("%[[=a=]b]\n", buffer);
++ trio_scanf("%[[=a=][=b=]]\n", buffer);
++@endverbatim
++
++Scanlist Character Class Expression ( @c [: @c :]) [TRIO]
++Locale dependent (LC_CTYPE).
++Only one expression can appear inside the delimiters.
++@li @c [:alnum:] Same as @c [:alpha:] and @c [:digit:]
++@li @c [:alpha:] Same as @c [:lower:] and @c [:upper:]
++@li @c [:cntrl:] Control characters
++@li @c [:digit:] Decimal digits
++@li @c [:graph:] Printable characters except space
++@li @c [:lower:] Lower case alphabetic letters
++@li @c [:print:] Printable characters
++@li @c [:punct:] Punctuation
++@li @c [:space:] Whitespace characters
++@li @c [:upper:] Upper case alphabetic letters
++@li @c [:xdigit:] Hexadecimal digits
++@verbatim
++ trio_scanf("%[[:alnum:]]\n", buffer);
++ trio_scanf("%[[:alpha:][:digit:]]\n", buffer);
++@endverbatim
++
++@b RETURN @b VALUES
++
++@b SEE @b ALSO
++
++@ref trio_printf
++
++*/
+diff -up ghostscript-9.07/trio/doc/doc_static.h.gs_sprintf ghostscript-9.07/trio/doc/doc_static.h
+--- ghostscript-9.07/trio/doc/doc_static.h.gs_sprintf 2013-05-09 17:02:39.103447244 +0100
++++ ghostscript-9.07/trio/doc/doc_static.h 2013-05-09 17:02:39.103447244 +0100
+@@ -0,0 +1,61 @@
++/*************************************************************************
++ *
++ * $Id: doc_static.h,v 1.1 2001/12/27 17:29:20 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/** @addtogroup StaticStrings Static String Functions.
++Replacements for the standard C string functions.
++
++@b SYNOPSIS
++
++@verbatim
++cc ... -ltrio -lm
++
++#include <triostr.h>
++@endverbatim
++
++@b DESCRIPTION
++
++This package renames, fixes, and extends the standard C string handling
++functions.
++
++@b Naming
++
++Renaming is done to provide more clear names, to provide a consistant naming
++and argument policy, and to hide portability issues.
++
++@li All functions starts with "trio_".
++@li Target is always the first argument, if present, except where the target
++is optional, such as @ref trio_to_double.
++@li Functions requiring a size for target includes "_max" in its name, and
++the size is always the second argument.
++@li Functions performing case-sensitive operations includes "_case" in its
++name.
++
++@b Fixing
++
++Fixing is done to avoid subtle error conditions.
++For example, @c strncpy does not terminate the result with a zero if the
++source string is bigger than the maximal length, so technically the result
++is not a C string anymore. @ref trio_copy_max makes sure that the result
++is zero terminated.
++
++@b Extending
++
++Extending is done to provide a richer set of fundamental functions.
++This includes functionality such as wildcard matching ( @c trio_match )
++and calculation of hash values ( @c trio_hash ).
++
++*/
+diff -up ghostscript-9.07/trio/doc/footer.html.gs_sprintf ghostscript-9.07/trio/doc/footer.html
+--- ghostscript-9.07/trio/doc/footer.html.gs_sprintf 2013-05-09 17:02:39.103447244 +0100
++++ ghostscript-9.07/trio/doc/footer.html 2013-05-09 17:02:39.103447244 +0100
+@@ -0,0 +1,4 @@
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/doc/header.html.gs_sprintf ghostscript-9.07/trio/doc/header.html
+--- ghostscript-9.07/trio/doc/header.html.gs_sprintf 2013-05-09 17:02:39.103447244 +0100
++++ ghostscript-9.07/trio/doc/header.html 2013-05-09 17:02:39.103447244 +0100
+@@ -0,0 +1,8 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
+diff -up ghostscript-9.07/trio/doc/trio.cfg.gs_sprintf ghostscript-9.07/trio/doc/trio.cfg
+--- ghostscript-9.07/trio/doc/trio.cfg.gs_sprintf 2013-05-09 17:02:39.103447244 +0100
++++ ghostscript-9.07/trio/doc/trio.cfg 2013-05-09 17:02:39.103447244 +0100
+@@ -0,0 +1,873 @@
++# Doxyfile 1.2.12
++
++# This file describes the settings to be used by the documentation system
++# doxygen (www.doxygen.org) for a project
++#
++# All text after a hash (#) is considered a comment and will be ignored
++# The format is:
++# TAG = value [value, ...]
++# For lists items can also be appended using:
++# TAG += value [value, ...]
++# Values that contain spaces should be placed between quotes (" ")
++
++#---------------------------------------------------------------------------
++# General configuration options
++#---------------------------------------------------------------------------
++
++# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
++# by quotes) that should identify the project.
++
++PROJECT_NAME = TRIO
++
++# The PROJECT_NUMBER tag can be used to enter a project or revision number.
++# This could be handy for archiving the generated documentation or
++# if some version control system is used.
++
++PROJECT_NUMBER =
++
++# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
++# base path where the generated documentation will be put.
++# If a relative path is entered, it will be relative to the location
++# where doxygen was started. If left blank the current directory will be used.
++
++OUTPUT_DIRECTORY =
++
++# The OUTPUT_LANGUAGE tag is used to specify the language in which all
++# documentation generated by doxygen is written. Doxygen will use this
++# information to generate all constant output in the proper language.
++# The default language is English, other supported languages are:
++# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French,
++# German, Hungarian, Italian, Japanese, Korean, Norwegian, Polish,
++# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish.
++
++OUTPUT_LANGUAGE = English
++
++# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
++# documentation are documented, even if no documentation was available.
++# Private class members and static file members will be hidden unless
++# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
++
++EXTRACT_ALL = NO
++
++# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
++# will be included in the documentation.
++
++EXTRACT_PRIVATE = NO
++
++# If the EXTRACT_STATIC tag is set to YES all static members of a file
++# will be included in the documentation.
++
++EXTRACT_STATIC = NO
++
++# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
++# undocumented members of documented classes, files or namespaces.
++# If set to NO (the default) these members will be included in the
++# various overviews, but no documentation section is generated.
++# This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_MEMBERS = YES
++
++# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
++# undocumented classes that are normally visible in the class hierarchy.
++# If set to NO (the default) these class will be included in the various
++# overviews. This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_CLASSES = YES
++
++# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
++# include brief member descriptions after the members that are listed in
++# the file and class documentation (similar to JavaDoc).
++# Set to NO to disable this.
++
++BRIEF_MEMBER_DESC = YES
++
++# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
++# the brief description of a member or function before the detailed description.
++# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
++# brief descriptions will be completely suppressed.
++
++REPEAT_BRIEF = YES
++
++# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
++# Doxygen will generate a detailed section even if there is only a brief
++# description.
++
++ALWAYS_DETAILED_SEC = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
++# path before files name in the file list and in the header files. If set
++# to NO the shortest path that makes the file name unique will be used.
++
++FULL_PATH_NAMES = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
++# can be used to strip a user defined part of the path. Stripping is
++# only done if one of the specified strings matches the left-hand part of
++# the path. It is allowed to use relative paths in the argument list.
++
++STRIP_FROM_PATH =
++
++# The INTERNAL_DOCS tag determines if documentation
++# that is typed after a \internal command is included. If the tag is set
++# to NO (the default) then the documentation will be excluded.
++# Set it to YES to include the internal documentation.
++
++INTERNAL_DOCS = NO
++
++# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
++# doxygen to hide any special comment blocks from generated source code
++# fragments. Normal C and C++ comments will always remain visible.
++
++STRIP_CODE_COMMENTS = YES
++
++# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
++# file names in lower case letters. If set to YES upper case letters are also
++# allowed. This is useful if you have classes or files whose names only differ
++# in case and if your file system supports case sensitive file names. Windows
++# users are adviced to set this option to NO.
++
++CASE_SENSE_NAMES = NO
++
++# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
++# (but less readable) file names. This can be useful is your file systems
++# doesn't support long names like on DOS, Mac, or CD-ROM.
++
++SHORT_NAMES = NO
++
++# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
++# will show members with their full class and namespace scopes in the
++# documentation. If set to YES the scope will be hidden.
++
++HIDE_SCOPE_NAMES = NO
++
++# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
++# will generate a verbatim copy of the header file for each class for
++# which an include is specified. Set to NO to disable this.
++
++VERBATIM_HEADERS = NO
++
++# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
++# will put list of the files that are included by a file in the documentation
++# of that file.
++
++SHOW_INCLUDE_FILES = NO
++
++# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
++# will interpret the first line (until the first dot) of a JavaDoc-style
++# comment as the brief description. If set to NO, the JavaDoc
++# comments will behave just like the Qt-style comments (thus requiring an
++# explict @brief command for a brief description.
++
++JAVADOC_AUTOBRIEF = YES
++
++# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
++# member inherits the documentation from any documented member that it
++# reimplements.
++
++INHERIT_DOCS = YES
++
++# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
++# is inserted in the documentation for inline members.
++
++INLINE_INFO = YES
++
++# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
++# will sort the (detailed) documentation of file and class members
++# alphabetically by member name. If set to NO the members will appear in
++# declaration order.
++
++SORT_MEMBER_DOCS = YES
++
++# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
++# tag is set to YES, then doxygen will reuse the documentation of the first
++# member in the group (if any) for the other members of the group. By default
++# all members of a group must be documented explicitly.
++
++DISTRIBUTE_GROUP_DOC = NO
++
++# The TAB_SIZE tag can be used to set the number of spaces in a tab.
++# Doxygen uses this value to replace tabs by spaces in code fragments.
++
++TAB_SIZE = 8
++
++# The GENERATE_TODOLIST tag can be used to enable (YES) or
++# disable (NO) the todo list. This list is created by putting \todo
++# commands in the documentation.
++
++GENERATE_TODOLIST = YES
++
++# The GENERATE_TESTLIST tag can be used to enable (YES) or
++# disable (NO) the test list. This list is created by putting \test
++# commands in the documentation.
++
++GENERATE_TESTLIST = YES
++
++# The GENERATE_BUGLIST tag can be used to enable (YES) or
++# disable (NO) the bug list. This list is created by putting \bug
++# commands in the documentation.
++
++GENERATE_BUGLIST = YES
++
++# This tag can be used to specify a number of aliases that acts
++# as commands in the documentation. An alias has the form "name=value".
++# For example adding "sideeffect=\par Side Effects:\n" will allow you to
++# put the command \sideeffect (or @sideeffect) in the documentation, which
++# will result in a user defined paragraph with heading "Side Effects:".
++# You can put \n's in the value part of an alias to insert newlines.
++
++ALIASES =
++
++# The ENABLED_SECTIONS tag can be used to enable conditional
++# documentation sections, marked by \if sectionname ... \endif.
++
++ENABLED_SECTIONS =
++
++# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
++# the initial value of a variable or define consist of for it to appear in
++# the documentation. If the initializer consists of more lines than specified
++# here it will be hidden. Use a value of 0 to hide initializers completely.
++# The appearance of the initializer of individual variables and defines in the
++# documentation can be controlled using \showinitializer or \hideinitializer
++# command in the documentation regardless of this setting.
++
++MAX_INITIALIZER_LINES = 30
++
++# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
++# only. Doxygen will then generate output that is more tailored for C.
++# For instance some of the names that are used will be different. The list
++# of all members will be omitted, etc.
++
++OPTIMIZE_OUTPUT_FOR_C = YES
++
++# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
++# at the bottom of the documentation of classes and structs. If set to YES the
++# list will mention the files that were used to generate the documentation.
++
++SHOW_USED_FILES = YES
++
++#---------------------------------------------------------------------------
++# configuration options related to warning and progress messages
++#---------------------------------------------------------------------------
++
++# The QUIET tag can be used to turn on/off the messages that are generated
++# by doxygen. Possible values are YES and NO. If left blank NO is used.
++
++QUIET = NO
++
++# The WARNINGS tag can be used to turn on/off the warning messages that are
++# generated by doxygen. Possible values are YES and NO. If left blank
++# NO is used.
++
++WARNINGS = YES
++
++# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
++# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
++# automatically be disabled.
++
++WARN_IF_UNDOCUMENTED = YES
++
++# The WARN_FORMAT tag determines the format of the warning messages that
++# doxygen can produce. The string should contain the $file, $line, and $text
++# tags, which will be replaced by the file and line number from which the
++# warning originated and the warning text.
++
++WARN_FORMAT =
++
++# The WARN_LOGFILE tag can be used to specify a file to which warning
++# and error messages should be written. If left blank the output is written
++# to stderr.
++
++WARN_LOGFILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to the input files
++#---------------------------------------------------------------------------
++
++# The INPUT tag can be used to specify the files and/or directories that contain
++# documented source files. You may enter file names like "myfile.cpp" or
++# directories like "/usr/src/myproject". Separate the files or directories
++# with spaces.
++
++INPUT = . doc
++
++# If the value of the INPUT tag contains directories, you can use the
++# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
++# and *.h) to filter out the source-files in the directories. If left
++# blank file matching one of the following patterns are included:
++# *.c *.cc *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
++# *.h++ *.idl
++
++FILE_PATTERNS = *.h *.c
++
++# The RECURSIVE tag can be used to turn specify whether or not subdirectories
++# should be searched for input files as well. Possible values are YES and NO.
++# If left blank NO is used.
++
++RECURSIVE = NO
++
++# The EXCLUDE tag can be used to specify files and/or directories that should
++# excluded from the INPUT source files. This way you can easily exclude a
++# subdirectory from a directory tree whose root is specified with the INPUT tag.
++
++EXCLUDE =
++
++# If the value of the INPUT tag contains directories, you can use the
++# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
++# certain files from those directories.
++
++EXCLUDE_PATTERNS =
++
++# The EXAMPLE_PATH tag can be used to specify one or more files or
++# directories that contain example code fragments that are included (see
++# the \include command).
++
++EXAMPLE_PATH = doc
++
++# If the value of the EXAMPLE_PATH tag contains directories, you can use the
++# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
++# and *.h) to filter out the source-files in the directories. If left
++# blank all files are included.
++
++EXAMPLE_PATTERNS =
++
++# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
++# searched for input files to be used with the \include or \dontinclude
++# commands irrespective of the value of the RECURSIVE tag.
++# Possible values are YES and NO. If left blank NO is used.
++
++EXAMPLE_RECURSIVE = NO
++
++# The IMAGE_PATH tag can be used to specify one or more files or
++# directories that contain image that are included in the documentation (see
++# the \image command).
++
++IMAGE_PATH =
++
++# The INPUT_FILTER tag can be used to specify a program that doxygen should
++# invoke to filter for each input file. Doxygen will invoke the filter program
++# by executing (via popen()) the command <filter> <input-file>, where <filter>
++# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
++# input file. Doxygen will then use the output that the filter program writes
++# to standard output.
++
++INPUT_FILTER =
++
++# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
++# INPUT_FILTER) will be used to filter the input files when producing source
++# files to browse.
++
++FILTER_SOURCE_FILES = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to source browsing
++#---------------------------------------------------------------------------
++
++# If the SOURCE_BROWSER tag is set to YES then a list of source files will
++# be generated. Documented entities will be cross-referenced with these sources.
++
++SOURCE_BROWSER = NO
++
++# Setting the INLINE_SOURCES tag to YES will include the body
++# of functions and classes directly in the documentation.
++
++INLINE_SOURCES = NO
++
++# If the REFERENCED_BY_RELATION tag is set to YES (the default)
++# then for each documented function all documented
++# functions referencing it will be listed.
++
++REFERENCED_BY_RELATION = YES
++
++# If the REFERENCES_RELATION tag is set to YES (the default)
++# then for each documented function all documented entities
++# called/used by that function will be listed.
++
++REFERENCES_RELATION = YES
++
++#---------------------------------------------------------------------------
++# configuration options related to the alphabetical class index
++#---------------------------------------------------------------------------
++
++# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
++# of all compounds will be generated. Enable this if the project
++# contains a lot of classes, structs, unions or interfaces.
++
++ALPHABETICAL_INDEX = NO
++
++# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
++# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
++# in which this list will be split (can be a number in the range [1..20])
++
++COLS_IN_ALPHA_INDEX = 5
++
++# In case all classes in a project start with a common prefix, all
++# classes will be put under the same header in the alphabetical index.
++# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
++# should be ignored while generating the index headers.
++
++IGNORE_PREFIX =
++
++#---------------------------------------------------------------------------
++# configuration options related to the HTML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
++# generate HTML output.
++
++GENERATE_HTML = YES
++
++# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `html' will be used as the default path.
++
++HTML_OUTPUT =
++
++# The HTML_HEADER tag can be used to specify a personal HTML header for
++# each generated HTML page. If it is left blank doxygen will generate a
++# standard header.
++
++HTML_HEADER = doc/header.html
++
++# The HTML_FOOTER tag can be used to specify a personal HTML footer for
++# each generated HTML page. If it is left blank doxygen will generate a
++# standard footer.
++
++HTML_FOOTER = doc/footer.html
++
++# The HTML_STYLESHEET tag can be used to specify a user defined cascading
++# style sheet that is used by each HTML page. It can be used to
++# fine-tune the look of the HTML output. If the tag is left blank doxygen
++# will generate a default style sheet
++
++HTML_STYLESHEET = doc/trio.css
++
++# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
++# files or namespaces will be aligned in HTML using tables. If set to
++# NO a bullet list will be used.
++
++HTML_ALIGN_MEMBERS = YES
++
++# If the GENERATE_HTMLHELP tag is set to YES, additional index files
++# will be generated that can be used as input for tools like the
++# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
++# of the generated HTML documentation.
++
++GENERATE_HTMLHELP = NO
++
++# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
++# controls if a separate .chi index file is generated (YES) or that
++# it should be included in the master .chm file (NO).
++
++GENERATE_CHI = NO
++
++# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
++# controls whether a binary table of contents is generated (YES) or a
++# normal table of contents (NO) in the .chm file.
++
++BINARY_TOC = NO
++
++# The TOC_EXPAND flag can be set to YES to add extra items for group members
++# to the contents of the Html help documentation and to the tree view.
++
++TOC_EXPAND = NO
++
++# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
++# top of each HTML page. The value NO (the default) enables the index and
++# the value YES disables it.
++
++DISABLE_INDEX = NO
++
++# This tag can be used to set the number of enum values (range [1..20])
++# that doxygen will group on one line in the generated HTML documentation.
++
++ENUM_VALUES_PER_LINE = 4
++
++# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
++# generated containing a tree-like index structure (just like the one that
++# is generated for HTML Help). For this to work a browser that supports
++# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
++# or Internet explorer 4.0+). Note that for large projects the tree generation
++# can take a very long time. In such cases it is better to disable this feature.
++# Windows users are probably better off using the HTML help feature.
++
++GENERATE_TREEVIEW = NO
++
++# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
++# used to set the initial width (in pixels) of the frame in which the tree
++# is shown.
++
++TREEVIEW_WIDTH = 250
++
++#---------------------------------------------------------------------------
++# configuration options related to the LaTeX output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
++# generate Latex output.
++
++GENERATE_LATEX = NO
++
++# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `latex' will be used as the default path.
++
++LATEX_OUTPUT =
++
++# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
++# LaTeX documents. This may be useful for small projects and may help to
++# save some trees in general.
++
++COMPACT_LATEX = NO
++
++# The PAPER_TYPE tag can be used to set the paper type that is used
++# by the printer. Possible values are: a4, a4wide, letter, legal and
++# executive. If left blank a4wide will be used.
++
++PAPER_TYPE = a4wide
++
++# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
++# packages that should be included in the LaTeX output.
++
++EXTRA_PACKAGES =
++
++# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
++# the generated latex document. The header should contain everything until
++# the first chapter. If it is left blank doxygen will generate a
++# standard header. Notice: only use this tag if you know what you are doing!
++
++LATEX_HEADER =
++
++# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
++# is prepared for conversion to pdf (using ps2pdf). The pdf file will
++# contain links (just like the HTML output) instead of page references
++# This makes the output suitable for online browsing using a pdf viewer.
++
++PDF_HYPERLINKS = NO
++
++# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
++# plain latex in the generated Makefile. Set this option to YES to get a
++# higher quality PDF documentation.
++
++USE_PDFLATEX = NO
++
++# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
++# command to the generated LaTeX files. This will instruct LaTeX to keep
++# running if errors occur, instead of asking the user for help.
++# This option is also used when generating formulas in HTML.
++
++LATEX_BATCHMODE = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the RTF output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
++# The RTF output is optimised for Word 97 and may not look very pretty with
++# other RTF readers or editors.
++
++GENERATE_RTF = NO
++
++# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `rtf' will be used as the default path.
++
++RTF_OUTPUT =
++
++# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
++# RTF documents. This may be useful for small projects and may help to
++# save some trees in general.
++
++COMPACT_RTF = NO
++
++# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
++# will contain hyperlink fields. The RTF file will
++# contain links (just like the HTML output) instead of page references.
++# This makes the output suitable for online browsing using WORD or other
++# programs which support those fields.
++# Note: wordpad (write) and others do not support links.
++
++RTF_HYPERLINKS = NO
++
++# Load stylesheet definitions from file. Syntax is similar to doxygen's
++# config file, i.e. a series of assigments. You only have to provide
++# replacements, missing definitions are set to their default value.
++
++RTF_STYLESHEET_FILE =
++
++# Set optional variables used in the generation of an rtf document.
++# Syntax is similar to doxygen's config file.
++
++RTF_EXTENSIONS_FILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to the man page output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
++# generate man pages
++
++GENERATE_MAN = NO
++
++# The MAN_OUTPUT tag is used to specify where the man pages will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `man' will be used as the default path.
++
++MAN_OUTPUT =
++
++# The MAN_EXTENSION tag determines the extension that is added to
++# the generated man pages (default is the subroutine's section .3)
++
++MAN_EXTENSION =
++
++# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
++# then it will generate one additional man file for each entity
++# documented in the real man page(s). These additional files
++# only source the real man page, but without them the man command
++# would be unable to find the correct page. The default is NO.
++
++MAN_LINKS = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the XML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_XML tag is set to YES Doxygen will
++# generate an XML file that captures the structure of
++# the code including all documentation. Note that this
++# feature is still experimental and incomplete at the
++# moment.
++
++GENERATE_XML = NO
++
++#---------------------------------------------------------------------------
++# Configuration options related to the preprocessor
++#---------------------------------------------------------------------------
++
++# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
++# evaluate all C-preprocessor directives found in the sources and include
++# files.
++
++ENABLE_PREPROCESSING = YES
++
++# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
++# names in the source code. If set to NO (the default) only conditional
++# compilation will be performed. Macro expansion can be done in a controlled
++# way by setting EXPAND_ONLY_PREDEF to YES.
++
++MACRO_EXPANSION = YES
++
++# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
++# then the macro expansion is limited to the macros specified with the
++# PREDEFINED and EXPAND_AS_PREDEFINED tags.
++
++EXPAND_ONLY_PREDEF = YES
++
++# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
++# in the INCLUDE_PATH (see below) will be search if a #include is found.
++
++SEARCH_INCLUDES = YES
++
++# The INCLUDE_PATH tag can be used to specify one or more directories that
++# contain include files that are not input files but should be processed by
++# the preprocessor.
++
++INCLUDE_PATH =
++
++# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
++# patterns (like *.h and *.hpp) to filter out the header-files in the
++# directories. If left blank, the patterns specified with FILE_PATTERNS will
++# be used.
++
++INCLUDE_FILE_PATTERNS =
++
++# The PREDEFINED tag can be used to specify one or more macro names that
++# are defined before the preprocessor is started (similar to the -D option of
++# gcc). The argument of the tag is a list of macros of the form: name
++# or name=definition (no spaces). If the definition and the = are
++# omitted =1 is assumed.
++
++PREDEFINED = __STDC__=1 TRIO_DOCUMENTATION= TRIO_PUBLIC= TRIO_PRIVATE=static TRIO_CONST=const TRIO_VOLATILE=volatile TRIO_SIGNED=signed TRIO_INLINE=inline TRIO_NOARGS=void TRIO_ARGS1(z,a)=(a) TRIO_ARGS2(z,a,b)=(a,b) TRIO_ARGS3(z,a,b,c)=(a,b,c) TRIO_ARGS4(z,a,b,c,d)=(a,b,c,d) TRIO_ARGS5(z,a,b,c,d,e)=(a,b,c,d,e) TRIO_ARGS6(z,a,b,c,d,e,f)=(a,b,c,d,e,f) TRIO_VARGS2(z,a,b)=(a,b) TRIO_VARGS3(z,a,b,c)=(a,b,c) TRIO_VARGS4(z,a,b,c,d)=(a,b,c,d) TRIO_VARGS5(z,a,b,c,d,e)=(a,b,c,d,e)
++
++# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
++# this tag can be used to specify a list of macro names that should be expanded.
++# The macro definition that is found in the sources will be used.
++# Use the PREDEFINED tag if you want to use a different macro definition.
++
++EXPAND_AS_DEFINED =
++
++# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
++# doxygen's preprocessor will remove all function-like macros that are alone
++# on a line and do not end with a semicolon. Such function macros are typically
++# used for boiler-plate code, and will confuse the parser if not removed.
++
++SKIP_FUNCTION_MACROS = YES
++
++#---------------------------------------------------------------------------
++# Configuration::addtions related to external references
++#---------------------------------------------------------------------------
++
++# The TAGFILES tag can be used to specify one or more tagfiles.
++
++TAGFILES =
++
++# When a file name is specified after GENERATE_TAGFILE, doxygen will create
++# a tag file that is based on the input files it reads.
++
++GENERATE_TAGFILE =
++
++# If the ALLEXTERNALS tag is set to YES all external classes will be listed
++# in the class index. If set to NO only the inherited external classes
++# will be listed.
++
++ALLEXTERNALS = NO
++
++# The PERL_PATH should be the absolute path and name of the perl script
++# interpreter (i.e. the result of `which perl').
++
++PERL_PATH =
++
++#---------------------------------------------------------------------------
++# Configuration options related to the dot tool
++#---------------------------------------------------------------------------
++
++# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
++# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
++# super classes. Setting the tag to NO turns the diagrams off. Note that this
++# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
++# recommended to install and use dot, since it yield more powerful graphs.
++
++CLASS_DIAGRAMS = YES
++
++# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
++# available from the path. This tool is part of Graphviz, a graph visualization
++# toolkit from AT&T and Lucent Bell Labs. The other options in this section
++# have no effect if this option is set to NO (the default)
++
++HAVE_DOT = NO
++
++# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for each documented class showing the direct and
++# indirect inheritance relations. Setting this tag to YES will force the
++# the CLASS_DIAGRAMS tag to NO.
++
++CLASS_GRAPH = YES
++
++# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for each documented class showing the direct and
++# indirect implementation dependencies (inheritance, containment, and
++# class references variables) of the class with other documented classes.
++
++COLLABORATION_GRAPH = YES
++
++# If set to YES, the inheritance and collaboration graphs will show the
++# relations between templates and their instances.
++
++TEMPLATE_RELATIONS = YES
++
++# If set to YES, the inheritance and collaboration graphs will hide
++# inheritance and usage relations if the target is undocumented
++# or is not a class.
++
++HIDE_UNDOC_RELATIONS = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
++# tags are set to YES then doxygen will generate a graph for each documented
++# file showing the direct and indirect include dependencies of the file with
++# other documented files.
++
++INCLUDE_GRAPH = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
++# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
++# documented header file showing the documented files that directly or
++# indirectly include this file.
++
++INCLUDED_BY_GRAPH = YES
++
++# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
++# will graphical hierarchy of all classes instead of a textual one.
++
++GRAPHICAL_HIERARCHY = YES
++
++# The tag DOT_PATH can be used to specify the path where the dot tool can be
++# found. If left blank, it is assumed the dot tool can be found on the path.
++
++DOT_PATH =
++
++# The DOTFILE_DIRS tag can be used to specify one or more directories that
++# contain dot files that are included in the documentation (see the
++# \dotfile command).
++
++DOTFILE_DIRS =
++
++# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
++# (in pixels) of the graphs generated by dot. If a graph becomes larger than
++# this value, doxygen will try to truncate the graph, so that it fits within
++# the specified constraint. Beware that most browsers cannot cope with very
++# large images.
++
++MAX_DOT_GRAPH_WIDTH = 1024
++
++# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
++# (in pixels) of the graphs generated by dot. If a graph becomes larger than
++# this value, doxygen will try to truncate the graph, so that it fits within
++# the specified constraint. Beware that most browsers cannot cope with very
++# large images.
++
++MAX_DOT_GRAPH_HEIGHT = 1024
++
++# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
++# generate a legend page explaining the meaning of the various boxes and
++# arrows in the dot generated graphs.
++
++GENERATE_LEGEND = YES
++
++# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
++# remove the intermedate dot files that are used to generate
++# the various graphs.
++
++DOT_CLEANUP = YES
++
++#---------------------------------------------------------------------------
++# Configuration::addtions related to the search engine
++#---------------------------------------------------------------------------
++
++# The SEARCHENGINE tag specifies whether or not a search engine should be
++# used. If set to NO the values of all tags below this one will be ignored.
++
++SEARCHENGINE = NO
++
++# The CGI_NAME tag should be the name of the CGI script that
++# starts the search engine (doxysearch) with the correct parameters.
++# A script with this name will be generated by doxygen.
++
++CGI_NAME =
++
++# The CGI_URL tag should be the absolute URL to the directory where the
++# cgi binaries are located. See the documentation of your http daemon for
++# details.
++
++CGI_URL =
++
++# The DOC_URL tag should be the absolute URL to the directory where the
++# documentation is located. If left blank the absolute path to the
++# documentation, with file:// prepended to it, will be used.
++
++DOC_URL =
++
++# The DOC_ABSPATH tag should be the absolute path to the directory where the
++# documentation is located. If left blank the directory on the local machine
++# will be used.
++
++DOC_ABSPATH =
++
++# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
++# is installed.
++
++BIN_ABSPATH =
++
++# The EXT_DOC_PATHS tag can be used to specify one or more paths to
++# documentation generated for other projects. This allows doxysearch to search
++# the documentation for these projects as well.
++
++EXT_DOC_PATHS =
+diff -up ghostscript-9.07/trio/doc/trio.css.gs_sprintf ghostscript-9.07/trio/doc/trio.css
+--- ghostscript-9.07/trio/doc/trio.css.gs_sprintf 2013-05-09 17:02:39.103447244 +0100
++++ ghostscript-9.07/trio/doc/trio.css 2013-05-09 17:02:39.103447244 +0100
+@@ -0,0 +1,35 @@
++/* HTML tags */
++
++BODY {
++ background-color: white;
++ color: darkblue;
++}
++
++TD { color: darkblue; }
++
++H1 { text-align: center; }
++
++H3 { font-style: italic; }
++
++HR {
++ width: 85%;
++ align: center;
++}
++
++.copyright { color: darkblue; }
++
++/* Links */
++
++:link { color: blue; }
++
++:visited { color: purple; }
++
++:active { color: red; }
++
++.el:link { font-style: italic; }
++
++/* Examples */
++
++DIV.fragment {
++ color: maroon;
++}
+diff -up ghostscript-9.07/trio/example.c.gs_sprintf ghostscript-9.07/trio/example.c
+--- ghostscript-9.07/trio/example.c.gs_sprintf 2013-05-09 17:02:39.104447249 +0100
++++ ghostscript-9.07/trio/example.c 2013-05-09 17:02:39.104447249 +0100
+@@ -0,0 +1,543 @@
++/*************************************************************************
++ * For testing purposes
++ */
++
++#include <stdarg.h>
++#include <limits.h>
++#include <math.h>
++#include <unistd.h>
++/* #include <nan.h> */
++#include <wchar.h>
++#include "strio.h"
++#include "trio.h"
++#undef printf
++
++#if !defined(USE_LONGLONG)
++# if defined(__GNUC__) && !defined(__STRICT_ANSI__)
++# define USE_LONGLONG
++# elif defined(__SUNPRO_C)
++# define USE_LONGLONG
++# endif
++#endif
++
++#if defined(USE_LONGLONG)
++# define LONGLONG long long
++#else
++# define LONGLONG long
++#endif
++
++#if defined(TRIO_C99)
++# define LONGEST intmax_t
++#else
++# define LONGEST LONGLONG
++#endif
++
++static const char rcsid[] = "@(#)$Id: example.c,v 1.9 2001/11/25 13:47:38 breese Exp $";
++
++/*************************************************************************
++ *
++ */
++void Dump(char *buffer, int rc)
++{
++ if (rc < 0)
++ {
++ printf("Err = %d (%s), Pos = %d\n",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ }
++ else
++ printf("buffer[% 3d] = \"%s\"\n", rc, buffer);
++}
++
++/*************************************************************************
++ *
++ */
++int main(void)
++{
++ char buffer[512];
++ int rc;
++ LONGLONG int dummy;
++ char *fool;
++ int num;
++ int num2;
++ int count;
++ double dnum;
++ char *end;
++ char text[256];
++ char ch;
++ int nerrors = 0;
++ void *p1;
++ char *p2;
++
++ printf("%s\n", rcsid);
++
++/* printf("%d %u %d %u\n", */
++/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
++/* trio_printf("%d %u %d %u\n", */
++/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
++/* printf("%d %u\n", INT_MIN, INT_MIN); */
++/* trio_printf("%d %u\n", INT_MIN, INT_MIN); */
++
++/* printf("%ld %lu %ld %lu\n", */
++/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
++/* trio_printf("%ld %lu %ld %lu\n", */
++/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
++/* printf("%ld %lu\n", INT_MIN, INT_MIN); */
++/* trio_printf("%ld %lu\n", INT_MIN, INT_MIN); */
++
++/* printf("%lld %llu %lld %llu\n", */
++/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
++/* trio_printf("%lld %llu %lld %llu\n", */
++/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
++/* printf("%lld %llu\n", INT_MIN, INT_MIN); */
++/* trio_printf("%lld %llu\n", INT_MIN, INT_MIN); */
++
++/* return 0; */
++
++
++/* dnum = StrToDouble("3.14e+44", (const char **)&end); */
++/* printf("double = %e (%s)\n", dnum, end); */
++/* dnum = StrToDouble("0xA3.14p44", (const char **)&end); */
++/* printf("double = %e (%s)\n", dnum, end); */
++
++ /* trio_printf("%.*stext\n", 0, "-----"); */ /* fails */
++
++/* trio_printf("%Zd\n", (size_t)sizeof(char)); */
++
++/* rc = StrFormat(buffer, "%a", 3.14e+44); */
++/* Dump(buffer, rc); */
++
++ /* rc = StrFormat(buffer, "Filled string: %-16<fill=_>s", "test"); */
++
++/* errno = EINTR; */
++/* rc = StrFormat(buffer, "Error: %m"); */
++
++/* rc = StrFormat(buffer, "Count %lln", &dummy); */
++/* printf("dummy = %lld\n", dummy); */
++
++/* rc = StrFormat(buffer, "Char %<quote='>c", 'X'); */
++
++/* rc = StrFormatMax(buffer, 20, "Here goes %-20<adjust=_>s", "test"); */
++
++/* rc = StrFormat(buffer, "Hex-float %a", 3.1415); */
++/* Dump(buffer, rc); */
++/* rc = StrFormat(buffer, "Hex-float %A", 3.1415e20); */
++/* Dump(buffer, rc); */
++/* rc = StrFormat(buffer, "Double %#g", 3.1415e20); */
++/* Dump(buffer, rc); */
++/* rc = StrFormat(buffer, "Double %.3f", 3.1415); */
++/* Dump(buffer, rc); */
++/* rc = StrFormat(buffer, "Double %+e", 3.1415); */
++/* Dump(buffer, rc); */
++
++/* printf("'%.2f'\n", 99.99999); */
++/* trio_printf("'%.2f'\n", 99.99999); */
++/* printf("'%f'\n", 0.0); */
++/* trio_printf("'%f'\n", 0.0); */
++/* printf("'%f'\n", 3141.0); */
++/* trio_printf("'%f'\n", 3141.0); */
++/* printf("'%#f'\n", 3141.0); */
++/* trio_printf("'%#f'\n", 3141.0); */
++/* printf("'%'f'\n", 31415.2); */
++/* trio_printf("'%'f'\n", 31415.2); */
++/* printf("'%-16e'\n", 3141.5); */
++/* trio_printf("'%-16e'\n", 3141.5); */
++/* printf("'%#f'\n", 3141.0); */
++/* trio_printf("'%#f'\n", 3141.0); */
++/* printf("'%f'\n", 3141.5); */
++/* trio_printf("'%f'\n", 3141.5); */
++/* printf("'%#.6g'\n", 3141.5); */
++/* trio_printf("'%#.6g'\n", 3141.5); */
++
++/* printf("'%20e'\n", 314.5); */
++/* trio_printf("'%20e'\n", 314.5); */
++
++/* printf("'%-16e'\n", 3141.5); */
++/* trio_printf("'%-16e'\n", 3141.5); */
++
++/* printf("'%#.4g'\n", 314151.5); */
++/* trio_printf("'%#.4g'\n", 314151.5); */
++
++/* printf("'%#.4g'\n", 0.0); */
++/* trio_printf("'%#.4g'\n", 0.0); */
++
++/* printf("'%#.4g'\n", 11.0); */
++/* trio_printf("'%#.4g'\n", 11.0); */
++
++/* printf("%f\n", HUGE_VAL); */
++/* trio_printf("%f\n", HUGE_VAL); */
++/* printf("%f\n", -HUGE_VAL); */
++/* trio_printf("%f\n", -HUGE_VAL); */
++/* #define NAN (cos(HUGE_VAL)) */
++/* printf("%f\n", NAN); */
++/* trio_printf("%f\n", NAN); */
++
++/* printf("'%+06d'\n", 1234); */
++/* trio_printf("'%+06d'\n", 1234); */
++/* printf("'%-#6.3x'\n", 12); */
++/* trio_printf("'%-#06.3x'\n", 12); */
++/* printf("'%+6d'\n", 1234); */
++/* trio_printf("'%+6d'\n", 1234); */
++/* printf("'%-08d'\n", 12); */
++/* trio_printf("'%-08d'\n", 12); */
++/* printf("'%08.6d'\n", 12); */
++/* trio_printf("'%08.6d'\n", 12); */
++/* printf("'%4d'\n", 123456); */
++/* trio_printf("'%4d'\n", 123456); */
++/* printf("'%.4d'\n", 12); */
++/* trio_printf("'%.4d'\n", 12); */
++
++/* trio_printf("%!#08x %04x %..10x\n", 42, 42, 42); */
++/* trio_printf("%*.*.*i\n", 8, 4, 2, 23); */
++/* trio_printf("%8.4.2i %<base=2>08i %.8.2i %..2i\n", 23, 23, 23, 23); */
++
++/* trio_printf("%8i\n", 42); */
++/* trio_printf("%.7i\n", 42); */
++/* trio_printf("%..2i\n", 42); */
++/* trio_printf("%8.7i\n", 42); */
++/* trio_printf("%8..2i\n", 42); */
++/* trio_printf("%8.7.2i\n", 42); */
++/* trio_printf("%*.*.*i\n", 8, 7, 2, 42); */
++
++/* { */
++/* LONGLONG ll = 1234567890; */
++/* rc = trio_printf("%&i %d\n", sizeof(ll), ll, 42); */
++/* Dump(buffer, rc); */
++/* } */
++/* { */
++/* char ch = 12; */
++/* rc = trio_printf("%&i %d\n", sizeof(ch), ch, 42); */
++/* Dump(buffer, rc); */
++/* } */
++/* { */
++/* pid_t pid = 99; */
++/* rc = trio_printf("%&i %d\n", sizeof(pid), pid, 42); */
++/* Dump(buffer, rc); */
++/* } */
++
++/* rc = trio_printf("%*.*.*i\n", 6, 4, 10, 12); */
++/* Dump(buffer, rc); */
++/* rc = trio_printf("%1$0*3$.*2$d\n", 3141, 6, 10); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_asprintf(&end, "%s%n", "0123456789", &num); */
++/* printf("%d %d '%s'\n", rc, num, end); */
++/* if (end) */
++/* free(end); */
++
++/* trio_printf("%016e\n", 3141.5); */
++/* trio_printf("%'f\n", 424242.42); */
++/* trio_printf("%#.4f\n", 0.0); */
++/* trio_printf("%'d\n", 424242); */
++
++/* rc = trio_sprintf(buffer, "%4$d %3$*8$d %2$.*7$d %1$*6$.*5$d\n", */
++/* 123, */
++/* 1234, */
++/* 12345, */
++/* 123456, */
++/* 5, 6, 7, 8 */
++/* ); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%2$s %1$#s", "111", "222"); */
++/* Dump(buffer, rc); */
++
++/* trio_printf(" %x %!#x %g %09x %x\n", 123456, 123456, 123456.0, 123456, 123456); */
++/* trio_printf("%!'i %f %i\n", 12345, 12345.0, 12345); */
++/* trio_printf("%!<base=2>i %i\n", 23, 23); */
++
++/* rc = trio_sprintf(buffer, "%I32d", 12345); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%I32I8d", 12345); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "*%5f*", 3.3); */
++/* Dump(buffer, rc); */
++
++/* { */
++/* wchar_t *wstring = L"some data"; */
++/* wchar_t wbuffer[512]; */
++
++/* rc = trio_sprintf(buffer, "%ls", wstring); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sscanf(buffer, "%ls", wbuffer); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%ls", wbuffer); */
++/* Dump(buffer, rc); */
++/* } */
++
++ /* rc = StrFormat(buffer, "\040-\040\040-\n"); */
++
++/* rc = StrFormat(buffer, "%.*s@%s", 3, "Daniel", "Fool"); */
++/* rc = StrFormatAppendMax(buffer, 512, " %s is a doh", "Simpson"); */
++
++/* rc = StrFormat(buffer, "hello %1$d %1$d", 31, 32); */
++/* Dump(buffer, rc); */
++/* rc = StrFormat(buffer, "%2$d %3$d", 31, 32, 33); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%d say %g hey %s", 42, 3.14, "text"); */
++/* Dump(buffer, rc); */
++/* trio_sscanf(buffer, "%d %*s %e hey %s", &num, &dnum, text); */
++/* printf("num = %d, dnum = %e, text = \"%s\"\n", num, dnum, text); */
++
++/* rc = trio_sprintf(buffer, "%g", HUGE_VAL); */
++/* Dump(buffer, rc); */
++/* trio_sscanf(buffer, "%f", &dnum); */
++/* printf("dnum = %e\n", dnum); */
++
++/* rc = trio_sprintf(buffer, "%g", -HUGE_VAL); */
++/* Dump(buffer, rc); */
++/* trio_sscanf(buffer, "%f", &dnum); */
++/* printf("dnum = %e\n", dnum); */
++
++/* #if defined(NAN) */
++/* rc = trio_sprintf(buffer, "%g", NAN); */
++/* Dump(buffer, rc); */
++/* if ((rc = trio_sscanf(buffer, "%f", &dnum)) < 0) */
++/* Dump(buffer, rc); */
++/* else */
++/* printf("dnum = %e\n", dnum); */
++/* #endif */
++
++/* rc = trio_sprintf(buffer, "%*d", 6, 1234); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "'%!08.6d' '%!d' '%d'", 4, 6, 8); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%0g", 0.123); */
++/* Dump(buffer, rc); */
++
++/* { */
++/* void *argarray[4]; */
++/* int value = 42; */
++/* double number = 123.456; */
++/* float small_number = 123.456; */
++
++/* argarray[0] = &value; */
++/* argarray[1] = "my string"; */
++/* rc = trio_sprintfv(buffer, "%d %s", argarray); */
++/* Dump(buffer, rc); */
++/* rc = trio_snprintfv(buffer, 8, "%d %s", argarray); */
++/* Dump(buffer, rc); */
++
++/* argarray[0] = &num; */
++/* argarray[1] = text; */
++/* rc = trio_sscanfv(buffer, "%d %s", argarray); */
++/* Dump(buffer, rc); */
++/* printf("num = %d text = \"%s\"\n", num, text); */
++
++/* argarray[0] = &number; */
++/* argarray[1] = &small_number; */
++/* rc = trio_sprintfv(buffer, "%f %hf", argarray); */
++/* Dump(buffer, rc); */
++/* printf("number = %f small_number = \"%f\"\n", number, small_number); */
++/* } */
++
++#if 0
++ rc = trio_sprintf(buffer, "abcba");
++ Dump(buffer, rc);
++ trio_sscanf(buffer, "%[ab]", text);
++ printf("text = \"%s\"\n", text);
++ trio_sscanf(buffer, "%*[ab]c%[^\n]", text);
++ printf("text = \"%s\"\n", text);
++
++ trio_sprintf(buffer, "aabcdba aaa");
++ rc = trio_sscanf(buffer, "%s", text);
++ Dump(buffer, rc);
++ printf("text = \"%s\"\n", text);
++ rc = trio_sscanf(buffer, "%*1[aA]%[a-c]", text);
++ Dump(buffer, rc);
++ printf("text = \"%s\"\n", text);
++
++ rc = trio_sprintf(buffer, "10021");
++ rc = trio_sscanf(buffer, "%b%n%d", &num, &count, &num2);
++ Dump(buffer, rc);
++ printf("num = %d %d %d\n", num, num2, count);
++#endif
++
++/* rc = trio_sprintf(buffer, "%'d", 10000); */
++/* rc = trio_sscanf(buffer, "%'d", &num); */
++/* Dump(buffer, rc); */
++/* printf("num = %d\n", num); */
++
++/* rc = trio_dprintf(STDOUT_FILENO, "%s\n", "hello there"); */
++/* Dump(buffer, rc); */
++/* rc = trio_dscanf(STDIN_FILENO, "%s", buffer); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_scanf("%s", buffer); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "Ttext"); */
++/* Dump(buffer, rc); */
++/* trio_sscanf(buffer, "%*[Tt]e%c", &ch); */
++/* printf("ch = %c\n", ch); */
++
++/* printf("%p\n", &main); */
++/* rc = trio_sprintf(buffer, "%p %p", &main, NULL); */
++/* Dump(buffer, rc); */
++/* trio_sscanf(buffer, "%p %p", &p1, &p2); */
++/* printf("pointer = %p %p\n", p1, p2); */
++
++/* rc = trio_sprintf(buffer, "%@.@.@i", 8, 7, 2, 42); */
++/* Dump(buffer, rc); */
++/* trio_sprintf(buffer, "abcdefghijklmnopqrstuvwxyz"); */
++/* rc = trio_sscanf(buffer, "%100s", text); */
++/* Dump(text, rc); */
++/* rc = trio_sscanf(buffer, "%@s", 100, text); */
++/* Dump(text, rc); */
++
++/* rc = trio_sprintf(buffer, "%..2i", 42); */
++/* Dump(buffer, rc); */
++/* rc = trio_sscanf(buffer, "%..2i", &num); */
++/* printf("%d\n", num); */
++/* rc = trio_sscanf(buffer, "%..@i", 2, &num); */
++/* printf("%d\n", num); */
++
++/* { */
++/* int num1, num2, num3, num4; */
++
++/* rc = trio_sprintf(buffer, "123_456 [12%%-34%%]"); */
++/* Dump(buffer, rc); */
++/* rc = trio_sscanf(buffer, "%5i%*1s%5i%*1s%5i%*2s%5i", */
++/* &num1, &num2, &num3, &num4); */
++/* Dump(buffer, rc); */
++/* printf("%d %d %d %d %d\n", rc, num1, num2, num3, num4); */
++/* rc = trio_sscanf(buffer, "%d_%d [%d%%-%d%%]", */
++/* &num1, &num2, &num3, &num4); */
++/* Dump(buffer, rc); */
++/* printf("%d %d %d %d %d\n", rc, num1, num2, num3, num4); */
++/* } */
++
++/* rc = trio_sprintf(buffer, "01 3456789"); */
++/* Dump(buffer, rc); */
++/* memset(&text, 0, sizeof(text)); */
++/* rc = trio_sscanf(buffer, "%4c", &text); */
++/* Dump(text, rc); */
++/* memset(&text, 0, sizeof(text)); */
++/* rc = sscanf(buffer, "%4c", &text); */
++/* Dump(text, rc); */
++
++/* rc = trio_sprintf(buffer, "12345 6"); */
++/* Dump(buffer, rc); */
++/* rc = trio_sscanf(buffer, "%2d", &num); */
++/* Dump(buffer, rc); */
++/* printf("%d\n", num); */
++/* rc = sscanf(buffer, "%2d", &num); */
++/* Dump(buffer, rc); */
++/* printf("%d\n", num); */
++
++/* rc = trio_sprintf(buffer, "aa\\x0abb"); */
++/* Dump(buffer, rc); */
++/* rc = trio_sscanf(buffer, "aa%#sbb", &text); */
++/* Dump(text, rc); */
++
++/* rc = trio_sscanf("0 ", "%f", &dnum, text); */
++/* printf("%d %f\n", rc, dnum); */
++/* rc = sscanf("0 ", "%f %s", &dnum, text); */
++/* printf("%d %f\n", rc, dnum); */
++
++/* rc = trio_sscanf("lære", "%[:alpha:]", text); */
++/* Dump(text, rc); */
++
++/* rc = trio_sscanf("-0.123e3", "%8e", &dnum); */
++/* printf("%d %f\n", rc, dnum); */
++
++/* rc = trio_sscanf("123,456.78", "%'f", &dnum); */
++/* printf("%d %f\n", rc, dnum); */
++
++/* rc = trio_sscanf("1.e-6","%g", &dnum); */
++/* printf("%d %g\n", rc, dnum); */
++/* rc = trio_sscanf("1e-6","%g", &dnum); */
++/* printf("%d %g\n", rc, dnum); */
++
++/* rc = trio_sprintf(buffer, "%0.40e\n", 14.0); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%010.3e\n", 3141.5); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%e", 0.6); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%e", 0.5); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%#11.5g", 1e5); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%010.3e", 3141.5); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%11.5g", 1e-5); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%g", 1.79769e+308); */
++/* printf("%d \"%s\"\n", rc, buffer); */
++/* trio_sscanf(buffer, "%g", &dnum); */
++/* printf("%d %g\n", rc, dnum); */
++
++/* rc = trio_snprintf(0, 0, "text"); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%.16.2f", (float)41.8713); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%.16.2f", (float)41.8687); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%.16.2f", (float)41.8684); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%#.4g", 1e-3); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%#.2g", (double)0.01); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%#11.5g", (double)1.0); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%#11.5g", (double)0.9999999999999999); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%#11.5g", (double)0.1); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%#11.5g", (double)0.0999999999999999); */
++/* Dump(buffer, rc); */
++
++/* rc = trio_sprintf(buffer, "%#11.5g", (double)0.01); */
++/* Dump(buffer, rc); */
++/* rc = trio_sprintf(buffer, "%#11.5g", (double)0.0099999999999999); */
++/* Dump(buffer, rc); */
++
++/* char * buf = "aaaaaaaaaaaaaaaaaaaaaaaaa"; */
++/* int buf_len = 4; */
++/* rc = trio_sprintf(buffer, ">%.*s\n", buf_len, buf); */
++
++/* rc = trio_sprintf(buffer, "$d", 1); */
++/* Dump(buffer, rc); */
++
++/* trio_sprintf(buffer, "%lld.%ld%s", 0LL, 0L, ","); */
++/* Dump(buffer, rc); */
++
++/* trio_sprintf(buffer, "%+.14e", (double)1.27299014704543e-313); */
++/* Dump(buffer, rc); */
++
++/* rc = scanf(""); */
++/* rc = trio_scanf(""); */
++
++/* trio_sprintf(buffer, "abcd"); */
++/* rc = trio_sscanf(buffer, "%c", &ch); */
++/* printf("%d %c\n", rc, ch); */
++
++/* for(unsigned int i = 0U ; i < 100000U ; ++i) */
++/* { */
++/* trio_sprintf(buffer, "The next value of '%s' is %d (ln: %d) ('%s')\n", */
++/* "i", i+1, __LINE__, "foo bar"); */
++/* } */
++
++ rc = trio_snprintf(NULL, 0, "%s", "not used");
++ Dump(buffer, rc);
++
++ return 0;
++}
+diff -up ghostscript-9.07/trio/FILES.gs_sprintf ghostscript-9.07/trio/FILES
+--- ghostscript-9.07/trio/FILES.gs_sprintf 2013-05-09 17:02:39.104447249 +0100
++++ ghostscript-9.07/trio/FILES 2013-05-09 17:02:39.104447249 +0100
+@@ -0,0 +1,33 @@
++FILES
++README
++CHANGES
++Makefile.in
++maketgz
++strio.h
++trio.c
++trio.h
++triodef.h
++trionan.c
++trionan.h
++triop.h
++triostr.c
++triostr.h
++compare.c
++example.c
++regression.c
++configure
++configure.in
++install-sh
++autogen.sh
++doc/doc.h
++doc/doc_dynamic.h
++doc/doc_printf.h
++doc/doc_register.h
++doc/doc_scanf.h
++doc/doc_static.h
++doc/footer.html
++doc/header.html
++doc/trio.cfg
++doc/trio.css
++html/trio.css
++html/*.html
+diff -up ghostscript-9.07/trio/html/group___dynamic_strings.html.gs_sprintf ghostscript-9.07/trio/html/group___dynamic_strings.html
+--- ghostscript-9.07/trio/html/group___dynamic_strings.html.gs_sprintf 2013-05-09 17:02:39.104447249 +0100
++++ ghostscript-9.07/trio/html/group___dynamic_strings.html 2013-05-09 17:02:39.104447249 +0100
+@@ -0,0 +1,300 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>Dynamic String Functions.</h1>Dynamic string functions.
++<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
++<tr><td></td></tr>
++<tr><td colspan=2><br><h2>Functions</h2></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING trio_string_t *&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a0">trio_string_create</a> (int initial_size)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Create a new dynamic string.</em> <a href="#a0"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING void&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a1">trio_string_destroy</a> (trio_string_t *self)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Deallocate the dynamic string and its contents.</em> <a href="#a1"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a2">trio_string_extract</a> (trio_string_t *self)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Extract the content.</em> <a href="#a2"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING void&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a3">trio_xstring_set</a> (trio_string_t *self, char *buffer)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Set the content of the dynamic string.</em> <a href="#a3"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a6">trio_string_append</a> (trio_string_t *self, trio_string_t *other)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Append the second string to the first.</em> <a href="#a6"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a9">trio_string_contains</a> (trio_string_t *self, trio_string_t *other)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Search for the first occurrence of second parameter in the first.</em> <a href="#a9"></a><em></em></font><br><br></td></tr>
++</table>
++<hr><a name="_details"></a><h2>Detailed Description</h2>
++Dynamic string functions.
++<p>
++<b>SYNOPSIS</b>
++<p>
++<div class="fragment"><pre>
++cc ... -ltrio -lm
++
++#include &lt;triostr.h&gt;
++</pre></div>
++<p>
++<b>DESCRIPTION</b> <hr><h2>Function Documentation</h2>
++<a name="a6" doxytag="triostr-macro.c::trio_string_append"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_string_append </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_string_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>other</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Append the second string to the first.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>self</em>&nbsp;</td><td>
++Dynamic string to be modified. </td></tr>
++<tr><td valign=top><em>other</em>&nbsp;</td><td>
++Dynamic string to copy from. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure. </dl> </td>
++ </tr>
++</table>
++<a name="a9" doxytag="triostr-macro.c::trio_string_contains"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_string_contains </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_string_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>other</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Search for the first occurrence of second parameter in the first.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>self</em>&nbsp;</td><td>
++Dynamic string to be modified. </td></tr>
++<tr><td valign=top><em>other</em>&nbsp;</td><td>
++Dynamic string to copy from. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure. </dl> </td>
++ </tr>
++</table>
++<a name="a0" doxytag="triostr-macro.c::trio_string_create"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING trio_string_t* trio_string_create </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>initial_size</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Create a new dynamic string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>initial_size</em>&nbsp;</td><td>
++Initial size of the buffer. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Newly allocated dynamic string, or NULL if memory allocation failed. </dl> </td>
++ </tr>
++</table>
++<a name="a1" doxytag="triostr-macro.c::trio_string_destroy"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING void trio_string_destroy </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>self</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Deallocate the dynamic string and its contents.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>self</em>&nbsp;</td><td>
++Dynamic string </td></tr>
++</table>
++</dl> </td>
++ </tr>
++</table>
++<a name="a2" doxytag="triostr-macro.c::trio_string_extract"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_string_extract </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>self</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Extract the content.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>self</em>&nbsp;</td><td>
++Dynamic String </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Content of dynamic string.</dl>The content is removed from the dynamic string. This enables destruction of the dynamic string without deallocation of the content. </td>
++ </tr>
++</table>
++<a name="a3" doxytag="triostr-macro.c::trio_xstring_set"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING void trio_xstring_set </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Set the content of the dynamic string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>self</em>&nbsp;</td><td>
++Dynamic String </td></tr>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++The new content.</td></tr>
++</table>
++</dl>Sets the content of the dynamic string to a copy <code>buffer</code>. An existing content will be deallocated first, if necessary.
++<p>
++<dl compact><dt><b>Remarks: </b></dt><dd>
++ This function will make a copy of <code>buffer</code>. You are responsible for deallocating <code>buffer</code> yourself. </dl> </td>
++ </tr>
++</table>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/group___printf.html.gs_sprintf ghostscript-9.07/trio/html/group___printf.html
+--- ghostscript-9.07/trio/html/group___printf.html.gs_sprintf 2013-05-09 17:02:39.105447253 +0100
++++ ghostscript-9.07/trio/html/group___printf.html 2013-05-09 17:02:39.105447253 +0100
+@@ -0,0 +1,1404 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>Formatted Printing Functions.</h1>Variations of formatted printing functions.
++<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
++<tr><td></td></tr>
++<tr><td colspan=2><br><h2>Functions</h2></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a0">trio_printf</a> (const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to standard output stream.</em> <a href="#a0"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a1">trio_vprintf</a> (const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to standard output stream.</em> <a href="#a1"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a2">trio_printfv</a> (const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to standard output stream.</em> <a href="#a2"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a3">trio_fprintf</a> (FILE *file, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to file.</em> <a href="#a3"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a4">trio_vfprintf</a> (FILE *file, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to file.</em> <a href="#a4"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a5">trio_fprintfv</a> (FILE *file, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to file.</em> <a href="#a5"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a6">trio_dprintf</a> (int fd, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to file descriptor.</em> <a href="#a6"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a7">trio_vdprintf</a> (int fd, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to file descriptor.</em> <a href="#a7"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a8">trio_dprintfv</a> (int fd, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to file descriptor.</em> <a href="#a8"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a12">trio_sprintf</a> (char *buffer, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to string.</em> <a href="#a12"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a13">trio_vsprintf</a> (char *buffer, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to string.</em> <a href="#a13"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a14">trio_sprintfv</a> (char *buffer, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print to string.</em> <a href="#a14"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a15">trio_snprintf</a> (char *buffer, size_t max, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print at most <code>max</code> characters to string.</em> <a href="#a15"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a16">trio_vsnprintf</a> (char *buffer, size_t max, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print at most <code>max</code> characters to string.</em> <a href="#a16"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a17">trio_snprintfv</a> (char *buffer, size_t max, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Print at most <code>max</code> characters to string.</em> <a href="#a17"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a22">trio_asprintf</a> (char **result, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Allocate and print to string.</em> <a href="#a22"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a23">trio_vasprintf</a> (char **result, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Allocate and print to string.</em> <a href="#a23"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a24">trio_asprintfv</a> (char **result, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Allocate and print to string.</em> <a href="#a24"></a><em></em></font><br><br></td></tr>
++</table>
++<hr><a name="_details"></a><h2>Detailed Description</h2>
++Variations of formatted printing functions.
++<p>
++<b>SYNOPSIS</b>
++<p>
++<div class="fragment"><pre>
++cc ... -ltrio -lm
++
++#include &lt;trio.h&gt;
++</pre></div>
++<p>
++<b>DESCRIPTION</b>
++<p>
++This documentation is incomplete. The documentation of the printf family in [C99] and [UNIX98] also applies to the trio counterparts.
++<p>
++All these functions outputs a string which is formatted according to the <code>format</code> string and the consecutive arguments. The <code>format</code> string is described in the Formatting section below.
++<p>
++<a class="el" href="group___printf.html#a218">Formatted Printing Functions.</a>, <a class="el" href="group___printf.html#a219">Formatted Printing Functions.</a>, and <a class="el" href="group___printf.html#a220">Formatted Printing Functions.</a> writes the output to the standard output stream (stdout).
++<p>
++<a class="el" href="group___printf.html#a221">Formatted Printing Functions.</a>, <a class="el" href="group___printf.html#a222">Formatted Printing Functions.</a>, and <a class="el" href="group___printf.html#a223">Formatted Printing Functions.</a> writes the output to a given output stream.
++<p>
++<a class="el" href="group___printf.html#a224">Formatted Printing Functions.</a>, <a class="el" href="group___printf.html#a225">Formatted Printing Functions.</a>, and <a class="el" href="group___printf.html#a226">Formatted Printing Functions.</a> writes the output to a file descriptor (this includes, for example, sockets).
++<p>
++<a class="el" href="group___printf.html#a230">Formatted Printing Functions.</a>, <a class="el" href="group___printf.html#a231">Formatted Printing Functions.</a>, and <a class="el" href="group___printf.html#a232">Formatted Printing Functions.</a> writes the output into <code>buffer</code>.
++<p>
++<a class="el" href="group___printf.html#a233">Formatted Printing Functions.</a>, <a class="el" href="group___printf.html#a234">Formatted Printing Functions.</a>, and <a class="el" href="group___printf.html#a235">Formatted Printing Functions.</a> writes <code>max</code> - 1 characters into <code>buffer</code> followed by a terminating zero character. If <code>max</code> is 1, then <code>buffer</code> will be an empty string. If <code>max</code> is 0, then <code>buffer</code> is left untouched, and can consequently be NULL. The number of characters that would have been written to <code>buffer</code>, had there been sufficient space, is returned.
++<p>
++trio_snprintfcat appends the formatted text at the end of <code>buffer</code>.
++<p>
++<a class="el" href="group___printf.html#a240">Formatted Printing Functions.</a>, <a class="el" href="group___printf.html#a241">Formatted Printing Functions.</a>, and <a class="el" href="group___printf.html#a242">Formatted Printing Functions.</a> allocates and returns an allocated string in <code>buffer</code> containing the formatted text.
++<p>
++<b>FORMATTING</b>
++<p>
++The <code>format</code> string can contain normal text and conversion indicators. The normal text can be any character except the nil character (\000 = '\0') and the percent character (\045 = '%'). Conversion indicators consists of an indication character (%), followed by zero or more conversion modifiers, and exactly one conversion specifier.
++<p>
++<b>Modifiers</b>
++<p>
++Some modifiers exhibit the same behaviour for all specifiers, other modifiers indicate different behaviours for different specifiers, and other modifiers are only applicable to certain specifiers. The relationship is described for each modifier. The number 9 is used to denotes an arbitrary integer.
++<p>
++<em>Positional</em> ( <code>9$</code> ) [UNIX98]
++<p>
++Normally the arguments supplied to these functions are interpreted incrementially from left to right. Arguments can be referenced specifically in the format string. The modifier n$ selects the nth argument. The first argument is referred as 1$. If this modifier is used, it must be the first modifier after the indication character. n$ can also be used for argument width, precision, and base.
++<p>
++The performance penalty of using positionals is almost neglible (contrary to most other printf implementations).
++<p>
++<ul>
++<li> <em>Reference</em> <em>Mix</em>. Mixing normal and positional specifiers is allowed [TRIO]. For example, <div class="fragment"><pre>
++ trio_printf("%d %3$d %2$d\n", 1, 2, 3);
++</pre></div> results in <div class="fragment"><pre>
++ 1 3 2
++</pre></div> Arguments for the printf family are passed on the stack. On most platforms it is not possible to determine the size of individual stack elements, so it is essential that the format string corresponds exactly to the passed arguments. If this is not the case, incorrect values may be put into the result.</ul>
++<ul>
++<li> <em>Reference</em> <em>Gap</em>. For the same reason it is also essential that the format string does not contain any "gaps" in the positional arguments. For example, <div class="fragment"><pre>
++ trio_printf("%1$d %3$d\n", 1, 2, 3);
++</pre></div> is NOT allowed. The format string parser has no knowledge about whether the second argument is, say, an integer or a long double (which have different sizes). <div class="fragment"><pre>
++</pre></div> [UNIX98] describes this as unspecified behaviour. [TRIO] will detect reference gaps and return an error.</ul>
++<ul>
++<li> <em>Double</em> <em>Reference</em>. It is also not allowed to reference an argument twice or more. For example, <div class="fragment"><pre>
++ trio_printf("%1$d %1$lf\n", 1);
++</pre></div> is NOT allowed, because it references the first argument as two differently sized objects. <div class="fragment"><pre>
++</pre></div> [UNIX98] describes this as unspecified behaviour. [TRIO] will detect double references and return an error.</ul>
++The following two statements are equivalent <div class="fragment"><pre>
++ trio_printf("|%d %s\n|", 42, "meanings");
++ |42 meanings|
++
++ trio_printf("|%1$d %2$s|\n", 42, "meanings");
++ |42 meanings|
++</pre></div>
++<p>
++<em>Width</em> ( <code>9</code> )
++<p>
++Specifies the minimum width of a field. If the fields has less characters than specified by the width, the field will be left adjusted and padded by spaces. The adjustment and padding can be changed by the Alignment ( <code>-</code> ) and Padding ( <code>0</code> ) modifiers.
++<p>
++The width is specified as a number. If an asterix ( <code>*</code> ) is used instead, the width will be read from the argument list.
++<p>
++Prefixes, such as 0x for hexadecimal integers, are part of width. <div class="fragment"><pre>
++ trio_printf("|%10i|\n", 42);
++ | 42|
++</pre></div>
++<p>
++<em>Precision</em> ( .<code>9</code> )
++<p>
++The precision has different semantics for the various data types. The precision specifies the maximum number of printed characters for strings, the number of digits after the decimal-point for floating-point numbers, the number of significant digits for the <code>g</code> (and <code>G)</code> representation of floating-point numbers, the minimum number of printed digits for integers. <div class="fragment"><pre>
++ trio_printf("|%10.8i|%.8i|\n", 42, 42);
++ | 00000042|00000042|
++</pre></div>
++<p>
++<em>Base</em> ( ..<code>9</code> ) [TRIO]
++<p>
++Sets the base that the associated integer must be converted to. The base can be between 2 and 36 (both included). <div class="fragment"><pre>
++ trio_printf("|%10.8.2i|%10..2i|%..2i|\n", 42, 42, 42);
++ | 00101010| 101010|101010|
++
++ trio_printf("|%*.8.*i|\n", 10, 2, 42);
++ | 00101010|
++</pre></div>
++<p>
++<em>Padding</em> ( <code>0</code> )
++<p>
++Integer and floating point numbers are prepended by zeros. The number of leading zeros are determined by the precision. If precision is not present, width is used instead.
++<p>
++<em>Short</em> ( <code>h</code> )
++<p>
++Integer arguments are read as an ( <code>unsigned</code> ) <code>short</code> <code>int</code>. String and character arguments are read as <code>char</code> <code>*</code> and <code>char</code> respectively.
++<p>
++<em>Short</em> <em>short</em> ( <code>hh</code> ) [C99, GNU]
++<p>
++The argument is read as an ( <code>unsigned</code> ) <code>char</code>.
++<p>
++<em>Fixed</em> <em>Size</em> ( <code>I</code> ) [MSVC]
++<p>
++The argument is read as a fixed sized integer. The modifier is followed by a number, which specifies the number of bits in the integer, and can be one of the following
++<p>
++<ul>
++<li> <code>I8</code> <li> <code>I16</code> <li> <code>I32</code> <li> <code>I64</code> (if 64-bits integers are supported)</ul>
++Works only for integers (i, u, d, o, x, X)
++<p>
++<em>Largest</em> ( <code>j</code> ) [C99]
++<p>
++The argument is read as an <code>intmax_t</code> / <code>uintmax_t</code>, which is defined to be the largest signed/unsigned integer.
++<p>
++<em>Long</em> ( <code>l</code> )
++<p>
++An integral argument is read as an ( <code>unsigned</code> ) <code>long</code> <code>int</code>. A string argument is read as a <code>wchar_t</code> <code>*</code>, and output as a multi-byte character sequence.
++<p>
++<em>Long</em> <em>long</em> ( <code>ll</code> ) [C99, UNIX98, GNU]
++<p>
++The argument is read as an ( <code>unsigned</code> ) <code>long</code> <code>long</code> <code>int</code>.
++<p>
++<em>Long</em> <em>double</em> ( <code>L</code> ) [C99, UNIX98, GNU]
++<p>
++The argument is read as a <code>long</code> <code>double</code>.
++<p>
++<em>ptrdiff_t</em> ( <code>t</code> ) [C99]
++<p>
++The argument is read as a <code>ptrdiff_t</code>, which is defined to be the signed integer type of the result of subtracting two pointers.
++<p>
++<em>Quad</em> ( <code>q</code> ) [BSD, GNU]
++<p>
++Corresponds to the long long modifier ( <code>ll</code> ).
++<p>
++<em>Wide</em> ( <code>w</code> ) [MISC]
++<p>
++For a string argument this is equivalent to using the long modifier ( <code>l</code> ).
++<p>
++<em>size_t</em> ( <code>z</code> ) [C99]
++<p>
++The argument is read as a <code>size_t</code>, which is defined to be the type returned by the <code>sizeof</code> operator.
++<p>
++<em>size_t</em> ( <code>Z</code> ) [GNU]
++<p>
++Corresponds to the size_t modifier ( <code>z</code> ).
++<p>
++<em>Alternative</em> ( <code>#</code> )
++<p>
++Prepend radix indicator for hexadecimal, octal, and binary integer numbers and for pointers. Always add a decimal-point for floating-point numbers. Escape non-printable characters for strings.
++<p>
++<em>Spacing</em> ( )
++<p>
++Prepend leading spaces when necessary.
++<p>
++<em>Sign</em> ( <code>+</code> )
++<p>
++Always prepend a sign to numbers. Normally only the negative sign is prepended to a number. With this modifier the positive sign may also be prepended.
++<p>
++<em>Alignment</em> ( <code>-</code> )
++<p>
++The output will be left-justified in the field specified by the width.
++<p>
++<em>Argument</em> ( <code>*</code> )
++<p>
++Width, precision, or base is read from the argument list, rather than from the formatting string.
++<p>
++<em>Quote</em> / <em>Grouping</em> ( ' <code>)</code> [MISC]
++<p>
++Groups integers and the integer-part of floating-point numbers according to the locale. Quote strings and characters.
++<p>
++<em>Sticky</em> ( <code>!</code> ) [TRIO]
++<p>
++The modifiers listed for the current specifier will be reused by subsequent specifiers of the same group. The following specifier groups exists <ul>
++<li> Integer ( <code>i</code>, <code>u</code>, <code>d</code>, <code>o</code>, <code>x</code>, <code>X</code> ) <li> Floating-point ( <code>f</code>, <code>F</code>, <code>e</code>, <code>E</code>, <code>g</code>, <code>G</code>, <code>a</code>, <code>A</code> ) <li> Character ( <code>c</code> ) <li> String ( <code>s</code> ) <li> Pointer ( <code>p</code> ) <li> Count ( <code>n</code> ) <li> Errno ( <code>m</code> ) <li> Group ( <code>[]</code> )</ul>
++The sticky modifiers are active until superseeded by other sticky modifiers, or the end of the format string is reached. Local modifiers overrides sticky modifiers for the given specifier only. <div class="fragment"><pre>
++ trio_printf("|%!08#x|%04x|%x|\n", 42, 42, 42);
++ |0x00002a|0x2a|0x00002a|
++</pre></div>
++<p>
++<b>Specifiers</b>
++<p>
++<em>Percent</em> ( <code>%</code> )
++<p>
++Produce a percent ( <code>%</code> ) character. This is used to quote the indication character. No modifiers are allowed. The full syntax is <code>%%</code>. <div class="fragment"><pre>
++ trio_printf("Percent is %%\n");
++ Percent is %
++</pre></div>
++<p>
++<em>Hex</em> <em>floats</em> ( <code>a</code>, <code>A</code> ) [C99]
++<p>
++Output a hexadecimal (base 16) representation of a floating point number. The number is automatically preceeded by <code>0x</code> ( or <code>0X</code> ). The exponent is <code>p</code> ( or <code>P</code> ). <div class="fragment"><pre>
++ trio_printf("|%a|%A|\n", 3.1415, 3.1415e20);
++ |0x3.228bc|0X3.228BCP+14|
++</pre></div>
++<p>
++<em>Binary</em> <em>numbers</em> ( <code>b</code>, <code>B</code> ) [MISC - SCO UnixWare 7]
++<p>
++DEPRECATED: Use Base modifier <code>%..2i</code> instead.
++<p>
++<em>Character</em> ( <code>c</code> )
++<p>
++Output a single character.
++<p>
++<ul>
++<li> Quote ( ' <code>)</code> [TRIO]. Quote the character.</ul>
++<em>Decimal</em> ( <code>d</code> )
++<p>
++Output a decimal (base 10) representation of a number.
++<p>
++<ul>
++<li> Grouping ( ' <code>)</code> [TRIO]. The number is separated by the locale thousand separator. <div class="fragment"><pre>
++ trio_printf("|%'ld|\n", 1234567);
++ |1,234,567|
++</pre></div></ul>
++<em>Floating-point</em> ( <code>e</code>, <code>E)</code>
++<p>
++Output a decimal floating-point number. The style is <code>[-]9.99e[-]9</code>, where <ul>
++<li> <code>[-]9.99</code> is the mantissa (as described for the <code>f</code>, <code>F</code> specifier), and <li> <code>e[-]9</code> is the exponent indicator (either <code>e</code> or <code>E</code>, depending on the floating-point specifier), followed by an optional sign and the exponent</ul>
++If the precision is wider than the maximum number of digits that can be represented by the floating-point unit, then the number will be adequately rounded. For example, assuming DBL_DIG is 15 <div class="fragment"><pre>
++ trio_printf("|%.18e|\n", (1.0 / 3.0));
++ |3.333333333333333000e-01|
++</pre></div>
++<p>
++<em>Floating-point</em> ( <code>f</code>, <code>F</code> )
++<p>
++Output a decimal floating-point number. The style is <code>[-]9.99</code>, where <ul>
++<li> <code>[-]</code> is an optional sign (either <code>+</code> or <code>-)</code>, <li> <code>9</code> is the integer-part (possibly interspersed with thousand-separators), <li> . <code>is</code> the decimal-point (depending on the locale), and <li> <code>99</code> is the fractional-part.</ul>
++If more digits are needed to output the number, than can be represented with the accuracy of the floating-point unit, then the number will be adequately rounded. For example, assuming that DBL_DIG is 15 <div class="fragment"><pre>
++ trio_printf("|%f|\n", (2.0 / 3.0) * 1E18);
++ |666666666666666700.000000|
++</pre></div>
++<p>
++The following modifiers holds a special meaning for this specifier <ul>
++<li> Alternative ( <code>#</code> ) [C99]. Add decimal point. <li> Grouping ( ' <code>)</code> [TRIO]. Group integer part of number into thousands (according to locale).</ul>
++<em>Floating-point</em> ( <code>g</code>, <code>G)</code>
++<p>
++Output a decimal floating-point representation of a number. The format of either the <code>f</code>, <code>F</code> specifier or the <code>e</code>, <code>E</code> specifier is used, whatever produces the shortest result.
++<p>
++<em>Integer</em> ( <code>i</code> )
++<p>
++Output a signed integer. Default base is 10.
++<p>
++<em>Errno</em> ( <code>m</code> ) [GNU]
++<p>
++<em>Count</em> ( <code>n</code> )
++<p>
++Insert into the location pointed to by the argument, the number of octets written to the output so far.
++<p>
++<em>Octal</em> ( <code>o</code> )
++<p>
++Output an octal (base 8) representation of a number.
++<p>
++<em>Pointer</em> ( <code>p</code> )
++<p>
++Ouput the address of the argument. The address is printed as a hexadecimal number. If the argument is the NULL pointer the text <code>(nil)</code> will be used instead. <ul>
++<li> Alternative ( <code>#</code> ) [TRIO]. Prepend 0x</ul>
++<em>String</em> ( <code>s</code>, <code>S</code> )
++<p>
++Output a string. The argument must point to a zero terminated string. If the argument is the NULL pointer the text <code>(nil)</code> will be used instead. <code>S</code> is equivalent to <code>ls</code>. <ul>
++<li> Alternative ( <code>#</code> ) [TRIO]. Escape non-printable characters.</ul>
++Non-printable characters are converted into C escapes, or hexadecimal numbers where no C escapes exists for the character. The C escapes, the hexadecimal number, and all backslashes are prepended by a backslash ( <code>\</code> ). The supported C escapes are <ul>
++<li> <code>\a</code> (\007) = alert <li> <code>\b</code> (\010) = backspace <li> <code>\f</code> (\014) = formfeed <li> <code>\n</code> (\012) = newline <li> <code>\r</code> (\015) = carriage return <li> <code>\t</code> (\011) = horizontal tab <li> <code>\v</code> (\013) = vertical tab</ul>
++<div class="fragment"><pre>
++ trio_printf("|One %s Three|One %'s Three|\n", "Two", "Two");
++ |One Two Three|One "Two" Three|
++
++ trio_printf("|Argument missing %s|\n", NULL);
++ |Argument missing (nil)|
++
++ trio_printf("|%#s|\n", "\007 \a.");
++ |\a \a.|
++</pre></div>
++<p>
++<em>Unsigned</em> ( <code>u</code> )
++<p>
++Output an unsigned integer. Default base is 10.
++<p>
++<em>Hex</em> ( <code>x</code>, <code>X</code> )
++<p>
++Output a hexadecimal (base 16) representation of a number.
++<p>
++<ul>
++<li> Alternative ( <code>#</code> ). Preceed the number by <code>0x</code> ( or <code>0X</code> ). The two characters are counted as part of the width.</ul>
++<em>User-defined</em> ( <code>&lt;&gt;</code> )
++<p>
++Invoke user-defined formatting. See <a class="el" href="group___user_defined.html#a243">User-defined Formatted Printing Functions.</a> for further information.
++<p>
++<b>RETURN</b> <b>VALUES</b>
++<p>
++All functions returns the number of outputted characters. If an error occured then a negative error code is returned [TRIO]. Note that this is a deviation from the standard, which simply returns -1 (or EOF) and errno set appropriately. The error condition can be detected by checking whether the function returns a negative number or not, and the number can be parsed with the following macros. The error codes are primarily intended as debugging aide for the developer.
++<p>
++<ul>
++<li> TRIO_EINVAL: Invalid argument. <li> TRIO_ETOOMANY: Too many arguments. <li> TRIO_EDBLREF: Double argument reference. <li> TRIO_EGAP: Argument reference gap. <li> TRIO_ENOMEM: Out of memory. <li> TRIO_ERANGE: Invalid range. <li> TRIO_ERRNO: The error is specified by the errno variable.</ul>
++Example: <div class="fragment"><pre>
++ int rc;
++
++ rc = trio_printf("%r\n", 42);
++ if (rc &lt; 0) {
++ if (TRIO_ERROR_CODE(rc) != TRIO_EOF) {
++ trio_printf("Error: %s at position %d\n",
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ }
++ }
++</pre></div>
++<p>
++<b>SEE</b> <b>ALSO</b>
++<p>
++<em>trio_scanf</em>, <em>trio_register</em>.
++<p>
++<b>NOTES</b>
++<p>
++The printfv family uses an array rather than the stack to pass arguments. This means that <code>short</code> <code>int</code> and <code>float</code> values will not be handled by the default argument promotion in C. Instead, these values must be explicitly converted with the Short (h) modifier in both cases.
++<p>
++Example: <div class="fragment"><pre>
++ void *array[2];
++ float float_number = 42.0;
++ short short_number = 42;
++
++ array[0] = &amp;float_number;
++ array[1] = &amp;short_number;
++
++ trio_printfv("%hf %hd\n", array); /* CORRECT
++ trio_printfv("%f %d\n", array); /* WRONG
++</pre></div>
++<p>
++<b>CONFORMING</b> <b>TO</b>
++<p>
++Throughout this document the following abbreviations have been used to indicate what standard a feature conforms to. If nothing else is indicated ANSI C (C89) is assumed.
++<p>
++<ul>
++<li> [C89] ANSI X3.159-1989 <li> [C99] ISO/IEC 9899:1999 <li> [UNIX98] The Single UNIX Specification, Version 2 <li> [BSD] 4.4BSD <li> [GNU] GNU libc <li> [MSVC] Microsoft Visual C <li> [MISC] Other non-standard sources <li> [TRIO] Extensions specific for this package </ul>
++<hr><h2>Function Documentation</h2>
++<a name="a22" doxytag="trio-cdetect.c::trio_asprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_asprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>result</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Allocate and print to string.
++<p>
++The memory allocated and returned by <code>result</code> must be freed by the calling application.<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>result</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a24" doxytag="trio-cdetect.c::trio_asprintfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_asprintfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>result</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Allocate and print to string.
++<p>
++The memory allocated and returned by <code>result</code> must be freed by the calling application.<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>result</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a6" doxytag="trio-cdetect.c::trio_dprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_dprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to file descriptor.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>fd</em>&nbsp;</td><td>
++File descriptor. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a8" doxytag="trio-cdetect.c::trio_dprintfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_dprintfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to file descriptor.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>fd</em>&nbsp;</td><td>
++File descriptor. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a3" doxytag="trio-cdetect.c::trio_fprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_fprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to file.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>file</em>&nbsp;</td><td>
++File pointer. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a5" doxytag="trio-cdetect.c::trio_fprintfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_fprintfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to file.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>file</em>&nbsp;</td><td>
++File pointer. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a0" doxytag="trio-cdetect.c::trio_printf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_printf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to standard output stream.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a2" doxytag="trio-cdetect.c::trio_printfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_printfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to standard output stream.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a15" doxytag="trio-cdetect.c::trio_snprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_snprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print at most <code>max</code> characters to string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to print. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a17" doxytag="trio-cdetect.c::trio_snprintfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_snprintfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print at most <code>max</code> characters to string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to print. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a12" doxytag="trio-cdetect.c::trio_sprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_sprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a14" doxytag="trio-cdetect.c::trio_sprintfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_sprintfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a23" doxytag="trio-cdetect.c::trio_vasprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vasprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>result</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Allocate and print to string.
++<p>
++The memory allocated and returned by <code>result</code> must be freed by the calling application.<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>result</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a7" doxytag="trio-cdetect.c::trio_vdprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vdprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to file descriptor.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>fd</em>&nbsp;</td><td>
++File descriptor. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a4" doxytag="trio-cdetect.c::trio_vfprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vfprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to file.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>file</em>&nbsp;</td><td>
++File pointer. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a1" doxytag="trio-cdetect.c::trio_vprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to standard output stream.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a16" doxytag="trio-cdetect.c::trio_vsnprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vsnprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print at most <code>max</code> characters to string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to print. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a13" doxytag="trio-cdetect.c::trio_vsprintf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vsprintf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Print to string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Output string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of printed characters. </dl> </td>
++ </tr>
++</table>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/group___scanf.html.gs_sprintf ghostscript-9.07/trio/html/group___scanf.html
+--- ghostscript-9.07/trio/html/group___scanf.html.gs_sprintf 2013-05-09 17:02:39.105447253 +0100
++++ ghostscript-9.07/trio/html/group___scanf.html 2013-05-09 17:02:39.105447253 +0100
+@@ -0,0 +1,766 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>Formatted Scanning Functions.</h1>Variations of formatted scanning functions.
++<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
++<tr><td></td></tr>
++<tr><td colspan=2><br><h2>Functions</h2></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a0">trio_scanf</a> (const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from standard input stream.</em> <a href="#a0"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a1">trio_vscanf</a> (const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from standard input stream.</em> <a href="#a1"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a2">trio_scanfv</a> (const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from standard input stream.</em> <a href="#a2"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a3">trio_fscanf</a> (FILE *file, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from file.</em> <a href="#a3"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a4">trio_vfscanf</a> (FILE *file, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from file.</em> <a href="#a4"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a5">trio_fscanfv</a> (FILE *file, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from file.</em> <a href="#a5"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a6">trio_dscanf</a> (int fd, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from file descriptor.</em> <a href="#a6"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a7">trio_vdscanf</a> (int fd, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from file descriptor.</em> <a href="#a7"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a8">trio_dscanfv</a> (int fd, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from file descriptor.</em> <a href="#a8"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a12">trio_sscanf</a> (const char *buffer, const char *format,...)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from string.</em> <a href="#a12"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a13">trio_vsscanf</a> (const char *buffer, const char *format, va_list args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from string.</em> <a href="#a13"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a14">trio_sscanfv</a> (const char *buffer, const char *format, trio_pointer_t *args)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from string.</em> <a href="#a14"></a><em></em></font><br><br></td></tr>
++</table>
++<hr><a name="_details"></a><h2>Detailed Description</h2>
++Variations of formatted scanning functions.
++<p>
++<b>SYNOPSIS</b>
++<p>
++<div class="fragment"><pre>
++cc ... -ltrio -lm
++
++#include &lt;trio.h&gt;
++</pre></div>
++<p>
++<b>DESCRIPTION</b>
++<p>
++This documentation is incomplete. The documentation of the scanf family in [C99] and [UNIX98] also applies to the trio counterparts.
++<p>
++<b>SCANNING</b>
++<p>
++The scanning is controlled by the format string. The format string can contain normal text and conversion indicators. The normal text can be any character except the nil character (\000) and the percent character (\045 = '%'). Conversion indicators consists of an indication character (%), followed by zero or more conversion modifiers, and exactly one conversion specifier.
++<p>
++<b>Modifiers</b>
++<p>
++<em>Positional</em> ( <code>9$</code> ) [UNIX98]
++<p>
++See <a class="el" href="group___printf.html#a218">Formatted Printing Functions.</a>.
++<p>
++<b>Specifiers</b>
++<p>
++<em>Percent</em> ( <code>%</code> )
++<p>
++<em>Character</em> ( <code>c</code> )
++<p>
++<em>Decimal</em> ( <code>d</code> )
++<p>
++<em>Floating-point</em> ( <code>a</code>, <code>A</code>, <code>e</code>, <code>E</code>, <code>f</code>, <code>F</code>, <code>g</code>, <code>G</code> )
++<p>
++<em>Integer</em> ( <code>i</code> )
++<p>
++<em>Count</em> ( <code>n</code> )
++<p>
++<em>Octal</em> ( <code>o</code> )
++<p>
++<em>Pointer</em> ( <code>p</code> )
++<p>
++<em>String</em> ( <code>s</code> )
++<p>
++<em>Unsigned</em> ( <code>u</code> )
++<p>
++<em>Hex</em> ( <code>x</code>, <code>X</code> )
++<p>
++<em>Scanlist</em> ( <code>[]</code> )
++<p>
++Scanlist Exclusion (<code>^</code> )
++<p>
++Scanlist Range ( <code>-</code> ) [TRIO]
++<p>
++<ul>
++<li> Only increasing ranges, i.e. <code>[a-b]</code>, but not <code>[b-a]</code>. <li> Transitive ranges, ie. <code>[a-b-c]</code> equals <code>[a-c]</code>. <li> Trailing minus, ie. <code>[a-]</code> is interpreted as an <code>a</code> and a <code>-</code>. <li> Duplicates are ignored.</ul>
++Scanlist Equivalence Class Expression ( <code>[</code>= =<code>]</code> ) [TRIO]
++<p>
++Locale dependent (LC_COLLATE). Only one expression can appear inside the delimiters. <ul>
++<li> <code>[=a=]</code> All letters in the same equivalence class as the letter <code>a</code>. <div class="fragment"><pre>
++ trio_scanf("%[[=a=]b]\n", buffer);
++ trio_scanf("%[[=a=][=b=]]\n", buffer);
++</pre></div></ul>
++Scanlist Character Class Expression ( <code>[</code>: :<code>])</code> [TRIO] Locale dependent (LC_CTYPE). Only one expression can appear inside the delimiters. <ul>
++<li> <code>[:alnum:]</code> Same as <code>[:alpha:]</code> and <code>[:digit:]</code> <li> <code>[:alpha:]</code> Same as <code>[:lower:]</code> and <code>[:upper:]</code> <li> <code>[:cntrl:]</code> Control characters <li> <code>[:digit:]</code> Decimal digits <li> <code>[:graph:]</code> Printable characters except space <li> <code>[:lower:]</code> Lower case alphabetic letters <li> <code>[:print:]</code> Printable characters <li> <code>[:punct:]</code> Punctuation <li> <code>[:space:]</code> Whitespace characters <li> <code>[:upper:]</code> Upper case alphabetic letters <li> <code>[:xdigit:]</code> Hexadecimal digits <div class="fragment"><pre>
++ trio_scanf("%[[:alnum:]]\n", buffer);
++ trio_scanf("%[[:alpha:][:digit:]]\n", buffer);
++</pre></div></ul>
++<b>RETURN</b> <b>VALUES</b>
++<p>
++<b>SEE</b> <b>ALSO</b>
++<p>
++<a class="el" href="group___printf.html#a218">Formatted Printing Functions.</a> <hr><h2>Function Documentation</h2>
++<a name="a6" doxytag="trio-cdetect.c::trio_dscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_dscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from file descriptor.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>fd</em>&nbsp;</td><td>
++File descriptor. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a8" doxytag="trio-cdetect.c::trio_dscanfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_dscanfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from file descriptor.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>fd</em>&nbsp;</td><td>
++File descriptor. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a3" doxytag="trio-cdetect.c::trio_fscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_fscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from file.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>file</em>&nbsp;</td><td>
++File pointer. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a5" doxytag="trio-cdetect.c::trio_fscanfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_fscanfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from file.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>file</em>&nbsp;</td><td>
++File pointer. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a0" doxytag="trio-cdetect.c::trio_scanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_scanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from standard input stream.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a2" doxytag="trio-cdetect.c::trio_scanfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_scanfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from standard input stream.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a12" doxytag="trio-cdetect.c::trio_sscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_sscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>...&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp;</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Input string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>...</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a14" doxytag="trio-cdetect.c::trio_sscanfv"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_sscanfv </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Input string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a7" doxytag="trio-cdetect.c::trio_vdscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vdscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from file descriptor.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>fd</em>&nbsp;</td><td>
++File descriptor. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a4" doxytag="trio-cdetect.c::trio_vfscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vfscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from file.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>file</em>&nbsp;</td><td>
++File pointer. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a1" doxytag="trio-cdetect.c::trio_vscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from standard input stream.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<a name="a13" doxytag="trio-cdetect.c::trio_vsscanf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> int trio_vsscanf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>va_list&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Scan characters from string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
++Input string. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>args</em>&nbsp;</td><td>
++Arguments. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of scanned characters. </dl> </td>
++ </tr>
++</table>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/group___special_quantities.html.gs_sprintf ghostscript-9.07/trio/html/group___special_quantities.html
+--- ghostscript-9.07/trio/html/group___special_quantities.html.gs_sprintf 2013-05-09 17:02:39.106447257 +0100
++++ ghostscript-9.07/trio/html/group___special_quantities.html 2013-05-09 17:02:39.106447257 +0100
+@@ -0,0 +1,377 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>Special Quantifies.</h1>Functions to detect and fabricate special quantities in floating-point numbers.
++<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
++<tr><td></td></tr>
++<tr><td colspan=2><br><h2>Functions</h2></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a4">trio_isnan</a> (double number)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Check for NaN.</em> <a href="#a4"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a5">trio_isinf</a> (double number)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Check for infinity.</em> <a href="#a5"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a6">trio_isfinite</a> (double number)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Check for finity.</em> <a href="#a6"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a7">trio_signbit</a> (double number)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Examine the sign of a number.</em> <a href="#a7"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a8">trio_fpclassify</a> (double number)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Examine the class of a number.</em> <a href="#a8"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a9">trio_nzero</a> (void)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Generate negative zero.</em> <a href="#a9"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a10">trio_pinf</a> (void)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Generate positive infinity.</em> <a href="#a10"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a11">trio_ninf</a> (void)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Generate negative infinity.</em> <a href="#a11"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_NAN double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a12">trio_nan</a> (void)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Generate NaN.</em> <a href="#a12"></a><em></em></font><br><br></td></tr>
++</table>
++<hr><a name="_details"></a><h2>Detailed Description</h2>
++Functions to detect and fabricate special quantities in floating-point numbers.
++<p>
++<b>SYNOPSIS</b>
++<p>
++<div class="fragment"><pre>
++cc ... -ltrio -lm
++
++#include &lt;trionan.h&gt;
++</pre></div>
++<p>
++<b>DESCRIPTION</b>
++<p>
++Certain arithmetical operations does not result in normal numbers. Instead they result in special quantities that must be handled differently by the floating-point hardware. These includes Infinity and Not-A-Number (NaN).
++<p>
++For example, 0/0 (zero divided by zero) yields NaN. Any operation which involves a NaN will result in NaN. Any comparison involving NaN will be unsuccessful, even if NaN is compared to NaN.
++<p>
++These special quantities are represented with special bit patterns by the floating-point hardware, and this bit patterns depend on the hardware. There may even be hardware that does not support special quantities, so the functions in this module are not guaranteed to work on all platforms.
++<p>
++The approach used in this module is to (in decreasing order of importance) <ul>
++<li> Use C99 functionality when available. <li> Use IEEE 754-1985 bit patterns if possible. <li> Use platform-specific techniques.</ul>
++<b>NOTES</b>
++<p>
++This module does not depend on the rest of trio, and can thus be reused separately. The following files are necessary: <ul>
++<li> <code>triodef.h</code> <li> <code>trionan.h</code> <li> <code>trionan.c</code> </ul>
++<hr><h2>Function Documentation</h2>
++<a name="a8" doxytag="trionan-macro.c::trio_fpclassify"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN int trio_fpclassify </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">double&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Examine the class of a number.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>number</em>&nbsp;</td><td>
++An arbitrary floating-point number. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Enumerable value indicating the class of <code>number</code> </dl> </td>
++ </tr>
++</table>
++<a name="a6" doxytag="trionan-macro.c::trio_isfinite"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN int trio_isfinite </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">double&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Check for finity.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>number</em>&nbsp;</td><td>
++An arbitrary floating-point number. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating whether or not the number is a finite. </dl> </td>
++ </tr>
++</table>
++<a name="a5" doxytag="trionan-macro.c::trio_isinf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN int trio_isinf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">double&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Check for infinity.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>number</em>&nbsp;</td><td>
++An arbitrary floating-point number. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++1 if positive infinity, -1 if negative infinity, 0 otherwise. </dl> </td>
++ </tr>
++</table>
++<a name="a4" doxytag="trionan-macro.c::trio_isnan"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN int trio_isnan </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">double&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Check for NaN.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>number</em>&nbsp;</td><td>
++An arbitrary floating-point number. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating whether or not the number is a NaN. </dl> </td>
++ </tr>
++</table>
++<a name="a12" doxytag="trionan-macro.c::trio_nan"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN double trio_nan </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">void&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Generate NaN.
++<p>
++<dl compact><dt><b>Returns: </b></dt><dd>
++Floating-point representation of NaN. </dl> </td>
++ </tr>
++</table>
++<a name="a11" doxytag="trionan-macro.c::trio_ninf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN double trio_ninf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">void&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Generate negative infinity.
++<p>
++<dl compact><dt><b>Returns: </b></dt><dd>
++Floating-point value of negative infinity. </dl> </td>
++ </tr>
++</table>
++<a name="a9" doxytag="trionan-macro.c::trio_nzero"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN double trio_nzero </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">void&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Generate negative zero.
++<p>
++<dl compact><dt><b>Returns: </b></dt><dd>
++Floating-point representation of negative zero. </dl> </td>
++ </tr>
++</table>
++<a name="a10" doxytag="trionan-macro.c::trio_pinf"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN double trio_pinf </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">void&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Generate positive infinity.
++<p>
++<dl compact><dt><b>Returns: </b></dt><dd>
++Floating-point representation of positive infinity. </dl> </td>
++ </tr>
++</table>
++<a name="a7" doxytag="trionan-macro.c::trio_signbit"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_NAN int trio_signbit </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">double&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Examine the sign of a number.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>number</em>&nbsp;</td><td>
++An arbitrary floating-point number. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating whether or not the number has the sign bit set (i.e. is negative). </dl> </td>
++ </tr>
++</table>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/group___static_strings.html.gs_sprintf ghostscript-9.07/trio/html/group___static_strings.html
+--- ghostscript-9.07/trio/html/group___static_strings.html.gs_sprintf 2013-05-09 17:02:39.107447262 +0100
++++ ghostscript-9.07/trio/html/group___static_strings.html 2013-05-09 17:02:39.107447262 +0100
+@@ -0,0 +1,1864 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>Static String Functions.</h1>Replacements for the standard C string functions.
++<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
++<tr><td></td></tr>
++<tr><td colspan=2><br><h2>Functions</h2></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a5">trio_create</a> (size_t size)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Create new string.</em> <a href="#a5"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING void&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a6">trio_destroy</a> (char *string)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Destroy string.</em> <a href="#a6"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a7">trio_length</a> (const char *string)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Count the number of characters in a string.</em> <a href="#a7"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a8">trio_append</a> (char *target, const char *source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Append <code>source</code> at the end of <code>target</code>.</em> <a href="#a8"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a9">trio_append_max</a> (char *target, size_t max, const char *source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Append at most <code>max</code> characters from <code>source</code> to <code>target</code>.</em> <a href="#a9"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a10">trio_contains</a> (const char *string, const char *substring)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Determine if a string contains a substring.</em> <a href="#a10"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a11">trio_copy</a> (char *target, const char *source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Copy <code>source</code> to <code>target</code>.</em> <a href="#a11"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a12">trio_copy_max</a> (char *target, size_t max, const char *source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Copy at most <code>max</code> characters from <code>source</code> to <code>target</code>.</em> <a href="#a12"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a13">trio_duplicate</a> (const char *source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Duplicate <code>source</code>.</em> <a href="#a13"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a14">trio_duplicate_max</a> (const char *source, size_t max)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Duplicate at most <code>max</code> characters of <code>source</code>.</em> <a href="#a14"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a15">trio_equal</a> (const char *first, const char *second)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings are equal.</em> <a href="#a15"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a16">trio_equal_case</a> (const char *first, const char *second)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings are equal.</em> <a href="#a16"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a17">trio_equal_case_max</a> (const char *first, size_t max, const char *second)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings up until the first <code>max</code> characters are equal.</em> <a href="#a17"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a18">trio_equal_locale</a> (const char *first, const char *second)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings are equal.</em> <a href="#a18"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a19">trio_equal_max</a> (const char *first, size_t max, const char *second)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings up until the first <code>max</code> characters are equal.</em> <a href="#a19"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING const char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a20">trio_error</a> (int error_number)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Provide a textual description of an error code (errno).</em> <a href="#a20"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a21">trio_format_date_max</a> (char *target, size_t max, const char *format, const struct tm *datetime)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Format the date/time according to <code>format</code>.</em> <a href="#a21"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING unsigned <br>
++long&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a22">trio_hash</a> (const char *string, int type)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Calculate a hash value for a string.</em> <a href="#a22"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a23">trio_index</a> (const char *string, int character)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Find first occurrence of a character in a string.</em> <a href="#a23"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a24">trio_index_last</a> (const char *string, int character)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Find last occurrence of a character in a string.</em> <a href="#a24"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a25">trio_lower</a> (char *target)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert the alphabetic letters in the string to lower-case.</em> <a href="#a25"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a26">trio_match</a> (const char *string, const char *pattern)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare two strings using wildcards.</em> <a href="#a26"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a27">trio_match_case</a> (const char *string, const char *pattern)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Compare two strings using wildcards.</em> <a href="#a27"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a28">trio_span_function</a> (char *target, const char *source, int(*Function)(int))</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Execute a function on each character in string.</em> <a href="#a28"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a29">trio_substring</a> (const char *string, const char *substring)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Search for a substring in a string.</em> <a href="#a29"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a30">trio_substring_max</a> (const char *string, size_t max, const char *substring)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Search for a substring in the first <code>max</code> characters of a string.</em> <a href="#a30"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a31">trio_tokenize</a> (char *string, const char *delimiters)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Tokenize string.</em> <a href="#a31"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING trio_long_double_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a32">trio_to_long_double</a> (const char *source, char **endp)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to floating-point number.</em> <a href="#a32"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING double&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a33">trio_to_double</a> (const char *source, char **endp)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to floating-point number.</em> <a href="#a33"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING float&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a34">trio_to_float</a> (const char *source, char **endp)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to floating-point number.</em> <a href="#a34"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING long&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a35">trio_to_long</a> (const char *string, char **endp, int base)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to signed integer.</em> <a href="#a35"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a36">trio_to_lower</a> (int source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert one alphabetic letter to lower-case.</em> <a href="#a36"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING unsigned <br>
++long&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a37">trio_to_unsigned_long</a> (const char *string, char **endp, int base)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to unsigned integer.</em> <a href="#a37"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a38">trio_to_upper</a> (int source)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert one alphabetic letter to upper-case.</em> <a href="#a38"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a39">trio_upper</a> (char *target)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Convert the alphabetic letters in the string to upper-case.</em> <a href="#a39"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>TRIO_PUBLIC_STRING size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a40">trio_length_max</a> (const char *string, size_t max)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Count at most <code>max</code> characters in a string.</em> <a href="#a40"></a><em></em></font><br><br></td></tr>
++</table>
++<hr><a name="_details"></a><h2>Detailed Description</h2>
++Replacements for the standard C string functions.
++<p>
++<b>SYNOPSIS</b>
++<p>
++<div class="fragment"><pre>
++cc ... -ltrio -lm
++
++#include &lt;triostr.h&gt;
++</pre></div>
++<p>
++<b>DESCRIPTION</b>
++<p>
++This package renames, fixes, and extends the standard C string handling functions.
++<p>
++<b>Naming</b>
++<p>
++Renaming is done to provide more clear names, to provide a consistant naming and argument policy, and to hide portability issues.
++<p>
++<ul>
++<li> All functions starts with "trio_". <li> Target is always the first argument, if present, except where the target is optional, such as <a class="el" href="group___static_strings.html#a33">Static String Functions.</a>. <li> Functions requiring a size for target includes "_max" in its name, and the size is always the second argument. <li> Functions performing case-sensitive operations includes "_case" in its name.</ul>
++<b>Fixing</b>
++<p>
++Fixing is done to avoid subtle error conditions. For example, <code>strncpy</code> does not terminate the result with a zero if the source string is bigger than the maximal length, so technically the result is not a C string anymore. <a class="el" href="group___static_strings.html#a12">Static String Functions.</a> makes sure that the result is zero terminated.
++<p>
++<b>Extending</b>
++<p>
++Extending is done to provide a richer set of fundamental functions. This includes functionality such as wildcard matching ( <code>trio_match</code> ) and calculation of hash values ( <code>trio_hash</code> ). <hr><h2>Function Documentation</h2>
++<a name="a8" doxytag="triostr-macro.c::trio_append"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_append </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Append <code>source</code> at the end of <code>target</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++Target string. </td></tr>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure.</dl><dl compact><dt><b>Precondition: </b></dt><dd>
++<code>target</code> must point to a memory chunk with sufficient room to contain the <code>target</code> string and <code>source</code> string. <dd>
++No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>Postcondition: </b></dt><dd>
++<code>target</code> will be zero terminated. </dl> </td>
++ </tr>
++</table>
++<a name="a9" doxytag="triostr-macro.c::trio_append_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_append_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Append at most <code>max</code> characters from <code>source</code> to <code>target</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++Target string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to append. </td></tr>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure.</dl><dl compact><dt><b>Precondition: </b></dt><dd>
++<code>target</code> must point to a memory chuck with sufficient room to contain the <code>target</code> string and the <code>source</code> string (at most <code>max</code> characters). <dd>
++No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>Postcondition: </b></dt><dd>
++<code>target</code> will be zero terminated. </dl> </td>
++ </tr>
++</table>
++<a name="a10" doxytag="triostr-macro.c::trio_contains"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_contains </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>substring</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Determine if a string contains a substring.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>substring</em>&nbsp;</td><td>
++String to be found. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure. </dl> </td>
++ </tr>
++</table>
++<a name="a11" doxytag="triostr-macro.c::trio_copy"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_copy </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Copy <code>source</code> to <code>target</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++Target string. </td></tr>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure.</dl><dl compact><dt><b>Precondition: </b></dt><dd>
++<code>target</code> must point to a memory chunk with sufficient room to contain the <code>source</code> string. <dd>
++No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>Postcondition: </b></dt><dd>
++<code>target</code> will be zero terminated. </dl> </td>
++ </tr>
++</table>
++<a name="a12" doxytag="triostr-macro.c::trio_copy_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_copy_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Copy at most <code>max</code> characters from <code>source</code> to <code>target</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++Target string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to append. </td></tr>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure.</dl><dl compact><dt><b>Precondition: </b></dt><dd>
++<code>target</code> must point to a memory chunk with sufficient room to contain the <code>source</code> string (at most <code>max</code> characters). <dd>
++No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>Postcondition: </b></dt><dd>
++<code>target</code> will be zero terminated. </dl> </td>
++ </tr>
++</table>
++<a name="a5" doxytag="triostr-macro.c::trio_create"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_create </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">size_t&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>size</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Create new string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>size</em>&nbsp;</td><td>
++Size of new string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Pointer to string, or NULL if allocation failed. </dl> </td>
++ </tr>
++</table>
++<a name="a6" doxytag="triostr-macro.c::trio_destroy"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING void trio_destroy </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>string</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Destroy string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be freed. </td></tr>
++</table>
++</dl> </td>
++ </tr>
++</table>
++<a name="a13" doxytag="triostr-macro.c::trio_duplicate"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_duplicate </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>source</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Duplicate <code>source</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A copy of the <code>source</code> string.</dl><dl compact><dt><b>Postcondition: </b></dt><dd>
++<code>target</code> will be zero terminated. </dl> </td>
++ </tr>
++</table>
++<a name="a14" doxytag="triostr-macro.c::trio_duplicate_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_duplicate_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Duplicate at most <code>max</code> characters of <code>source</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to duplicate. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A copy of the <code>source</code> string.</dl><dl compact><dt><b>Postcondition: </b></dt><dd>
++<code>target</code> will be zero terminated. </dl> </td>
++ </tr>
++</table>
++<a name="a15" doxytag="triostr-macro.c::trio_equal"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_equal </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare if two strings are equal.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>first</em>&nbsp;</td><td>
++First string. </td></tr>
++<tr><td valign=top><em>second</em>&nbsp;</td><td>
++Second string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean indicating whether the two strings are equal or not.</dl>Case-insensitive comparison. </td>
++ </tr>
++</table>
++<a name="a16" doxytag="triostr-macro.c::trio_equal_case"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_equal_case </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare if two strings are equal.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>first</em>&nbsp;</td><td>
++First string. </td></tr>
++<tr><td valign=top><em>second</em>&nbsp;</td><td>
++Second string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean indicating whether the two strings are equal or not.</dl>Case-sensitive comparison. </td>
++ </tr>
++</table>
++<a name="a17" doxytag="triostr-macro.c::trio_equal_case_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_equal_case_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare if two strings up until the first <code>max</code> characters are equal.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>first</em>&nbsp;</td><td>
++First string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to compare. </td></tr>
++<tr><td valign=top><em>second</em>&nbsp;</td><td>
++Second string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean indicating whether the two strings are equal or not.</dl>Case-sensitive comparison. </td>
++ </tr>
++</table>
++<a name="a18" doxytag="triostr-macro.c::trio_equal_locale"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_equal_locale </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare if two strings are equal.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>first</em>&nbsp;</td><td>
++First string. </td></tr>
++<tr><td valign=top><em>second</em>&nbsp;</td><td>
++Second string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean indicating whether the two strings are equal or not.</dl>Collating characters are considered equal. </td>
++ </tr>
++</table>
++<a name="a19" doxytag="triostr-macro.c::trio_equal_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_equal_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare if two strings up until the first <code>max</code> characters are equal.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>first</em>&nbsp;</td><td>
++First string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to compare. </td></tr>
++<tr><td valign=top><em>second</em>&nbsp;</td><td>
++Second string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean indicating whether the two strings are equal or not.</dl>Case-insensitive comparison. </td>
++ </tr>
++</table>
++<a name="a20" doxytag="triostr-macro.c::trio_error"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING const char* trio_error </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>error_number</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Provide a textual description of an error code (errno).
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>error_number</em>&nbsp;</td><td>
++Error number. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Textual description of <code>error_number</code>. </dl> </td>
++ </tr>
++</table>
++<a name="a21" doxytag="triostr-macro.c::trio_format_date_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING size_t trio_format_date_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const struct tm *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>datetime</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Format the date/time according to <code>format</code>.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++Target string. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to format. </td></tr>
++<tr><td valign=top><em>format</em>&nbsp;</td><td>
++Formatting string. </td></tr>
++<tr><td valign=top><em>datetime</em>&nbsp;</td><td>
++Date/time structure. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of formatted characters.</dl>The formatting string accepts the same specifiers as the standard C function strftime. </td>
++ </tr>
++</table>
++<a name="a22" doxytag="triostr-macro.c::trio_hash"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING unsigned long trio_hash </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>type</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Calculate a hash value for a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be calculated on. </td></tr>
++<tr><td valign=top><em>type</em>&nbsp;</td><td>
++Hash function. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Calculated hash value.</dl><code>type</code> can be one of the following <ul>
++<li> <code>TRIO_HASH_PLAIN</code> Plain hash function. </ul>
++ </td>
++ </tr>
++</table>
++<a name="a23" doxytag="triostr-macro.c::trio_index"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_index </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>character</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Find first occurrence of a character in a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>character</em>&nbsp;</td><td>
++Character to be found. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A pointer to the found character, or NULL if character was not found. </dl> </td>
++ </tr>
++</table>
++<a name="a24" doxytag="triostr-macro.c::trio_index_last"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_index_last </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>character</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Find last occurrence of a character in a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>character</em>&nbsp;</td><td>
++Character to be found. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A pointer to the found character, or NULL if character was not found. </dl> </td>
++ </tr>
++</table>
++<a name="a7" doxytag="triostr-macro.c::trio_length"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING size_t trio_length </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>string</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Count the number of characters in a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to measure. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of characters in <code>string</code>. </dl> </td>
++ </tr>
++</table>
++<a name="a40" doxytag="triostr.c::trio_length_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING size_t trio_length_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Count at most <code>max</code> characters in a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to measure. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum number of characters to count. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++The maximum value of <code>max</code> and number of characters in <code>string</code>. </dl> </td>
++ </tr>
++</table>
++<a name="a25" doxytag="triostr-macro.c::trio_lower"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_lower </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>target</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert the alphabetic letters in the string to lower-case.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++String to be converted. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of processed characters (converted or not). </dl> </td>
++ </tr>
++</table>
++<a name="a26" doxytag="triostr-macro.c::trio_match"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_match </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>pattern</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare two strings using wildcards.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>pattern</em>&nbsp;</td><td>
++Pattern, including wildcards, to search for. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure.</dl>Case-insensitive comparison.
++<p>
++The following wildcards can be used <ul>
++<li> <code>*</code> Match any number of characters. <li> ? <code>Match</code> a single character. </ul>
++ </td>
++ </tr>
++</table>
++<a name="a27" doxytag="triostr-macro.c::trio_match_case"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_match_case </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>pattern</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Compare two strings using wildcards.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>pattern</em>&nbsp;</td><td>
++Pattern, including wildcards, to search for. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Boolean value indicating success or failure.</dl>Case-sensitive comparison.
++<p>
++The following wildcards can be used <ul>
++<li> <code>*</code> Match any number of characters. <li> ? <code>Match</code> a single character. </ul>
++ </td>
++ </tr>
++</table>
++<a name="a28" doxytag="triostr-macro.c::trio_span_function"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING size_t trio_span_function </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>int(*&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>Function</em>)(int)</td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Execute a function on each character in string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++Target string. </td></tr>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++Source string. </td></tr>
++<tr><td valign=top><em>Function</em>&nbsp;</td><td>
++Function to be executed. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Number of processed characters. </dl> </td>
++ </tr>
++</table>
++<a name="a29" doxytag="triostr-macro.c::trio_substring"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_substring </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>substring</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Search for a substring in a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>substring</em>&nbsp;</td><td>
++String to be found. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Pointer to first occurrence of <code>substring</code> in <code>string</code>, or NULL if no match was found. </dl> </td>
++ </tr>
++</table>
++<a name="a30" doxytag="triostr-macro.c::trio_substring_max"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_substring_max </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>size_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>substring</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Search for a substring in the first <code>max</code> characters of a string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be searched. </td></tr>
++<tr><td valign=top><em>max</em>&nbsp;</td><td>
++Maximum characters to be searched. </td></tr>
++<tr><td valign=top><em>substring</em>&nbsp;</td><td>
++String to be found. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Pointer to first occurrence of <code>substring</code> in <code>string</code>, or NULL if no match was found. </dl> </td>
++ </tr>
++</table>
++<a name="a33" doxytag="triostr-macro.c::trio_to_double"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING double trio_to_double </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>endp</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert string to floating-point number.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++String to be converted. </td></tr>
++<tr><td valign=top><em>endp</em>&nbsp;</td><td>
++Pointer to end of the converted string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A floating-point number.</dl>See <a class="el" href="group___static_strings.html#a32">Static String Functions.</a>. </td>
++ </tr>
++</table>
++<a name="a34" doxytag="triostr-macro.c::trio_to_float"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING float trio_to_float </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>endp</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert string to floating-point number.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++String to be converted. </td></tr>
++<tr><td valign=top><em>endp</em>&nbsp;</td><td>
++Pointer to end of the converted string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A floating-point number.</dl>See <a class="el" href="group___static_strings.html#a32">Static String Functions.</a>. </td>
++ </tr>
++</table>
++<a name="a35" doxytag="triostr-macro.c::trio_to_long"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING long trio_to_long </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>endp</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>base</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert string to signed integer.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be converted. </td></tr>
++<tr><td valign=top><em>endp</em>&nbsp;</td><td>
++Pointer to end of converted string. </td></tr>
++<tr><td valign=top><em>base</em>&nbsp;</td><td>
++Radix number of number. </td></tr>
++</table>
++</dl> </td>
++ </tr>
++</table>
++<a name="a32" doxytag="triostr-macro.c::trio_to_long_double"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING trio_long_double_t trio_to_long_double </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>endp</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert string to floating-point number.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++String to be converted. </td></tr>
++<tr><td valign=top><em>endp</em>&nbsp;</td><td>
++Pointer to end of the converted string. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++A floating-point number.</dl>The following Extended Backus-Naur form is used <div class="fragment"><pre>
++ double ::= [ &lt;sign&gt; ]
++ ( &lt;number&gt; |
++ &lt;number&gt; &lt;decimal_point&gt; &lt;number&gt; |
++ &lt;decimal_point&gt; &lt;number&gt; )
++ [ &lt;exponential&gt; [ &lt;sign&gt; ] &lt;number&gt; ]
++ number ::= 1*( &lt;digit&gt; )
++ digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
++ exponential ::= ( 'e' | 'E' )
++ sign ::= ( '-' | '+' )
++ decimal_point ::= '.'
++ </pre></div> </td>
++ </tr>
++</table>
++<a name="a36" doxytag="triostr-macro.c::trio_to_lower"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_to_lower </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>source</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert one alphabetic letter to lower-case.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++The letter to be converted. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++The converted letter. </dl> </td>
++ </tr>
++</table>
++<a name="a37" doxytag="triostr-macro.c::trio_to_unsigned_long"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING unsigned long trio_to_unsigned_long </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>char **&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>endp</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>int&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>base</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert string to unsigned integer.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be converted. </td></tr>
++<tr><td valign=top><em>endp</em>&nbsp;</td><td>
++Pointer to end of converted string. </td></tr>
++<tr><td valign=top><em>base</em>&nbsp;</td><td>
++Radix number of number. </td></tr>
++</table>
++</dl> </td>
++ </tr>
++</table>
++<a name="a38" doxytag="triostr-macro.c::trio_to_upper"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_to_upper </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">int&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>source</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert one alphabetic letter to upper-case.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>source</em>&nbsp;</td><td>
++The letter to be converted. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++The converted letter. </dl> </td>
++ </tr>
++</table>
++<a name="a31" doxytag="triostr-macro.c::trio_tokenize"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING char* trio_tokenize </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>delimiters</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Tokenize string.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>string</em>&nbsp;</td><td>
++String to be tokenized. </td></tr>
++<tr><td valign=top><em>delimiters</em>&nbsp;</td><td>
++String containing list of delimiting characters. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Start of new token.</dl><dl compact><dt><b>Warning: </b></dt><dd>
++<code>string</code> will be destroyed. </dl> </td>
++ </tr>
++</table>
++<a name="a39" doxytag="triostr-macro.c::trio_upper"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> TRIO_PUBLIC_STRING int trio_upper </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">char *&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>target</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Convert the alphabetic letters in the string to upper-case.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>target</em>&nbsp;</td><td>
++The string to be converted. </td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++The number of processed characters (converted or not). </dl> </td>
++ </tr>
++</table>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/group___user_defined.html.gs_sprintf ghostscript-9.07/trio/html/group___user_defined.html
+--- ghostscript-9.07/trio/html/group___user_defined.html.gs_sprintf 2013-05-09 17:02:39.107447262 +0100
++++ ghostscript-9.07/trio/html/group___user_defined.html 2013-05-09 17:02:39.107447262 +0100
+@@ -0,0 +1,391 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>User-defined Formatted Printing Functions.</h1>Functions for using customized formatting specifiers.
++<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
++<tr><td></td></tr>
++<tr><td colspan=2><br><h2>Functions</h2></td></tr>
++<tr><td nowrap align=right valign=top>trio_pointer_t&nbsp;</td><td valign=bottom><a class="el" href="group___user_defined.html#a0">trio_register</a> (trio_callback_t callback, const char *name)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Register new user-defined specifier.</em> <a href="#a0"></a><em></em></font><br><br></td></tr>
++<tr><td nowrap align=right valign=top>void&nbsp;</td><td valign=bottom><a class="el" href="group___user_defined.html#a1">trio_unregister</a> (trio_pointer_t handle)</td></tr>
++<tr><td>&nbsp;</td><td><font size=-1><em>Unregister an existing user-defined specifier.</em> <a href="#a1"></a><em></em></font><br><br></td></tr>
++</table>
++<hr><a name="_details"></a><h2>Detailed Description</h2>
++Functions for using customized formatting specifiers.
++<p>
++<b>SYNOPSIS</b>
++<p>
++<div class="fragment"><pre>
++cc ... -ltrio -lm
++
++#include &lt;trio.h&gt;
++#include &lt;triop.h&gt;
++</pre></div>
++<p>
++<b>DESCRIPTION</b>
++<p>
++This documentation is incomplete.
++<p>
++<b>User-defined</b> <b>Specifier</b>
++<p>
++The user-defined specifier consists of a start character (\074 = '&lt;'), an optional namespace string followed by a namespace separator (\072 = ':'), a format string, an optional skipping separator (\174 = '|'), and an end character (\076 = '&gt;').
++<p>
++The namespace string can consist of alphanumeric characters, and is used to define a named reference (see below). The namespace is case-sensitive. If no namespace is specified, then we use an unnamed reference (see below).
++<p>
++The format can consist of any character except the end character ('&gt;'), the namespace separator (':'), the skipping separator ('|'), and the nil character (\000).
++<p>
++Any modifier can be used together with the user-defined specifier.
++<p>
++There are two formats for invoking a user-defined specifier. The first format is an extension of the normal printf/scanf formatting. It uses the percent character (\045 = '%') followed by optional qualifiers and a specifier. For example:
++<p>
++<div class="fragment"><pre>
++ trio_printf("%&lt;format&gt;\n", my_handle, my_data);
++</pre></div>
++<p>
++Some C compilers can issue a warning if there is a mismatch between specifiers and arguments. Unfortunately, these warnings does not work with the first format for user-defined specifiers. Therefore the second format has been introduced. The second format can only be applied to user-defined specifiers.
++<p>
++The second format starts with a dollar character (\044 = '$') instead of the percent character, and is followed by optional qualifiers and the user-defined specifier. If the specifier contains a pipe character (\174 = '|'), then everything between the pipe character and the end character ('&gt;') is ignored. The ignored part can be used to list the normal specifiers that the C compiler uses to determine mismatches. For example:
++<p>
++<div class="fragment"><pre>
++ trio_printf("$&lt;format|%p%p&gt;\n", my_handle, my_data);
++</pre></div>
++<p>
++<b>Registering</b>
++<p>
++A user-defined specifier must be registered before it can be used. Unregistered user-defined specifiers are ignored. The <a class="el" href="group___user_defined.html#a243">User-defined Formatted Printing Functions.</a> function is used to register a user-defined specifier. It takes two argument, a callback function and a namespace, and it returns a handle. The handle must be used to unregister the specifier later.
++<p>
++The following example registers a user-define specifier with the "my_namespace" namespace:
++<p>
++<div class="fragment"><pre>
++ my_handle = trio_register(my_callback, "my_namespace");
++</pre></div>
++<p>
++There can only be one user-defined specifier with a given namespace. There can be an unlimited number (subject to maximum length of the namespace) of different user-defined specifiers.
++<p>
++Passing NULL as the namespace argument results in an anonymous reference. There can be an unlimited number of anonymous references.
++<p>
++<b>REFERENCES</b>
++<p>
++There are two ways that a registered callback can be called. Either the user-defined specifier must contain the registered namespace in the format string, or the handle is passed as an argument to the formatted printing function.
++<p>
++If the namespace is used, then a user-defined pointer must be passed as an argument:
++<p>
++<div class="fragment"><pre>
++ trio_printf("%&lt;my_namespace:format&gt;\n", my_data);
++</pre></div>
++<p>
++If the handle is used, then the user-defined specifier must not contain a namespace. Instead the handle must be passed as an argument, followed by a user-defined pointer:
++<p>
++<div class="fragment"><pre>
++ trio_printf("%&lt;format&gt;\n", my_handle, my_data);
++</pre></div>
++<p>
++The two examples above are equivalent.
++<p>
++There must be exactly one user-defined pointer per user-defined specifier. This pointer can be used within the callback function with the trio_get_argument getter function (see below).
++<p>
++The format string is optional. It can be used within the callback function with the trio_get_format getter function.
++<p>
++<b>Anonymous</b> <b>References</b> Anonymous references are specified by passing NULL as the namespace.
++<p>
++The handle must be passed as an argument followed by a user-defined pointer. No namespace can be specified.
++<p>
++<div class="fragment"><pre>
++ anon_handle = trio_register(callback, NULL);
++ trio_printf("%&lt;format&gt;\n", anon_handle, my_data);
++</pre></div>
++<p>
++<b>Restrictions</b>
++<p>
++<ul>
++<li> The length of the namespace string cannot exceed 63 characters. <li> The length of the user-defined format string cannot exceed 255 characters. <li> User-defined formatting cannot re-define existing specifiers. This restriction was imposed because the existing formatting specifiers have a well-defined behaviour, and any re-definition would apply globally to an application (imagine a third-party library changing the behaviour of a specifier that is crusial to your application).</ul>
++<b>CALLBACK</b> <b>FUNCTION</b>
++<p>
++The callback function will be called if a matching user-defined specifier is found within the formatting string. The callback function takes one input parameter, an opaque reference which is needed by the private functions. It returns an <code>int</code>, which is currently ignored. The prototype is
++<p>
++<div class="fragment"><pre>
++ int (*trio_callback_t)(void *ref);
++</pre></div>
++<p>
++See the Example section for full examples.
++<p>
++<b>PRINTING</b> <b>FUNCTIONS</b>
++<p>
++The following printing functions must only be used inside a callback function. These functions will print to the same output medium as the printf function which invoked the callback function. For example, if the user-defined specifier is used in an sprintf function, then these print functions will output their result to the same string.
++<p>
++<b>Elementary</b> <b>Printing</b>
++<p>
++There are a number of function to print elementary data types.
++<p>
++<ul>
++<li> trio_print_int Print a signed integer. For example: <div class="fragment"><pre>
++ trio_print_int(42);
++</pre></div> <li> trio_print_uint Print an unsigned integer. <li> trio_print_double Print a floating-point number. <li> trio_print_string Print a string. For example: <div class="fragment"><pre>
++ trio_print_string("Hello World");
++ trio_print_string(trio_get_format());
++</pre></div> <li> trio_print_pointer Print a pointer.</ul>
++<b>Formatted</b> <b>Printing</b>
++<p>
++The functions trio_print_ref, trio_vprint_ref, and trio_printv_ref outputs a formatted string just like its printf equivalents.
++<p>
++<div class="fragment"><pre>
++ trio_print_ref(ref, "There are %d towels\n", 42);
++ trio_print_ref(ref, "%&lt;recursive&gt;\n", recursive_writer, trio_get_argument(ref));
++</pre></div>
++<p>
++<b>GETTER</b> <b>AND</b> <b>SETTER</b> <b>FUNCTIONS</b>
++<p>
++The following getter and setter functions must only be used inside a callback function. They can either operate on the modifiers or on special data.
++<p>
++<b>Modifiers</b>
++<p>
++The value of a modifier, or a boolean indication of its presence or absence, can be found or set with the getter and setter functions. The generic prototypes of the these getter and setter functions are
++<p>
++<div class="fragment"><pre>
++ int trio_get_???(void *ref);
++ void trio_set_???(void *ref, int);
++</pre></div>
++<p>
++where ??? <code>refers</code> to a modifier. For example, to get the width of the user-defined specifier use
++<p>
++<div class="fragment"><pre>
++ int width = trio_get_width(ref);
++</pre></div>
++<p>
++<b>Special</b> <b>Data</b>
++<p>
++Consider the following user-defined specifier, in its two possible referencing presentations.
++<p>
++<div class="fragment"><pre>
++ trio_printf("%&lt;format&gt;\n", namespace_writer, argument);
++ trio_printf("%&lt;namespace:format&gt;\n", argument);
++</pre></div>
++<p>
++trio_get_format will get the <code>format</code> string, and trio_get_argument} will get the <code>argument</code> parameter. There are no associated setter functions.
++<p>
++<b>EXAMPLES</b>
++<p>
++The following examples show various types of user-defined specifiers. Although each specifier is demonstrated in isolation, they can all co-exist within the same application.
++<p>
++<b>Time</b> <b>Example</b>
++<p>
++Print the time in the format "HOUR:MINUTE:SECOND" if "time" is specified inside the user-defined specifier.
++<p>
++<div class="fragment"><pre>
++ static int time_print(void *ref)
++ {
++ const char *format;
++ time_t *data;
++ char buffer[256];
++
++ format = trio_get_format(ref);
++ if ((format) &amp;&amp; (strcmp(format, "time") == 0)) {
++ data = trio_get_argument(ref);
++ if (data == NULL)
++ return -1;
++ strftime(buffer, sizeof(buffer), "%H:%M:%S", localtime(data));
++ trio_print_string(ref, buffer);
++ }
++ return 0;
++ }
++</pre></div>
++<p>
++<div class="fragment"><pre>
++ int main(void)
++ {
++ void *handle;
++ time_t now = time(NULL);
++
++ handle = trio_register(time_print, "my_time");
++
++ trio_printf("%&lt;time&gt;\n", handle, &amp;now);
++ trio_printf("%&lt;my_time:time&gt;\n", &amp;now);
++
++ trio_unregister(handle);
++ return 0;
++ }
++</pre></div>
++<p>
++<b>Complex</b> <b>Numbers</b> <b>Example</b>
++<p>
++Consider a complex number consisting of a real part, re, and an imaginary part, im.
++<p>
++<div class="fragment"><pre>
++ struct Complex {
++ double re;
++ double im;
++ };
++</pre></div>
++<p>
++This example can print such a complex number in one of two formats. The default format is "re + i im". If the alternative modifier is used, then the format is "r exp(i theta)", where r is the length of the complex vector (re, im) and theta is its angle.
++<p>
++<div class="fragment"><pre>
++ static int complex_print(void *ref)
++ {
++ struct Complex *data;
++ const char *format;
++
++ data = (struct Complex *)trio_get_argument(ref);
++ if (data) {
++ format = trio_get_format(ref);
++
++ if (trio_get_alternative(ref)) {
++ double r, theta;
++
++ r = sqrt(pow(data-&gt;re, 2) + pow(data-&gt;im, 2));
++ theta = acos(data-&gt;re / r);
++ trio_print_ref(ref, "%#f exp(i %#f)", r, theta);
++
++ } else {
++ trio_print_ref(ref, "%#f + i %#f", data-&gt;re, data-&gt;im);
++ }
++ }
++ return 0;
++ }
++</pre></div>
++<p>
++<div class="fragment"><pre>
++ int main(void)
++ {
++ void *handle;
++
++ handle = trio_register(complex_print, "complex");
++
++ /* Normal format. With handle and the with namespace
++ trio_printf("%&lt;&gt;\n", handle, &amp;complex);
++ trio_printf("%&lt;complex:&gt;\n", &amp;complex);
++ /* In exponential notation
++ trio_printf("%#&lt;&gt;\n", handle, &amp;complex);
++ trio_printf("%#&lt;complex:unused data&gt;\n", &amp;complex);
++
++ trio_unregister(handle);
++ return 0;
++ }
++</pre></div>
++<p>
++<b>RETURN</b> <b>VALUES</b>
++<p>
++<a class="el" href="group___user_defined.html#a243">User-defined Formatted Printing Functions.</a> returns a handle, or NULL if an error occured.
++<p>
++<b>SEE</b> <b>ALSO</b>
++<p>
++<a class="el" href="group___printf.html#a218">Formatted Printing Functions.</a>
++<p>
++<b>NOTES</b>
++<p>
++User-defined specifiers, <a class="el" href="group___user_defined.html#a243">User-defined Formatted Printing Functions.</a>, and <a class="el" href="group___user_defined.html#a244">User-defined Formatted Printing Functions.</a> are not thread-safe. In multi-threaded applications they must be guarded by mutexes. Trio provides two special callback functions, called ":enter" and ":leave", which are invoked every time a thread-unsafe operation is attempted. As the thread model is determined by the application, these callback functions must be implemented by the application.
++<p>
++The following callback functions are for demonstration-purposes only. Replace their bodies with locking and unlocking of a mutex to achieve thread-safety. <div class="fragment"><pre>
++ static int enter_region(void *ref)
++ {
++ fprintf(stderr, "Enter Region\n");
++ return 1;
++ }
++
++ static int leave_region(void *ref)
++ {
++ fprintf(stderr, "Leave Region\n");
++ return 1;
++ }
++</pre></div> These two callbacks must be registered before other callbacks are registered. <div class="fragment"><pre>
++ trio_register(enter_region, ":enter");
++ trio_register(leave_region, ":leave");
++
++ another_handle = trio_register(another_callback, NULL);
++</pre></div> <hr><h2>Function Documentation</h2>
++<a name="a0" doxytag="trio-cdetect.c::trio_register"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> trio_pointer_t trio_register </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_callback_t&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>callback</em>, </td>
++ </tr>
++ <tr>
++ <td></td>
++ <td></td>
++ <td class="md" nowrap>const char *&nbsp;</td>
++ <td class="mdname" nowrap>&nbsp; <em>name</em></td>
++ </tr>
++ <tr>
++ <td></td>
++ <td class="md">)&nbsp;</td>
++ <td class="md" colspan="2"></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Register new user-defined specifier.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>callback</em>&nbsp;</td><td>
++</td></tr>
++<tr><td valign=top><em>name</em>&nbsp;</td><td>
++</td></tr>
++</table>
++</dl><dl compact><dt><b>Returns: </b></dt><dd>
++Handle. </dl> </td>
++ </tr>
++</table>
++<a name="a1" doxytag="trio-cdetect.c::trio_unregister"></a><p>
++<table width="100%" cellpadding="2" cellspacing="0" border="0">
++ <tr>
++ <td class="md">
++ <table cellpadding="0" cellspacing="0" border="0">
++ <tr>
++ <td class="md" nowrap valign="top"> void trio_unregister </td>
++ <td class="md" valign="top">(&nbsp;</td>
++ <td class="md" nowrap valign="top">trio_pointer_t&nbsp;</td>
++ <td class="mdname1" valign="top" nowrap>&nbsp; <em>handle</em> </td>
++ <td class="md" valign="top">)&nbsp;</td>
++ <td class="md" nowrap></td>
++ </tr>
++
++ </table>
++ </td>
++ </tr>
++</table>
++<table cellspacing=5 cellpadding=0 border=0>
++ <tr>
++ <td>
++ &nbsp;
++ </td>
++ <td>
++
++<p>
++Unregister an existing user-defined specifier.
++<p>
++<dl compact><dt><b>Parameters: </b></dt><dd>
++<table border=0 cellspacing=2 cellpadding=0>
++<tr><td valign=top><em>handle</em>&nbsp;</td><td>
++</td></tr>
++</table>
++</dl> </td>
++ </tr>
++</table>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/index.html.gs_sprintf ghostscript-9.07/trio/html/index.html
+--- ghostscript-9.07/trio/html/index.html.gs_sprintf 2013-05-09 17:02:39.107447262 +0100
++++ ghostscript-9.07/trio/html/index.html 2013-05-09 17:02:39.107447262 +0100
+@@ -0,0 +1,89 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>TRIO Documentation</h1>
++<p>
++
++<p>
++<dl compact><dt><b>Author: </b></dt><dd>
++Bjørn Reese , Daniel Stenberg</dl><h2><a name="intro">Introduction</a>
++</h2>
++<p>
++Trio is a fully matured and stable set of printf and string functions designed be used by applications with focus on portability or with the need for additional features that are not supported by standard stdio implementation.
++<p>
++There are several cases where you may want to consider using trio:
++<p>
++<ul>
++<li> Portability across heterogeneous platforms. <li> Embedded systems without stdio support. <li> Extendability of unsupported features. <li> Your native version does not do everything you need.</ul>
++When you write applications that must be portable to a wide range of platforms you often have to deal with inadequate implementations of the stdio library functions. Most notably is the lack of secure formatting functions, such as snprintf, or the lack of parameter reordering commonly used for the internationalization of applications, such as the &lt;num&gt;$ modifier. Sometimes the feature you need is simply not present in stdio. So you end up spending much effort on determining which platforms supports what, and to write your own versions of various features. This is where trio can help you. Trio is a platform-independent implementation of the stdio printf and scanf functions and the string library functions.
++<p>
++The functionality described in the stdio standards is a compromise, and does unfortunately not include a mechanism to extend the functionality for an individual application. Oftentimes an application has the need for an extra feature, and the application code can become much more clear and readable by using an extension mechanism. Trio supports a range of useful extensions such as user-defined specifiers, passing of arguments in arrays, localized string scanning, thousand-separators, and arbitrary integer bases.
++<p>
++Trio fully implements the C99 (ISO/IEC 9899:1999) and UNIX98 (the Single Unix Specification, Version 2) standards, as well as many features from other implemenations, e.g. the GNU libc and BSD4.
++<p>
++<h2><a name="examples">Examples</a>
++</h2>
++<p>
++<h3><a name="ex1">Binary Numbers</a>
++</h3> Output an integer as a binary number using a trio extension. <div class="fragment"><pre>
++ trio_printf("%..2i\n", number);
++</pre></div>
++<p>
++<h3><a name="ex2">Thousand-separator</a>
++</h3> Output a number with thousand-separator using a trio extension. <div class="fragment"><pre>
++ trio_printf("%'f\n", 12345.6);
++</pre></div> The thousand-separator described by the locale is used.
++<p>
++<h3><a name="ex3">Fixed Length Array and Sticky Modifier</a>
++</h3> Output an fixed length array of floating-point numbers. <div class="fragment"><pre>
++ double array[] = {1.0, 2.0, 3.0};
++ printf("%.2f %.2f %.2f\n", array[0], array[1], array[2]);
++</pre></div> The same with two trio extensions (arguments are passed in an array, and the first formatting specifier sets the sticky option so we do not have to type all the formatting modifiers for the remaining formatting specifiers) <div class="fragment"><pre>
++ trio_printfv("%!.2f %f %f\n", array);
++</pre></div> Another, and more powerful, application of being able to pass arguments in an array is the creation of the printf/scanf statement at run-time, where the formatting string, and thus the argument list, is based on an external configuration file.
++<p>
++<h3><a name="ex4">Localized scanning</a>
++</h3> Parse a string consisting of one or more upper-case alphabetic characters followed by one or more numeric characters. <div class="fragment"><pre>
++ sscanf(buffer, "%[A-Z]%[0-9]", alphabetic, numeric);
++</pre></div> The same but with locale using a trio extension. <div class="fragment"><pre>
++ trio_sscanf(buffer, "%[[:upper:]]%[[:digit:]]", alphabetic, numeric);
++</pre></div>
++<p>
++<h2><a name="legal">Legal Issues</a>
++</h2> Trio is distributed under the following license, which allows practically anybody to use it in almost any kind of software, including proprietary software, without difficulty.
++<p>
++"Copyright (C) 1998-2001 Bjorn Reese and Daniel Stenberg.
++<p>
++Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
++<p>
++THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER."
++<p>
++<h2><a name="contribution">Contribution</a>
++</h2>
++<p>
++<h3><a name="contribute">Contribute</a>
++</h3> We appreciate any type of contribution, from ideas over improvements to error corrections.
++<p>
++The project space contains references to bug and feature tracking, mailing-list, and the CVS repository. We prefer communication via the mailing-list, but do not require you to be subscribed, because trio is a small project.
++<p>
++The project space is located at <a href="http://sourceforge.net/projects/ctrio/">http://sourceforge.net/projects/ctrio/</a>
++<p>
++<h3><a name="contributors">Contributors</a>
++</h3> We have received contributions from the following persons (in alphabetic order sorted by surname)
++<p>
++<ul>
++<li> Craig Berry <li> Karl Bochert <li> Stan Boehm <li> David Byron <li> Brian Chapman <li> Robert Collins <li> Danny Dulai <li> Bob Friesenhahn <li> Jon Foster <li> John Fotheringham <li> Markus Henke <li> Ken Gibson <li> Paul Janzen <li> Patrick Jessee <li> Richard Jinks <li> Tero Jänkä <li> Howard Kapustein <li> Rune Enggaard Lausen <li> Mehdi Lavasani <li> Alexander Lukyanov <li> Andreas Maus <li> Mikey Menezes <li> Emmanuel Mogenet <li> Jacob Navia <li> Jose Ortiz <li> Joe Orton <li> Gisli Ottarsson <li> Mark Pickelmann <li> Olli Savia <li> Shaun Tancheff <li> Marc Werwerft <li> Igor Zlatkovic</ul>
++Please let us know, and accept our apology, if we have omitted anybody.
++<p>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/modules.html.gs_sprintf ghostscript-9.07/trio/html/modules.html
+--- ghostscript-9.07/trio/html/modules.html.gs_sprintf 2013-05-09 17:02:39.107447262 +0100
++++ ghostscript-9.07/trio/html/modules.html 2013-05-09 17:02:39.107447262 +0100
+@@ -0,0 +1,23 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html>
++<head>
++ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++ <title>TRIO</title>
++ <link href="trio.css" rel="stylesheet" type="text/css">
++</head>
++<body>
++<!-- Generated by Doxygen 1.2.18 -->
++<center>
++<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
++<hr><h1>TRIO Modules</h1>Here is a list of all modules:<ul>
++<li><a class="el" href="group___printf.html">Formatted Printing Functions.</a>
++<li><a class="el" href="group___user_defined.html">User-defined Formatted Printing Functions.</a>
++<li><a class="el" href="group___scanf.html">Formatted Scanning Functions.</a>
++<li><a class="el" href="group___special_quantities.html">Special Quantifies.</a>
++<li><a class="el" href="group___static_strings.html">Static String Functions.</a>
++<li><a class="el" href="group___dynamic_strings.html">Dynamic String Functions.</a>
++</ul>
++<HR>
++<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
++</body>
++</html>
+diff -up ghostscript-9.07/trio/html/trio.css.gs_sprintf ghostscript-9.07/trio/html/trio.css
+--- ghostscript-9.07/trio/html/trio.css.gs_sprintf 2013-05-09 17:02:39.107447262 +0100
++++ ghostscript-9.07/trio/html/trio.css 2013-05-09 17:02:39.107447262 +0100
+@@ -0,0 +1,35 @@
++/* HTML tags */
++
++BODY {
++ background-color: white;
++ color: darkblue;
++}
++
++TD { color: darkblue; }
++
++H1 { text-align: center; }
++
++H3 { font-style: italic; }
++
++HR {
++ width: 85%;
++ align: center;
++}
++
++.copyright { color: darkblue; }
++
++/* Links */
++
++:link { color: blue; }
++
++:visited { color: purple; }
++
++:active { color: red; }
++
++.el:link { font-style: italic; }
++
++/* Examples */
++
++DIV.fragment {
++ color: maroon;
++}
+diff -up ghostscript-9.07/trio/install-sh.gs_sprintf ghostscript-9.07/trio/install-sh
+--- ghostscript-9.07/trio/install-sh.gs_sprintf 2013-05-09 17:02:39.108447266 +0100
++++ ghostscript-9.07/trio/install-sh 2013-05-09 17:02:39.108447266 +0100
+@@ -0,0 +1,250 @@
++#!/bin/sh
++#
++# install - install a program, script, or datafile
++# This comes from X11R5 (mit/util/scripts/install.sh).
++#
++# Copyright 1991 by the Massachusetts Institute of Technology
++#
++# Permission to use, copy, modify, distribute, and sell this software and its
++# documentation for any purpose is hereby granted without fee, provided that
++# the above copyright notice appear in all copies and that both that
++# copyright notice and this permission notice appear in supporting
++# documentation, and that the name of M.I.T. not be used in advertising or
++# publicity pertaining to distribution of the software without specific,
++# written prior permission. M.I.T. makes no representations about the
++# suitability of this software for any purpose. It is provided "as is"
++# without express or implied warranty.
++#
++# Calling this script install-sh is preferred over install.sh, to prevent
++# `make' implicit rules from creating a file called install from it
++# when there is no Makefile.
++#
++# This script is compatible with the BSD install script, but was written
++# from scratch. It can only install one file at a time, a restriction
++# shared with many OS's install programs.
++
++
++# set DOITPROG to echo to test this script
++
++# Don't use :- since 4.3BSD and earlier shells don't like it.
++doit="${DOITPROG-}"
++
++
++# put in absolute paths if you don't have them in your path; or use env. vars.
++
++mvprog="${MVPROG-mv}"
++cpprog="${CPPROG-cp}"
++chmodprog="${CHMODPROG-chmod}"
++chownprog="${CHOWNPROG-chown}"
++chgrpprog="${CHGRPPROG-chgrp}"
++stripprog="${STRIPPROG-strip}"
++rmprog="${RMPROG-rm}"
++mkdirprog="${MKDIRPROG-mkdir}"
++
++transformbasename=""
++transform_arg=""
++instcmd="$mvprog"
++chmodcmd="$chmodprog 0755"
++chowncmd=""
++chgrpcmd=""
++stripcmd=""
++rmcmd="$rmprog -f"
++mvcmd="$mvprog"
++src=""
++dst=""
++dir_arg=""
++
++while [ x"$1" != x ]; do
++ case $1 in
++ -c) instcmd="$cpprog"
++ shift
++ continue;;
++
++ -d) dir_arg=true
++ shift
++ continue;;
++
++ -m) chmodcmd="$chmodprog $2"
++ shift
++ shift
++ continue;;
++
++ -o) chowncmd="$chownprog $2"
++ shift
++ shift
++ continue;;
++
++ -g) chgrpcmd="$chgrpprog $2"
++ shift
++ shift
++ continue;;
++
++ -s) stripcmd="$stripprog"
++ shift
++ continue;;
++
++ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
++ shift
++ continue;;
++
++ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
++ shift
++ continue;;
++
++ *) if [ x"$src" = x ]
++ then
++ src=$1
++ else
++ # this colon is to work around a 386BSD /bin/sh bug
++ :
++ dst=$1
++ fi
++ shift
++ continue;;
++ esac
++done
++
++if [ x"$src" = x ]
++then
++ echo "install: no input file specified"
++ exit 1
++else
++ true
++fi
++
++if [ x"$dir_arg" != x ]; then
++ dst=$src
++ src=""
++
++ if [ -d $dst ]; then
++ instcmd=:
++ else
++ instcmd=mkdir
++ fi
++else
++
++# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
++# might cause directories to be created, which would be especially bad
++# if $src (and thus $dsttmp) contains '*'.
++
++ if [ -f $src -o -d $src ]
++ then
++ true
++ else
++ echo "install: $src does not exist"
++ exit 1
++ fi
++
++ if [ x"$dst" = x ]
++ then
++ echo "install: no destination specified"
++ exit 1
++ else
++ true
++ fi
++
++# If destination is a directory, append the input filename; if your system
++# does not like double slashes in filenames, you may need to add some logic
++
++ if [ -d $dst ]
++ then
++ dst="$dst"/`basename $src`
++ else
++ true
++ fi
++fi
++
++## this sed command emulates the dirname command
++dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
++
++# Make sure that the destination directory exists.
++# this part is taken from Noah Friedman's mkinstalldirs script
++
++# Skip lots of stat calls in the usual case.
++if [ ! -d "$dstdir" ]; then
++defaultIFS='
++'
++IFS="${IFS-${defaultIFS}}"
++
++oIFS="${IFS}"
++# Some sh's can't handle IFS=/ for some reason.
++IFS='%'
++set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
++IFS="${oIFS}"
++
++pathcomp=''
++
++while [ $# -ne 0 ] ; do
++ pathcomp="${pathcomp}${1}"
++ shift
++
++ if [ ! -d "${pathcomp}" ] ;
++ then
++ $mkdirprog "${pathcomp}"
++ else
++ true
++ fi
++
++ pathcomp="${pathcomp}/"
++done
++fi
++
++if [ x"$dir_arg" != x ]
++then
++ $doit $instcmd $dst &&
++
++ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
++ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
++ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
++ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
++else
++
++# If we're going to rename the final executable, determine the name now.
++
++ if [ x"$transformarg" = x ]
++ then
++ dstfile=`basename $dst`
++ else
++ dstfile=`basename $dst $transformbasename |
++ sed $transformarg`$transformbasename
++ fi
++
++# don't allow the sed command to completely eliminate the filename
++
++ if [ x"$dstfile" = x ]
++ then
++ dstfile=`basename $dst`
++ else
++ true
++ fi
++
++# Make a temp file name in the proper directory.
++
++ dsttmp=$dstdir/#inst.$$#
++
++# Move or copy the file name to the temp name
++
++ $doit $instcmd $src $dsttmp &&
++
++ trap "rm -f ${dsttmp}" 0 &&
++
++# and set any options; do chmod last to preserve setuid bits
++
++# If any of these fail, we abort the whole thing. If we want to
++# ignore errors from any of these, just make sure not to ignore
++# errors from the above "$doit $instcmd $src $dsttmp" command.
++
++ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
++ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
++ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
++ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
++
++# Now rename the file to the real destination.
++
++ $doit $rmcmd -f $dstdir/$dstfile &&
++ $doit $mvcmd $dsttmp $dstdir/$dstfile
++
++fi &&
++
++
++exit 0
+diff -up ghostscript-9.07/trio/Makefile.in.gs_sprintf ghostscript-9.07/trio/Makefile.in
+--- ghostscript-9.07/trio/Makefile.in.gs_sprintf 2013-05-09 17:02:39.108447266 +0100
++++ ghostscript-9.07/trio/Makefile.in 2013-05-09 17:02:39.108447266 +0100
+@@ -0,0 +1,73 @@
++SHELL = @SHELL@
++CC = @CC@
++CFLAGS = @CFLAGS@ -I. -DDEBUG
++OBJS = triostr.o trio.o trionan.o
++TARGETLIB = libtrio.a
++TARGETINCS = trio.h triop.h triodef.h trionan.h triostr.h
++LDFLAGS = -L. -ltrio -lm
++AR = ar
++RANLIB = @RANLIB@
++ERASE = rm -f
++MKDIR = mkdir -p
++GENDOC = doxygen
++srcdir = @srcdir@
++# VPATH doesn't seem to work with /usr/xpg4/bin/make on Solaris
++# (use /usr/ccs/bin/make), and doesn't work on older Solaris make
++# such as Solaris 2.6.
++VPATH = @srcdir@
++
++# Installation settings
++INSTALL = @INSTALL@
++INSTALL_DATA = @INSTALL_DATA@
++prefix = @prefix@
++exec_prefix = @exec_prefix@
++includedir = @includedir@
++libdir = @libdir@
++
++all: $(TARGETLIB) $(TARGET)
++
++.PHONY: all check test install doc clean
++
++$(srcdir)/configure: configure.in
++ cd $(srcdir) && autoconf
++
++Makefile: Makefile.in config.status
++ CONFIG_COMMANDS= CONFIG_LINKS= CONFIG_HEADERS= \
++ CONFIG_FILES=Makefile ./config.status
++
++config.status: configure
++ ./config.status --recheck
++
++check: test
++test: regression
++ ./regression
++
++install: $(TARGETLIB)
++ $(MKDIR) $(libdir)
++ $(MKDIR) $(includedir)
++ $(INSTALL_DATA) $(TARGETLIB) $(libdir)/$(TARGETLIB)
++ for i in $(TARGETINCS);do \
++ (set -x;$(INSTALL_DATA) $(srcdir)/$$i $(includedir)); \
++ done
++
++regression: regression.o $(TARGETLIB)
++ $(CC) $(CFLAGS) regression.o $(LDFLAGS) -o $@
++
++example: example.o $(TARGETLIB)
++ $(CC) $(CFLAGS) example.o $(LDFLAGS) -o $@
++
++compare: compare.o $(TARGETLIB)
++ $(CC) $(CFLAGS) compare.o $(LDFLAGS) -o $@
++
++userdef: userdef.o $(TARGETLIB)
++ $(CC) $(CFLAGS) userdef.o $(LDFLAGS) -o $@
++
++$(TARGETLIB): $(OBJS)
++ $(AR) ruv $(TARGETLIB) $(OBJS)
++ $(RANLIB) $(TARGETLIB)
++
++doc::
++ (cd $(srcdir) && $(GENDOC) doc/trio.cfg)
++
++clean:
++ $(ERASE) *~ core core.* regression example $(TOBJS) $(OBJS) $(TARGET) $(TARGETLIB) example.o regression.o
+diff -up ghostscript-9.07/trio/maketgz.gs_sprintf ghostscript-9.07/trio/maketgz
+--- ghostscript-9.07/trio/maketgz.gs_sprintf 2013-05-09 17:02:39.108447266 +0100
++++ ghostscript-9.07/trio/maketgz 2013-05-09 17:02:39.108447266 +0100
+@@ -0,0 +1,46 @@
++#! /bin/sh
++# Script to build archives with
++#
++
++echo "Version number?"
++read version
++
++# get current dir
++dir=`pwd`
++
++# Get basename
++orig=`basename $dir`
++
++# Get the left part of the dash (-)
++new=`echo $orig | cut -d- -f1`
++
++# Build new directory name
++n=$new-$version;
++
++# Tell the world what we're doing
++echo "creates $n.tar.gz";
++
++if [ -r $n ]; then
++ echo "Directory already exists!"
++ exit
++fi
++
++# Create the new dir
++mkdir $n
++
++# Copy all relevant files, with path and permissions!
++tar -cf - `cat FILES` | (cd $n; tar -xBpf -) || exit 1
++
++(cd $n && sh autogen.sh) || exit 1
++
++# Make a tar archive of it all
++tar -cvf $n.tar $n
++
++# gzip the archive
++gzip $n.tar
++
++# Make it world readable
++chmod a+r $n.tar.gz ;
++
++# Delete the temp dir
++rm -rf $n
+diff -up ghostscript-9.07/trio/README.gs_sprintf ghostscript-9.07/trio/README
+--- ghostscript-9.07/trio/README.gs_sprintf 2013-05-09 17:02:39.108447266 +0100
++++ ghostscript-9.07/trio/README 2013-05-09 17:02:39.108447266 +0100
+@@ -0,0 +1,38 @@
++README -- trio
++
++Trio is a package with portable string functions. Including printf() clones
++and others.
++
++ Copyright (C) 1998-2001 by Bjorn Reese and Daniel Stenberg.
++
++ Permission to use, copy, modify, and distribute this software for any
++ purpose with or without fee is hereby granted, provided that the above
++ copyright notice and this permission notice appear in all copies.
++
++ THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++
++Trio is intended to be an integral part of another application, so we
++have not done anything to create a proper installation.
++
++Compile with 'make' (edit the Makefile if you want a release build)
++
++Test the package with 'make test'
++
++Install by copying trio.h, triop.h, and libtrio.a (and man/man?/* if
++you want documentation) to the appropriate directories.
++
++Catch some usage examples in example.c
++
++Send feedback and patches to the mailing list, subscription and other
++information is found here:
++
++ http://lists.sourceforge.net/lists/listinfo/ctrio-talk
++
++Enjoy!
++
++Trio web page
++
++ http://daniel.haxx.se/trio/
+diff -up ghostscript-9.07/trio/regression.c.gs_sprintf ghostscript-9.07/trio/regression.c
+--- ghostscript-9.07/trio/regression.c.gs_sprintf 2013-05-09 17:02:39.109447270 +0100
++++ ghostscript-9.07/trio/regression.c 2013-05-09 17:02:39.109447270 +0100
+@@ -0,0 +1,1640 @@
++/*************************************************************************
++ * Regression test
++ */
++
++#include "triodef.h"
++#if defined(TRIO_COMPILER_ANCIENT)
++# include <varargs.h>
++#else
++# include <stdarg.h>
++#endif
++#include <math.h>
++#include <limits.h>
++#include <float.h>
++#include <errno.h>
++
++#include "trio.h"
++#include "triop.h"
++#if defined(TRIO_EMBED_NAN)
++# define TRIO_PUBLIC_NAN static
++# define TRIO_FUNC_NINF
++# define TRIO_FUNC_PINF
++# define TRIO_FUNC_NAN
++# define TRIO_FUNC_ISINF
++# define TRIO_FUNC_ISNAN
++# if TRIO_FEATURE_FLOAT
++# define TRIO_FUNC_NZERO
++# endif
++#endif
++#include "trionan.h"
++#if defined(TRIO_EMBED_STRING)
++# define TRIO_PUBLIC_STRING static
++# define TRIO_FUNC_EQUAL_CASE
++#endif
++#include "triostr.h"
++#undef printf
++
++#if TRIO_FEATURE_WIDECHAR
++# include <wchar.h>
++#endif
++
++#define QUOTE(x) #x
++
++#define DOUBLE_EQUAL(x,y) (((x)>(y)-DBL_EPSILON) && ((x)<(y)+DBL_EPSILON))
++#define FLOAT_EQUAL(x,y) (((x)>(y)-FLT_EPSILON) && ((x)<(y)+FLT_EPSILON))
++
++static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.67 2010/01/26 13:02:02 breese Exp $";
++
++#if defined(TRIO_EMBED_NAN)
++# include "trionan.c"
++#endif
++#if defined(TRIO_EMBED_STRING)
++# include "triostr.c"
++#endif
++
++/*************************************************************************
++ *
++ */
++static void
++Dump
++TRIO_ARGS2((buffer, rc),
++ char *buffer,
++ int rc)
++{
++ if (rc < 0)
++ {
++ printf("Err = %d (%s), Pos = %d\n",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ }
++ else if (buffer)
++ printf("buffer[% 3d] = \"%s\"\n", rc, buffer);
++}
++
++/*************************************************************************
++ *
++ */
++static void
++Report0
++TRIO_ARGS2((file, line),
++ TRIO_CONST char *file,
++ int line)
++{
++ printf("Verification failed in %s:%d.\n", file, line);
++}
++
++/*************************************************************************
++ *
++ */
++static void
++Report
++TRIO_ARGS4((file, line, expected, got),
++ TRIO_CONST char *file,
++ int line,
++ TRIO_CONST char *expected,
++ TRIO_CONST char *got)
++{
++ Report0(file, line);
++ printf(" Expected \"%s\"\n", expected);
++ printf(" Got \"%s\"\n", got);
++}
++
++/*************************************************************************
++ *
++ */
++int
++Verify
++TRIO_VARGS5((file, line, result, fmt, va_alist),
++ TRIO_CONST char *file,
++ int line,
++ TRIO_CONST char *result,
++ TRIO_CONST char *fmt,
++ TRIO_VA_DECL)
++{
++ int rc;
++ va_list args;
++ char buffer[4096];
++
++ TRIO_VA_START(args, fmt);
++ rc = trio_vsnprintf(buffer, sizeof(buffer), fmt, args);
++ if (rc < 0)
++ Dump(buffer, rc);
++ TRIO_VA_END(args);
++
++ if (!trio_equal_case(result, buffer))
++ {
++ Report(file, line, result, buffer);
++ return 1;
++ }
++ return 0;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyReturnValues(TRIO_NOARGS)
++{
++ int nerrors = 0;
++ int rc;
++ int count;
++ char *expected;
++ char buffer[4096];
++ char result[4096];
++
++ rc = trio_sprintf(buffer, "%s%n", "0123456789", &count);
++ trio_sprintf(result, "%d %d %s", rc, count, buffer);
++ expected = "10 10 0123456789";
++ if (!trio_equal_case(result, expected))
++ {
++ nerrors++;
++ Report(__FILE__, __LINE__, expected, result);
++ }
++
++ rc = trio_snprintf(buffer, sizeof(buffer), "%s%n", "0123456789", &count);
++ trio_sprintf(result, "%d %d %s", rc, count, buffer);
++ expected = "10 10 0123456789";
++ if (!trio_equal_case(result, expected))
++ {
++ nerrors++;
++ Report(__FILE__, __LINE__, expected, result);
++ }
++
++ rc = trio_snprintf(buffer, 4, "%s%n", "0123456789", &count);
++ trio_sprintf(result, "%d %d %s", rc, count, buffer);
++ expected = "10 3 012";
++ if (!trio_equal_case(result, expected))
++ {
++ nerrors++;
++ Report(__FILE__, __LINE__, expected, result);
++ }
++
++ /* The output buffer contains the empty string */
++ rc = trio_snprintf(buffer, 1, "%s%n", "0123456789", &count);
++ trio_sprintf(result, "%d %d %s", rc, count, buffer);
++ expected = "10 0 ";
++ if (!trio_equal_case(result, expected))
++ {
++ nerrors++;
++ Report(__FILE__, __LINE__, expected, result);
++ }
++
++ /* The output buffer should be left untouched when max size is 0 */
++ trio_sprintf(buffer, "DO NOT TOUCH");
++ rc = trio_snprintf(buffer, 0, "%s%n", "0123456789", &count);
++ trio_sprintf(result, "%d %d %s", rc, count, buffer);
++ expected = "10 0 DO NOT TOUCH";
++ if (!trio_equal_case(result, expected))
++ {
++ nerrors++;
++ Report(__FILE__, __LINE__, expected, result);
++ }
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++#define TEST_STRING "0123456789"
++
++int
++VerifyAllocate(TRIO_NOARGS)
++{
++ int nerrors = 0;
++#if TRIO_FEATURE_DYNAMICSTRING
++ int rc;
++ char *string;
++ int count;
++ int test_size = sizeof(TEST_STRING) - 1;
++
++ /* Allocate a string with the result */
++ rc = trio_asprintf(&string, "%s%n", TEST_STRING, &count);
++ if (rc < 0)
++ {
++ nerrors++;
++ Dump(string, rc);
++ }
++ else if (count != test_size)
++ {
++ nerrors++;
++ printf("Validation failed in %s:%d\n", __FILE__, __LINE__);
++ printf(" Expected %%n = %d\n", test_size);
++ printf(" Got %%n = %d\n", count);
++ }
++ else if (!trio_equal_case(string, TEST_STRING))
++ {
++ nerrors++;
++ Report(__FILE__, __LINE__, TEST_STRING, string);
++ }
++ if (string)
++ free(string);
++#endif
++
++ return nerrors;
++}
++
++
++/*************************************************************************
++ *
++ */
++int
++VerifyFormattingStrings(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++ /* Normal text */
++ nerrors += Verify(__FILE__, __LINE__, "Hello world",
++ "Hello world");
++ /* String */
++ nerrors += Verify(__FILE__, __LINE__, "Hello world",
++ "%s", "Hello world");
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyFormattingIntegers(TRIO_NOARGS)
++{
++ int nerrors = 0;
++ char buffer[256];
++
++ /* Integer */
++ nerrors += Verify(__FILE__, __LINE__, "Number 42",
++ "Number %d", 42);
++ nerrors += Verify(__FILE__, __LINE__, "Number -42",
++ "Number %d", -42);
++ nerrors += Verify(__FILE__, __LINE__, "Number 42",
++ "Number %ld", 42L);
++ nerrors += Verify(__FILE__, __LINE__, "Number -42",
++ "Number %ld", -42L);
++ /* Integer width */
++ nerrors += Verify(__FILE__, __LINE__, " 1234",
++ "%6d", 1234);
++ nerrors += Verify(__FILE__, __LINE__, " 1234",
++ "%*d", 6, 1234);
++ /* Integer width overrun */
++ nerrors += Verify(__FILE__, __LINE__, "123456",
++ "%4d", 123456);
++ /* Integer precision */
++ nerrors += Verify(__FILE__, __LINE__, "0012",
++ "%.4d", 12);
++ nerrors += Verify(__FILE__, __LINE__, "0012",
++ "%.*d", 4, 12);
++ nerrors += Verify(__FILE__, __LINE__, " 0012",
++ "%6.*d", 4, 12);
++ nerrors += Verify(__FILE__, __LINE__, " 0012",
++ "%*.*d", 6, 4, 12);
++ nerrors += Verify(__FILE__, __LINE__, " 0012",
++ "%*.*.*d", 6, 4, 2, 12);
++ nerrors += Verify(__FILE__, __LINE__, " 0012",
++ "%*.*.*i", 6, 4, 10, 12);
++ /* Integer sign, zero-padding, and width */
++ nerrors += Verify(__FILE__, __LINE__, "+01234",
++ "%+06d", 1234);
++ nerrors += Verify(__FILE__, __LINE__, " 01234",
++ "% 06d", 1234);
++ nerrors += Verify(__FILE__, __LINE__, "+01234",
++ "% +06d", 1234);
++ /* Integer adjust, zero-padding, and width */
++ nerrors += Verify(__FILE__, __LINE__, "12 ",
++ "%-08d", 12);
++ /* Integer zero-padding, width, and precision */
++ nerrors += Verify(__FILE__, __LINE__, " 000012",
++ "%08.6d", 12);
++ /* Integer base */
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%u", 42);
++ nerrors += Verify(__FILE__, __LINE__, "-1",
++ "%d", -1);
++ nerrors += Verify(__FILE__, __LINE__, "52",
++ "%o", 42);
++ nerrors += Verify(__FILE__, __LINE__, "052",
++ "%#o", 42);
++ nerrors += Verify(__FILE__, __LINE__, "0",
++ "%#o", 0);
++ nerrors += Verify(__FILE__, __LINE__, "2a",
++ "%x", 42);
++ nerrors += Verify(__FILE__, __LINE__, "2A",
++ "%X", 42);
++ nerrors += Verify(__FILE__, __LINE__, "0x2a",
++ "%#x", 42);
++ nerrors += Verify(__FILE__, __LINE__, "0X2A",
++ "%#X", 42);
++ nerrors += Verify(__FILE__, __LINE__, "0x00c ",
++ "%-#6.3x", 12);
++ nerrors += Verify(__FILE__, __LINE__, "",
++ "%.d", 0);
++ nerrors += Verify(__FILE__, __LINE__, "",
++ "%#.d", 0);
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%.d", 42);
++ nerrors += Verify(__FILE__, __LINE__, "",
++ "%.o", 0);
++ nerrors += Verify(__FILE__, __LINE__, " 0000",
++ "%8.4o", 0);
++ nerrors += Verify(__FILE__, __LINE__, " 0",
++ "%8o", 0);
++ nerrors += Verify(__FILE__, __LINE__, "00000000",
++ "%08o", 0);
++ nerrors += Verify(__FILE__, __LINE__, "0",
++ "%#.o", 0);
++ nerrors += Verify(__FILE__, __LINE__, "52",
++ "%.o", 42);
++ nerrors += Verify(__FILE__, __LINE__, "",
++ "%.x", 0);
++ nerrors += Verify(__FILE__, __LINE__, "",
++ "%#.x", 0);
++ nerrors += Verify(__FILE__, __LINE__, "2a",
++ "%.x", 42);
++ sprintf(buffer, "%u", UINT_MAX);
++ nerrors += Verify(__FILE__, __LINE__, buffer,
++ "%u", -1);
++ sprintf(buffer, "%x", UINT_MAX);
++ nerrors += Verify(__FILE__, __LINE__, buffer,
++ "%x", -1);
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyFormattingFloats(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++#if TRIO_FEATURE_FLOAT
++ /* Double */
++ nerrors += Verify(__FILE__, __LINE__, "3141.000000",
++ "%f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "3141.500000",
++ "%f", 3141.5);
++ nerrors += Verify(__FILE__, __LINE__, "3.141000e+03",
++ "%e", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, " -2.3420e-02",
++ "%16.4e", -2.342E-02);
++ nerrors += Verify(__FILE__, __LINE__, " -2.3420e-22",
++ "%16.4e", -2.342E-22);
++ nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02",
++ "% 16.4e", 2.342E-02);
++ nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02",
++ "% 1.4e", 2.342E-02);
++ nerrors += Verify(__FILE__, __LINE__, "3.141000E-44",
++ "%E", 3.141e-44);
++ nerrors += Verify(__FILE__, __LINE__, "0",
++ "%g", 0.0);
++ nerrors += Verify(__FILE__, __LINE__, "-0",
++ "%g", trio_nzero());
++ nerrors += Verify(__FILE__, __LINE__, "3141.5",
++ "%g", 3141.5);
++ nerrors += Verify(__FILE__, __LINE__, "3.1415E-06",
++ "%G", 3.1415e-6);
++ nerrors += Verify(__FILE__, __LINE__, "+3141.000000",
++ "%+f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "-3141.000000",
++ "%+f", -3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "0.333333",
++ "%f", 1.0/3.0);
++ nerrors += Verify(__FILE__, __LINE__, "0.666667",
++ "%f", 2.0/3.0);
++ /* Beyond accuracy */
++ nerrors += Verify(__FILE__, __LINE__, "0.000000",
++ "%f", 1.234567890123456789e-20);
++# if defined(TRIO_BREESE)
++ nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580299875",
++ "%.32g", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991118215802998748",
++ "%.32f", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580300",
++ "%.28f", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "1.399999999999999911182158",
++ "%.24f", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991",
++ "%.17f", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "1.40000000000000",
++ "%.14f", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "39413.800000000002910383045673370361",
++ "%.30f", 39413.80);
++# endif
++ /* 2^-1 + 2^-15 */
++ nerrors += Verify(__FILE__, __LINE__, "0.500030517578125",
++ "%.*g", DBL_DIG + 10, 0.500030517578125);
++ /* Double decimal point */
++ nerrors += Verify(__FILE__, __LINE__, "3141",
++ "%.0f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "3142",
++ "%.0f", 3141.5);
++ nerrors += Verify(__FILE__, __LINE__, "3141",
++ "%.f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "12",
++ "%.f", 12.34);
++ nerrors += Verify(__FILE__, __LINE__, "3141.000",
++ "%.3f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "3141.000000",
++ "%#f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "0.0000",
++ "%#.4f", 0.0);
++ nerrors += Verify(__FILE__, __LINE__, "0.000",
++ "%#.4g", 0.0);
++ nerrors += Verify(__FILE__, __LINE__, "0.001000",
++ "%#.4g", 1e-3);
++ nerrors += Verify(__FILE__, __LINE__, "3141.0000",
++ "%#.4f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "3141.",
++ "%#.0f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "3141.",
++ "%#.f", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "11.0000",
++ "%#.4f", 11.0);
++ nerrors += Verify(__FILE__, __LINE__, "100.00",
++ "%.2f", 99.9999);
++ nerrors += Verify(__FILE__, __LINE__, "3e+03",
++ "%.e", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "3.e+03",
++ "%#.e", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "1.23457e+06",
++ "%g", 1234567.0);
++ nerrors += Verify(__FILE__, __LINE__, "1e+02",
++ "%.2g", 99.9999);
++ nerrors += Verify(__FILE__, __LINE__, "1.0e+02",
++ "%#.2g", 99.9999);
++ nerrors += Verify(__FILE__, __LINE__, "0.123",
++ "%0g", 0.123);
++ nerrors += Verify(__FILE__, __LINE__, "1.00e+00",
++ "%.2e", 0.9999);
++ nerrors += Verify(__FILE__, __LINE__, "1",
++ "%.2g", 0.9999);
++ nerrors += Verify(__FILE__, __LINE__, "2",
++ "%.0g", 1.5);
++ nerrors += Verify(__FILE__, __LINE__, "2",
++ "%.g", 1.5);
++ nerrors += Verify(__FILE__, __LINE__, "0.01",
++ "%.2g", 0.01);
++ nerrors += Verify(__FILE__, __LINE__, "0.010",
++ "%#.2g", 0.01);
++ nerrors += Verify(__FILE__, __LINE__, "1e-04",
++ "%5.g", 0.999999e-4);
++ /* Double width and precision */
++ nerrors += Verify(__FILE__, __LINE__, " 1e-05",
++ "%11.5g", 1e-5);
++ nerrors += Verify(__FILE__, __LINE__, " 0.0001",
++ "%11.5g", 1e-4);
++ nerrors += Verify(__FILE__, __LINE__, " 0.001",
++ "%11.5g", 1e-3);
++ nerrors += Verify(__FILE__, __LINE__, " 0.01",
++ "%11.5g", 1e-2);
++ nerrors += Verify(__FILE__, __LINE__, " 0.1",
++ "%11.5g", 1e-1);
++ nerrors += Verify(__FILE__, __LINE__, " 1",
++ "%11.5g", 1e0);
++ nerrors += Verify(__FILE__, __LINE__, " 10",
++ "%11.5g", 1e1);
++ nerrors += Verify(__FILE__, __LINE__, " 100",
++ "%11.5g", 1e2);
++ nerrors += Verify(__FILE__, __LINE__, " 1000",
++ "%11.5g", 1e3);
++ nerrors += Verify(__FILE__, __LINE__, " 10000",
++ "%11.5g", 1e4);
++ nerrors += Verify(__FILE__, __LINE__, " 1e+05",
++ "%11.5g", 1e5);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e-05",
++ "%11.2g", 0.99e-4);
++ nerrors += Verify(__FILE__, __LINE__, " 0.00099",
++ "%11.2g", 0.99e-3);
++ nerrors += Verify(__FILE__, __LINE__, " 0.0099",
++ "%11.2g", 0.99e-2);
++ nerrors += Verify(__FILE__, __LINE__, " 0.099",
++ "%11.2g", 0.99e-1);
++ nerrors += Verify(__FILE__, __LINE__, " 0.99",
++ "%11.2g", 0.99e0);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9",
++ "%11.2g", 0.99e1);
++ nerrors += Verify(__FILE__, __LINE__, " 99",
++ "%11.2g", 0.99e2);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e+02",
++ "%11.2g", 0.99e3);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e+03",
++ "%11.2g", 0.99e4);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e+04",
++ "%11.2g", 0.99e5);
++ /* Double width, precision, and alternative */
++ nerrors += Verify(__FILE__, __LINE__, " 1.0000e-05",
++ "%#11.5g", 1e-5);
++ nerrors += Verify(__FILE__, __LINE__, " 0.00010000",
++ "%#11.5g", 1e-4);
++ nerrors += Verify(__FILE__, __LINE__, " 0.0010000",
++ "%#11.5g", 1e-3);
++ nerrors += Verify(__FILE__, __LINE__, " 0.0010000",
++ "%#11.5g", 0.999999e-3);
++ nerrors += Verify(__FILE__, __LINE__, " 0.010000",
++ "%#11.5g", 1e-2);
++ nerrors += Verify(__FILE__, __LINE__, " 0.010000",
++ "%#11.5g", 0.999999e-2);
++ nerrors += Verify(__FILE__, __LINE__, " 0.10000",
++ "%#11.5g", 1e-1);
++ nerrors += Verify(__FILE__, __LINE__, " 0.10000",
++ "%#11.5g", 0.999999e-1);
++ nerrors += Verify(__FILE__, __LINE__, " 1.0000",
++ "%#11.5g", 1e0);
++ nerrors += Verify(__FILE__, __LINE__, " 1.0000",
++ "%#11.5g", 0.999999e0);
++ nerrors += Verify(__FILE__, __LINE__, " 10.000",
++ "%#11.5g", 1e1);
++ nerrors += Verify(__FILE__, __LINE__, " 100.00",
++ "%#11.5g", 1e2);
++ nerrors += Verify(__FILE__, __LINE__, " 1000.0",
++ "%#11.5g", 1e3);
++ nerrors += Verify(__FILE__, __LINE__, " 10000.",
++ "%#11.5g", 1e4);
++ nerrors += Verify(__FILE__, __LINE__, " 1.0000e+05",
++ "%#11.5g", 1e5);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e-05",
++ "%#11.2g", 0.99e-4);
++ nerrors += Verify(__FILE__, __LINE__, " 0.00099",
++ "%#11.2g", 0.99e-3);
++ nerrors += Verify(__FILE__, __LINE__, " 0.0099",
++ "%#11.2g", 0.99e-2);
++ nerrors += Verify(__FILE__, __LINE__, " 0.099",
++ "%#11.2g", 0.99e-1);
++ nerrors += Verify(__FILE__, __LINE__, " 0.99",
++ "%#11.2g", 0.99e0);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9",
++ "%#11.2g", 0.99e1);
++ nerrors += Verify(__FILE__, __LINE__, " 99.",
++ "%#11.2g", 0.99e2);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e+02",
++ "%#11.2g", 0.99e3);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e+03",
++ "%#11.2g", 0.99e4);
++ nerrors += Verify(__FILE__, __LINE__, " 9.9e+04",
++ "%#11.2g", 0.99e5);
++ /* Double width, precision, and zero padding */
++ nerrors += Verify(__FILE__, __LINE__, "00003.141500e+03",
++ "%016e", 3141.5);
++ nerrors += Verify(__FILE__, __LINE__, " 3.141500e+03",
++ "%16e", 3141.5);
++ nerrors += Verify(__FILE__, __LINE__, "3.141500e+03 ",
++ "%-16e", 3141.5);
++ nerrors += Verify(__FILE__, __LINE__, "03.142e+03",
++ "%010.3e", 3141.5);
++#if !defined(TRIO_COMPILER_ANCIENT)
++ /* Long double */
++ nerrors += Verify(__FILE__, __LINE__, "1.400000",
++ "%Lf", 1.4L);
++#endif
++
++ /* Special cases */
++ nerrors += Verify(__FILE__, __LINE__, "1.00",
++ "%.2f", 0.999);
++ nerrors += Verify(__FILE__, __LINE__, "100",
++ "%.0f", 99.9);
++ nerrors += Verify(__FILE__, __LINE__, "inf",
++ "%f", trio_pinf());
++ nerrors += Verify(__FILE__, __LINE__, "-inf",
++ "%f", trio_ninf());
++ nerrors += Verify(__FILE__, __LINE__, "INF",
++ "%F", trio_pinf());
++ nerrors += Verify(__FILE__, __LINE__, "-INF",
++ "%F", trio_ninf());
++ /* May fail if NaN is unsupported */
++ nerrors += Verify(__FILE__, __LINE__, "nan",
++ "%f", trio_nan());
++ nerrors += Verify(__FILE__, __LINE__, "NAN",
++ "%F", trio_nan());
++
++# if TRIO_FEATURE_HEXFLOAT
++ nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4",
++ "%a", 42.0);
++ nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4",
++ "%a", -42.0);
++ nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0",
++ "%a", 1.5);
++ nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0",
++ "%a", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8",
++ "%a", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8",
++ "%A", 3141.0);
++ nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148",
++ "%a", 3.141e-44);
++# endif
++
++#endif /* TRIO_FEATURE_FLOAT */
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++#if TRIO_EXTENSION
++int number_writer(void *ref)
++{
++ const char *format;
++ int *data;
++
++ format = trio_get_format(ref);
++ if ((format) && trio_equal(format, "integer"))
++ {
++ data = trio_get_argument(ref);
++ if (data)
++ {
++ trio_print_int(ref, *data);
++ }
++ }
++ return 0;
++}
++
++#endif
++
++int
++VerifyFormattingUserDefined(TRIO_NOARGS)
++{
++ int nerrors = 0;
++#if TRIO_EXTENSION
++ void *number_handle;
++ int integer = 123;
++
++ number_handle = trio_register(number_writer, "number");
++
++ /* Old style */
++ nerrors += Verify(__FILE__, __LINE__, "123",
++ "%<number:integer>", &integer);
++
++ /* New style */
++ nerrors += Verify(__FILE__, __LINE__, "123",
++ "$<number:integer|%p>", &integer);
++ nerrors += Verify(__FILE__, __LINE__, "123",
++ "$<integer|%p%p>", number_handle, &integer);
++ nerrors += Verify(__FILE__, __LINE__, "$<integer|123",
++ "$<integer|%d", 123);
++ nerrors += Verify(__FILE__, __LINE__, "$integer|123>",
++ "$integer|%d>", 123);
++
++ trio_unregister(number_handle);
++#endif
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyFormattingRegression(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++#if TRIO_FEATURE_FLOAT
++ /* 0.6 was formatted as 0.600000e+00 */
++ nerrors += Verify(__FILE__, __LINE__, "5.000000e-01",
++ "%e", 0.5);
++ nerrors += Verify(__FILE__, __LINE__, "6.000000e-01",
++ "%e", 0.6);
++#endif
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyFormatting(TRIO_NOARGS)
++{
++ int nerrors = 0;
++#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
++ char buffer[256];
++#endif
++
++ nerrors += VerifyFormattingStrings();
++ nerrors += VerifyFormattingIntegers();
++ nerrors += VerifyFormattingFloats();
++ nerrors += VerifyFormattingRegression();
++ nerrors += VerifyFormattingUserDefined();
++
++ /* Pointer */
++ if (sizeof(void *) == 4)
++ {
++ nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567",
++ "Pointer %p", 0x1234567);
++ }
++#if defined(TRIO_COMPILER_SUPPORTS_LL)
++ else if (sizeof(void *) == 8)
++ {
++ nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345",
++ "Pointer %p", 0x123456789012345LL);
++ }
++#endif
++ /* Nil pointer */
++ nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)",
++ "Pointer %p", NULL);
++
++ /* Char width alignment */
++ nerrors += Verify(__FILE__, __LINE__, "Char X .",
++ "Char %-4c.", 'X');
++ /* String width / precision */
++ nerrors += Verify(__FILE__, __LINE__, " testing",
++ "%8s", "testing");
++ nerrors += Verify(__FILE__, __LINE__, "testing ",
++ "%-8s", "testing");
++ nerrors += Verify(__FILE__, __LINE__, " testing",
++ "%*s", 8, "testing");
++ nerrors += Verify(__FILE__, __LINE__, "testing ",
++ "%*s", -8, "testing");
++ nerrors += Verify(__FILE__, __LINE__, "test",
++ "%.4s", "testing");
++ nerrors += Verify(__FILE__, __LINE__, "test",
++ "%.*s", 4, "testing");
++ nerrors += Verify(__FILE__, __LINE__, "testing",
++ "%.*s", -4, "testing");
++#if TRIO_FEATURE_POSITIONAL
++ /* Positional */
++ nerrors += Verify(__FILE__, __LINE__, "222 111",
++ "%2$s %1$s", "111", "222");
++ nerrors += Verify(__FILE__, __LINE__, "123456 12345 0001234 00123",
++ "%4$d %3$*8$d %2$.*7$d %1$*6$.*5$d",
++ 123, 1234, 12345, 123456, 5, 6, 7, 8);
++#endif
++
++#if TRIO_FEATURE_SIZE_T_UPPER
++ nerrors += Verify(__FILE__, __LINE__, "256",
++ "%Zd", sizeof(buffer));
++#endif
++
++#if TRIO_FEATURE_ERRNO
++ errno = EINTR;
++# if defined(TRIO_PLATFORM_LYNX)
++# if defined(PREDEF_STANDARD_POSIX_1996)
++ nerrors += Verify(__FILE__, __LINE__, "Interrupted system call ",
++ "%m");
++# else
++ nerrors += Verify(__FILE__, __LINE__, "System call interrupted",
++ "%m");
++# endif
++# else
++ nerrors += Verify(__FILE__, __LINE__, "Interrupted system call",
++ "%m");
++# endif
++#endif
++
++#if TRIO_FEATURE_QUAD
++# if defined(TRIO_COMPILER_SUPPORTS_LL)
++ /* This may fail if the preprocessor does not recognize LL */
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%qd", 42LL);
++# endif
++#endif
++
++#if TRIO_FEATURE_SIZE_T
++ nerrors += Verify(__FILE__, __LINE__, "256",
++ "%zd", sizeof(buffer));
++#endif
++#if TRIO_FEATURE_PTRDIFF_T
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%td", 42);
++#endif
++#if TRIO_FEATURE_INTMAX_T
++# if defined(TRIO_COMPILER_SUPPORTS_LL)
++ /* Some compilers may not handle the LL suffix correctly */
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%jd", 42LL);
++# endif
++#endif
++
++#if TRIO_FEATURE_WIDECHAR
++ nerrors += Verify(__FILE__, __LINE__, "Hello World",
++ "%ls", L"Hello World");
++ nerrors += Verify(__FILE__, __LINE__, "\\aHello World",
++ "%#ls", L"\aHello World");
++ nerrors += Verify(__FILE__, __LINE__, "A",
++ "%lc", L'A');
++ nerrors += Verify(__FILE__, __LINE__, "\\a",
++ "%#lc", L'\a');
++#endif
++
++#if TRIO_FEATURE_FIXED_SIZE
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%I8d", 42);
++ nerrors += Verify(__FILE__, __LINE__, "ffffffff",
++ "%I16x", -1);
++#endif
++
++#if TRIO_EXTENSION
++ nerrors += Verify(__FILE__, __LINE__, " 42 86",
++ "%!4d %d", 42, 86);
++ nerrors += Verify(__FILE__, __LINE__, "0042 0086",
++ "%!04d %d", 42, 86);
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%&d", sizeof(long), 42L);
++ /* Non-printable string */
++ nerrors += Verify(__FILE__, __LINE__, "NonPrintable \\x01 \\a \\\\",
++ "NonPrintable %#s", "\01 \07 \\");
++ nerrors += Verify(__FILE__, __LINE__, "\\a \\b \\t \\n \\v \\f \\r",
++ "%#s", "\007 \010 \011 \012 \013 \014 \015");
++ /* Quote flag */
++ nerrors += Verify(__FILE__, __LINE__, "Another \"quoted\" string",
++ "Another %'s string", "quoted");
++ /* Integer base */
++ nerrors += Verify(__FILE__, __LINE__, "Number 42 == 1120 (base 3)",
++ "Number %d == %..3i (base 3)", 42, 42);
++ /* Integer base (specifier base must be used instead of base modifier) */
++ nerrors += Verify(__FILE__, __LINE__, "42",
++ "%..3d", 42);
++ nerrors += Verify(__FILE__, __LINE__, "52",
++ "%..3o", 42);
++ nerrors += Verify(__FILE__, __LINE__, "2a",
++ "%..3x", 42);
++ /* Integer thousand separator */
++ nerrors += Verify(__FILE__, __LINE__, "Number 100",
++ "Number %'d", 100);
++ nerrors += Verify(__FILE__, __LINE__, "Number 1,000,000",
++ "Number %'d", 1000000);
++# if TRIO_FEATURE_FLOAT
++ /* Float thousand separator */
++ nerrors += Verify(__FILE__, __LINE__, "31,415.200000",
++ "%'f", 31415.2);
++ nerrors += Verify(__FILE__, __LINE__, "1,000,000.000000",
++ "%'f", 1000000.0);
++ /* Rounding modifier */
++ nerrors += Verify(__FILE__, __LINE__, "1.4",
++ "%.32Rf", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "1.4",
++ "%.17Rf", 1.4);
++ nerrors += Verify(__FILE__, __LINE__, "39413.8",
++ "%.30Rf", 39413.80);
++# if !defined(TRIO_COMPILER_ANCIENT)
++ /* Long double */
++ nerrors += Verify(__FILE__, __LINE__, "1.4",
++ "%RLf", 1.4L);
++ nerrors += Verify(__FILE__, __LINE__, "1.4",
++ "%.30RLf", 1.4L);
++# endif
++# endif
++#endif
++
++#if defined(TRIO_BREESE)
++ /*
++ * These results depends on issues beyond our control. For example,
++ * the accuracy of floating-point numbers depends on the underlying
++ * floating-point hardware (e.g. whether IEEE 754 double or extended-
++ * double format is used).
++ *
++ * These tests are therefore not part of the normal regression test,
++ * but we keep them here for development purposes.
++ */
++ nerrors += Verify(__FILE__, __LINE__, "123456789012345680868.000000",
++ "%f", 1.234567890123456789e20);
++ nerrors += Verify(__FILE__, __LINE__, "1.23456789012345677901e-20",
++ "%.20e", 1.2345678901234567e-20);
++ nerrors += Verify(__FILE__, __LINE__, "0.666666666666666629659233",
++ "%.*g", DBL_DIG + 10, 2.0/3.0);
++ nerrors += Verify(__FILE__, __LINE__, "123456789012345700000",
++ "%Rf", 1.234567890123456789e20);
++# if !defined(TRIO_COMPILER_ANCIENT)
++ nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667",
++ "%RLf", (2.0L/3.0L));
++ nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667",
++ "%.30RLf", (2.0L/3.0L));
++# endif
++#endif
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyErrors(TRIO_NOARGS)
++{
++ char buffer[512];
++ int rc;
++ int nerrors = 0;
++
++ /* Error: Invalid argument 1 */
++ rc = trio_snprintf(buffer, sizeof(buffer), "%d %r", 42, "text");
++#if TRIO_FEATURE_ERRORCODE
++# if TRIO_FEATURE_STRERR
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 5",
++ "%s", buffer);
++# else
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_POSITION(rc));
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 5",
++ "%s", buffer);
++# endif
++#else
++ nerrors += (rc != -1);
++#endif
++
++ /* Error: Invalid argument 2 */
++ rc = trio_snprintf(buffer, sizeof(buffer), "%#");
++#if TRIO_FEATURE_ERRORCODE
++# if TRIO_FEATURE_STRERR
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
++ "%s", buffer);
++# else
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_POSITION(rc));
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3",
++ "%s", buffer);
++# endif
++#else
++ nerrors += (rc != -1);
++#endif
++
++ /* Error: Invalid argument 3 */
++ rc = trio_snprintf(buffer, sizeof(buffer), "%hhhd", 42);
++#if TRIO_FEATURE_ERRORCODE
++# if TRIO_FEATURE_STRERR
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 4",
++ "%s", buffer);
++# else
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_POSITION(rc));
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 4",
++ "%s", buffer);
++# endif
++#else
++ nerrors += (rc != -1);
++#endif
++
++ /* Error: Double reference */
++ rc = trio_snprintf(buffer, sizeof(buffer), "hello %1$d %1$d", 31, 32);
++#if TRIO_FEATURE_ERRORCODE
++# if TRIO_FEATURE_STRERR
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++# if TRIO_UNIX98
++ nerrors += Verify(__FILE__, __LINE__, "Err = 4 (Double reference), Pos = 0",
++ "%s", buffer);
++# else
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 9",
++ "%s", buffer);
++# endif
++# else
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_POSITION(rc));
++# if TRIO_UNIX98
++ nerrors += Verify(__FILE__, __LINE__, "Err = 4, Pos = 0",
++ "%s", buffer);
++# else
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 9",
++ "%s", buffer);
++# endif
++# endif
++#else
++ nerrors += (rc != -1);
++#endif
++
++ /* Error: Reference gap */
++ rc = trio_snprintf(buffer, sizeof(buffer), "%3$d %1$d", 31, 32, 33);
++#if TRIO_FEATURE_ERRORCODE
++# if TRIO_FEATURE_STRERR
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_NAME(rc),
++ TRIO_ERROR_POSITION(rc));
++# if TRIO_UNIX98
++ nerrors += Verify(__FILE__, __LINE__, "Err = 5 (Reference gap), Pos = 1",
++ "%s", buffer);
++# else
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
++ "%s", buffer);
++# endif
++# else
++ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
++ TRIO_ERROR_CODE(rc),
++ TRIO_ERROR_POSITION(rc));
++# if TRIO_UNIX98
++ nerrors += Verify(__FILE__, __LINE__, "Err = 5, Pos = 1",
++ "%s", buffer);
++# else
++ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3",
++ "%s", buffer);
++# endif
++# endif
++#else
++ nerrors += (rc != -1);
++#endif
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++#if TRIO_FEATURE_SCANF
++int
++VerifyScanningOneInteger
++TRIO_ARGS5((file, line, expected, format, original),
++ TRIO_CONST char *file,
++ int line,
++ TRIO_CONST char *expected,
++ TRIO_CONST char *format,
++ int original)
++{
++ int number;
++ char data[512];
++
++ trio_snprintf(data, sizeof(data), format, original);
++ trio_sscanf(data, format, &number);
++ return Verify(file, line, expected, format, number);
++}
++
++int
++VerifyScanningIntegers(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42",
++ "%i", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42",
++ "%d", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "-42",
++ "%d", -42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2147483647",
++ "%d", 2147483647);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42",
++ "%u", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2a",
++ "%x", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "52",
++ "%o", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "101010",
++ "%..2i", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "0x2a",
++ "%#x", 42);
++ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "052",
++ "%#o", 42);
++
++ return nerrors;
++}
++#endif
++
++/*************************************************************************
++ *
++ */
++#if TRIO_FEATURE_SCANF
++int
++VerifyScanningOneFloat
++TRIO_ARGS5((file, line, expected, format, original),
++ TRIO_CONST char *file,
++ int line,
++ TRIO_CONST char *expected,
++ TRIO_CONST char *format,
++ double original)
++{
++ float number;
++ char data[512];
++
++ trio_snprintf(data, sizeof(data), format, original);
++ trio_sscanf(data, format, &number);
++ return Verify(file, line, expected, format, number);
++}
++
++int
++VerifyScanningOneDouble
++TRIO_ARGS5((file, line, expected, format, original),
++ TRIO_CONST char *file,
++ int line,
++ TRIO_CONST char *expected,
++ TRIO_CONST char *format,
++ double original)
++{
++ double number;
++ char data[512];
++
++ trio_snprintf(data, sizeof(data), format, original);
++ trio_sscanf(data, format, &number);
++ return Verify(file, line, expected, format, number);
++}
++
++int
++VerifyScanningFloats(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++#if TRIO_FEATURE_FLOAT
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42.000000",
++ "%f", 42.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-42.000000",
++ "%f", -42.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000e+01",
++ "%e", 42.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000E+01",
++ "%E", 42.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42",
++ "%g", 42.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06",
++ "%g", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e-06",
++ "%g", 1.234567e-6);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457E+06",
++ "%G", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06",
++ "%12e", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234500e+00",
++ "%6e", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06",
++ "%.6e", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.2345670000e+06",
++ "%.10e", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06",
++ "%.6g", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1234567",
++ "%.10g", 1234567.0);
++# if TRIO_FEATURE_HEXFLOAT
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x2.ap+4",
++ "%a", 42.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x1.2d687p+20",
++ "%a", 1234567.0);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0X1.2D687P+20",
++ "%A", 1234567.0);
++# endif
++ nerrors += VerifyScanningOneDouble(__FILE__, __LINE__, "1.79769e+308",
++ "%lg", 1.79769e+308);
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "nan",
++ "%f", trio_nan());
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "NAN",
++ "%F", trio_nan());
++ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-inf",
++ "%f", trio_ninf());
++#endif
++
++ return nerrors;
++}
++#endif
++
++/*************************************************************************
++ *
++ */
++#if TRIO_FEATURE_SCANF
++int
++VerifyScanningOneString
++TRIO_ARGS5((file, line, expected, format, original),
++ TRIO_CONST char *file,
++ int line,
++ TRIO_CONST char *expected,
++ TRIO_CONST char *format,
++ char *original)
++{
++ char string[512];
++ char data[512];
++
++ trio_snprintf(data, sizeof(data), "%s", original);
++ string[0] = 0;
++ trio_sscanf(data, format, string);
++ return Verify(file, line, expected, "%s", string);
++}
++
++int
++VerifyScanningStrings(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "",
++ "hello", "hello");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "",
++ "", "");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
++ "%s", "hello");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
++ "%s", "hello world");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello world",
++ "%[^\n]", "hello world");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "(nil)",
++ "%s", NULL);
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
++ "%20s", "hello");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "he",
++ "%2s", "hello");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ab",
++ "%[ab]", "abcba");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba",
++ "%[abc]", "abcba");
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba",
++ "%[a-c]", "abcba");
++#if TRIO_EXTENSION
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba",
++ "%[[:alpha:]]", "abcba");
++#endif
++ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ba",
++ "%*[ab]c%[^\n]", "abcba");
++
++ return nerrors;
++}
++#endif
++
++/*************************************************************************
++ *
++ */
++#if TRIO_FEATURE_SCANF
++int
++VerifyScanningRegression(TRIO_NOARGS)
++{
++ int nerrors = 0;
++ int rc;
++#if TRIO_FEATURE_FLOAT
++ int offset;
++ double dnumber;
++# if defined(TRIO_BREESE)
++ trio_long_double_t ldnumber;
++# endif
++#endif
++ long lnumber;
++ int number;
++ char ch;
++ char buffer[4096];
++ FILE *stream;
++
++#if TRIO_FEATURE_FLOAT
++ rc = trio_sscanf("1.5", "%lf%n", &dnumber, &offset);
++ nerrors += Verify(__FILE__, __LINE__, "1 3 1.500000",
++ "%d %d %f", rc, offset, dnumber);
++#endif
++ rc = trio_sscanf("q 123", "%c%ld", &ch, &lnumber);
++ nerrors += Verify(__FILE__, __LINE__, "q 123",
++ "%c %ld", ch, lnumber);
++ rc = trio_sscanf("abc", "%*s%n", &number);
++ nerrors += Verify(__FILE__, __LINE__, "0 3",
++ "%d %d", rc, number);
++ rc = trio_sscanf("abc def", "%*s%n", &number);
++ nerrors += Verify(__FILE__, __LINE__, "0 3",
++ "%d %d", rc, number);
++#if TRIO_FEATURE_FLOAT
++ rc = trio_sscanf("0.141882295971771490", "%lf", &dnumber);
++ /* FIXME: Verify */
++#endif
++ number = 33;
++ rc = trio_sscanf("total 1", "total %d", &number);
++ nerrors += Verify(__FILE__, __LINE__, "1 1",
++ "%d %d", rc, number);
++#if defined(TRIO_BREESE)
++# if TRIO_FEATURE_FLOAT
++ nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771488",
++ "%d %.18f", rc, dnumber);
++ rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnumber);
++ nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771490",
++ "%d %.18Lf", rc, ldnumber);
++# endif
++#endif
++#if TRIO_FEATURE_FLOAT
++ rc = trio_sscanf("1.e-6", "%lg", &dnumber);
++ nerrors += Verify(__FILE__, __LINE__, "1e-06",
++ "%g", dnumber);
++ rc = trio_sscanf("1e-6", "%lg", &dnumber);
++ nerrors += Verify(__FILE__, __LINE__, "1e-06",
++ "%g", dnumber);
++#endif
++
++ /* Do not overwrite result on matching error */
++ ch = 'a';
++ rc = trio_sscanf("0123456789", "%1[c]", &ch);
++ nerrors += Verify(__FILE__, __LINE__, "a",
++ "%c", ch);
++
++ /* Scan plus prefix for unsigned integer */
++ rc = trio_sscanf("+42", "%u", &number);
++ nerrors += Verify(__FILE__, __LINE__, "1 42",
++ "%d %u", rc, number);
++
++ /* Scan minus prefix even for unsigned integer */
++ rc = trio_sscanf("-42", "%u", &number);
++ sprintf(buffer, "1 %u", -42U);
++ nerrors += Verify(__FILE__, __LINE__, buffer,
++ "%d %u", rc, number);
++
++ /* A scangroup match failure should not bind its argument,
++ * i.e., it shouldn't match the empty string. */
++ sprintf(buffer, "SPQR");
++ rc = trio_sscanf("asdf", "%[c]", buffer);
++ nerrors += Verify(__FILE__, __LINE__, "0 SPQR",
++ "%d %s", rc, buffer);
++
++ /* Even whitespace scanning shouldn't try to read past EOF */
++ stream = tmpfile();
++ trio_fprintf(stream, "");
++ rewind(stream);
++ rc = trio_fscanf(stream, " ");
++ nerrors += Verify(__FILE__, __LINE__, "0",
++ "%d", rc);
++ fclose(stream);
++
++ /* Idem, after a succesfull read */
++ stream = tmpfile();
++ trio_fprintf(stream, "123");
++ rewind(stream);
++ rc = trio_fscanf(stream, "%i ", &number);
++ nerrors += Verify(__FILE__, __LINE__, "1 123",
++ "%d %i", rc, number);
++ fclose(stream);
++
++ /* The scanner should unget its read-ahead char */
++ stream = tmpfile();
++ trio_fprintf(stream, "123");
++ rewind(stream);
++ trio_fscanf(stream, "%*c");
++ trio_fscanf(stream, "%c", &ch);
++ nerrors += Verify(__FILE__, __LINE__, "2",
++ "%c", ch);
++ fclose(stream);
++
++ return nerrors;
++}
++#endif
++
++/*************************************************************************
++ *
++ */
++int
++VerifyScanning(TRIO_NOARGS)
++{
++ int nerrors = 0;
++#if TRIO_FEATURE_SCANF
++ nerrors += VerifyScanningIntegers();
++ nerrors += VerifyScanningFloats();
++ nerrors += VerifyScanningStrings();
++ nerrors += VerifyScanningRegression();
++#endif
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyStrings(TRIO_NOARGS)
++{
++ int nerrors = 0;
++#if !defined(TRIO_MINIMAL)
++ char buffer[512];
++#if TRIO_FEATURE_FLOAT
++ double dnumber;
++ float fnumber;
++#endif
++ char *end;
++
++ /* Comparison */
++ trio_copy(buffer, "Find me now");
++ if (trio_length(buffer) != sizeof("Find me now") - 1) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_equal(buffer, "Find me now")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_equal_case(buffer, "Find me now")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_equal_case(buffer, "FIND ME NOW")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_equal_max(buffer, sizeof("Find me") - 1, "Find ME")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_contains(buffer, "me")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_contains(buffer, "and me")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_substring(buffer, "me") == NULL) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_substring_max(buffer, 4, "me") != NULL) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_match(buffer, "* me *")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_match_case(buffer, "* ME *")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_index(buffer, 'n') == NULL) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_index(buffer, '_') != NULL) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_index_last(buffer, 'n') == NULL) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++
++ /* Append */
++ trio_copy(buffer, "Find me now");
++ if (!trio_append(buffer, " and again")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_equal(buffer, "Find me now and again")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_append_max(buffer, 0, "should not appear")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (!trio_equal(buffer, "Find me now and again")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++
++ /* To upper/lower */
++ trio_copy(buffer, "Find me now");
++ trio_upper(buffer);
++ if (!trio_equal_case(buffer, "FIND ME NOW")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ trio_lower(buffer);
++ if (!trio_equal_case(buffer, "find me now")) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++
++#if TRIO_FEATURE_FLOAT
++ /* Double conversion */
++ trio_copy(buffer, "3.1415");
++ dnumber = trio_to_double(buffer, NULL);
++ if (!DOUBLE_EQUAL(dnumber, 3.1415)) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ fnumber = trio_to_float(buffer, NULL);
++ if (!FLOAT_EQUAL(fnumber, 3.1415)) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++#endif
++
++ /* Long conversion */
++ trio_copy(buffer, "3.1415");
++ if (trio_to_long(buffer, NULL, 10) != 3L) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ if (trio_to_long(buffer, NULL, 4) != 3L) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++ trio_to_long(buffer, &end, 2);
++ if (end != buffer) {
++ nerrors++;
++ Report0(__FILE__, __LINE__);
++ }
++
++#endif /* !defined(TRIO_MINIMAL) */
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyDynamicStrings(TRIO_NOARGS)
++{
++ int nerrors = 0;
++#if !defined(TRIO_MINIMAL)
++ trio_string_t *string;
++ const char no_terminate[5] = { 'h', 'e', 'l', 'l', 'o' };
++
++ string = trio_xstring_duplicate("Find me now");
++ if (string == NULL) {
++ nerrors++;
++ goto error;
++ }
++ if (!trio_xstring_equal(string, "FIND ME NOW"))
++ nerrors++;
++ if (!trio_xstring_append(string, " and again") ||
++ !trio_xstring_equal(string, "FIND ME NOW AND AGAIN"))
++ nerrors++;
++ if (!trio_xstring_contains(string, "me"))
++ nerrors++;
++ if (trio_xstring_contains(string, "ME"))
++ nerrors++;
++ if (!trio_xstring_match(string, "* me *"))
++ nerrors++;
++ if (trio_xstring_match_case(string, "* ME *"))
++ nerrors++;
++ if (!trio_xstring_append_max(string, no_terminate, 5) ||
++ !trio_xstring_equal(string, "FIND ME NOW AND AGAINhello"))
++ nerrors++;
++
++ error:
++ if (string)
++ trio_string_destroy(string);
++
++#endif /* !defined(TRIO_MINIMAL) */
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++VerifyNaN(TRIO_NOARGS)
++{
++ double ninf_number = trio_ninf();
++ double pinf_number = trio_pinf();
++ double nan_number = trio_nan();
++ int nerrors = 0;
++
++ nerrors += Verify(__FILE__, __LINE__, "-1",
++ "%d", trio_isinf(ninf_number));
++ nerrors += Verify(__FILE__, __LINE__, "0",
++ "%d", trio_isinf(42.0));
++ nerrors += Verify(__FILE__, __LINE__, "1",
++ "%d", trio_isinf(pinf_number));
++ nerrors += Verify(__FILE__, __LINE__, "1",
++ "%d", trio_isnan(nan_number));
++ nerrors += Verify(__FILE__, __LINE__, "0",
++ "%d", trio_isnan(42.0));
++
++ return nerrors;
++}
++
++/*************************************************************************
++ *
++ */
++int
++main(TRIO_NOARGS)
++{
++ int nerrors = 0;
++
++ printf("%s\n", rcsid);
++
++#if TRIO_EXTENSION
++ /* Override system locale settings */
++ trio_locale_set_decimal_point(".");
++ trio_locale_set_thousand_separator(",");
++ trio_locale_set_grouping("\3");
++#endif
++
++ printf("Verifying strings\n");
++ nerrors += VerifyStrings();
++
++ printf("Verifying dynamic strings\n");
++ nerrors += VerifyDynamicStrings();
++
++ printf("Verifying special quantities\n");
++ nerrors += VerifyNaN();
++
++ printf("Verifying formatting\n");
++ nerrors += VerifyFormatting();
++
++ printf("Verifying scanning\n");
++ nerrors += VerifyScanning();
++
++ printf("Verifying return values\n");
++ nerrors += VerifyErrors();
++ nerrors += VerifyReturnValues();
++
++ printf("Verifying allocation\n");
++ nerrors += VerifyAllocate();
++
++ if (nerrors == 0)
++ printf("Regression test succeeded\n");
++ else
++ printf("Regression test failed in %d instance(s)\n", nerrors);
++
++ return nerrors ? 1 : 0;
++}
+diff -up ghostscript-9.07/trio/strio.h.gs_sprintf ghostscript-9.07/trio/strio.h
+--- ghostscript-9.07/trio/strio.h.gs_sprintf 2013-05-09 17:02:39.109447270 +0100
++++ ghostscript-9.07/trio/strio.h 2013-05-09 17:02:39.109447270 +0100
+@@ -0,0 +1,73 @@
++/*************************************************************************
++ *
++ * $Id: strio.h,v 1.11 2001/12/27 17:29:20 breese Exp $
++ *
++ * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************
++ *
++ * This maintains backwards compatibility with the strio functions.
++ *
++ ************************************************************************/
++
++#ifndef TRIO_STRIO_H
++#define TRIO_STRIO_H
++
++#if !(defined(DEBUG) || defined(NDEBUG))
++# define NDEBUG
++#endif
++#include "triostr.h"
++
++enum {
++ STRIO_HASH_NONE = TRIO_HASH_NONE,
++ STRIO_HASH_PLAIN = TRIO_HASH_PLAIN,
++ STRIO_HASH_TWOSIGNED = TRIO_HASH_TWOSIGNED
++};
++
++#define StrAlloc(n) trio_create(n)
++#define StrAppend(x,y) ((void)trio_append((x),(y)),(x))
++#define StrAppendMax(x,n,y) ((void)trio_append_max((x),(n),(y)),(x))
++#define StrContains(x,y) trio_contains((x),(y))
++#define StrCopy(x,y) ((void)trio_copy((x),(y)),(x))
++#define StrCopyMax(x,n,y) ((void)trio_copy_max((x),(n),(y)),(x))
++#define StrDuplicate(x) trio_duplicate(x)
++#define StrDuplicateMax(x,n) trio_duplicate((x),(n))
++#define StrEqual(x,y) trio_equal((x),(y))
++#define StrEqualCase(x,y) trio_equal_case((x),(y))
++#define StrEqualCaseMax(x,n,y) trio_equal_case_max((x),(n),(y))
++#define StrEqualLocale(x,y) trio_equal_locale((x),(y))
++#define StrEqualMax(x,n,y) trio_equal_max((x),(n),(y))
++#define StrError(n) trio_error(n)
++#define StrFree(x) trio_destroy(x)
++#define StrFormat trio_sprintf
++#define StrFormatAlloc trio_aprintf
++#define StrFormatAppendMax trio_snprintfcat
++#define StrFormatDateMax(x,n,y,t) trio_format_date_max((x),(n),(y),(t))
++#define StrFormatMax trio_snprintf
++#define StrHash(x,n) trio_hash((x),(n))
++#define StrIndex(x,y) trio_index((x),(y))
++#define StrIndexLast(x,y) trio_index_last((x),(y))
++#define StrLength(x) trio_length((x))
++#define StrMatch(x,y) trio_match((x),(y))
++#define StrMatchCase(x,y) trio_match_case((x),(y))
++#define StrScan trio_sscanf
++#define StrSpanFunction(x,f) trio_span_function((x),(f))
++#define StrSubstring(x,y) trio_substring((x),(y))
++#define StrSubstringMax(x,n,y) trio_substring_max((x),(n),(y))
++#define StrToDouble(x,y) trio_to_double((x),(y))
++#define StrToFloat(x,y) trio_to_float((x),(y))
++#define StrTokenize(x,y) trio_tokenize((x),(y))
++#define StrToLong(x,y,n) trio_to_long((x),(y),(n))
++#define StrToUnsignedLong(x,y,n) trio_to_unsigned_long((x),(n),(y))
++#define StrToUpper(x) trio_upper(x)
++
++#endif /* TRIO_STRIO_H */
+diff -up ghostscript-9.07/trio/trio.c.gs_sprintf ghostscript-9.07/trio/trio.c
+--- ghostscript-9.07/trio/trio.c.gs_sprintf 2013-05-09 17:02:39.111447279 +0100
++++ ghostscript-9.07/trio/trio.c 2013-05-09 17:02:39.111447279 +0100
+@@ -0,0 +1,7771 @@
++/*************************************************************************
++ *
++ * $Id: trio.c,v 1.129 2009/09/20 11:37:15 breese Exp $
++ *
++ * Copyright (C) 1998, 2009 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ *************************************************************************
++ *
++ * A note to trio contributors:
++ *
++ * Avoid heap allocation at all costs to ensure that the trio functions
++ * are async-safe. The exceptions are the printf/fprintf functions, which
++ * uses fputc, and the asprintf functions and the <alloc> modifier, which
++ * by design are required to allocate form the heap.
++ *
++ ************************************************************************/
++
++/*
++ * TODO:
++ * - Scan is probably too permissive about its modifiers.
++ * - C escapes in %#[] ?
++ * - Multibyte characters (done for format parsing, except scan groups)
++ * - Complex numbers? (C99 _Complex)
++ * - Boolean values? (C99 _Bool)
++ * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used
++ * to print the mantissa, e.g. NaN(0xc000000000000000)
++ * - Should we support the GNU %a alloc modifier? GNU has an ugly hack
++ * for %a, because C99 used %a for other purposes. If specified as
++ * %as or %a[ it is interpreted as the alloc modifier, otherwise as
++ * the C99 hex-float. This means that you cannot scan %as as a hex-float
++ * immediately followed by an 's'.
++ * - Scanning of collating symbols.
++ */
++
++/*************************************************************************
++ * Trio include files
++ */
++#include "triodef.h"
++#include "trio.h"
++#include "triop.h"
++
++#if defined(TRIO_EMBED_NAN)
++# define TRIO_PUBLIC_NAN static
++# if TRIO_FEATURE_FLOAT
++# define TRIO_FUNC_NAN
++# define TRIO_FUNC_NINF
++# define TRIO_FUNC_PINF
++# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
++# define TRIO_FUNC_ISINF
++# endif
++#endif
++#include "trionan.h"
++
++#if defined(TRIO_EMBED_STRING)
++# define TRIO_PUBLIC_STRING static
++# define TRIO_FUNC_LENGTH
++# define TRIO_FUNC_LENGTH_MAX
++# define TRIO_FUNC_TO_LONG
++# if TRIO_FEATURE_LOCALE
++# define TRIO_FUNC_COPY_MAX
++# endif
++# if TRIO_FEATURE_DYNAMICSTRING
++# define TRIO_FUNC_XSTRING_DUPLICATE
++# endif
++# if TRIO_EXTENSION && TRIO_FEATURE_SCANF
++# define TRIO_FUNC_EQUAL_LOCALE
++# endif
++# if TRIO_FEATURE_ERRNO
++# define TRIO_FUNC_ERROR
++# endif
++# if TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF
++# define TRIO_FUNC_TO_DOUBLE
++# endif
++# if TRIO_FEATURE_DYNAMICSTRING
++# define TRIO_FUNC_STRING_EXTRACT
++# endif
++# if TRIO_FEATURE_DYNAMICSTRING
++# define TRIO_FUNC_STRING_TERMINATE
++# endif
++# if TRIO_FEATURE_USER_DEFINED
++# define TRIO_FUNC_DUPLICATE
++# endif
++# if TRIO_FEATURE_DYNAMICSTRING
++# define TRIO_FUNC_STRING_DESTROY
++# endif
++# if TRIO_FEATURE_USER_DEFINED
++# define TRIO_FUNC_DESTROY
++# endif
++# if TRIO_FEATURE_USER_DEFINED || (TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF)
++# define TRIO_FUNC_EQUAL
++# endif
++# if TRIO_FEATURE_USER_DEFINED || TRIO_FEATURE_SCANF
++# define TRIO_FUNC_EQUAL_CASE
++# endif
++# if (TRIO_EXTENSION && TRIO_FEATURE_SCANF)
++# define TRIO_FUNC_EQUAL_MAX
++# endif
++# if TRIO_FEATURE_SCANF
++# define TRIO_FUNC_TO_UPPER
++# endif
++# if TRIO_FEATURE_DYNAMICSTRING
++# define TRIO_FUNC_XSTRING_APPEND_CHAR
++# endif
++#endif
++#include "triostr.h"
++
++/**************************************************************************
++ *
++ * Definitions
++ *
++ *************************************************************************/
++
++#include <limits.h>
++#if TRIO_FEATURE_FLOAT
++# include <math.h>
++# include <float.h>
++#endif
++
++#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_FEATURE_WIDECHAR
++# if !defined(TRIO_PLATFORM_WINCE)
++# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
++# if !defined(MB_LEN_MAX)
++# define MB_LEN_MAX 6
++# endif
++# endif
++#endif
++
++#if (defined(TRIO_COMPILER_VISUALC) && (TRIO_COMPILER_VISUALC - 0 >= 1100)) || defined(TRIO_COMPILER_BORLAND)
++# define TRIO_COMPILER_SUPPORTS_VISUALC_INT
++#endif
++
++#if TRIO_FEATURE_FLOAT
++# if defined(PREDEF_STANDARD_C99) \
++ || defined(PREDEF_STANDARD_UNIX03)
++# if !defined(HAVE_FLOORL) && !defined(TRIO_NO_FLOORL)
++# define HAVE_FLOORL
++# endif
++# if !defined(HAVE_CEILL) && !defined(TRIO_NO_CEILL)
++# define HAVE_CEILL
++# endif
++# if !defined(HAVE_POWL) && !defined(TRIO_NO_POWL)
++# define HAVE_POWL
++# endif
++# if !defined(HAVE_FMODL) && !defined(TRIO_NO_FMODL)
++# define HAVE_FMODL
++# endif
++# if !defined(HAVE_LOG10L) && !defined(TRIO_NO_LOG10L)
++# define HAVE_LOG10L
++# endif
++# endif
++# if defined(TRIO_COMPILER_VISUALC)
++# if defined(floorl)
++# define HAVE_FLOORL
++# endif
++# if defined(ceill)
++# define HAVE_CEILL
++# endif
++# if defined(powl)
++# define HAVE_POWL
++# endif
++# if defined(fmodl)
++# define HAVE_FMODL
++# endif
++# if defined(log10l)
++# define HAVE_LOG10L
++# endif
++# endif
++#endif
++
++/*************************************************************************
++ * Generic definitions
++ */
++
++#if !(defined(DEBUG) || defined(NDEBUG))
++# define NDEBUG
++#endif
++
++#include <assert.h>
++#include <ctype.h>
++#if defined(PREDEF_STANDARD_C99) && !defined(isascii)
++# define isascii(x) ((x) & 0x7F)
++#endif
++#if defined(TRIO_COMPILER_ANCIENT)
++# include <varargs.h>
++#else
++# include <stdarg.h>
++#endif
++#include <stddef.h>
++#if defined(TRIO_PLATFORM_WINCE)
++extern int errno;
++#else
++# include <errno.h>
++#endif
++
++#ifndef NULL
++# define NULL 0
++#endif
++#define NIL ((char)0)
++#ifndef FALSE
++# define FALSE (1 == 0)
++# define TRUE (! FALSE)
++#endif
++#define BOOLEAN_T int
++
++/* mincore() can be used for debugging purposes */
++#define VALID(x) (NULL != (x))
++
++#if TRIO_FEATURE_ERRORCODE
++ /*
++ * Encode the error code and the position. This is decoded
++ * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
++ */
++# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
++#else
++# define TRIO_ERROR_RETURN(x,y) (-1)
++#endif
++
++typedef unsigned long trio_flags_t;
++
++
++/*************************************************************************
++ * Platform specific definitions
++ */
++#if defined(TRIO_PLATFORM_UNIX)
++# include <unistd.h>
++# include <signal.h>
++# include <locale.h>
++# if !defined(TRIO_FEATURE_LOCALE)
++# define USE_LOCALE
++# endif
++#endif /* TRIO_PLATFORM_UNIX */
++#if defined(TRIO_PLATFORM_VMS)
++# include <unistd.h>
++#endif
++#if defined(TRIO_PLATFORM_WIN32)
++# if defined(TRIO_PLATFORM_WINCE)
++int read(int handle, char *buffer, unsigned int length);
++int write(int handle, const char *buffer, unsigned int length);
++# else
++# include <io.h>
++# define read _read
++# define write _write
++# endif
++#endif /* TRIO_PLATFORM_WIN32 */
++
++#if TRIO_FEATURE_WIDECHAR
++# if defined(PREDEF_STANDARD_C94)
++# include <wchar.h>
++# include <wctype.h>
++typedef wchar_t trio_wchar_t;
++typedef wint_t trio_wint_t;
++# else
++typedef char trio_wchar_t;
++typedef int trio_wint_t;
++# define WCONST(x) L ## x
++# define WEOF EOF
++# define iswalnum(x) isalnum(x)
++# define iswalpha(x) isalpha(x)
++# define iswcntrl(x) iscntrl(x)
++# define iswdigit(x) isdigit(x)
++# define iswgraph(x) isgraph(x)
++# define iswlower(x) islower(x)
++# define iswprint(x) isprint(x)
++# define iswpunct(x) ispunct(x)
++# define iswspace(x) isspace(x)
++# define iswupper(x) isupper(x)
++# define iswxdigit(x) isxdigit(x)
++# endif
++#endif
++
++
++/*************************************************************************
++ * Compiler dependent definitions
++ */
++
++/* Support for long long */
++#ifndef __cplusplus
++# if !defined(USE_LONGLONG)
++# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
++# define USE_LONGLONG
++# else
++# if defined(TRIO_COMPILER_SUNPRO)
++# define USE_LONGLONG
++# else
++# if defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1400)
++# define USE_LONGLONG
++# else
++# if defined(_LONG_LONG) || defined(_LONGLONG)
++# define USE_LONGLONG
++# endif
++# endif
++# endif
++# endif
++# endif
++#endif
++
++/* The extra long numbers */
++#if defined(USE_LONGLONG)
++typedef signed long long int trio_longlong_t;
++typedef unsigned long long int trio_ulonglong_t;
++#else
++# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
++typedef signed __int64 trio_longlong_t;
++typedef unsigned __int64 trio_ulonglong_t;
++# else
++typedef TRIO_SIGNED long int trio_longlong_t;
++typedef unsigned long int trio_ulonglong_t;
++# endif
++#endif
++
++/* Maximal and fixed integer types */
++#if defined(PREDEF_STANDARD_C99)
++# include <stdint.h>
++typedef intmax_t trio_intmax_t;
++typedef uintmax_t trio_uintmax_t;
++typedef int8_t trio_int8_t;
++typedef int16_t trio_int16_t;
++typedef int32_t trio_int32_t;
++typedef int64_t trio_int64_t;
++#else
++# if defined(PREDEF_STANDARD_UNIX98)
++# include <inttypes.h>
++typedef intmax_t trio_intmax_t;
++typedef uintmax_t trio_uintmax_t;
++typedef int8_t trio_int8_t;
++typedef int16_t trio_int16_t;
++typedef int32_t trio_int32_t;
++typedef int64_t trio_int64_t;
++# else
++# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
++typedef trio_longlong_t trio_intmax_t;
++typedef trio_ulonglong_t trio_uintmax_t;
++typedef __int8 trio_int8_t;
++typedef __int16 trio_int16_t;
++typedef __int32 trio_int32_t;
++typedef __int64 trio_int64_t;
++# else
++typedef trio_longlong_t trio_intmax_t;
++typedef trio_ulonglong_t trio_uintmax_t;
++# if defined(TRIO_INT8_T)
++typedef TRIO_INT8_T trio_int8_t;
++# else
++typedef TRIO_SIGNED char trio_int8_t;
++# endif
++# if defined(TRIO_INT16_T)
++typedef TRIO_INT16_T trio_int16_t;
++# else
++typedef TRIO_SIGNED short trio_int16_t;
++# endif
++# if defined(TRIO_INT32_T)
++typedef TRIO_INT32_T trio_int32_t;
++# else
++typedef TRIO_SIGNED int trio_int32_t;
++# endif
++# if defined(TRIO_INT64_T)
++typedef TRIO_INT64_T trio_int64_t;
++# else
++typedef trio_longlong_t trio_int64_t;
++# endif
++# endif
++# endif
++#endif
++
++#if defined(HAVE_FLOORL)
++# define trio_floor(x) floorl((x))
++#else
++# define trio_floor(x) floor((double)(x))
++#endif
++
++#if defined(HAVE_CEILL)
++# define trio_ceil(x) ceill((x))
++#else
++# define trio_ceil(x) ceil((double)(x))
++#endif
++
++#if defined(HAVE_FMODL)
++# define trio_fmod(x,y) fmodl((x),(y))
++#else
++# define trio_fmod(x,y) fmod((double)(x),(double)(y))
++#endif
++
++#if defined(HAVE_POWL)
++# define trio_pow(x,y) powl((x),(y))
++#else
++# define trio_pow(x,y) pow((double)(x),(double)(y))
++#endif
++
++#if defined(HAVE_LOG10L)
++# define trio_log10(x) log10l((x))
++#else
++# define trio_log10(x) log10((double)(x))
++#endif
++
++#if TRIO_FEATURE_FLOAT
++# define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
++#endif
++
++/*************************************************************************
++ * Internal Definitions
++ */
++
++#if TRIO_FEATURE_FLOAT
++
++# if !defined(DECIMAL_DIG)
++# define DECIMAL_DIG DBL_DIG
++# endif
++
++/* Long double sizes */
++# ifdef LDBL_DIG
++# define MAX_MANTISSA_DIGITS LDBL_DIG
++# define MAX_EXPONENT_DIGITS 4
++# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
++# else
++# define MAX_MANTISSA_DIGITS DECIMAL_DIG
++# define MAX_EXPONENT_DIGITS 3
++# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
++# endif
++
++# if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
++# undef LDBL_DIG
++# undef LDBL_MANT_DIG
++# undef LDBL_EPSILON
++# define LDBL_DIG DBL_DIG
++# define LDBL_MANT_DIG DBL_MANT_DIG
++# define LDBL_EPSILON DBL_EPSILON
++# endif
++
++#endif /* TRIO_FEATURE_FLOAT */
++
++/* The maximal number of digits is for base 2 */
++#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
++/* The width of a pointer. The number of bits in a hex digit is 4 */
++#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
++
++#if TRIO_FEATURE_FLOAT
++/* Infinite and Not-A-Number for floating-point */
++# define INFINITE_LOWER "inf"
++# define INFINITE_UPPER "INF"
++# define LONG_INFINITE_LOWER "infinite"
++# define LONG_INFINITE_UPPER "INFINITE"
++# define NAN_LOWER "nan"
++# define NAN_UPPER "NAN"
++#endif
++
++/* Various constants */
++enum {
++ TYPE_PRINT = 1,
++#if TRIO_FEATURE_SCANF
++ TYPE_SCAN = 2,
++#endif
++
++ /* Flags. FLAGS_LAST must be less than ULONG_MAX */
++ FLAGS_NEW = 0,
++ FLAGS_STICKY = 1,
++ FLAGS_SPACE = 2 * FLAGS_STICKY,
++ FLAGS_SHOWSIGN = 2 * FLAGS_SPACE,
++ FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN,
++ FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST,
++ FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE,
++ FLAGS_SHORTSHORT = 2 * FLAGS_SHORT,
++ FLAGS_LONG = 2 * FLAGS_SHORTSHORT,
++ FLAGS_QUAD = 2 * FLAGS_LONG,
++ FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD,
++ FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE,
++ FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T,
++ FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T,
++ FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T,
++ FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING,
++ FLAGS_UPPER = 2 * FLAGS_UNSIGNED,
++ FLAGS_WIDTH = 2 * FLAGS_UPPER,
++ FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH,
++ FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER,
++ FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION,
++ FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER,
++ FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE,
++ FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER,
++ FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E,
++ FLAGS_QUOTE = 2 * FLAGS_FLOAT_G,
++ FLAGS_WIDECHAR = 2 * FLAGS_QUOTE,
++ FLAGS_IGNORE = 2 * FLAGS_WIDECHAR,
++ FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE,
++ FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
++ FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER,
++ FLAGS_LAST = FLAGS_FIXED_SIZE,
++ /* Reused flags */
++ FLAGS_EXCLUDE = FLAGS_SHORT,
++ FLAGS_USER_DEFINED = FLAGS_IGNORE,
++ FLAGS_USER_DEFINED_PARAMETER = FLAGS_IGNORE_PARAMETER,
++ FLAGS_ROUNDING = FLAGS_INTMAX_T,
++ /* Compounded flags */
++ FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
++ FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT,
++
++ NO_POSITION = -1,
++ NO_WIDTH = 0,
++ NO_PRECISION = -1,
++ NO_SIZE = -1,
++
++ /* Do not change these */
++ NO_BASE = -1,
++ MIN_BASE = 2,
++ MAX_BASE = 36,
++ BASE_BINARY = 2,
++ BASE_OCTAL = 8,
++ BASE_DECIMAL = 10,
++ BASE_HEX = 16,
++
++ /* Maximal number of allowed parameters */
++ MAX_PARAMETERS = 64,
++ /* Maximal number of characters in class */
++ MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
++
++#if TRIO_FEATURE_USER_DEFINED
++ /* Maximal string lengths for user-defined specifiers */
++ MAX_USER_NAME = 64,
++ MAX_USER_DATA = 256,
++#endif
++
++ /* Maximal length of locale separator strings */
++ MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
++ /* Maximal number of integers in grouping */
++ MAX_LOCALE_GROUPS = 64
++};
++
++#define NO_GROUPING ((int)CHAR_MAX)
++
++/* Fundamental formatting parameter types */
++#define FORMAT_SENTINEL -1 /* marks end of parameters array */
++#define FORMAT_UNKNOWN 0
++#define FORMAT_INT 1
++#define FORMAT_DOUBLE 2
++#define FORMAT_CHAR 3
++#define FORMAT_STRING 4
++#define FORMAT_POINTER 5
++#define FORMAT_COUNT 6
++#define FORMAT_PARAMETER 7
++#define FORMAT_GROUP 8
++#define FORMAT_ERRNO 9
++#define FORMAT_USER_DEFINED 10
++
++/* Character constants */
++#define CHAR_IDENTIFIER '%'
++#define CHAR_ALT_IDENTIFIER '$'
++#define CHAR_BACKSLASH '\\'
++#define CHAR_QUOTE '\"'
++#define CHAR_ADJUST ' '
++
++#if TRIO_EXTENSION
++/* Character class expressions */
++# define CLASS_ALNUM "[:alnum:]"
++# define CLASS_ALPHA "[:alpha:]"
++# define CLASS_BLANK "[:blank:]"
++# define CLASS_CNTRL "[:cntrl:]"
++# define CLASS_DIGIT "[:digit:]"
++# define CLASS_GRAPH "[:graph:]"
++# define CLASS_LOWER "[:lower:]"
++# define CLASS_PRINT "[:print:]"
++# define CLASS_PUNCT "[:punct:]"
++# define CLASS_SPACE "[:space:]"
++# define CLASS_UPPER "[:upper:]"
++# define CLASS_XDIGIT "[:xdigit:]"
++#endif
++
++/*
++ * SPECIFIERS:
++ *
++ *
++ * a Hex-float
++ * A Hex-float
++ * c Character
++ * C Widechar character (wint_t)
++ * d Decimal
++ * e Float
++ * E Float
++ * F Float
++ * F Float
++ * g Float
++ * G Float
++ * i Integer
++ * m Error message
++ * n Count
++ * o Octal
++ * p Pointer
++ * s String
++ * S Widechar string (wchar_t *)
++ * u Unsigned
++ * x Hex
++ * X Hex
++ * [] Group
++ * <> User-defined
++ *
++ * Reserved:
++ *
++ * D Binary Coded Decimal %D(length,precision) (OS/390)
++ */
++#define SPECIFIER_CHAR 'c'
++#define SPECIFIER_STRING 's'
++#define SPECIFIER_DECIMAL 'd'
++#define SPECIFIER_INTEGER 'i'
++#define SPECIFIER_UNSIGNED 'u'
++#define SPECIFIER_OCTAL 'o'
++#define SPECIFIER_HEX 'x'
++#define SPECIFIER_HEX_UPPER 'X'
++#if TRIO_FEATURE_FLOAT
++# define SPECIFIER_FLOAT_E 'e'
++# define SPECIFIER_FLOAT_E_UPPER 'E'
++# define SPECIFIER_FLOAT_F 'f'
++# define SPECIFIER_FLOAT_F_UPPER 'F'
++# define SPECIFIER_FLOAT_G 'g'
++# define SPECIFIER_FLOAT_G_UPPER 'G'
++#endif
++#define SPECIFIER_POINTER 'p'
++#if TRIO_FEATURE_SCANF
++# define SPECIFIER_GROUP '['
++# define SPECIFIER_UNGROUP ']'
++#endif
++#define SPECIFIER_COUNT 'n'
++#if TRIO_UNIX98
++# define SPECIFIER_CHAR_UPPER 'C'
++# define SPECIFIER_STRING_UPPER 'S'
++#endif
++#define SPECIFIER_HEXFLOAT 'a'
++#define SPECIFIER_HEXFLOAT_UPPER 'A'
++#define SPECIFIER_ERRNO 'm'
++#if TRIO_FEATURE_BINARY
++# define SPECIFIER_BINARY 'b'
++# define SPECIFIER_BINARY_UPPER 'B'
++#endif
++#if TRIO_FEATURE_USER_DEFINED
++# define SPECIFIER_USER_DEFINED_BEGIN '<'
++# define SPECIFIER_USER_DEFINED_END '>'
++# define SPECIFIER_USER_DEFINED_SEPARATOR ':'
++# define SPECIFIER_USER_DEFINED_EXTRA '|'
++#endif
++
++/*
++ * QUALIFIERS:
++ *
++ *
++ * Numbers = d,i,o,u,x,X
++ * Float = a,A,e,E,f,F,g,G
++ * String = s
++ * Char = c
++ *
++ *
++ * 9$ Position
++ * Use the 9th parameter. 9 can be any number between 1 and
++ * the maximal argument
++ *
++ * 9 Width
++ * Set width to 9. 9 can be any number, but must not be postfixed
++ * by '$'
++ *
++ * h Short
++ * Numbers:
++ * (unsigned) short int
++ *
++ * hh Short short
++ * Numbers:
++ * (unsigned) char
++ *
++ * l Long
++ * Numbers:
++ * (unsigned) long int
++ * String:
++ * as the S specifier
++ * Char:
++ * as the C specifier
++ *
++ * ll Long Long
++ * Numbers:
++ * (unsigned) long long int
++ *
++ * L Long Double
++ * Float
++ * long double
++ *
++ * # Alternative
++ * Float:
++ * Decimal-point is always present
++ * String:
++ * non-printable characters are handled as \number
++ *
++ * Spacing
++ *
++ * + Sign
++ *
++ * - Alignment
++ *
++ * . Precision
++ *
++ * * Parameter
++ * print: use parameter
++ * scan: no parameter (ignore)
++ *
++ * q Quad
++ *
++ * Z size_t
++ *
++ * w Widechar
++ *
++ * ' Thousands/quote
++ * Numbers:
++ * Integer part grouped in thousands
++ * Binary numbers:
++ * Number grouped in nibbles (4 bits)
++ * String:
++ * Quoted string
++ *
++ * j intmax_t
++ * t prtdiff_t
++ * z size_t
++ *
++ * ! Sticky
++ * @ Parameter (for both print and scan)
++ *
++ * I n-bit Integer
++ * Numbers:
++ * The following options exists
++ * I8 = 8-bit integer
++ * I16 = 16-bit integer
++ * I32 = 32-bit integer
++ * I64 = 64-bit integer
++ */
++#define QUALIFIER_POSITION '$'
++#define QUALIFIER_SHORT 'h'
++#define QUALIFIER_LONG 'l'
++#define QUALIFIER_LONG_UPPER 'L'
++#define QUALIFIER_ALTERNATIVE '#'
++#define QUALIFIER_SPACE ' '
++#define QUALIFIER_PLUS '+'
++#define QUALIFIER_MINUS '-'
++#define QUALIFIER_DOT '.'
++#define QUALIFIER_STAR '*'
++#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
++#define QUALIFIER_SIZE_T 'z'
++#define QUALIFIER_PTRDIFF_T 't'
++#define QUALIFIER_INTMAX_T 'j'
++#define QUALIFIER_QUAD 'q'
++#define QUALIFIER_SIZE_T_UPPER 'Z'
++#if TRIO_MISC
++# define QUALIFIER_WIDECHAR 'w'
++#endif
++#define QUALIFIER_FIXED_SIZE 'I'
++#define QUALIFIER_QUOTE '\''
++#define QUALIFIER_STICKY '!'
++#define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
++#define QUALIFIER_ROUNDING_UPPER 'R'
++#if TRIO_EXTENSION
++# define QUALIFIER_PARAM '@' /* Experimental */
++# define QUALIFIER_COLON ':' /* For scanlists */
++# define QUALIFIER_EQUAL '=' /* For scanlists */
++#endif
++
++
++/*************************************************************************
++ *
++ * Internal Structures
++ *
++ *************************************************************************/
++
++/* Parameters */
++typedef struct {
++ /* An indication of which entry in the data union is used */
++ int type;
++ /* The flags */
++ trio_flags_t flags;
++ /* The width qualifier */
++ int width;
++ /* The precision qualifier */
++ int precision;
++ /* The base qualifier */
++ int base;
++ /* Base from specifier */
++ int baseSpecifier;
++ /* The size for the variable size qualifier */
++ int varsize;
++ /* Offset of the first character of the specifier */
++ int beginOffset;
++ /* Offset of the first character after the specifier */
++ int endOffset;
++ /* Position in the argument list that this parameter refers to */
++ int position;
++ /* The data from the argument list */
++ union {
++ char *string;
++#if TRIO_FEATURE_WIDECHAR
++ trio_wchar_t *wstring;
++#endif
++ trio_pointer_t pointer;
++ union {
++ trio_intmax_t as_signed;
++ trio_uintmax_t as_unsigned;
++ } number;
++#if TRIO_FEATURE_FLOAT
++ double doubleNumber;
++ double *doublePointer;
++ trio_long_double_t longdoubleNumber;
++ trio_long_double_t *longdoublePointer;
++#endif
++ int errorNumber;
++ } data;
++#if TRIO_FEATURE_USER_DEFINED
++ /* For the user-defined specifier */
++ union {
++ char namespace[MAX_USER_NAME];
++ int handler; /* if flags & FLAGS_USER_DEFINED_PARAMETER */
++ } user_defined;
++ char user_data[MAX_USER_DATA];
++#endif
++} trio_parameter_t;
++
++/* Container for customized functions */
++typedef struct {
++ union {
++ trio_outstream_t out;
++ trio_instream_t in;
++ } stream;
++ trio_pointer_t closure;
++} trio_custom_t;
++
++/* General trio "class" */
++typedef struct _trio_class_t {
++ /*
++ * The function to write characters to a stream.
++ */
++ void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int));
++ /*
++ * The function to read characters from a stream.
++ */
++ void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
++ /*
++ * The function to undo read characters from a stream.
++ */
++ void (*UndoStream) TRIO_PROTO((struct _trio_class_t *));
++ /*
++ * The current location in the stream.
++ */
++ trio_pointer_t location;
++ /*
++ * The character currently being processed.
++ */
++ int current;
++ /*
++ * The number of characters that would have been written/read
++ * if there had been sufficient space.
++ */
++ int processed;
++ union {
++ /*
++ * The number of characters that are actually written. Processed and
++ * committed will only differ for the *nprintf functions.
++ */
++ int committed;
++ /*
++ * The number of look-ahead characters read.
++ */
++ int cached;
++ } actually;
++ /*
++ * The upper limit of characters that may be written/read.
++ */
++ int max;
++ /*
++ * The last output error that was detected.
++ */
++ int error;
++} trio_class_t;
++
++/* References (for user-defined callbacks) */
++typedef struct _trio_reference_t {
++ trio_class_t *data;
++ trio_parameter_t *parameter;
++} trio_reference_t;
++
++#if TRIO_FEATURE_USER_DEFINED
++/* Registered entries (for user-defined callbacks) */
++typedef struct _trio_userdef_t {
++ struct _trio_userdef_t *next;
++ trio_callback_t callback;
++ char *name;
++} trio_userdef_t;
++#endif
++
++/*************************************************************************
++ *
++ * Internal Variables
++ *
++ *************************************************************************/
++
++static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.129 2009/09/20 11:37:15 breese Exp $";
++
++#if TRIO_FEATURE_FLOAT
++/*
++ * Need this to workaround a parser bug in HP C/iX compiler that fails
++ * to resolves macro definitions that includes type 'long double',
++ * e.g: va_arg(arg_ptr, long double)
++ */
++# if defined(TRIO_PLATFORM_MPEIX)
++static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
++# endif
++#endif
++
++static TRIO_CONST char internalNullString[] = "(nil)";
++
++#if defined(USE_LOCALE)
++static struct lconv *internalLocaleValues = NULL;
++#endif
++
++/*
++ * UNIX98 says "in a locale where the radix character is not defined,
++ * the radix character defaults to a period (.)"
++ */
++#if TRIO_FEATURE_FLOAT || TRIO_FEATURE_LOCALE || defined(USE_LOCALE)
++static int internalDecimalPointLength = 1;
++static char internalDecimalPoint = '.';
++static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
++#endif
++#if TRIO_FEATURE_QUOTE || TRIO_FEATURE_LOCALE || TRIO_EXTENSION
++static int internalThousandSeparatorLength = 1;
++static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
++static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
++#endif
++
++static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
++static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
++#if TRIO_FEATURE_SCANF
++static BOOLEAN_T internalDigitsUnconverted = TRUE;
++static int internalDigitArray[128];
++# if TRIO_EXTENSION
++static BOOLEAN_T internalCollationUnconverted = TRUE;
++static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
++# endif
++#endif
++
++#if TRIO_FEATURE_USER_DEFINED
++static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
++static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
++static trio_userdef_t *internalUserDef = NULL;
++#endif
++
++
++/*************************************************************************
++ *
++ * Internal Functions
++ *
++ ************************************************************************/
++
++#if defined(TRIO_EMBED_NAN)
++# include "trionan.c"
++#endif
++
++#if defined(TRIO_EMBED_STRING)
++# include "triostr.c"
++#endif
++
++/*************************************************************************
++ * TrioInitializeParameter
++ *
++ * Description:
++ * Initialize a trio_parameter_t struct.
++ */
++TRIO_PRIVATE void
++TrioInitializeParameter
++TRIO_ARGS1((parameter),
++ trio_parameter_t *parameter)
++{
++ parameter->type = FORMAT_UNKNOWN;
++ parameter->flags = 0;
++ parameter->width = 0;
++ parameter->precision = 0;
++ parameter->base = 0;
++ parameter->baseSpecifier = 0;
++ parameter->varsize = 0;
++ parameter->beginOffset = 0;
++ parameter->endOffset = 0;
++ parameter->position = 0;
++ parameter->data.pointer = 0;
++#if TRIO_FEATURE_USER_DEFINED
++ parameter->user_defined.handler = 0;
++ parameter->user_data[0] = 0;
++#endif
++}
++
++/*************************************************************************
++ * TrioCopyParameter
++ *
++ * Description:
++ * Copies one trio_parameter_t struct to another.
++ */
++TRIO_PRIVATE void
++TrioCopyParameter
++TRIO_ARGS2((target, source),
++ trio_parameter_t *target,
++ TRIO_CONST trio_parameter_t *source)
++{
++#if TRIO_FEATURE_USER_DEFINED
++ size_t i;
++#endif
++
++ target->type = source->type;
++ target->flags = source->flags;
++ target->width = source->width;
++ target->precision = source->precision;
++ target->base = source->base;
++ target->baseSpecifier = source->baseSpecifier;
++ target->varsize = source->varsize;
++ target->beginOffset = source->beginOffset;
++ target->endOffset = source->endOffset;
++ target->position = source->position;
++ target->data = source->data;
++
++#if TRIO_FEATURE_USER_DEFINED
++ target->user_defined = source->user_defined;
++
++ for (i = 0U; i < sizeof(target->user_data); ++i)
++ {
++ if ((target->user_data[i] = source->user_data[i]) == NIL)
++ break;
++ }
++#endif
++}
++
++/*************************************************************************
++ * TrioIsQualifier
++ *
++ * Description:
++ * Remember to add all new qualifiers to this function.
++ * QUALIFIER_POSITION must not be added.
++ */
++TRIO_PRIVATE BOOLEAN_T
++TrioIsQualifier
++TRIO_ARGS1((character),
++ TRIO_CONST char character)
++{
++ /* QUALIFIER_POSITION is not included */
++ switch (character)
++ {
++ case '0': case '1': case '2': case '3': case '4':
++ case '5': case '6': case '7': case '8': case '9':
++ case QUALIFIER_PLUS:
++ case QUALIFIER_MINUS:
++ case QUALIFIER_SPACE:
++ case QUALIFIER_DOT:
++ case QUALIFIER_STAR:
++ case QUALIFIER_ALTERNATIVE:
++ case QUALIFIER_SHORT:
++ case QUALIFIER_LONG:
++ case QUALIFIER_CIRCUMFLEX:
++ case QUALIFIER_LONG_UPPER:
++ case QUALIFIER_SIZE_T:
++ case QUALIFIER_PTRDIFF_T:
++ case QUALIFIER_INTMAX_T:
++ case QUALIFIER_QUAD:
++ case QUALIFIER_SIZE_T_UPPER:
++#if defined(QUALIFIER_WIDECHAR)
++ case QUALIFIER_WIDECHAR:
++#endif
++ case QUALIFIER_QUOTE:
++ case QUALIFIER_STICKY:
++ case QUALIFIER_VARSIZE:
++#if defined(QUALIFIER_PARAM)
++ case QUALIFIER_PARAM:
++#endif
++ case QUALIFIER_FIXED_SIZE:
++ case QUALIFIER_ROUNDING_UPPER:
++ return TRUE;
++ default:
++ return FALSE;
++ }
++}
++
++/*************************************************************************
++ * TrioSetLocale
++ */
++#if defined(USE_LOCALE)
++TRIO_PRIVATE void
++TrioSetLocale(TRIO_NOARGS)
++{
++ internalLocaleValues = (struct lconv *)localeconv();
++ if (internalLocaleValues)
++ {
++ if ((internalLocaleValues->decimal_point) &&
++ (internalLocaleValues->decimal_point[0] != NIL))
++ {
++ internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point);
++ if (internalDecimalPointLength == 1)
++ {
++ internalDecimalPoint = internalLocaleValues->decimal_point[0];
++ }
++ else
++ {
++ internalDecimalPoint = NIL;
++ trio_copy_max(internalDecimalPointString,
++ sizeof(internalDecimalPointString),
++ internalLocaleValues->decimal_point);
++ }
++ }
++# if TRIO_EXTENSION
++ if ((internalLocaleValues->thousands_sep) &&
++ (internalLocaleValues->thousands_sep[0] != NIL))
++ {
++ trio_copy_max(internalThousandSeparator,
++ sizeof(internalThousandSeparator),
++ internalLocaleValues->thousands_sep);
++ internalThousandSeparatorLength = trio_length(internalThousandSeparator);
++ }
++# endif
++# if TRIO_EXTENSION
++ if ((internalLocaleValues->grouping) &&
++ (internalLocaleValues->grouping[0] != NIL))
++ {
++ trio_copy_max(internalGrouping,
++ sizeof(internalGrouping),
++ internalLocaleValues->grouping);
++ }
++# endif
++ }
++}
++#endif /* defined(USE_LOCALE) */
++
++#if TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE
++TRIO_PRIVATE int
++TrioCalcThousandSeparatorLength
++TRIO_ARGS1((digits),
++ int digits)
++{
++ int count = 0;
++ int step = NO_GROUPING;
++ char *groupingPointer = internalGrouping;
++
++ while (digits > 0)
++ {
++ if (*groupingPointer == CHAR_MAX)
++ {
++ /* Disable grouping */
++ break; /* while */
++ }
++ else if (*groupingPointer == 0)
++ {
++ /* Repeat last group */
++ if (step == NO_GROUPING)
++ {
++ /* Error in locale */
++ break; /* while */
++ }
++ }
++ else
++ {
++ step = *groupingPointer++;
++ }
++ if (digits > step)
++ count += internalThousandSeparatorLength;
++ digits -= step;
++ }
++ return count;
++}
++#endif /* TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE */
++
++#if TRIO_FEATURE_QUOTE
++TRIO_PRIVATE BOOLEAN_T
++TrioFollowedBySeparator
++TRIO_ARGS1((position),
++ int position)
++{
++ int step = 0;
++ char *groupingPointer = internalGrouping;
++
++ position--;
++ if (position == 0)
++ return FALSE;
++ while (position > 0)
++ {
++ if (*groupingPointer == CHAR_MAX)
++ {
++ /* Disable grouping */
++ break; /* while */
++ }
++ else if (*groupingPointer != 0)
++ {
++ step = *groupingPointer++;
++ }
++ if (step == 0)
++ break;
++ position -= step;
++ }
++ return (position == 0);
++}
++#endif /* TRIO_FEATURE_QUOTE */
++
++/*************************************************************************
++ * TrioGetPosition
++ *
++ * Get the %n$ position.
++ */
++TRIO_PRIVATE int
++TrioGetPosition
++TRIO_ARGS2((format, offsetPointer),
++ TRIO_CONST char *format,
++ int *offsetPointer)
++{
++#if TRIO_FEATURE_POSITIONAL
++ char *tmpformat;
++ int number = 0;
++ int offset = *offsetPointer;
++
++ number = (int)trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL);
++ offset = (int)(tmpformat - format);
++ if ((number != 0) && (QUALIFIER_POSITION == format[offset++]))
++ {
++ *offsetPointer = offset;
++ /*
++ * number is decreased by 1, because n$ starts from 1, whereas
++ * the array it is indexing starts from 0.
++ */
++ return number - 1;
++ }
++#endif
++ return NO_POSITION;
++}
++
++/*************************************************************************
++ * TrioFindNamespace
++ *
++ * Find registered user-defined specifier.
++ * The prev argument is used for optimization only.
++ */
++#if TRIO_FEATURE_USER_DEFINED
++TRIO_PRIVATE trio_userdef_t *
++TrioFindNamespace
++TRIO_ARGS2((name, prev),
++ TRIO_CONST char *name,
++ trio_userdef_t **prev)
++{
++ trio_userdef_t *def;
++
++ if (internalEnterCriticalRegion)
++ (void)internalEnterCriticalRegion(NULL);
++
++ for (def = internalUserDef; def; def = def->next)
++ {
++ /* Case-sensitive string comparison */
++ if (trio_equal_case(def->name, name))
++ break;
++
++ if (prev)
++ *prev = def;
++ }
++
++ if (internalLeaveCriticalRegion)
++ (void)internalLeaveCriticalRegion(NULL);
++
++ return def;
++}
++#endif
++
++/*************************************************************************
++ * TrioPower
++ *
++ * Description:
++ * Calculate pow(base, exponent), where number and exponent are integers.
++ */
++#if TRIO_FEATURE_FLOAT
++TRIO_PRIVATE trio_long_double_t
++TrioPower
++TRIO_ARGS2((number, exponent),
++ int number,
++ int exponent)
++{
++ trio_long_double_t result;
++
++ if (number == 10)
++ {
++ switch (exponent)
++ {
++ /* Speed up calculation of common cases */
++ case 0:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1);
++ break;
++ case 1:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0);
++ break;
++ case 2:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1);
++ break;
++ case 3:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2);
++ break;
++ case 4:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3);
++ break;
++ case 5:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4);
++ break;
++ case 6:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5);
++ break;
++ case 7:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6);
++ break;
++ case 8:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7);
++ break;
++ case 9:
++ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8);
++ break;
++ default:
++ result = trio_pow((trio_long_double_t)number,
++ (trio_long_double_t)exponent);
++ break;
++ }
++ }
++ else
++ {
++ return trio_pow((trio_long_double_t)number,
++ (trio_long_double_t)exponent);
++ }
++ return result;
++}
++#endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * TrioLogarithm
++ */
++#if TRIO_FEATURE_FLOAT
++TRIO_PRIVATE trio_long_double_t
++TrioLogarithm
++TRIO_ARGS2((number, base),
++ trio_long_double_t number,
++ int base)
++{
++ trio_long_double_t result;
++
++ if (number <= 0.0)
++ {
++ /* xlC crashes on log(0) */
++ result = (number == 0.0) ? trio_ninf() : trio_nan();
++ }
++ else
++ {
++ if (base == 10)
++ {
++ result = trio_log10(number);
++ }
++ else
++ {
++ result = trio_log10(number) / trio_log10((double)base);
++ }
++ }
++ return result;
++}
++#endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * TrioLogarithmBase
++ */
++#if TRIO_FEATURE_FLOAT
++TRIO_PRIVATE double
++TrioLogarithmBase
++TRIO_ARGS1((base),
++ int base)
++{
++ switch (base)
++ {
++ case BASE_BINARY : return 1.0;
++ case BASE_OCTAL : return 3.0;
++ case BASE_DECIMAL: return 3.321928094887362345;
++ case BASE_HEX : return 4.0;
++ default : return TrioLogarithm((double)base, 2);
++ }
++}
++#endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * TrioParseQualifiers
++ *
++ * Description:
++ * Parse the qualifiers of a potential conversion specifier
++ */
++TRIO_PRIVATE int
++TrioParseQualifiers
++TRIO_ARGS4((type, format, offset, parameter),
++ int type,
++ TRIO_CONST char *format,
++ int offset,
++ trio_parameter_t *parameter)
++{
++ char ch;
++ int dots = 0; /* Count number of dots in modifier part */
++ char *tmpformat;
++
++ parameter->beginOffset = offset - 1;
++ parameter->flags = FLAGS_NEW;
++ parameter->position = TrioGetPosition(format, &offset);
++
++ /* Default values */
++ parameter->width = NO_WIDTH;
++ parameter->precision = NO_PRECISION;
++ parameter->base = NO_BASE;
++ parameter->varsize = NO_SIZE;
++
++ while (TrioIsQualifier(format[offset]))
++ {
++ ch = format[offset++];
++
++ switch (ch)
++ {
++ case QUALIFIER_SPACE:
++ parameter->flags |= FLAGS_SPACE;
++ break;
++
++ case QUALIFIER_PLUS:
++ parameter->flags |= FLAGS_SHOWSIGN;
++ break;
++
++ case QUALIFIER_MINUS:
++ parameter->flags |= FLAGS_LEFTADJUST;
++ parameter->flags &= ~FLAGS_NILPADDING;
++ break;
++
++ case QUALIFIER_ALTERNATIVE:
++ parameter->flags |= FLAGS_ALTERNATIVE;
++ break;
++
++ case QUALIFIER_DOT:
++ if (dots == 0) /* Precision */
++ {
++ dots++;
++
++ /* Skip if no precision */
++ if (QUALIFIER_DOT == format[offset])
++ break;
++
++ /* After the first dot we have the precision */
++ parameter->flags |= FLAGS_PRECISION;
++ if ((QUALIFIER_STAR == format[offset])
++#if defined(QUALIFIER_PARAM)
++ || (QUALIFIER_PARAM == format[offset])
++#endif
++ )
++ {
++ offset++;
++ parameter->flags |= FLAGS_PRECISION_PARAMETER;
++ parameter->precision = TrioGetPosition(format, &offset);
++ }
++ else
++ {
++ parameter->precision = trio_to_long(&format[offset],
++ &tmpformat,
++ BASE_DECIMAL);
++ offset = (int)(tmpformat - format);
++ }
++ }
++ else if (dots == 1) /* Base */
++ {
++ dots++;
++
++ /* After the second dot we have the base */
++ parameter->flags |= FLAGS_BASE;
++ if ((QUALIFIER_STAR == format[offset])
++#if defined(QUALIFIER_PARAM)
++ || (QUALIFIER_PARAM == format[offset])
++#endif
++ )
++ {
++ offset++;
++ parameter->flags |= FLAGS_BASE_PARAMETER;
++ parameter->base = TrioGetPosition(format, &offset);
++ }
++ else
++ {
++ parameter->base = trio_to_long(&format[offset],
++ &tmpformat,
++ BASE_DECIMAL);
++ if (parameter->base > MAX_BASE)
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ offset = (int)(tmpformat - format);
++ }
++ }
++ else
++ {
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ }
++ break; /* QUALIFIER_DOT */
++
++#if defined(QUALIFIER_PARAM)
++ case QUALIFIER_PARAM:
++ parameter->type = TYPE_PRINT;
++ /* FALLTHROUGH */
++#endif
++ case QUALIFIER_STAR:
++ /* This has different meanings for print and scan */
++ if (TYPE_PRINT == type)
++ {
++ /* Read with from parameter */
++ int width = TrioGetPosition(format, &offset);
++ parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
++ if (NO_POSITION != width)
++ parameter->width = width;
++ /* else keep parameter->width = NO_WIDTH which != NO_POSITION */
++ }
++#if TRIO_FEATURE_SCANF
++ else
++ {
++ /* Scan, but do not store result */
++ parameter->flags |= FLAGS_IGNORE;
++ }
++#endif
++ break; /* QUALIFIER_STAR */
++
++ case '0':
++ if (! (parameter->flags & FLAGS_LEFTADJUST))
++ parameter->flags |= FLAGS_NILPADDING;
++ /* FALLTHROUGH */
++ case '1': case '2': case '3': case '4':
++ case '5': case '6': case '7': case '8': case '9':
++ parameter->flags |= FLAGS_WIDTH;
++ /*
++ * &format[offset - 1] is used to "rewind" the read
++ * character from format
++ */
++ parameter->width = trio_to_long(&format[offset - 1],
++ &tmpformat,
++ BASE_DECIMAL);
++ offset = (int)(tmpformat - format);
++ break;
++
++ case QUALIFIER_SHORT:
++ if (parameter->flags & FLAGS_SHORTSHORT)
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ else if (parameter->flags & FLAGS_SHORT)
++ parameter->flags |= FLAGS_SHORTSHORT;
++ else
++ parameter->flags |= FLAGS_SHORT;
++ break;
++
++ case QUALIFIER_LONG:
++ if (parameter->flags & FLAGS_QUAD)
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ else if (parameter->flags & FLAGS_LONG)
++ parameter->flags |= FLAGS_QUAD;
++ else
++ parameter->flags |= FLAGS_LONG;
++ break;
++
++#if TRIO_FEATURE_LONGDOUBLE
++ case QUALIFIER_LONG_UPPER:
++ parameter->flags |= FLAGS_LONGDOUBLE;
++ break;
++#endif
++
++#if TRIO_FEATURE_SIZE_T
++ case QUALIFIER_SIZE_T:
++ parameter->flags |= FLAGS_SIZE_T;
++ /* Modify flags for later truncation of number */
++ if (sizeof(size_t) == sizeof(trio_ulonglong_t))
++ parameter->flags |= FLAGS_QUAD;
++ else if (sizeof(size_t) == sizeof(long))
++ parameter->flags |= FLAGS_LONG;
++ break;
++#endif
++
++#if TRIO_FEATURE_PTRDIFF_T
++ case QUALIFIER_PTRDIFF_T:
++ parameter->flags |= FLAGS_PTRDIFF_T;
++ if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
++ parameter->flags |= FLAGS_QUAD;
++ else if (sizeof(ptrdiff_t) == sizeof(long))
++ parameter->flags |= FLAGS_LONG;
++ break;
++#endif
++
++#if TRIO_FEATURE_INTMAX_T
++ case QUALIFIER_INTMAX_T:
++ parameter->flags |= FLAGS_INTMAX_T;
++ if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
++ parameter->flags |= FLAGS_QUAD;
++ else if (sizeof(trio_intmax_t) == sizeof(long))
++ parameter->flags |= FLAGS_LONG;
++ break;
++#endif
++
++#if TRIO_FEATURE_QUAD
++ case QUALIFIER_QUAD:
++ parameter->flags |= FLAGS_QUAD;
++ break;
++#endif
++
++#if TRIO_FEATURE_FIXED_SIZE
++ case QUALIFIER_FIXED_SIZE:
++ if (parameter->flags & FLAGS_FIXED_SIZE)
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++
++ if (parameter->flags & (FLAGS_ALL_SIZES |
++ FLAGS_LONGDOUBLE |
++ FLAGS_WIDECHAR |
++ FLAGS_VARSIZE_PARAMETER))
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++
++ if ((format[offset] == '6') &&
++ (format[offset + 1] == '4'))
++ {
++ parameter->varsize = sizeof(trio_int64_t);
++ offset += 2;
++ }
++ else if ((format[offset] == '3') &&
++ (format[offset + 1] == '2'))
++ {
++ parameter->varsize = sizeof(trio_int32_t);
++ offset += 2;
++ }
++ else if ((format[offset] == '1') &&
++ (format[offset + 1] == '6'))
++ {
++ parameter->varsize = sizeof(trio_int16_t);
++ offset += 2;
++ }
++ else if (format[offset] == '8')
++ {
++ parameter->varsize = sizeof(trio_int8_t);
++ offset++;
++ }
++ else
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++
++ parameter->flags |= FLAGS_FIXED_SIZE;
++ break;
++#endif /* TRIO_FEATURE_FIXED_SIZE */
++
++#if defined(QUALIFIER_WIDECHAR)
++ case QUALIFIER_WIDECHAR:
++ parameter->flags |= FLAGS_WIDECHAR;
++ break;
++#endif
++
++#if TRIO_FEATURE_SIZE_T_UPPER
++ case QUALIFIER_SIZE_T_UPPER:
++ break;
++#endif
++
++#if TRIO_FEATURE_QUOTE
++ case QUALIFIER_QUOTE:
++ parameter->flags |= FLAGS_QUOTE;
++ break;
++#endif
++
++#if TRIO_FEATURE_STICKY
++ case QUALIFIER_STICKY:
++ parameter->flags |= FLAGS_STICKY;
++ break;
++#endif
++
++#if TRIO_FEATURE_VARSIZE
++ case QUALIFIER_VARSIZE:
++ parameter->flags |= FLAGS_VARSIZE_PARAMETER;
++ break;
++#endif
++
++#if TRIO_FEATURE_ROUNDING
++ case QUALIFIER_ROUNDING_UPPER:
++ parameter->flags |= FLAGS_ROUNDING;
++ break;
++#endif
++
++ default:
++ /* Bail out completely to make the error more obvious */
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ }
++ } /* while qualifier */
++
++ parameter->endOffset = offset;
++
++ return 0;
++}
++
++/*************************************************************************
++ * TrioParseSpecifier
++ *
++ * Description:
++ * Parse the specifier part of a potential conversion specifier
++ */
++TRIO_PRIVATE int
++TrioParseSpecifier
++TRIO_ARGS4((type, format, offset, parameter),
++ int type,
++ TRIO_CONST char *format,
++ int offset,
++ trio_parameter_t *parameter)
++{
++ parameter->baseSpecifier = NO_BASE;
++
++ switch (format[offset++])
++ {
++#if defined(SPECIFIER_CHAR_UPPER)
++ case SPECIFIER_CHAR_UPPER:
++ parameter->flags |= FLAGS_WIDECHAR;
++ /* FALLTHROUGH */
++#endif
++ case SPECIFIER_CHAR:
++ if (parameter->flags & FLAGS_LONG)
++ parameter->flags |= FLAGS_WIDECHAR;
++ else if (parameter->flags & FLAGS_SHORT)
++ parameter->flags &= ~FLAGS_WIDECHAR;
++ parameter->type = FORMAT_CHAR;
++ break;
++
++#if defined(SPECIFIER_STRING_UPPER)
++ case SPECIFIER_STRING_UPPER:
++ parameter->flags |= FLAGS_WIDECHAR;
++ /* FALLTHROUGH */
++#endif
++ case SPECIFIER_STRING:
++ if (parameter->flags & FLAGS_LONG)
++ parameter->flags |= FLAGS_WIDECHAR;
++ else if (parameter->flags & FLAGS_SHORT)
++ parameter->flags &= ~FLAGS_WIDECHAR;
++ parameter->type = FORMAT_STRING;
++ break;
++
++#if defined(SPECIFIER_GROUP)
++ case SPECIFIER_GROUP:
++ if (TYPE_SCAN == type)
++ {
++ int depth = 1;
++ parameter->type = FORMAT_GROUP;
++ if (format[offset] == QUALIFIER_CIRCUMFLEX)
++ offset++;
++ if (format[offset] == SPECIFIER_UNGROUP)
++ offset++;
++ if (format[offset] == QUALIFIER_MINUS)
++ offset++;
++ /* Skip nested brackets */
++ while (format[offset] != NIL)
++ {
++ if (format[offset] == SPECIFIER_GROUP)
++ {
++ depth++;
++ }
++ else if (format[offset] == SPECIFIER_UNGROUP)
++ {
++ if (--depth <= 0)
++ {
++ offset++;
++ break;
++ }
++ }
++ offset++;
++ }
++ }
++ break;
++#endif /* defined(SPECIFIER_GROUP) */
++
++ case SPECIFIER_INTEGER:
++ parameter->type = FORMAT_INT;
++ break;
++
++ case SPECIFIER_UNSIGNED:
++ parameter->flags |= FLAGS_UNSIGNED;
++ parameter->type = FORMAT_INT;
++ break;
++
++ case SPECIFIER_DECIMAL:
++ parameter->baseSpecifier = BASE_DECIMAL;
++ parameter->type = FORMAT_INT;
++ break;
++
++ case SPECIFIER_OCTAL:
++ parameter->flags |= FLAGS_UNSIGNED;
++ parameter->baseSpecifier = BASE_OCTAL;
++ parameter->type = FORMAT_INT;
++ break;
++
++#if TRIO_FEATURE_BINARY
++ case SPECIFIER_BINARY_UPPER:
++ parameter->flags |= FLAGS_UPPER;
++ /* FALLTHROUGH */
++ case SPECIFIER_BINARY:
++ parameter->flags |= FLAGS_NILPADDING;
++ parameter->baseSpecifier = BASE_BINARY;
++ parameter->type = FORMAT_INT;
++ break;
++#endif
++
++ case SPECIFIER_HEX_UPPER:
++ parameter->flags |= FLAGS_UPPER;
++ /* FALLTHROUGH */
++ case SPECIFIER_HEX:
++ parameter->flags |= FLAGS_UNSIGNED;
++ parameter->baseSpecifier = BASE_HEX;
++ parameter->type = FORMAT_INT;
++ break;
++
++#if defined(SPECIFIER_FLOAT_E)
++# if defined(SPECIFIER_FLOAT_E_UPPER)
++ case SPECIFIER_FLOAT_E_UPPER:
++ parameter->flags |= FLAGS_UPPER;
++ /* FALLTHROUGH */
++# endif
++ case SPECIFIER_FLOAT_E:
++ parameter->flags |= FLAGS_FLOAT_E;
++ parameter->type = FORMAT_DOUBLE;
++ break;
++#endif
++
++#if defined(SPECIFIER_FLOAT_G)
++# if defined(SPECIFIER_FLOAT_G_UPPER)
++ case SPECIFIER_FLOAT_G_UPPER:
++ parameter->flags |= FLAGS_UPPER;
++ /* FALLTHROUGH */
++# endif
++ case SPECIFIER_FLOAT_G:
++ parameter->flags |= FLAGS_FLOAT_G;
++ parameter->type = FORMAT_DOUBLE;
++ break;
++#endif
++
++#if defined(SPECIFIER_FLOAT_F)
++# if defined(SPECIFIER_FLOAT_F_UPPER)
++ case SPECIFIER_FLOAT_F_UPPER:
++ parameter->flags |= FLAGS_UPPER;
++ /* FALLTHROUGH */
++# endif
++ case SPECIFIER_FLOAT_F:
++ parameter->type = FORMAT_DOUBLE;
++ break;
++#endif
++
++#if defined(TRIO_COMPILER_VISUALC)
++# pragma warning( push )
++# pragma warning( disable : 4127 ) /* Conditional expression is constant */
++#endif
++ case SPECIFIER_POINTER:
++ if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
++ parameter->flags |= FLAGS_QUAD;
++ else if (sizeof(trio_pointer_t) == sizeof(long))
++ parameter->flags |= FLAGS_LONG;
++ parameter->type = FORMAT_POINTER;
++ break;
++#if defined(TRIO_COMPILER_VISUALC)
++# pragma warning( pop )
++#endif
++
++ case SPECIFIER_COUNT:
++ parameter->type = FORMAT_COUNT;
++ break;
++
++#if TRIO_FEATURE_HEXFLOAT
++ case SPECIFIER_HEXFLOAT_UPPER:
++ parameter->flags |= FLAGS_UPPER;
++ /* FALLTHROUGH */
++ case SPECIFIER_HEXFLOAT:
++ parameter->baseSpecifier = BASE_HEX;
++ parameter->type = FORMAT_DOUBLE;
++ break;
++#endif
++
++#if TRIO_FEATURE_ERRNO
++ case SPECIFIER_ERRNO:
++ parameter->type = FORMAT_ERRNO;
++ break;
++#endif
++
++#if TRIO_FEATURE_USER_DEFINED
++ case SPECIFIER_USER_DEFINED_BEGIN:
++ {
++ unsigned int max;
++ int without_namespace = TRUE;
++ char* tmpformat = (char *)&format[offset];
++ int ch;
++
++ parameter->type = FORMAT_USER_DEFINED;
++ parameter->user_defined.namespace[0] = NIL;
++
++ while ((ch = format[offset]) != NIL)
++ {
++ offset++;
++ if ((ch == SPECIFIER_USER_DEFINED_END) || (ch == SPECIFIER_USER_DEFINED_EXTRA))
++ {
++ if (without_namespace)
++ /* No namespace, handler will be passed as an argument */
++ parameter->flags |= FLAGS_USER_DEFINED_PARAMETER;
++
++ /* Copy the user data */
++ max = (unsigned int)(&format[offset] - tmpformat);
++ if (max > MAX_USER_DATA)
++ max = MAX_USER_DATA;
++ trio_copy_max(parameter->user_data, max, tmpformat);
++
++ /* Skip extra data (which is only there to keep the compiler happy) */
++ while ((ch != NIL) && (ch != SPECIFIER_USER_DEFINED_END))
++ ch = format[offset++];
++
++ break; /* while */
++ }
++
++ if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
++ {
++ without_namespace = FALSE;
++ /* Copy the namespace for later looking-up */
++ max = (int)(&format[offset] - tmpformat);
++ if (max > MAX_USER_NAME)
++ max = MAX_USER_NAME;
++ trio_copy_max(parameter->user_defined.namespace, max, tmpformat);
++ tmpformat = (char *)&format[offset];
++ }
++ }
++
++ if (ch != SPECIFIER_USER_DEFINED_END)
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ }
++ break;
++#endif /* TRIO_FEATURE_USER_DEFINED */
++
++ default:
++ /* Bail out completely to make the error more obvious */
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ }
++
++ parameter->endOffset = offset;
++
++ return 0;
++}
++
++/*************************************************************************
++ * TrioParse
++ *
++ * Description:
++ * Parse the format string
++ */
++TRIO_PRIVATE int
++TrioParse
++TRIO_ARGS5((type, format, parameters, arglist, argarray),
++ int type,
++ TRIO_CONST char *format,
++ trio_parameter_t *parameters,
++ va_list arglist,
++ trio_pointer_t *argarray)
++{
++ /* Count the number of times a parameter is referenced */
++ unsigned short usedEntries[MAX_PARAMETERS];
++ /* Parameter counters */
++ int parameterPosition;
++ int maxParam = -1;
++ /* Utility variables */
++ int offset; /* Offset into formatting string */
++ BOOLEAN_T positional; /* Does the specifier have a positional? */
++#if TRIO_FEATURE_STICKY
++ BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */
++#endif
++ /*
++ * indices specifies the order in which the parameters must be
++ * read from the va_args (this is necessary to handle positionals)
++ */
++ int indices[MAX_PARAMETERS];
++ int pos = 0;
++ /* Various variables */
++#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
++ int charlen;
++#endif
++ int save_errno;
++ int i = -1;
++ int num;
++ trio_parameter_t workParameter;
++ int status;
++
++ /*
++ * The 'parameters' array is not initialized, but we need to
++ * know which entries we have used.
++ */
++ memset(usedEntries, 0, sizeof(usedEntries));
++
++ save_errno = errno;
++ offset = 0;
++ parameterPosition = 0;
++#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
++ charlen = mblen(NULL, 0);
++#endif
++
++ while (format[offset])
++ {
++ TrioInitializeParameter(&workParameter);
++
++#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
++ if (! isascii(format[offset]))
++ {
++ /*
++ * Multibyte characters cannot be legal specifiers or
++ * modifiers, so we skip over them.
++ */
++ charlen = mblen(&format[offset], MB_LEN_MAX);
++ offset += (charlen > 0) ? charlen : 1;
++ continue; /* while */
++ }
++#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
++
++ switch(format[offset++]) {
++
++ case CHAR_IDENTIFIER:
++ {
++ if (CHAR_IDENTIFIER == format[offset])
++ {
++ /* skip double "%" */
++ offset++;
++ continue; /* while */
++ }
++
++ status = TrioParseQualifiers(type, format, offset, &workParameter);
++ if (status < 0)
++ return status; /* Return qualifier syntax error */
++
++ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
++ if (status < 0)
++ return status; /* Return specifier syntax error */
++ }
++ break;
++
++#if TRIO_EXTENSION
++ case CHAR_ALT_IDENTIFIER:
++ {
++ status = TrioParseQualifiers(type, format, offset, &workParameter);
++ if (status < 0)
++ continue; /* False alert, not a user defined specifier */
++
++ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
++ if ((status < 0) || (FORMAT_USER_DEFINED != workParameter.type))
++ continue; /* False alert, not a user defined specifier */
++ }
++ break;
++#endif
++
++ default:
++ continue; /* while */
++ }
++
++ /* now handle the parsed conversion specification */
++ positional = (NO_POSITION != workParameter.position);
++
++ /*
++ * Parameters only need the type and value. The value is
++ * read later.
++ */
++ if (workParameter.flags & FLAGS_WIDTH_PARAMETER)
++ {
++ if (workParameter.width == NO_WIDTH)
++ {
++ workParameter.width = parameterPosition++;
++ }
++ else
++ {
++ if (! positional)
++ workParameter.position = workParameter.width + 1;
++ }
++
++ usedEntries[workParameter.width] += 1;
++ if (workParameter.width > maxParam)
++ maxParam = workParameter.width;
++ parameters[pos].type = FORMAT_PARAMETER;
++ parameters[pos].flags = 0;
++ indices[workParameter.width] = pos;
++ workParameter.width = pos++;
++ }
++ if (workParameter.flags & FLAGS_PRECISION_PARAMETER)
++ {
++ if (workParameter.precision == NO_PRECISION)
++ {
++ workParameter.precision = parameterPosition++;
++ }
++ else
++ {
++ if (! positional)
++ workParameter.position = workParameter.precision + 1;
++ }
++
++ usedEntries[workParameter.precision] += 1;
++ if (workParameter.precision > maxParam)
++ maxParam = workParameter.precision;
++ parameters[pos].type = FORMAT_PARAMETER;
++ parameters[pos].flags = 0;
++ indices[workParameter.precision] = pos;
++ workParameter.precision = pos++;
++ }
++ if (workParameter.flags & FLAGS_BASE_PARAMETER)
++ {
++ if (workParameter.base == NO_BASE)
++ {
++ workParameter.base = parameterPosition++;
++ }
++ else
++ {
++ if (! positional)
++ workParameter.position = workParameter.base + 1;
++ }
++
++ usedEntries[workParameter.base] += 1;
++ if (workParameter.base > maxParam)
++ maxParam = workParameter.base;
++ parameters[pos].type = FORMAT_PARAMETER;
++ parameters[pos].flags = 0;
++ indices[workParameter.base] = pos;
++ workParameter.base = pos++;
++ }
++#if TRIO_FEATURE_VARSIZE
++ if (workParameter.flags & FLAGS_VARSIZE_PARAMETER)
++ {
++ workParameter.varsize = parameterPosition++;
++
++ usedEntries[workParameter.varsize] += 1;
++ if (workParameter.varsize > maxParam)
++ maxParam = workParameter.varsize;
++ parameters[pos].type = FORMAT_PARAMETER;
++ parameters[pos].flags = 0;
++ indices[workParameter.varsize] = pos;
++ workParameter.varsize = pos++;
++ }
++#endif
++#if TRIO_FEATURE_USER_DEFINED
++ if (workParameter.flags & FLAGS_USER_DEFINED_PARAMETER)
++ {
++ workParameter.user_defined.handler = parameterPosition++;
++
++ usedEntries[workParameter.user_defined.handler] += 1;
++ if (workParameter.user_defined.handler > maxParam)
++ maxParam = workParameter.user_defined.handler;
++ parameters[pos].type = FORMAT_PARAMETER;
++ parameters[pos].flags = FLAGS_USER_DEFINED;
++ indices[workParameter.user_defined.handler] = pos;
++ workParameter.user_defined.handler = pos++;
++ }
++#endif
++
++ if (NO_POSITION == workParameter.position)
++ {
++ workParameter.position = parameterPosition++;
++ }
++
++ if (workParameter.position > maxParam)
++ maxParam = workParameter.position;
++
++ if (workParameter.position >= MAX_PARAMETERS)
++ {
++ /* Bail out completely to make the error more obvious */
++ return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset);
++ }
++
++ indices[workParameter.position] = pos;
++
++ /* Count the number of times this entry has been used */
++ usedEntries[workParameter.position] += 1;
++
++ /* Find last sticky parameters */
++#if TRIO_FEATURE_STICKY
++ if (workParameter.flags & FLAGS_STICKY)
++ {
++ gotSticky = TRUE;
++ }
++ else if (gotSticky)
++ {
++ for (i = pos - 1; i >= 0; i--)
++ {
++ if (parameters[i].type == FORMAT_PARAMETER)
++ continue;
++ if ((parameters[i].flags & FLAGS_STICKY) &&
++ (parameters[i].type == workParameter.type))
++ {
++ /* Do not overwrite current qualifiers */
++ workParameter.flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
++ if (workParameter.width == NO_WIDTH)
++ workParameter.width = parameters[i].width;
++ if (workParameter.precision == NO_PRECISION)
++ workParameter.precision = parameters[i].precision;
++ if (workParameter.base == NO_BASE)
++ workParameter.base = parameters[i].base;
++ break;
++ }
++ }
++ }
++#endif
++
++ if (workParameter.base == NO_BASE)
++ workParameter.base = BASE_DECIMAL;
++
++ offset = workParameter.endOffset;
++
++ TrioCopyParameter(&parameters[pos++], &workParameter);
++ } /* while format characters left */
++
++ parameters[pos].type = FORMAT_SENTINEL; /* end parameter array with sentinel */
++ parameters[pos].beginOffset = offset;
++
++ for (num = 0; num <= maxParam; num++)
++ {
++ if (usedEntries[num] != 1)
++ {
++ if (usedEntries[num] == 0) /* gap detected */
++ return TRIO_ERROR_RETURN(TRIO_EGAP, num);
++ else /* double references detected */
++ return TRIO_ERROR_RETURN(TRIO_EDBLREF, num);
++ }
++
++ i = indices[num];
++
++ /*
++ * FORMAT_PARAMETERS are only present if they must be read,
++ * so it makes no sense to check the ignore flag (besides,
++ * the flags variable is not set for that particular type)
++ */
++ if ((parameters[i].type != FORMAT_PARAMETER) &&
++ (parameters[i].flags & FLAGS_IGNORE))
++ continue; /* for all arguments */
++
++ /*
++ * The stack arguments are read according to ANSI C89
++ * default argument promotions:
++ *
++ * char = int
++ * short = int
++ * unsigned char = unsigned int
++ * unsigned short = unsigned int
++ * float = double
++ *
++ * In addition to the ANSI C89 these types are read (the
++ * default argument promotions of C99 has not been
++ * considered yet)
++ *
++ * long long
++ * long double
++ * size_t
++ * ptrdiff_t
++ * intmax_t
++ */
++ switch (parameters[i].type)
++ {
++ case FORMAT_GROUP:
++ case FORMAT_STRING:
++#if TRIO_FEATURE_WIDECHAR
++ if (parameters[i].flags & FLAGS_WIDECHAR)
++ {
++ parameters[i].data.wstring = (argarray == NULL)
++ ? va_arg(arglist, trio_wchar_t *)
++ : (trio_wchar_t *)(argarray[num]);
++ }
++ else
++#endif
++ {
++ parameters[i].data.string = (argarray == NULL)
++ ? va_arg(arglist, char *)
++ : (char *)(argarray[num]);
++ }
++ break;
++
++#if TRIO_FEATURE_USER_DEFINED
++ case FORMAT_USER_DEFINED:
++#endif
++ case FORMAT_POINTER:
++ case FORMAT_COUNT:
++ case FORMAT_UNKNOWN:
++ parameters[i].data.pointer = (argarray == NULL)
++ ? va_arg(arglist, trio_pointer_t )
++ : argarray[num];
++ break;
++
++ case FORMAT_CHAR:
++ case FORMAT_INT:
++#if TRIO_FEATURE_SCANF
++ if (TYPE_SCAN == type)
++ {
++ if (argarray == NULL)
++ parameters[i].data.pointer =
++ (trio_pointer_t)va_arg(arglist, trio_pointer_t);
++ else
++ {
++ if (parameters[i].type == FORMAT_CHAR)
++ parameters[i].data.pointer =
++ (trio_pointer_t)((char *)argarray[num]);
++ else if (parameters[i].flags & FLAGS_SHORT)
++ parameters[i].data.pointer =
++ (trio_pointer_t)((short *)argarray[num]);
++ else
++ parameters[i].data.pointer =
++ (trio_pointer_t)((int *)argarray[num]);
++ }
++ }
++ else
++#endif /* TRIO_FEATURE_SCANF */
++ {
++#if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE
++ if (parameters[i].flags
++ & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
++ {
++ int varsize;
++ if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
++ {
++ /*
++ * Variable sizes are mapped onto the fixed sizes, in
++ * accordance with integer promotion.
++ *
++ * Please note that this may not be portable, as we
++ * only guess the size, not the layout of the numbers.
++ * For example, if int is little-endian, and long is
++ * big-endian, then this will fail.
++ */
++ varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
++ }
++ else
++ {
++ /* Used for the I<bits> modifiers */
++ varsize = parameters[i].varsize;
++ }
++ parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
++
++ if (varsize <= (int)sizeof(int))
++ ;
++ else if (varsize <= (int)sizeof(long))
++ parameters[i].flags |= FLAGS_LONG;
++#if TRIO_FEATURE_INTMAX_T
++ else if (varsize <= (int)sizeof(trio_longlong_t))
++ parameters[i].flags |= FLAGS_QUAD;
++ else
++ parameters[i].flags |= FLAGS_INTMAX_T;
++#else
++ else
++ parameters[i].flags |= FLAGS_QUAD;
++#endif
++ }
++#endif /* TRIO_FEATURE_VARSIZE */
++#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
++ if (parameters[i].flags & FLAGS_SIZE_T)
++ parameters[i].data.number.as_unsigned = (argarray == NULL)
++ ? (trio_uintmax_t)va_arg(arglist, size_t)
++ : (trio_uintmax_t)(*((size_t *)argarray[num]));
++ else
++#endif
++#if TRIO_FEATURE_PTRDIFF_T
++ if (parameters[i].flags & FLAGS_PTRDIFF_T)
++ parameters[i].data.number.as_unsigned = (argarray == NULL)
++ ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t)
++ : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
++ else
++#endif
++#if TRIO_FEATURE_INTMAX_T
++ if (parameters[i].flags & FLAGS_INTMAX_T)
++ parameters[i].data.number.as_unsigned = (argarray == NULL)
++ ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t)
++ : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
++ else
++#endif
++ if (parameters[i].flags & FLAGS_QUAD)
++ parameters[i].data.number.as_unsigned = (argarray == NULL)
++ ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t)
++ : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
++ else if (parameters[i].flags & FLAGS_LONG)
++ parameters[i].data.number.as_unsigned = (argarray == NULL)
++ ? (trio_uintmax_t)va_arg(arglist, long)
++ : (trio_uintmax_t)(*((long *)argarray[num]));
++ else
++ {
++ if (argarray == NULL)
++ parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int);
++ else
++ {
++ if (parameters[i].type == FORMAT_CHAR)
++ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
++ else if (parameters[i].flags & FLAGS_SHORT)
++ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
++ else
++ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
++ }
++ }
++ }
++ break;
++
++ case FORMAT_PARAMETER:
++ /*
++ * The parameter for the user-defined specifier is a pointer,
++ * whereas the rest (width, precision, base) uses an integer.
++ */
++ if (parameters[i].flags & FLAGS_USER_DEFINED)
++ parameters[i].data.pointer = (argarray == NULL)
++ ? va_arg(arglist, trio_pointer_t )
++ : argarray[num];
++ else
++ parameters[i].data.number.as_unsigned = (argarray == NULL)
++ ? (trio_uintmax_t)va_arg(arglist, int)
++ : (trio_uintmax_t)(*((int *)argarray[num]));
++ break;
++
++#if TRIO_FEATURE_FLOAT
++ case FORMAT_DOUBLE:
++# if TRIO_FEATURE_SCANF
++ if (TYPE_SCAN == type)
++ {
++ if (parameters[i].flags & FLAGS_LONGDOUBLE)
++ parameters[i].data.longdoublePointer = (argarray == NULL)
++ ? va_arg(arglist, trio_long_double_t *)
++ : (trio_long_double_t *)argarray[num];
++ else
++ {
++ if (parameters[i].flags & FLAGS_LONG)
++ parameters[i].data.doublePointer = (argarray == NULL)
++ ? va_arg(arglist, double *)
++ : (double *)argarray[num];
++ else
++ parameters[i].data.doublePointer = (argarray == NULL)
++ ? (double *)va_arg(arglist, float *)
++ : (double *)((float *)argarray[num]);
++ }
++ }
++ else
++# endif /* TRIO_FEATURE_SCANF */
++ {
++ if (parameters[i].flags & FLAGS_LONGDOUBLE)
++ parameters[i].data.longdoubleNumber = (argarray == NULL)
++ ? va_arg(arglist, trio_long_double_t)
++ : (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
++ else
++ {
++ if (argarray == NULL)
++ parameters[i].data.longdoubleNumber =
++ (trio_long_double_t)va_arg(arglist, double);
++ else
++ {
++ if (parameters[i].flags & FLAGS_SHORT)
++ parameters[i].data.longdoubleNumber =
++ (trio_long_double_t)(*((float *)argarray[num]));
++ else
++ parameters[i].data.longdoubleNumber =
++ (trio_long_double_t)(*((double *)argarray[num]));
++ }
++ }
++ }
++ break;
++#endif /* TRIO_FEATURE_FLOAT */
++
++#if TRIO_FEATURE_ERRNO
++ case FORMAT_ERRNO:
++ parameters[i].data.errorNumber = save_errno;
++ break;
++#endif
++
++ default:
++ break;
++ }
++ } /* for all specifiers */
++ return num;
++}
++
++
++/*************************************************************************
++ *
++ * FORMATTING
++ *
++ ************************************************************************/
++
++
++/*************************************************************************
++ * TrioWriteNumber
++ *
++ * Description:
++ * Output a number.
++ * The complexity of this function is a result of the complexity
++ * of the dependencies of the flags.
++ */
++TRIO_PRIVATE void
++TrioWriteNumber
++TRIO_ARGS6((self, number, flags, width, precision, base),
++ trio_class_t *self,
++ trio_uintmax_t number,
++ trio_flags_t flags,
++ int width,
++ int precision,
++ int base)
++{
++ BOOLEAN_T isNegative;
++ BOOLEAN_T isNumberZero;
++ BOOLEAN_T isPrecisionZero;
++ BOOLEAN_T ignoreNumber;
++ char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
++ char *bufferend;
++ char *pointer;
++ TRIO_CONST char *digits;
++ int i;
++#if TRIO_FEATURE_QUOTE
++ int length;
++ char *p;
++#endif
++ int count;
++ int digitOffset;
++
++ assert(VALID(self));
++ assert(VALID(self->OutStream));
++ assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
++
++ digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
++ if (base == NO_BASE)
++ base = BASE_DECIMAL;
++
++ isNumberZero = (number == 0);
++ isPrecisionZero = (precision == 0);
++ ignoreNumber = (isNumberZero
++ && isPrecisionZero
++ && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL)));
++
++ if (flags & FLAGS_UNSIGNED)
++ {
++ isNegative = FALSE;
++ flags &= ~FLAGS_SHOWSIGN;
++ }
++ else
++ {
++ isNegative = ((trio_intmax_t)number < 0);
++ if (isNegative)
++ number = -((trio_intmax_t)number);
++ }
++
++ if (flags & FLAGS_QUAD)
++ number &= (trio_ulonglong_t)-1;
++ else if (flags & FLAGS_LONG)
++ number &= (unsigned long)-1;
++ else
++ number &= (unsigned int)-1;
++
++ /* Build number */
++ pointer = bufferend = &buffer[sizeof(buffer) - 1];
++ *pointer-- = NIL;
++ for (i = 1; i < (int)sizeof(buffer); i++)
++ {
++ digitOffset = number % base;
++ *pointer-- = digits[digitOffset];
++ number /= base;
++ if (number == 0)
++ break;
++
++#if TRIO_FEATURE_QUOTE
++ if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
++ {
++ /*
++ * We are building the number from the least significant
++ * to the most significant digit, so we have to copy the
++ * thousand separator backwards
++ */
++ length = internalThousandSeparatorLength;
++ if (((int)(pointer - buffer) - length) > 0)
++ {
++ p = &internalThousandSeparator[length - 1];
++ while (length-- > 0)
++ *pointer-- = *p--;
++ }
++ }
++#endif
++ }
++
++ if (! ignoreNumber)
++ {
++ /* Adjust width */
++ width -= (bufferend - pointer) - 1;
++ }
++
++ /* Adjust precision */
++ if (NO_PRECISION != precision)
++ {
++ precision -= (bufferend - pointer) - 1;
++ if (precision < 0)
++ precision = 0;
++ flags |= FLAGS_NILPADDING;
++ }
++
++ /* Calculate padding */
++ count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION)))
++ ? precision
++ : 0;
++
++ /* Adjust width further */
++ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
++ width--;
++ if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
++ {
++ switch (base)
++ {
++ case BASE_BINARY:
++ case BASE_HEX:
++ width -= 2;
++ break;
++ case BASE_OCTAL:
++ if (!(flags & FLAGS_NILPADDING) || (count == 0))
++ width--;
++ break;
++ default:
++ break;
++ }
++ }
++
++ /* Output prefixes spaces if needed */
++ if (! ((flags & FLAGS_LEFTADJUST) ||
++ ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION))))
++ {
++ while (width-- > count)
++ self->OutStream(self, CHAR_ADJUST);
++ }
++
++ /* width has been adjusted for signs and alternatives */
++ if (isNegative)
++ self->OutStream(self, '-');
++ else if (flags & FLAGS_SHOWSIGN)
++ self->OutStream(self, '+');
++ else if (flags & FLAGS_SPACE)
++ self->OutStream(self, ' ');
++
++ /* Prefix is not written when the value is zero */
++ if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
++ {
++ switch (base)
++ {
++ case BASE_BINARY:
++ self->OutStream(self, '0');
++ self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b');
++ break;
++
++ case BASE_OCTAL:
++ if (!(flags & FLAGS_NILPADDING) || (count == 0))
++ self->OutStream(self, '0');
++ break;
++
++ case BASE_HEX:
++ self->OutStream(self, '0');
++ self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
++ break;
++
++ default:
++ break;
++ } /* switch base */
++ }
++
++ /* Output prefixed zero padding if needed */
++ if (flags & FLAGS_NILPADDING)
++ {
++ if (precision == NO_PRECISION)
++ precision = width;
++ while (precision-- > 0)
++ {
++ self->OutStream(self, '0');
++ width--;
++ }
++ }
++
++ if (! ignoreNumber)
++ {
++ /* Output the number itself */
++ while (*(++pointer))
++ {
++ self->OutStream(self, *pointer);
++ }
++ }
++
++ /* Output trailing spaces if needed */
++ if (flags & FLAGS_LEFTADJUST)
++ {
++ while (width-- > 0)
++ self->OutStream(self, CHAR_ADJUST);
++ }
++}
++
++/*************************************************************************
++ * TrioWriteStringCharacter
++ *
++ * Description:
++ * Output a single character of a string
++ */
++TRIO_PRIVATE void
++TrioWriteStringCharacter
++TRIO_ARGS3((self, ch, flags),
++ trio_class_t *self,
++ int ch,
++ trio_flags_t flags)
++{
++ if (flags & FLAGS_ALTERNATIVE)
++ {
++ if (! isprint(ch))
++ {
++ /*
++ * Non-printable characters are converted to C escapes or
++ * \number, if no C escape exists.
++ */
++ self->OutStream(self, CHAR_BACKSLASH);
++ switch (ch)
++ {
++ case '\007': self->OutStream(self, 'a'); break;
++ case '\b': self->OutStream(self, 'b'); break;
++ case '\f': self->OutStream(self, 'f'); break;
++ case '\n': self->OutStream(self, 'n'); break;
++ case '\r': self->OutStream(self, 'r'); break;
++ case '\t': self->OutStream(self, 't'); break;
++ case '\v': self->OutStream(self, 'v'); break;
++ case '\\': self->OutStream(self, '\\'); break;
++ default:
++ self->OutStream(self, 'x');
++ TrioWriteNumber(self, (trio_uintmax_t)ch,
++ FLAGS_UNSIGNED | FLAGS_NILPADDING,
++ 2, 2, BASE_HEX);
++ break;
++ }
++ }
++ else if (ch == CHAR_BACKSLASH)
++ {
++ self->OutStream(self, CHAR_BACKSLASH);
++ self->OutStream(self, CHAR_BACKSLASH);
++ }
++ else
++ {
++ self->OutStream(self, ch);
++ }
++ }
++ else
++ {
++ self->OutStream(self, ch);
++ }
++}
++
++/*************************************************************************
++ * TrioWriteString
++ *
++ * Description:
++ * Output a string
++ */
++TRIO_PRIVATE void
++TrioWriteString
++TRIO_ARGS5((self, string, flags, width, precision),
++ trio_class_t *self,
++ TRIO_CONST char *string,
++ trio_flags_t flags,
++ int width,
++ int precision)
++{
++ int length;
++ int ch;
++
++ assert(VALID(self));
++ assert(VALID(self->OutStream));
++
++ if (string == NULL)
++ {
++ string = internalNullString;
++ length = sizeof(internalNullString) - 1;
++#if TRIO_FEATURE_QUOTE
++ /* Disable quoting for the null pointer */
++ flags &= (~FLAGS_QUOTE);
++#endif
++ width = 0;
++ }
++ else
++ {
++ if (precision == 0)
++ {
++ length = trio_length(string);
++ }
++ else
++ {
++ length = trio_length_max(string, precision);
++ }
++ }
++ if ((NO_PRECISION != precision) &&
++ (precision < length))
++ {
++ length = precision;
++ }
++ width -= length;
++
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ self->OutStream(self, CHAR_QUOTE);
++#endif
++
++ if (! (flags & FLAGS_LEFTADJUST))
++ {
++ while (width-- > 0)
++ self->OutStream(self, CHAR_ADJUST);
++ }
++
++ while (length-- > 0)
++ {
++ /* The ctype parameters must be an unsigned char (or EOF) */
++ ch = (int)((unsigned char)(*string++));
++ TrioWriteStringCharacter(self, ch, flags);
++ }
++
++ if (flags & FLAGS_LEFTADJUST)
++ {
++ while (width-- > 0)
++ self->OutStream(self, CHAR_ADJUST);
++ }
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ self->OutStream(self, CHAR_QUOTE);
++#endif
++}
++
++/*************************************************************************
++ * TrioWriteWideStringCharacter
++ *
++ * Description:
++ * Output a wide string as a multi-byte sequence
++ */
++#if TRIO_FEATURE_WIDECHAR
++TRIO_PRIVATE int
++TrioWriteWideStringCharacter
++TRIO_ARGS4((self, wch, flags, width),
++ trio_class_t *self,
++ trio_wchar_t wch,
++ trio_flags_t flags,
++ int width)
++{
++ int size;
++ int i;
++ int ch;
++ char *string;
++ char buffer[MB_LEN_MAX + 1];
++
++ if (width == NO_WIDTH)
++ width = sizeof(buffer);
++
++ size = wctomb(buffer, wch);
++ if ((size <= 0) || (size > width) || (buffer[0] == NIL))
++ return 0;
++
++ string = buffer;
++ i = size;
++ while ((width >= i) && (width-- > 0) && (i-- > 0))
++ {
++ /* The ctype parameters must be an unsigned char (or EOF) */
++ ch = (int)((unsigned char)(*string++));
++ TrioWriteStringCharacter(self, ch, flags);
++ }
++ return size;
++}
++#endif /* TRIO_FEATURE_WIDECHAR */
++
++/*************************************************************************
++ * TrioWriteWideString
++ *
++ * Description:
++ * Output a wide character string as a multi-byte string
++ */
++#if TRIO_FEATURE_WIDECHAR
++TRIO_PRIVATE void
++TrioWriteWideString
++TRIO_ARGS5((self, wstring, flags, width, precision),
++ trio_class_t *self,
++ TRIO_CONST trio_wchar_t *wstring,
++ trio_flags_t flags,
++ int width,
++ int precision)
++{
++ int length;
++ int size;
++
++ assert(VALID(self));
++ assert(VALID(self->OutStream));
++
++#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
++ /* Required by TrioWriteWideStringCharacter */
++ length = mblen(NULL, 0);
++#endif
++
++ if (wstring == NULL)
++ {
++ TrioWriteString(self, NULL, flags, width, precision);
++ return;
++ }
++
++ if (NO_PRECISION == precision)
++ {
++ length = INT_MAX;
++ }
++ else
++ {
++ length = precision;
++ width -= length;
++ }
++
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ self->OutStream(self, CHAR_QUOTE);
++#endif
++
++ if (! (flags & FLAGS_LEFTADJUST))
++ {
++ while (width-- > 0)
++ self->OutStream(self, CHAR_ADJUST);
++ }
++
++ while (length > 0)
++ {
++ size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
++ if (size == 0)
++ break; /* while */
++ length -= size;
++ }
++
++ if (flags & FLAGS_LEFTADJUST)
++ {
++ while (width-- > 0)
++ self->OutStream(self, CHAR_ADJUST);
++ }
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ self->OutStream(self, CHAR_QUOTE);
++#endif
++}
++#endif /* TRIO_FEATURE_WIDECHAR */
++
++/*************************************************************************
++ * TrioWriteDouble
++ *
++ * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm
++ *
++ * "5.2.4.2.2 paragraph #4
++ *
++ * The accuracy [...] is implementation defined, as is the accuracy
++ * of the conversion between floating-point internal representations
++ * and string representations performed by the libray routine in
++ * <stdio.h>"
++ */
++/* FIXME: handle all instances of constant long-double number (L)
++ * and *l() math functions.
++ */
++#if TRIO_FEATURE_FLOAT
++TRIO_PRIVATE void
++TrioWriteDouble
++TRIO_ARGS6((self, number, flags, width, precision, base),
++ trio_class_t *self,
++ trio_long_double_t number,
++ trio_flags_t flags,
++ int width,
++ int precision,
++ int base)
++{
++ trio_long_double_t integerNumber;
++ trio_long_double_t fractionNumber;
++ trio_long_double_t workNumber;
++ int integerDigits;
++ int fractionDigits;
++ int exponentDigits;
++ int workDigits;
++ int baseDigits;
++ int integerThreshold;
++ int fractionThreshold;
++ int expectedWidth;
++ int exponent = 0;
++ unsigned int uExponent = 0;
++ int exponentBase;
++ trio_long_double_t dblBase;
++ trio_long_double_t dblFractionBase;
++ trio_long_double_t integerAdjust;
++ trio_long_double_t fractionAdjust;
++ trio_long_double_t workFractionNumber;
++ trio_long_double_t workFractionAdjust;
++ int fractionDigitsInspect;
++ BOOLEAN_T isNegative;
++ BOOLEAN_T isExponentNegative = FALSE;
++ BOOLEAN_T requireTwoDigitExponent;
++ BOOLEAN_T isHex;
++ TRIO_CONST char *digits;
++# if TRIO_FEATURE_QUOTE
++ char *groupingPointer;
++# endif
++ int i;
++ int offset;
++ BOOLEAN_T hasOnlyZeroes;
++ int leadingFractionZeroes = -1;
++ register int trailingZeroes;
++ BOOLEAN_T keepTrailingZeroes;
++ BOOLEAN_T keepDecimalPoint;
++ trio_long_double_t epsilon;
++ BOOLEAN_T adjustNumber = FALSE;
++
++ assert(VALID(self));
++ assert(VALID(self->OutStream));
++ assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
++
++ /* Determine sign and look for special quantities */
++ switch (trio_fpclassify_and_signbit(number, &isNegative))
++ {
++ case TRIO_FP_NAN:
++ TrioWriteString(self,
++ (flags & FLAGS_UPPER)
++ ? NAN_UPPER
++ : NAN_LOWER,
++ flags, width, precision);
++ return;
++
++ case TRIO_FP_INFINITE:
++ if (isNegative)
++ {
++ /* Negative infinity */
++ TrioWriteString(self,
++ (flags & FLAGS_UPPER)
++ ? "-" INFINITE_UPPER
++ : "-" INFINITE_LOWER,
++ flags, width, precision);
++ return;
++ }
++ else
++ {
++ /* Positive infinity */
++ TrioWriteString(self,
++ (flags & FLAGS_UPPER)
++ ? INFINITE_UPPER
++ : INFINITE_LOWER,
++ flags, width, precision);
++ return;
++ }
++
++ default:
++ /* Finitude */
++ break;
++ }
++
++ /* Normal numbers */
++ if (flags & FLAGS_LONGDOUBLE)
++ {
++ baseDigits = (base == 10)
++ ? LDBL_DIG
++ : (int)trio_floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
++ epsilon = LDBL_EPSILON;
++ }
++ else if (flags & FLAGS_SHORT)
++ {
++ baseDigits = (base == BASE_DECIMAL)
++ ? FLT_DIG
++ : (int)trio_floor(FLT_MANT_DIG / TrioLogarithmBase(base));
++ epsilon = FLT_EPSILON;
++ }
++ else
++ {
++ baseDigits = (base == BASE_DECIMAL)
++ ? DBL_DIG
++ : (int)trio_floor(DBL_MANT_DIG / TrioLogarithmBase(base));
++ epsilon = DBL_EPSILON;
++ }
++
++ digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
++ isHex = (base == BASE_HEX);
++ if (base == NO_BASE)
++ base = BASE_DECIMAL;
++ dblBase = (trio_long_double_t)base;
++ keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) ||
++ ( (flags & FLAGS_FLOAT_G) &&
++ !(flags & FLAGS_ALTERNATIVE) ) );
++
++# if TRIO_FEATURE_ROUNDING
++ if (flags & FLAGS_ROUNDING)
++ {
++ precision = baseDigits;
++ }
++# endif
++
++ if (precision == NO_PRECISION)
++ {
++ if (isHex)
++ {
++ keepTrailingZeroes = FALSE;
++ precision = FLT_MANT_DIG;
++ }
++ else
++ {
++ precision = FLT_DIG;
++ }
++ }
++
++ if (isNegative)
++ {
++ number = -number;
++ }
++
++ if (isHex)
++ {
++ flags |= FLAGS_FLOAT_E;
++ }
++
++ reprocess:
++
++ if (flags & FLAGS_FLOAT_G)
++ {
++ if (precision == 0)
++ precision = 1;
++
++#if 0 /* GS Modification */
++ if ( (number < TRIO_SUFFIX_LONG(1.0E-4)) ||
++ (number >= TrioPower(base, (trio_long_double_t)precision)) )
++#else /* GS Modification */
++ /* This gives us a better match to the trip over point that we want */
++ if ( (number < TRIO_SUFFIX_LONG(9.9999989999999991e-05)) ||
++ (number >= TrioPower(base, (trio_long_double_t)precision)) )
++#endif /* GS Modification */
++ {
++ /* Use scientific notation */
++ flags |= FLAGS_FLOAT_E;
++ }
++ else if (number < 1.0)
++ {
++ /*
++ * Use normal notation. If the integer part of the number is
++ * zero, then adjust the precision to include leading fractional
++ * zeros.
++ */
++ workNumber = TrioLogarithm(number, base);
++ workNumber = TRIO_FABS(workNumber);
++ if (workNumber - trio_floor(workNumber) < epsilon)
++ workNumber--;
++ leadingFractionZeroes = (int)trio_floor(workNumber);
++ }
++ }
++
++ if (flags & FLAGS_FLOAT_E)
++ {
++ /* Scale the number */
++ workNumber = TrioLogarithm(number, base);
++ if (trio_isinf(workNumber) == -1)
++ {
++ exponent = 0;
++ /* Undo setting */
++ if (flags & FLAGS_FLOAT_G)
++ flags &= ~FLAGS_FLOAT_E;
++ }
++ else
++ {
++ exponent = (int)trio_floor(workNumber);
++ workNumber = number;
++ /*
++ * The expression A * 10^-B is equivalent to A / 10^B but the former
++ * usually gives better accuracy.
++ */
++ workNumber *= TrioPower(dblBase, (trio_long_double_t)-exponent);
++ if (trio_isinf(workNumber)) {
++ /*
++ * Scaling is done it two steps to avoid problems with subnormal
++ * numbers.
++ */
++ workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent / 2));
++ workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent - (exponent / 2)));
++ }
++ number = workNumber;
++ isExponentNegative = (exponent < 0);
++ uExponent = (isExponentNegative) ? -exponent : exponent;
++ if (isHex)
++ uExponent *= 4; /* log16(2) */
++#if TRIO_FEATURE_QUOTE
++ /* No thousand separators */
++ flags &= ~FLAGS_QUOTE;
++#endif
++ }
++ }
++
++ integerNumber = trio_floor(number);
++ fractionNumber = number - integerNumber;
++
++ /*
++ * Truncated number.
++ *
++ * Precision is number of significant digits for FLOAT_G and number of
++ * fractional digits for others.
++ */
++ integerDigits = 1;
++ if (integerNumber > epsilon)
++ {
++ integerDigits += (int)TrioLogarithm(integerNumber, base);
++ }
++
++ fractionDigits = precision;
++ if (flags & FLAGS_FLOAT_G)
++ {
++ if (leadingFractionZeroes > 0)
++ {
++ fractionDigits += leadingFractionZeroes;
++ }
++ if ((integerNumber > epsilon) || (number <= epsilon))
++ {
++ fractionDigits -= integerDigits;
++ }
++ }
++
++ dblFractionBase = TrioPower(base, fractionDigits);
++
++ if (integerNumber < 1.0)
++ {
++ workNumber = number * dblFractionBase + TRIO_SUFFIX_LONG(0.5);
++ if (trio_floor(number * dblFractionBase) != trio_floor(workNumber))
++ {
++ adjustNumber = TRUE;
++ /* Remove a leading fraction zero if fraction is rounded up */
++ if ((int)TrioLogarithm(number * dblFractionBase, base) != (int)TrioLogarithm(workNumber, base))
++ {
++ --leadingFractionZeroes;
++ }
++ }
++ workNumber /= dblFractionBase;
++ }
++ else
++ {
++ workNumber = number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase;
++ adjustNumber = (trio_floor(number) != trio_floor(workNumber));
++ }
++ if (adjustNumber)
++ {
++ if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_FLOAT_E))
++ {
++ /* The adjustment may require a change to scientific notation */
++ if ( (workNumber < TRIO_SUFFIX_LONG(1.0E-4)) ||
++ (workNumber >= TrioPower(base, (trio_long_double_t)precision)) )
++ {
++ /* Use scientific notation */
++ flags |= FLAGS_FLOAT_E;
++ goto reprocess;
++ }
++ }
++
++ if (flags & FLAGS_FLOAT_E)
++ {
++ workDigits = 1 + TrioLogarithm(trio_floor(workNumber), base);
++ if (integerDigits == workDigits)
++ {
++ /* Adjust if the same number of digits are used */
++ number += TRIO_SUFFIX_LONG(0.5) / dblFractionBase;
++ integerNumber = trio_floor(number);
++ fractionNumber = number - integerNumber;
++ }
++ else
++ {
++ /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
++ exponent++;
++ isExponentNegative = (exponent < 0);
++ uExponent = (isExponentNegative) ? -exponent : exponent;
++ if (isHex)
++ uExponent *= 4; /* log16(2) */
++ workNumber = (number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase) / dblBase;
++ integerNumber = trio_floor(workNumber);
++ fractionNumber = workNumber - integerNumber;
++ }
++ }
++ else
++ {
++ if (workNumber > 1.0)
++ {
++ /* Adjust if number was rounded up one digit (ie. 99 to 100) */
++ integerNumber = trio_floor(workNumber);
++ fractionNumber = 0.0;
++ integerDigits = (integerNumber > epsilon)
++ ? 1 + (int)TrioLogarithm(integerNumber, base)
++ : 1;
++ if (flags & FLAGS_FLOAT_G)
++ {
++ if (flags & FLAGS_ALTERNATIVE)
++ {
++ if ((integerNumber > epsilon) || (number <= epsilon))
++ {
++ fractionDigits -= integerDigits;
++ }
++ }
++ else
++ {
++ fractionDigits = 0;
++ }
++ }
++ }
++ else
++ {
++ integerNumber = trio_floor(workNumber);
++ fractionNumber = workNumber - integerNumber;
++ if (flags & FLAGS_FLOAT_G)
++ {
++ if (flags & FLAGS_ALTERNATIVE)
++ {
++ fractionDigits = precision;
++ if (leadingFractionZeroes > 0)
++ {
++ fractionDigits += leadingFractionZeroes;
++ }
++ if ((integerNumber > epsilon) || (number <= epsilon))
++ {
++ fractionDigits -= integerDigits;
++ }
++ }
++ }
++ }
++ }
++ }
++
++ /* Estimate accuracy */
++ integerAdjust = fractionAdjust = TRIO_SUFFIX_LONG(0.5);
++# if TRIO_FEATURE_ROUNDING
++ if (flags & FLAGS_ROUNDING)
++ {
++ if (integerDigits > baseDigits)
++ {
++ integerThreshold = baseDigits;
++ fractionDigits = 0;
++ dblFractionBase = 1.0;
++ fractionThreshold = 0;
++ precision = 0; /* Disable decimal-point */
++ integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1);
++ fractionAdjust = 0.0;
++ }
++ else
++ {
++ integerThreshold = integerDigits;
++ fractionThreshold = fractionDigits - integerThreshold;
++ fractionAdjust = 1.0;
++ }
++ }
++ else
++# endif
++ {
++ integerThreshold = INT_MAX;
++ fractionThreshold = INT_MAX;
++ }
++
++ /*
++ * Calculate expected width.
++ * sign + integer part + thousands separators + decimal point
++ * + fraction + exponent
++ */
++ fractionAdjust /= dblFractionBase;
++ hasOnlyZeroes = (trio_floor((fractionNumber + fractionAdjust) *
++ dblFractionBase) < epsilon);
++ keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
++ !((precision == 0) ||
++ (!keepTrailingZeroes && hasOnlyZeroes)) );
++
++ expectedWidth = integerDigits + fractionDigits;
++
++ if (!keepTrailingZeroes)
++ {
++ trailingZeroes = 0;
++ workFractionNumber = fractionNumber;
++ workFractionAdjust = fractionAdjust;
++ fractionDigitsInspect = fractionDigits;
++
++ if (integerDigits > integerThreshold)
++ {
++ fractionDigitsInspect = 0;
++ }
++ else if (fractionThreshold <= fractionDigits)
++ {
++ fractionDigitsInspect = fractionThreshold + 1;
++ }
++
++ trailingZeroes = fractionDigits - fractionDigitsInspect;
++ for (i = 0; i < fractionDigitsInspect; i++)
++ {
++ workFractionNumber *= dblBase;
++ workFractionAdjust *= dblBase;
++ workNumber = trio_floor(workFractionNumber + workFractionAdjust);
++ workFractionNumber -= workNumber;
++ offset = (int)trio_fmod(workNumber, dblBase);
++ if (offset == 0)
++ {
++ trailingZeroes++;
++ }
++ else
++ {
++ trailingZeroes = 0;
++ }
++ }
++ expectedWidth -= trailingZeroes;
++ }
++
++ if (keepDecimalPoint)
++ {
++ expectedWidth += internalDecimalPointLength;
++ }
++
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ {
++ expectedWidth += TrioCalcThousandSeparatorLength(integerDigits);
++ }
++#endif
++
++ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
++ {
++ expectedWidth += sizeof("-") - 1;
++ }
++
++ exponentDigits = 0;
++ if (flags & FLAGS_FLOAT_E)
++ {
++ exponentDigits = (uExponent == 0)
++ ? 1
++ : (int)trio_ceil(TrioLogarithm((double)(uExponent + 1),
++ (isHex) ? 10 : base));
++ }
++ requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1));
++ if (exponentDigits > 0)
++ {
++ expectedWidth += exponentDigits;
++ expectedWidth += (requireTwoDigitExponent
++ ? sizeof("E+0") - 1
++ : sizeof("E+") - 1);
++ }
++
++ if (isHex)
++ {
++ expectedWidth += sizeof("0X") - 1;
++ }
++
++ /* Output prefixing */
++ if (flags & FLAGS_NILPADDING)
++ {
++ /* Leading zeros must be after sign */
++ if (isNegative)
++ self->OutStream(self, '-');
++ else if (flags & FLAGS_SHOWSIGN)
++ self->OutStream(self, '+');
++ else if (flags & FLAGS_SPACE)
++ self->OutStream(self, ' ');
++ if (isHex)
++ {
++ self->OutStream(self, '0');
++ self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
++ }
++ if (!(flags & FLAGS_LEFTADJUST))
++ {
++ for (i = expectedWidth; i < width; i++)
++ {
++ self->OutStream(self, '0');
++ }
++ }
++ }
++ else
++ {
++ /* Leading spaces must be before sign */
++ if (!(flags & FLAGS_LEFTADJUST))
++ {
++ for (i = expectedWidth; i < width; i++)
++ {
++ self->OutStream(self, CHAR_ADJUST);
++ }
++ }
++ if (isNegative)
++ self->OutStream(self, '-');
++ else if (flags & FLAGS_SHOWSIGN)
++ self->OutStream(self, '+');
++ else if (flags & FLAGS_SPACE)
++ self->OutStream(self, ' ');
++ if (isHex)
++ {
++ self->OutStream(self, '0');
++ self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
++ }
++ }
++
++ /* Output the integer part and thousand separators */
++ for (i = 0; i < integerDigits; i++)
++ {
++ workNumber = trio_floor(((integerNumber + integerAdjust)
++ / TrioPower(base, integerDigits - i - 1)));
++ if (i > integerThreshold)
++ {
++ /* Beyond accuracy */
++ self->OutStream(self, digits[0]);
++ }
++ else
++ {
++ self->OutStream(self, digits[(int)trio_fmod(workNumber, dblBase)]);
++ }
++
++#if TRIO_FEATURE_QUOTE
++ if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
++ && TrioFollowedBySeparator(integerDigits - i))
++ {
++ for (groupingPointer = internalThousandSeparator;
++ *groupingPointer != NIL;
++ groupingPointer++)
++ {
++ self->OutStream(self, *groupingPointer);
++ }
++ }
++#endif
++ }
++
++ /* Insert decimal point and build the fraction part */
++ trailingZeroes = 0;
++
++ if (keepDecimalPoint)
++ {
++ if (internalDecimalPoint)
++ {
++ self->OutStream(self, internalDecimalPoint);
++ }
++ else
++ {
++ for (i = 0; i < internalDecimalPointLength; i++)
++ {
++ self->OutStream(self, internalDecimalPointString[i]);
++ }
++ }
++ }
++
++ for (i = 0; i < fractionDigits; i++)
++ {
++ if ((integerDigits > integerThreshold) || (i > fractionThreshold))
++ {
++ /* Beyond accuracy */
++ trailingZeroes++;
++ }
++ else
++ {
++ fractionNumber *= dblBase;
++ fractionAdjust *= dblBase;
++ workNumber = trio_floor(fractionNumber + fractionAdjust);
++ if (workNumber > fractionNumber)
++ {
++ /* fractionNumber should never become negative */
++ fractionNumber = 0.0;
++ fractionAdjust = 0.0;
++ }
++ else
++ {
++ fractionNumber -= workNumber;
++ }
++ offset = (int)trio_fmod(workNumber, dblBase);
++ if (offset == 0)
++ {
++ trailingZeroes++;
++ }
++ else
++ {
++ while (trailingZeroes > 0)
++ {
++ /* Not trailing zeroes after all */
++ self->OutStream(self, digits[0]);
++ trailingZeroes--;
++ }
++ self->OutStream(self, digits[offset]);
++ }
++ }
++ }
++
++ if (keepTrailingZeroes)
++ {
++ while (trailingZeroes > 0)
++ {
++ self->OutStream(self, digits[0]);
++ trailingZeroes--;
++ }
++ }
++
++ /* Output exponent */
++ if (exponentDigits > 0)
++ {
++ self->OutStream(self,
++ isHex
++ ? ((flags & FLAGS_UPPER) ? 'P' : 'p')
++ : ((flags & FLAGS_UPPER) ? 'E' : 'e'));
++ self->OutStream(self, (isExponentNegative) ? '-' : '+');
++
++ /* The exponent must contain at least two digits */
++ if (requireTwoDigitExponent)
++ self->OutStream(self, '0');
++
++ if (isHex)
++ base = 10;
++ exponentBase = (int)TrioPower(base, exponentDigits - 1);
++ for (i = 0; i < exponentDigits; i++)
++ {
++ self->OutStream(self, digits[(uExponent / exponentBase) % base]);
++ exponentBase /= base;
++ }
++ }
++ /* Output trailing spaces */
++ if (flags & FLAGS_LEFTADJUST)
++ {
++ for (i = expectedWidth; i < width; i++)
++ {
++ self->OutStream(self, CHAR_ADJUST);
++ }
++ }
++}
++#endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * TrioFormatProcess
++ *
++ * Description:
++ * This is the main engine for formatting output
++ */
++TRIO_PRIVATE int
++TrioFormatProcess
++TRIO_ARGS3((data, format, parameters),
++ trio_class_t *data,
++ TRIO_CONST char *format,
++ trio_parameter_t *parameters)
++{
++ int i;
++#if TRIO_FEATURE_ERRNO
++ TRIO_CONST char *string;
++#endif
++ trio_pointer_t pointer;
++ trio_flags_t flags;
++ int width;
++ int precision;
++ int base;
++ int offset;
++
++ offset = 0;
++ i = 0;
++
++ for (;;)
++ {
++ /* Skip the parameter entries */
++ while (parameters[i].type == FORMAT_PARAMETER)
++ i++;
++
++ /* Copy non conversion-specifier part of format string */
++ while (offset < parameters[i].beginOffset)
++ {
++ if (CHAR_IDENTIFIER == format[offset] && CHAR_IDENTIFIER == format[offset + 1])
++ {
++ data->OutStream(data, CHAR_IDENTIFIER);
++ offset += 2;
++ }
++ else
++ {
++ data->OutStream(data, format[offset++]);
++ }
++ }
++
++ /* Abort if we reached end of format string */
++ if (parameters[i].type == FORMAT_SENTINEL)
++ break;
++
++ /* Ouput parameter */
++ flags = parameters[i].flags;
++
++ /* Find width */
++ width = parameters[i].width;
++ if (flags & FLAGS_WIDTH_PARAMETER)
++ {
++ /* Get width from parameter list */
++ width = (int)parameters[width].data.number.as_signed;
++ if (width < 0)
++ {
++ /*
++ * A negative width is the same as the - flag and
++ * a positive width.
++ */
++ flags |= FLAGS_LEFTADJUST;
++ flags &= ~FLAGS_NILPADDING;
++ width = -width;
++ }
++ }
++
++ /* Find precision */
++ if (flags & FLAGS_PRECISION)
++ {
++ precision = parameters[i].precision;
++ if (flags & FLAGS_PRECISION_PARAMETER)
++ {
++ /* Get precision from parameter list */
++ precision = (int)parameters[precision].data.number.as_signed;
++ if (precision < 0)
++ {
++ /*
++ * A negative precision is the same as no
++ * precision
++ */
++ precision = NO_PRECISION;
++ }
++ }
++ }
++ else
++ {
++ precision = NO_PRECISION;
++ }
++
++ /* Find base */
++ if (NO_BASE != parameters[i].baseSpecifier)
++ {
++ /* Base from specifier has priority */
++ base = parameters[i].baseSpecifier;
++ }
++ else if (flags & FLAGS_BASE_PARAMETER)
++ {
++ /* Get base from parameter list */
++ base = parameters[i].base;
++ base = (int)parameters[base].data.number.as_signed;
++ }
++ else
++ {
++ /* Use base from format string */
++ base = parameters[i].base;
++ }
++
++ switch (parameters[i].type)
++ {
++ case FORMAT_CHAR:
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ data->OutStream(data, CHAR_QUOTE);
++#endif
++ if (! (flags & FLAGS_LEFTADJUST))
++ {
++ while (--width > 0)
++ data->OutStream(data, CHAR_ADJUST);
++ }
++#if TRIO_FEATURE_WIDECHAR
++ if (flags & FLAGS_WIDECHAR)
++ {
++ TrioWriteWideStringCharacter(data,
++ (trio_wchar_t)parameters[i].data.number.as_signed,
++ flags,
++ NO_WIDTH);
++ }
++ else
++#endif
++ {
++ TrioWriteStringCharacter(data,
++ (int)parameters[i].data.number.as_signed,
++ flags);
++ }
++
++ if (flags & FLAGS_LEFTADJUST)
++ {
++ while(--width > 0)
++ data->OutStream(data, CHAR_ADJUST);
++ }
++#if TRIO_FEATURE_QUOTE
++ if (flags & FLAGS_QUOTE)
++ data->OutStream(data, CHAR_QUOTE);
++#endif
++
++ break; /* FORMAT_CHAR */
++
++ case FORMAT_INT:
++ TrioWriteNumber(data,
++ parameters[i].data.number.as_unsigned,
++ flags,
++ width,
++ precision,
++ base);
++
++ break; /* FORMAT_INT */
++
++#if TRIO_FEATURE_FLOAT
++ case FORMAT_DOUBLE:
++ TrioWriteDouble(data,
++ parameters[i].data.longdoubleNumber,
++ flags,
++ width,
++ precision,
++ base);
++ break; /* FORMAT_DOUBLE */
++#endif
++
++ case FORMAT_STRING:
++#if TRIO_FEATURE_WIDECHAR
++ if (flags & FLAGS_WIDECHAR)
++ {
++ TrioWriteWideString(data,
++ parameters[i].data.wstring,
++ flags,
++ width,
++ precision);
++ }
++ else
++#endif
++ {
++ TrioWriteString(data,
++ parameters[i].data.string,
++ flags,
++ width,
++ precision);
++ }
++ break; /* FORMAT_STRING */
++
++ case FORMAT_POINTER:
++ {
++ trio_reference_t reference;
++
++ reference.data = data;
++ reference.parameter = &parameters[i];
++ trio_print_pointer(&reference, parameters[i].data.pointer);
++ }
++ break; /* FORMAT_POINTER */
++
++ case FORMAT_COUNT:
++ pointer = parameters[i].data.pointer;
++ if (NULL != pointer)
++ {
++ /*
++ * C99 paragraph 7.19.6.1.8 says "the number of
++ * characters written to the output stream so far by
++ * this call", which is data->actually.committed
++ */
++#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
++ if (flags & FLAGS_SIZE_T)
++ *(size_t *)pointer = (size_t)data->actually.committed;
++ else
++#endif
++#if TRIO_FEATURE_PTRDIFF_T
++ if (flags & FLAGS_PTRDIFF_T)
++ *(ptrdiff_t *)pointer = (ptrdiff_t)data->actually.committed;
++ else
++#endif
++#if TRIO_FEATURE_INTMAX_T
++ if (flags & FLAGS_INTMAX_T)
++ *(trio_intmax_t *)pointer = (trio_intmax_t)data->actually.committed;
++ else
++#endif
++ if (flags & FLAGS_QUAD)
++ {
++ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->actually.committed;
++ }
++ else if (flags & FLAGS_LONG)
++ {
++ *(long int *)pointer = (long int)data->actually.committed;
++ }
++ else if (flags & FLAGS_SHORT)
++ {
++ *(short int *)pointer = (short int)data->actually.committed;
++ }
++ else
++ {
++ *(int *)pointer = (int)data->actually.committed;
++ }
++ }
++ break; /* FORMAT_COUNT */
++
++ case FORMAT_PARAMETER:
++ break; /* FORMAT_PARAMETER */
++
++#if TRIO_FEATURE_ERRNO
++ case FORMAT_ERRNO:
++ string = trio_error(parameters[i].data.errorNumber);
++ if (string)
++ {
++ TrioWriteString(data,
++ string,
++ flags,
++ width,
++ precision);
++ }
++ else
++ {
++ data->OutStream(data, '#');
++ TrioWriteNumber(data,
++ (trio_uintmax_t)parameters[i].data.errorNumber,
++ flags,
++ width,
++ precision,
++ BASE_DECIMAL);
++ }
++ break; /* FORMAT_ERRNO */
++#endif /* TRIO_FEATURE_ERRNO */
++
++#if TRIO_FEATURE_USER_DEFINED
++ case FORMAT_USER_DEFINED:
++ {
++ trio_reference_t reference;
++ trio_userdef_t *def = NULL;
++
++ if (parameters[i].flags & FLAGS_USER_DEFINED_PARAMETER)
++ {
++ /* Use handle */
++ if ((i > 0) ||
++ (parameters[i - 1].type == FORMAT_PARAMETER))
++ def = (trio_userdef_t *)parameters[i - 1].data.pointer;
++ }
++ else
++ {
++ /* Look up namespace */
++ def = TrioFindNamespace(parameters[i].user_defined.namespace, NULL);
++ }
++ if (def)
++ {
++ reference.data = data;
++ reference.parameter = &parameters[i];
++ def->callback(&reference);
++ }
++ }
++ break;
++#endif /* TRIO_FEATURE_USER_DEFINED */
++
++ default:
++ break;
++ } /* switch parameter type */
++
++ /* Prepare for next */
++ offset = parameters[i].endOffset;
++ i++;
++ }
++
++ return data->processed;
++}
++
++/*************************************************************************
++ * TrioFormatRef
++ */
++#if TRIO_EXTENSION
++TRIO_PRIVATE int
++TrioFormatRef
++TRIO_ARGS4((reference, format, arglist, argarray),
++ trio_reference_t *reference,
++ TRIO_CONST char *format,
++ va_list arglist,
++ trio_pointer_t *argarray)
++{
++ int status;
++ trio_parameter_t parameters[MAX_PARAMETERS];
++
++ status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
++ if (status < 0)
++ return status;
++
++ status = TrioFormatProcess(reference->data, format, parameters);
++ if (reference->data->error != 0)
++ {
++ status = reference->data->error;
++ }
++ return status;
++}
++#endif /* TRIO_EXTENSION */
++
++/*************************************************************************
++ * TrioFormat
++ */
++TRIO_PRIVATE int
++TrioFormat
++TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
++ trio_pointer_t destination,
++ size_t destinationSize,
++ void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
++ TRIO_CONST char *format,
++ va_list arglist,
++ trio_pointer_t *argarray)
++{
++ int status;
++ trio_class_t data;
++ trio_parameter_t parameters[MAX_PARAMETERS];
++
++ assert(VALID(OutStream));
++ assert(VALID(format));
++
++ memset(&data, 0, sizeof(data));
++ data.OutStream = OutStream;
++ data.location = destination;
++ data.max = destinationSize;
++ data.error = 0;
++
++#if defined(USE_LOCALE)
++ if (NULL == internalLocaleValues)
++ {
++ TrioSetLocale();
++ }
++#endif
++
++ status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
++ if (status < 0)
++ return status;
++
++ status = TrioFormatProcess(&data, format, parameters);
++ if (data.error != 0)
++ {
++ status = data.error;
++ }
++ return status;
++}
++
++/*************************************************************************
++ * TrioOutStreamFile
++ */
++#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
++TRIO_PRIVATE void
++TrioOutStreamFile
++TRIO_ARGS2((self, output),
++ trio_class_t *self,
++ int output)
++{
++ FILE *file;
++
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ file = (FILE *)self->location;
++ self->processed++;
++ if (fputc(output, file) == EOF)
++ {
++ self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0);
++ }
++ else
++ {
++ self->actually.committed++;
++ }
++}
++#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
++
++/*************************************************************************
++ * TrioOutStreamFileDescriptor
++ */
++#if TRIO_FEATURE_FD
++TRIO_PRIVATE void
++TrioOutStreamFileDescriptor
++TRIO_ARGS2((self, output),
++ trio_class_t *self,
++ int output)
++{
++ int fd;
++ char ch;
++
++ assert(VALID(self));
++
++ fd = *((int *)self->location);
++ ch = (char)output;
++ self->processed++;
++ if (write(fd, &ch, sizeof(char)) == -1)
++ {
++ self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
++ }
++ else
++ {
++ self->actually.committed++;
++ }
++}
++#endif /* TRIO_FEATURE_FD */
++
++/*************************************************************************
++ * TrioOutStreamCustom
++ */
++#if TRIO_FEATURE_CLOSURE
++TRIO_PRIVATE void
++TrioOutStreamCustom
++TRIO_ARGS2((self, output),
++ trio_class_t *self,
++ int output)
++{
++ int status;
++ trio_custom_t *data;
++
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ data = (trio_custom_t *)self->location;
++ if (data->stream.out)
++ {
++ status = (data->stream.out)(data->closure, output);
++ if (status >= 0)
++ {
++ self->actually.committed++;
++ }
++ else
++ {
++ if (self->error == 0)
++ {
++ self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status);
++ }
++ }
++ }
++ self->processed++;
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++/*************************************************************************
++ * TrioOutStreamString
++ */
++TRIO_PRIVATE void
++TrioOutStreamString
++TRIO_ARGS2((self, output),
++ trio_class_t *self,
++ int output)
++{
++ char **buffer;
++
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ buffer = (char **)self->location;
++ **buffer = (char)output;
++ (*buffer)++;
++ self->processed++;
++ self->actually.committed++;
++}
++
++/*************************************************************************
++ * TrioOutStreamStringMax
++ */
++TRIO_PRIVATE void
++TrioOutStreamStringMax
++TRIO_ARGS2((self, output),
++ trio_class_t *self,
++ int output)
++{
++ char **buffer;
++
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ buffer = (char **)self->location;
++
++ if (self->processed < self->max)
++ {
++ **buffer = (char)output;
++ (*buffer)++;
++ self->actually.committed++;
++ }
++ self->processed++;
++}
++
++/*************************************************************************
++ * TrioOutStreamStringDynamic
++ */
++#if TRIO_FEATURE_DYNAMICSTRING
++TRIO_PRIVATE void
++TrioOutStreamStringDynamic
++TRIO_ARGS2((self, output),
++ trio_class_t *self,
++ int output)
++{
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ if (self->error == 0)
++ {
++ trio_xstring_append_char((trio_string_t *)self->location,
++ (char)output);
++ self->actually.committed++;
++ }
++ /* The processed variable must always be increased */
++ self->processed++;
++}
++#endif /* TRIO_FEATURE_DYNAMICSTRING */
++
++/*************************************************************************
++ *
++ * Formatted printing functions
++ *
++ ************************************************************************/
++
++#if defined(TRIO_DOCUMENTATION)
++# include "doc/doc_printf.h"
++#endif
++/** @addtogroup Printf
++ @{
++*/
++
++/*************************************************************************
++ * printf
++ */
++
++/**
++ Print to standard output stream.
++
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_STDIO
++TRIO_PUBLIC int
++trio_printf
++TRIO_VARGS2((format, va_alist),
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_STDIO */
++
++/**
++ Print to standard output stream.
++
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_STDIO
++TRIO_PUBLIC int
++trio_vprintf
++TRIO_ARGS2((format, args),
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(format));
++
++ return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
++}
++#endif /* TRIO_FEATURE_STDIO */
++
++/**
++ Print to standard output stream.
++
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_STDIO
++TRIO_PUBLIC int
++trio_printfv
++TRIO_ARGS2((format, args),
++ TRIO_CONST char *format,
++ trio_pointer_t * args)
++{
++ static va_list unused;
++
++ assert(VALID(format));
++
++ return TrioFormat(stdout, 0, TrioOutStreamFile, format, unused, args);
++}
++#endif /* TRIO_FEATURE_STDIO */
++
++/*************************************************************************
++ * fprintf
++ */
++
++/**
++ Print to file.
++
++ @param file File pointer.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_FILE
++TRIO_PUBLIC int
++trio_fprintf
++TRIO_VARGS3((file, format, va_alist),
++ FILE *file,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(file));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_FILE */
++
++/**
++ Print to file.
++
++ @param file File pointer.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_FILE
++TRIO_PUBLIC int
++trio_vfprintf
++TRIO_ARGS3((file, format, args),
++ FILE *file,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(file));
++ assert(VALID(format));
++
++ return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
++}
++#endif /* TRIO_FEATURE_FILE */
++
++/**
++ Print to file.
++
++ @param file File pointer.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_FILE
++TRIO_PUBLIC int
++trio_fprintfv
++TRIO_ARGS3((file, format, args),
++ FILE *file,
++ TRIO_CONST char *format,
++ trio_pointer_t * args)
++{
++ static va_list unused;
++
++ assert(VALID(file));
++ assert(VALID(format));
++
++ return TrioFormat(file, 0, TrioOutStreamFile, format, unused, args);
++}
++#endif /* TRIO_FEATURE_FILE */
++
++/*************************************************************************
++ * dprintf
++ */
++
++/**
++ Print to file descriptor.
++
++ @param fd File descriptor.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_FD
++TRIO_PUBLIC int
++trio_dprintf
++TRIO_VARGS3((fd, format, va_alist),
++ int fd,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_FD */
++
++/**
++ Print to file descriptor.
++
++ @param fd File descriptor.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_FD
++TRIO_PUBLIC int
++trio_vdprintf
++TRIO_ARGS3((fd, format, args),
++ int fd,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(format));
++
++ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
++}
++#endif /* TRIO_FEATURE_FD */
++
++/**
++ Print to file descriptor.
++
++ @param fd File descriptor.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_FD
++TRIO_PUBLIC int
++trio_dprintfv
++TRIO_ARGS3((fd, format, args),
++ int fd,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++
++ assert(VALID(format));
++
++ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, unused, args);
++}
++#endif /* TRIO_FEATURE_FD */
++
++/*************************************************************************
++ * cprintf
++ */
++#if TRIO_FEATURE_CLOSURE
++TRIO_PUBLIC int
++trio_cprintf
++TRIO_VARGS4((stream, closure, format, va_alist),
++ trio_outstream_t stream,
++ trio_pointer_t closure,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++ trio_custom_t data;
++
++ assert(VALID(stream));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ data.stream.out = stream;
++ data.closure = closure;
++ status = TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++#if TRIO_FEATURE_CLOSURE
++TRIO_PUBLIC int
++trio_vcprintf
++TRIO_ARGS4((stream, closure, format, args),
++ trio_outstream_t stream,
++ trio_pointer_t closure,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ trio_custom_t data;
++
++ assert(VALID(stream));
++ assert(VALID(format));
++
++ data.stream.out = stream;
++ data.closure = closure;
++ return TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++#if TRIO_FEATURE_CLOSURE
++TRIO_PUBLIC int
++trio_cprintfv
++TRIO_ARGS4((stream, closure, format, args),
++ trio_outstream_t stream,
++ trio_pointer_t closure,
++ TRIO_CONST char *format,
++ void **args)
++{
++ static va_list unused;
++ trio_custom_t data;
++
++ assert(VALID(stream));
++ assert(VALID(format));
++
++ data.stream.out = stream;
++ data.closure = closure;
++ return TrioFormat(&data, 0, TrioOutStreamCustom, format, unused, args);
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++/*************************************************************************
++ * sprintf
++ */
++
++/**
++ Print to string.
++
++ @param buffer Output string.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of printed characters.
++ */
++TRIO_PUBLIC int
++trio_sprintf
++TRIO_VARGS3((buffer, format, va_alist),
++ char *buffer,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
++ *buffer = NIL; /* Terminate with NIL character */
++ TRIO_VA_END(args);
++ return status;
++}
++
++/**
++ Print to string.
++
++ @param buffer Output string.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++TRIO_PUBLIC int
++trio_vsprintf
++TRIO_ARGS3((buffer, format, args),
++ char *buffer,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ int status;
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
++ *buffer = NIL;
++ return status;
++}
++
++/**
++ Print to string.
++
++ @param buffer Output string.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++TRIO_PUBLIC int
++trio_sprintfv
++TRIO_ARGS3((buffer, format, args),
++ char *buffer,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++ int status;
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, unused, args);
++ *buffer = NIL;
++ return status;
++}
++
++/*************************************************************************
++ * snprintf
++ */
++
++/**
++ Print at most @p max characters to string.
++
++ @param buffer Output string.
++ @param max Maximum number of characters to print.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of printed characters.
++ */
++TRIO_PUBLIC int
++trio_snprintf
++TRIO_VARGS4((buffer, max, format, va_alist),
++ char *buffer,
++ size_t max,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(buffer) || (max == 0));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
++ TrioOutStreamStringMax, format, args, NULL);
++ if (max > 0)
++ *buffer = NIL;
++ TRIO_VA_END(args);
++ return status;
++}
++
++/**
++ Print at most @p max characters to string.
++
++ @param buffer Output string.
++ @param max Maximum number of characters to print.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++TRIO_PUBLIC int
++trio_vsnprintf
++TRIO_ARGS4((buffer, max, format, args),
++ char *buffer,
++ size_t max,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ int status;
++
++ assert(VALID(buffer) || (max == 0));
++ assert(VALID(format));
++
++ status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
++ TrioOutStreamStringMax, format, args, NULL);
++ if (max > 0)
++ *buffer = NIL;
++ return status;
++}
++
++/**
++ Print at most @p max characters to string.
++
++ @param buffer Output string.
++ @param max Maximum number of characters to print.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++TRIO_PUBLIC int
++trio_snprintfv
++TRIO_ARGS4((buffer, max, format, args),
++ char *buffer,
++ size_t max,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++ int status;
++
++ assert(VALID(buffer) || (max == 0));
++ assert(VALID(format));
++
++ status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
++ TrioOutStreamStringMax, format, unused, args);
++ if (max > 0)
++ *buffer = NIL;
++ return status;
++}
++
++/*************************************************************************
++ * snprintfcat
++ * Appends the new string to the buffer string overwriting the '\0'
++ * character at the end of buffer.
++ */
++#if TRIO_EXTENSION
++TRIO_PUBLIC int
++trio_snprintfcat
++TRIO_VARGS4((buffer, max, format, va_alist),
++ char *buffer,
++ size_t max,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++ size_t buf_len;
++
++ TRIO_VA_START(args, format);
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ buf_len = trio_length(buffer);
++ buffer = &buffer[buf_len];
++
++ status = TrioFormat(&buffer, max - 1 - buf_len,
++ TrioOutStreamStringMax, format, args, NULL);
++ TRIO_VA_END(args);
++ *buffer = NIL;
++ return status;
++}
++#endif
++
++#if TRIO_EXTENSION
++TRIO_PUBLIC int
++trio_vsnprintfcat
++TRIO_ARGS4((buffer, max, format, args),
++ char *buffer,
++ size_t max,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ int status;
++ size_t buf_len;
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ buf_len = trio_length(buffer);
++ buffer = &buffer[buf_len];
++ status = TrioFormat(&buffer, max - 1 - buf_len,
++ TrioOutStreamStringMax, format, args, NULL);
++ *buffer = NIL;
++ return status;
++}
++#endif
++
++/*************************************************************************
++ * trio_aprintf
++ */
++
++#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
++TRIO_PUBLIC char *
++trio_aprintf
++TRIO_VARGS2((format, va_alist),
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ va_list args;
++ trio_string_t *info;
++ char *result = NULL;
++
++ assert(VALID(format));
++
++ info = trio_xstring_duplicate("");
++ if (info)
++ {
++ TRIO_VA_START(args, format);
++ (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
++ format, args, NULL);
++ TRIO_VA_END(args);
++
++ trio_string_terminate(info);
++ result = trio_string_extract(info);
++ trio_string_destroy(info);
++ }
++ return result;
++}
++#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
++
++#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
++TRIO_PUBLIC char *
++trio_vaprintf
++TRIO_ARGS2((format, args),
++ TRIO_CONST char *format,
++ va_list args)
++{
++ trio_string_t *info;
++ char *result = NULL;
++
++ assert(VALID(format));
++
++ info = trio_xstring_duplicate("");
++ if (info)
++ {
++ (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
++ format, args, NULL);
++ trio_string_terminate(info);
++ result = trio_string_extract(info);
++ trio_string_destroy(info);
++ }
++ return result;
++}
++#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
++
++/**
++ Allocate and print to string.
++ The memory allocated and returned by @p result must be freed by the
++ calling application.
++
++ @param result Output string.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_DYNAMICSTRING
++TRIO_PUBLIC int
++trio_asprintf
++TRIO_VARGS3((result, format, va_alist),
++ char **result,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ va_list args;
++ int status;
++ trio_string_t *info;
++
++ assert(VALID(format));
++
++ *result = NULL;
++
++ info = trio_xstring_duplicate("");
++ if (info == NULL)
++ {
++ status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
++ }
++ else
++ {
++ TRIO_VA_START(args, format);
++ status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
++ format, args, NULL);
++ TRIO_VA_END(args);
++ if (status >= 0)
++ {
++ trio_string_terminate(info);
++ *result = trio_string_extract(info);
++ }
++ trio_string_destroy(info);
++ }
++ return status;
++}
++#endif /* TRIO_FEATURE_DYNAMICSTRING */
++
++/**
++ Allocate and print to string.
++ The memory allocated and returned by @p result must be freed by the
++ calling application.
++
++ @param result Output string.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_DYNAMICSTRING
++TRIO_PUBLIC int
++trio_vasprintf
++TRIO_ARGS3((result, format, args),
++ char **result,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ int status;
++ trio_string_t *info;
++
++ assert(VALID(format));
++
++ *result = NULL;
++
++ info = trio_xstring_duplicate("");
++ if (info == NULL)
++ {
++ status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
++ }
++ else
++ {
++ status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
++ format, args, NULL);
++ if (status >= 0)
++ {
++ trio_string_terminate(info);
++ *result = trio_string_extract(info);
++ }
++ trio_string_destroy(info);
++ }
++ return status;
++}
++#endif /* TRIO_FEATURE_DYNAMICSTRING */
++
++/**
++ Allocate and print to string.
++ The memory allocated and returned by @p result must be freed by the
++ calling application.
++
++ @param result Output string.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of printed characters.
++ */
++#if TRIO_FEATURE_DYNAMICSTRING
++TRIO_PUBLIC int
++trio_asprintfv
++TRIO_ARGS3((result, format, args),
++ char **result,
++ TRIO_CONST char *format,
++ trio_pointer_t * args)
++{
++ static va_list unused;
++ int status;
++ trio_string_t *info;
++
++ assert(VALID(format));
++
++ *result = NULL;
++
++ info = trio_xstring_duplicate("");
++ if (info == NULL)
++ {
++ status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
++ }
++ else
++ {
++ status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
++ format, unused, args);
++ if (status >= 0)
++ {
++ trio_string_terminate(info);
++ *result = trio_string_extract(info);
++ }
++ trio_string_destroy(info);
++ }
++ return status;
++}
++#endif /* TRIO_FEATURE_DYNAMICSTRING */
++
++/** @} End of Printf documentation module */
++
++/*************************************************************************
++ *
++ * CALLBACK
++ *
++ ************************************************************************/
++
++#if defined(TRIO_DOCUMENTATION)
++# include "doc/doc_register.h"
++#endif
++/**
++ @addtogroup UserDefined
++ @{
++*/
++
++#if TRIO_FEATURE_USER_DEFINED
++
++/*************************************************************************
++ * trio_register
++ */
++
++/**
++ Register new user-defined specifier.
++
++ @param callback
++ @param name
++ @return Handle.
++ */
++TRIO_PUBLIC trio_pointer_t
++trio_register
++TRIO_ARGS2((callback, name),
++ trio_callback_t callback,
++ TRIO_CONST char *name)
++{
++ trio_userdef_t *def;
++ trio_userdef_t *prev = NULL;
++
++ if (callback == NULL)
++ return NULL;
++
++ if (name)
++ {
++ /* Handle built-in namespaces */
++ if (name[0] == ':')
++ {
++ if (trio_equal(name, ":enter"))
++ {
++ internalEnterCriticalRegion = callback;
++ }
++ else if (trio_equal(name, ":leave"))
++ {
++ internalLeaveCriticalRegion = callback;
++ }
++ return NULL;
++ }
++
++ /* Bail out if namespace is too long */
++ if (trio_length(name) >= MAX_USER_NAME)
++ return NULL;
++
++ /* Bail out if namespace already is registered */
++ def = TrioFindNamespace(name, &prev);
++ if (def)
++ return NULL;
++ }
++
++ def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t));
++ if (def)
++ {
++ if (internalEnterCriticalRegion)
++ (void)internalEnterCriticalRegion(NULL);
++
++ if (name)
++ {
++ /* Link into internal list */
++ if (prev == NULL)
++ internalUserDef = def;
++ else
++ prev->next = def;
++ }
++ /* Initialize */
++ def->callback = callback;
++ def->name = (name == NULL)
++ ? NULL
++ : trio_duplicate(name);
++ def->next = NULL;
++
++ if (internalLeaveCriticalRegion)
++ (void)internalLeaveCriticalRegion(NULL);
++ }
++ return (trio_pointer_t)def;
++}
++
++/**
++ Unregister an existing user-defined specifier.
++
++ @param handle
++ */
++void
++trio_unregister
++TRIO_ARGS1((handle),
++ trio_pointer_t handle)
++{
++ trio_userdef_t *self = (trio_userdef_t *)handle;
++ trio_userdef_t *def;
++ trio_userdef_t *prev = NULL;
++
++ assert(VALID(self));
++
++ if (self->name)
++ {
++ def = TrioFindNamespace(self->name, &prev);
++ if (def)
++ {
++ if (internalEnterCriticalRegion)
++ (void)internalEnterCriticalRegion(NULL);
++
++ if (prev == NULL)
++ internalUserDef = internalUserDef->next;
++ else
++ prev->next = def->next;
++
++ if (internalLeaveCriticalRegion)
++ (void)internalLeaveCriticalRegion(NULL);
++ }
++ trio_destroy(self->name);
++ }
++ TRIO_FREE(self);
++}
++
++/*************************************************************************
++ * trio_get_format [public]
++ */
++TRIO_CONST char *
++trio_get_format
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++#if TRIO_FEATURE_USER_DEFINED
++ assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
++#endif
++
++ return (((trio_reference_t *)ref)->parameter->user_data);
++}
++
++/*************************************************************************
++ * trio_get_argument [public]
++ */
++TRIO_CONST trio_pointer_t
++trio_get_argument
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++#if TRIO_FEATURE_USER_DEFINED
++ assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
++#endif
++
++ return ((trio_reference_t *)ref)->parameter->data.pointer;
++}
++
++/*************************************************************************
++ * trio_get_width / trio_set_width [public]
++ */
++int
++trio_get_width
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return ((trio_reference_t *)ref)->parameter->width;
++}
++
++void
++trio_set_width
++TRIO_ARGS2((ref, width),
++ trio_pointer_t ref,
++ int width)
++{
++ ((trio_reference_t *)ref)->parameter->width = width;
++}
++
++/*************************************************************************
++ * trio_get_precision / trio_set_precision [public]
++ */
++int
++trio_get_precision
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->precision);
++}
++
++void
++trio_set_precision
++TRIO_ARGS2((ref, precision),
++ trio_pointer_t ref,
++ int precision)
++{
++ ((trio_reference_t *)ref)->parameter->precision = precision;
++}
++
++/*************************************************************************
++ * trio_get_base / trio_set_base [public]
++ */
++int
++trio_get_base
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->base);
++}
++
++void
++trio_set_base
++TRIO_ARGS2((ref, base),
++ trio_pointer_t ref,
++ int base)
++{
++ ((trio_reference_t *)ref)->parameter->base = base;
++}
++
++/*************************************************************************
++ * trio_get_long / trio_set_long [public]
++ */
++int
++trio_get_long
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_long
++TRIO_ARGS2((ref, is_long),
++ trio_pointer_t ref,
++ int is_long)
++{
++ if (is_long)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG;
++}
++
++/*************************************************************************
++ * trio_get_longlong / trio_set_longlong [public]
++ */
++int
++trio_get_longlong
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_longlong
++TRIO_ARGS2((ref, is_longlong),
++ trio_pointer_t ref,
++ int is_longlong)
++{
++ if (is_longlong)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD;
++}
++
++/*************************************************************************
++ * trio_get_longdouble / trio_set_longdouble [public]
++ */
++# if TRIO_FEATURE_FLOAT
++int
++trio_get_longdouble
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_longdouble
++TRIO_ARGS2((ref, is_longdouble),
++ trio_pointer_t ref,
++ int is_longdouble)
++{
++ if (is_longdouble)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
++}
++# endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * trio_get_short / trio_set_short [public]
++ */
++int
++trio_get_short
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_short
++TRIO_ARGS2((ref, is_short),
++ trio_pointer_t ref,
++ int is_short)
++{
++ if (is_short)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT;
++}
++
++/*************************************************************************
++ * trio_get_shortshort / trio_set_shortshort [public]
++ */
++int
++trio_get_shortshort
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_shortshort
++TRIO_ARGS2((ref, is_shortshort),
++ trio_pointer_t ref,
++ int is_shortshort)
++{
++ if (is_shortshort)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT;
++}
++
++/*************************************************************************
++ * trio_get_alternative / trio_set_alternative [public]
++ */
++int
++trio_get_alternative
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_alternative
++TRIO_ARGS2((ref, is_alternative),
++ trio_pointer_t ref,
++ int is_alternative)
++{
++ if (is_alternative)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE;
++}
++
++/*************************************************************************
++ * trio_get_alignment / trio_set_alignment [public]
++ */
++int
++trio_get_alignment
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_alignment
++TRIO_ARGS2((ref, is_leftaligned),
++ trio_pointer_t ref,
++ int is_leftaligned)
++{
++ if (is_leftaligned)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST;
++}
++
++/*************************************************************************
++ * trio_get_spacing /trio_set_spacing [public]
++ */
++int
++trio_get_spacing
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_spacing
++TRIO_ARGS2((ref, is_space),
++ trio_pointer_t ref,
++ int is_space)
++{
++ if (is_space)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE;
++}
++
++/*************************************************************************
++ * trio_get_sign / trio_set_sign [public]
++ */
++int
++trio_get_sign
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_sign
++TRIO_ARGS2((ref, is_sign),
++ trio_pointer_t ref,
++ int is_sign)
++{
++ if (is_sign)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN;
++}
++
++/*************************************************************************
++ * trio_get_padding / trio_set_padding [public]
++ */
++int
++trio_get_padding
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_padding
++TRIO_ARGS2((ref, is_padding),
++ trio_pointer_t ref,
++ int is_padding)
++{
++ if (is_padding)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING;
++}
++
++/*************************************************************************
++ * trio_get_quote / trio_set_quote [public]
++ */
++# if TRIO_FEATURE_QUOTE
++int
++trio_get_quote
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_quote
++TRIO_ARGS2((ref, is_quote),
++ trio_pointer_t ref,
++ int is_quote)
++{
++ if (is_quote)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
++}
++#endif /* TRIO_FEATURE_QUOTE */
++
++/*************************************************************************
++ * trio_get_upper / trio_set_upper [public]
++ */
++int
++trio_get_upper
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_upper
++TRIO_ARGS2((ref, is_upper),
++ trio_pointer_t ref,
++ int is_upper)
++{
++ if (is_upper)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER;
++}
++
++/*************************************************************************
++ * trio_get_largest / trio_set_largest [public]
++ */
++#if TRIO_FEATURE_INTMAX_T
++int
++trio_get_largest
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_largest
++TRIO_ARGS2((ref, is_largest),
++ trio_pointer_t ref,
++ int is_largest)
++{
++ if (is_largest)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
++}
++#endif /* TRIO_FEATURE_INTMAX_T */
++
++/*************************************************************************
++ * trio_get_ptrdiff / trio_set_ptrdiff [public]
++ */
++#if TRIO_FEATURE_PTRDIFF_T
++int
++trio_get_ptrdiff
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_ptrdiff
++TRIO_ARGS2((ref, is_ptrdiff),
++ trio_pointer_t ref,
++ int is_ptrdiff)
++{
++ if (is_ptrdiff)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
++}
++#endif /* TRIO_FEATURE_PTRDIFF_T */
++
++/*************************************************************************
++ * trio_get_size / trio_set_size [public]
++ */
++#if TRIO_FEATURE_SIZE_T
++int
++trio_get_size
++TRIO_ARGS1((ref),
++ trio_pointer_t ref)
++{
++ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T)
++ ? TRUE
++ : FALSE;
++}
++
++void
++trio_set_size
++TRIO_ARGS2((ref, is_size),
++ trio_pointer_t ref,
++ int is_size)
++{
++ if (is_size)
++ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T;
++ else
++ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
++}
++#endif /* TRIO_FEATURE_SIZE_T */
++
++/*************************************************************************
++ * trio_print_int [public]
++ */
++void
++trio_print_int
++TRIO_ARGS2((ref, number),
++ trio_pointer_t ref,
++ int number)
++{
++ trio_reference_t *self = (trio_reference_t *)ref;
++
++ TrioWriteNumber(self->data,
++ (trio_uintmax_t)number,
++ self->parameter->flags,
++ self->parameter->width,
++ self->parameter->precision,
++ self->parameter->base);
++}
++
++/*************************************************************************
++ * trio_print_uint [public]
++ */
++void
++trio_print_uint
++TRIO_ARGS2((ref, number),
++ trio_pointer_t ref,
++ unsigned int number)
++{
++ trio_reference_t *self = (trio_reference_t *)ref;
++
++ TrioWriteNumber(self->data,
++ (trio_uintmax_t)number,
++ self->parameter->flags | FLAGS_UNSIGNED,
++ self->parameter->width,
++ self->parameter->precision,
++ self->parameter->base);
++}
++
++/*************************************************************************
++ * trio_print_double [public]
++ */
++#if TRIO_FEATURE_FLOAT
++void
++trio_print_double
++TRIO_ARGS2((ref, number),
++ trio_pointer_t ref,
++ double number)
++{
++ trio_reference_t *self = (trio_reference_t *)ref;
++
++ TrioWriteDouble(self->data,
++ number,
++ self->parameter->flags,
++ self->parameter->width,
++ self->parameter->precision,
++ self->parameter->base);
++}
++#endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * trio_print_string [public]
++ */
++void
++trio_print_string
++TRIO_ARGS2((ref, string),
++ trio_pointer_t ref,
++ TRIO_CONST char *string)
++{
++ trio_reference_t *self = (trio_reference_t *)ref;
++
++ TrioWriteString(self->data,
++ string,
++ self->parameter->flags,
++ self->parameter->width,
++ self->parameter->precision);
++}
++
++/*************************************************************************
++ * trio_print_ref [public]
++ */
++int
++trio_print_ref
++TRIO_VARGS3((ref, format, va_alist),
++ trio_pointer_t ref,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list arglist;
++
++ assert(VALID(format));
++
++ TRIO_VA_START(arglist, format);
++ status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
++ TRIO_VA_END(arglist);
++ return status;
++}
++
++/*************************************************************************
++ * trio_vprint_ref [public]
++ */
++int
++trio_vprint_ref
++TRIO_ARGS3((ref, format, arglist),
++ trio_pointer_t ref,
++ TRIO_CONST char *format,
++ va_list arglist)
++{
++ assert(VALID(format));
++
++ return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
++}
++
++/*************************************************************************
++ * trio_printv_ref [public]
++ */
++int
++trio_printv_ref
++TRIO_ARGS3((ref, format, argarray),
++ trio_pointer_t ref,
++ TRIO_CONST char *format,
++ trio_pointer_t *argarray)
++{
++ static va_list unused;
++
++ assert(VALID(format));
++
++ return TrioFormatRef((trio_reference_t *)ref, format, unused, argarray);
++}
++
++#endif
++
++/*************************************************************************
++ * trio_print_pointer [public]
++ */
++void
++trio_print_pointer
++TRIO_ARGS2((ref, pointer),
++ trio_pointer_t ref,
++ trio_pointer_t pointer)
++{
++ trio_reference_t *self = (trio_reference_t *)ref;
++ trio_flags_t flags;
++ trio_uintmax_t number;
++
++ if (NULL == pointer)
++ {
++ TRIO_CONST char *string = internalNullString;
++ while (*string)
++ self->data->OutStream(self->data, *string++);
++ }
++ else
++ {
++ /*
++ * The subtraction of the null pointer is a workaround
++ * to avoid a compiler warning. The performance overhead
++ * is negligible (and likely to be removed by an
++ * optimizing compiler). The (char *) casting is done
++ * to please ANSI C++.
++ */
++ number = (trio_uintmax_t)((char *)pointer - (char *)0);
++ /* Shrink to size of pointer */
++ number &= (trio_uintmax_t)-1;
++ flags = self->parameter->flags;
++ flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
++ FLAGS_NILPADDING);
++ TrioWriteNumber(self->data,
++ number,
++ flags,
++ POINTER_WIDTH,
++ NO_PRECISION,
++ BASE_HEX);
++ }
++}
++
++/** @} End of UserDefined documentation module */
++
++/*************************************************************************
++ *
++ * LOCALES
++ *
++ ************************************************************************/
++
++/*************************************************************************
++ * trio_locale_set_decimal_point
++ *
++ * Decimal point can only be one character. The input argument is a
++ * string to enable multibyte characters. At most MB_LEN_MAX characters
++ * will be used.
++ */
++#if TRIO_FEATURE_LOCALE
++TRIO_PUBLIC void
++trio_locale_set_decimal_point
++TRIO_ARGS1((decimalPoint),
++ char *decimalPoint)
++{
++#if defined(USE_LOCALE)
++ if (NULL == internalLocaleValues)
++ {
++ TrioSetLocale();
++ }
++#endif
++ internalDecimalPointLength = trio_length(decimalPoint);
++ if (internalDecimalPointLength == 1)
++ {
++ internalDecimalPoint = *decimalPoint;
++ }
++ else
++ {
++ internalDecimalPoint = NIL;
++ trio_copy_max(internalDecimalPointString,
++ sizeof(internalDecimalPointString),
++ decimalPoint);
++ }
++}
++#endif
++
++/*************************************************************************
++ * trio_locale_set_thousand_separator
++ *
++ * See trio_locale_set_decimal_point
++ */
++#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
++TRIO_PUBLIC void
++trio_locale_set_thousand_separator
++TRIO_ARGS1((thousandSeparator),
++ char *thousandSeparator)
++{
++# if defined(USE_LOCALE)
++ if (NULL == internalLocaleValues)
++ {
++ TrioSetLocale();
++ }
++# endif
++ trio_copy_max(internalThousandSeparator,
++ sizeof(internalThousandSeparator),
++ thousandSeparator);
++ internalThousandSeparatorLength = trio_length(internalThousandSeparator);
++}
++#endif
++
++/*************************************************************************
++ * trio_locale_set_grouping
++ *
++ * Array of bytes. Reversed order.
++ *
++ * CHAR_MAX : No further grouping
++ * 0 : Repeat last group for the remaining digits (not necessary
++ * as C strings are zero-terminated)
++ * n : Set current group to n
++ *
++ * Same order as the grouping attribute in LC_NUMERIC.
++ */
++#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
++TRIO_PUBLIC void
++trio_locale_set_grouping
++TRIO_ARGS1((grouping),
++ char *grouping)
++{
++# if defined(USE_LOCALE)
++ if (NULL == internalLocaleValues)
++ {
++ TrioSetLocale();
++ }
++# endif
++ trio_copy_max(internalGrouping,
++ sizeof(internalGrouping),
++ grouping);
++}
++#endif
++
++
++/*************************************************************************
++ *
++ * SCANNING
++ *
++ ************************************************************************/
++
++#if TRIO_FEATURE_SCANF
++
++/*************************************************************************
++ * TrioSkipWhitespaces
++ */
++TRIO_PRIVATE int
++TrioSkipWhitespaces
++TRIO_ARGS1((self),
++ trio_class_t *self)
++{
++ int ch;
++
++ ch = self->current;
++ while (isspace(ch))
++ {
++ self->InStream(self, &ch);
++ }
++ return ch;
++}
++
++/*************************************************************************
++ * TrioGetCollation
++ */
++#if TRIO_EXTENSION
++TRIO_PRIVATE void
++TrioGetCollation(TRIO_NOARGS)
++{
++ int i;
++ int j;
++ int k;
++ char first[2];
++ char second[2];
++
++ /* This is computationally expensive */
++ first[1] = NIL;
++ second[1] = NIL;
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ {
++ k = 0;
++ first[0] = (char)i;
++ for (j = 0; j < MAX_CHARACTER_CLASS; j++)
++ {
++ second[0] = (char)j;
++ if (trio_equal_locale(first, second))
++ internalCollationArray[i][k++] = (char)j;
++ }
++ internalCollationArray[i][k] = NIL;
++ }
++}
++#endif
++
++/*************************************************************************
++ * TrioGetCharacterClass
++ *
++ * FIXME:
++ * multibyte
++ */
++TRIO_PRIVATE int
++TrioGetCharacterClass
++TRIO_ARGS4((format, offsetPointer, flagsPointer, characterclass),
++ TRIO_CONST char *format,
++ int *offsetPointer,
++ trio_flags_t *flagsPointer,
++ int *characterclass)
++{
++ int offset = *offsetPointer;
++ int i;
++ char ch;
++ char range_begin;
++ char range_end;
++
++ *flagsPointer &= ~FLAGS_EXCLUDE;
++
++ if (format[offset] == QUALIFIER_CIRCUMFLEX)
++ {
++ *flagsPointer |= FLAGS_EXCLUDE;
++ offset++;
++ }
++ /*
++ * If the ungroup character is at the beginning of the scanlist,
++ * it will be part of the class, and a second ungroup character
++ * must follow to end the group.
++ */
++ if (format[offset] == SPECIFIER_UNGROUP)
++ {
++ characterclass[(int)SPECIFIER_UNGROUP]++;
++ offset++;
++ }
++ /*
++ * Minus is used to specify ranges. To include minus in the class,
++ * it must be at the beginning of the list
++ */
++ if (format[offset] == QUALIFIER_MINUS)
++ {
++ characterclass[(int)QUALIFIER_MINUS]++;
++ offset++;
++ }
++ /* Collect characters */
++ for (ch = format[offset];
++ (ch != SPECIFIER_UNGROUP) && (ch != NIL);
++ ch = format[++offset])
++ {
++ switch (ch)
++ {
++ case QUALIFIER_MINUS: /* Scanlist ranges */
++
++ /*
++ * Both C99 and UNIX98 describes ranges as implementation-
++ * defined.
++ *
++ * We support the following behaviour (although this may
++ * change as we become wiser)
++ * - only increasing ranges, ie. [a-b] but not [b-a]
++ * - transitive ranges, ie. [a-b-c] == [a-c]
++ * - trailing minus, ie. [a-] is interpreted as an 'a'
++ * and a '-'
++ * - duplicates (although we can easily convert these
++ * into errors)
++ */
++ range_begin = format[offset - 1];
++ range_end = format[++offset];
++ if (range_end == SPECIFIER_UNGROUP)
++ {
++ /* Trailing minus is included */
++ characterclass[(int)ch]++;
++ ch = range_end;
++ break; /* for */
++ }
++ if (range_end == NIL)
++ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ if (range_begin > range_end)
++ return TRIO_ERROR_RETURN(TRIO_ERANGE, offset);
++
++ for (i = (int)range_begin; i <= (int)range_end; i++)
++ characterclass[i]++;
++
++ ch = range_end;
++ break;
++
++#if TRIO_EXTENSION
++
++ case SPECIFIER_GROUP:
++
++ switch (format[offset + 1])
++ {
++ case QUALIFIER_DOT: /* Collating symbol */
++ /*
++ * FIXME: This will be easier to implement when multibyte
++ * characters have been implemented. Until now, we ignore
++ * this feature.
++ */
++ for (i = offset + 2; ; i++)
++ {
++ if (format[i] == NIL)
++ /* Error in syntax */
++ return -1;
++ else if (format[i] == QUALIFIER_DOT)
++ break; /* for */
++ }
++ if (format[++i] != SPECIFIER_UNGROUP)
++ return -1;
++
++ offset = i;
++ break;
++
++ case QUALIFIER_EQUAL: /* Equivalence class expressions */
++ {
++ unsigned int j;
++ unsigned int k;
++
++ if (internalCollationUnconverted)
++ {
++ /* Lazy evaluation of collation array */
++ TrioGetCollation();
++ internalCollationUnconverted = FALSE;
++ }
++ for (i = offset + 2; ; i++)
++ {
++ if (format[i] == NIL)
++ /* Error in syntax */
++ return -1;
++ else if (format[i] == QUALIFIER_EQUAL)
++ break; /* for */
++ else
++ {
++ /* Mark any equivalent character */
++ k = (unsigned int)format[i];
++ for (j = 0; internalCollationArray[k][j] != NIL; j++)
++ characterclass[(int)internalCollationArray[k][j]]++;
++ }
++ }
++ if (format[++i] != SPECIFIER_UNGROUP)
++ return -1;
++
++ offset = i;
++ }
++ break;
++
++ case QUALIFIER_COLON: /* Character class expressions */
++
++ if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isalnum(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_ALNUM) - 1;
++ }
++ else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isalpha(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_ALPHA) - 1;
++ }
++ else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (iscntrl(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_CNTRL) - 1;
++ }
++ else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isdigit(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_DIGIT) - 1;
++ }
++ else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isgraph(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_GRAPH) - 1;
++ }
++ else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (islower(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_LOWER) - 1;
++ }
++ else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isprint(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_PRINT) - 1;
++ }
++ else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (ispunct(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_PUNCT) - 1;
++ }
++ else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isspace(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_SPACE) - 1;
++ }
++ else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isupper(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_UPPER) - 1;
++ }
++ else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
++ &format[offset]))
++ {
++ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
++ if (isxdigit(i))
++ characterclass[i]++;
++ offset += sizeof(CLASS_XDIGIT) - 1;
++ }
++ else
++ {
++ characterclass[(int)ch]++;
++ }
++ break;
++
++ default:
++ characterclass[(int)ch]++;
++ break;
++ }
++ break;
++
++#endif /* TRIO_EXTENSION */
++
++ default:
++ characterclass[(int)ch]++;
++ break;
++ }
++ }
++ return 0;
++}
++
++/*************************************************************************
++ * TrioReadNumber
++ *
++ * We implement our own number conversion in preference of strtol and
++ * strtoul, because we must handle 'long long' and thousand separators.
++ */
++TRIO_PRIVATE BOOLEAN_T
++TrioReadNumber
++TRIO_ARGS5((self, target, flags, width, base),
++ trio_class_t *self,
++ trio_uintmax_t *target,
++ trio_flags_t flags,
++ int width,
++ int base)
++{
++ trio_uintmax_t number = 0;
++ int digit;
++ int count;
++ BOOLEAN_T isNegative = FALSE;
++ BOOLEAN_T gotNumber = FALSE;
++ int j;
++
++ assert(VALID(self));
++ assert(VALID(self->InStream));
++ assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE));
++
++ if (internalDigitsUnconverted)
++ {
++ /* Lazy evaluation of digits array */
++ memset(internalDigitArray, -1, sizeof(internalDigitArray));
++ for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++)
++ {
++ internalDigitArray[(int)internalDigitsLower[j]] = j;
++ internalDigitArray[(int)internalDigitsUpper[j]] = j;
++ }
++ internalDigitsUnconverted = FALSE;
++ }
++
++ TrioSkipWhitespaces(self);
++
++ /* Leading sign */
++ if (self->current == '+')
++ {
++ self->InStream(self, NULL);
++ }
++ else if (self->current == '-')
++ {
++ self->InStream(self, NULL);
++ isNegative = TRUE;
++ }
++
++ count = self->processed;
++
++ if (flags & FLAGS_ALTERNATIVE)
++ {
++ switch (base)
++ {
++ case NO_BASE:
++ case BASE_OCTAL:
++ case BASE_HEX:
++ case BASE_BINARY:
++ if (self->current == '0')
++ {
++ self->InStream(self, NULL);
++ if (self->current)
++ {
++ if ((base == BASE_HEX) &&
++ (trio_to_upper(self->current) == 'X'))
++ {
++ self->InStream(self, NULL);
++ }
++ else if ((base == BASE_BINARY) &&
++ (trio_to_upper(self->current) == 'B'))
++ {
++ self->InStream(self, NULL);
++ }
++ }
++ }
++ else
++ return FALSE;
++ break;
++ default:
++ break;
++ }
++ }
++
++ while (((width == NO_WIDTH) || (self->processed - count < width)) &&
++ (! ((self->current == EOF) || isspace(self->current))))
++ {
++ if (isascii(self->current))
++ {
++ digit = internalDigitArray[self->current];
++ /* Abort if digit is not allowed in the specified base */
++ if ((digit == -1) || (digit >= base))
++ break;
++ }
++#if TRIO_FEATURE_QUOTE
++ else if (flags & FLAGS_QUOTE)
++ {
++ /* Compare with thousands separator */
++ for (j = 0; internalThousandSeparator[j] && self->current; j++)
++ {
++ if (internalThousandSeparator[j] != self->current)
++ break;
++
++ self->InStream(self, NULL);
++ }
++ if (internalThousandSeparator[j])
++ break; /* Mismatch */
++ else
++ continue; /* Match */
++ }
++#endif
++ else
++ break;
++
++ number *= base;
++ number += digit;
++ gotNumber = TRUE; /* we need at least one digit */
++
++ self->InStream(self, NULL);
++ }
++
++ /* Was anything read at all? */
++ if (!gotNumber)
++ return FALSE;
++
++ if (target)
++ *target = (isNegative) ? (trio_uintmax_t)(-((trio_intmax_t)number)) : number;
++ return TRUE;
++}
++
++/*************************************************************************
++ * TrioReadChar
++ */
++TRIO_PRIVATE int
++TrioReadChar
++TRIO_ARGS4((self, target, flags, width),
++ trio_class_t *self,
++ char *target,
++ trio_flags_t flags,
++ int width)
++{
++ int i;
++ char ch;
++ trio_uintmax_t number;
++
++ assert(VALID(self));
++ assert(VALID(self->InStream));
++
++ for (i = 0;
++ (self->current != EOF) && (i < width);
++ i++)
++ {
++ ch = (char)self->current;
++ self->InStream(self, NULL);
++ if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
++ {
++ switch (self->current)
++ {
++ case '\\': ch = '\\'; break;
++ case 'a': ch = '\007'; break;
++ case 'b': ch = '\b'; break;
++ case 'f': ch = '\f'; break;
++ case 'n': ch = '\n'; break;
++ case 'r': ch = '\r'; break;
++ case 't': ch = '\t'; break;
++ case 'v': ch = '\v'; break;
++ default:
++ if (isdigit(self->current))
++ {
++ /* Read octal number */
++ if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
++ return 0;
++ ch = (char)number;
++ }
++ else if (trio_to_upper(self->current) == 'X')
++ {
++ /* Read hexadecimal number */
++ self->InStream(self, NULL);
++ if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
++ return 0;
++ ch = (char)number;
++ }
++ else
++ {
++ ch = (char)self->current;
++ }
++ break;
++ }
++ }
++
++ if (target)
++ target[i] = ch;
++ }
++ return i + 1;
++}
++
++/*************************************************************************
++ * TrioReadString
++ */
++TRIO_PRIVATE BOOLEAN_T
++TrioReadString
++TRIO_ARGS4((self, target, flags, width),
++ trio_class_t *self,
++ char *target,
++ trio_flags_t flags,
++ int width)
++{
++ int i;
++
++ assert(VALID(self));
++ assert(VALID(self->InStream));
++
++ TrioSkipWhitespaces(self);
++
++ /*
++ * Continue until end of string is reached, a whitespace is encountered,
++ * or width is exceeded
++ */
++ for (i = 0;
++ ((width == NO_WIDTH) || (i < width)) &&
++ (! ((self->current == EOF) || isspace(self->current)));
++ i++)
++ {
++ if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0)
++ break; /* for */
++ }
++ if (target)
++ target[i] = NIL;
++ return TRUE;
++}
++
++/*************************************************************************
++ * TrioReadWideChar
++ */
++#if TRIO_FEATURE_WIDECHAR
++TRIO_PRIVATE int
++TrioReadWideChar
++TRIO_ARGS4((self, target, flags, width),
++ trio_class_t *self,
++ trio_wchar_t *target,
++ trio_flags_t flags,
++ int width)
++{
++ int i;
++ int j;
++ int size;
++ int amount = 0;
++ trio_wchar_t wch;
++ char buffer[MB_LEN_MAX + 1];
++
++ assert(VALID(self));
++ assert(VALID(self->InStream));
++
++ for (i = 0;
++ (self->current != EOF) && (i < width);
++ i++)
++ {
++ if (isascii(self->current))
++ {
++ if (TrioReadChar(self, buffer, flags, 1) == 0)
++ return 0;
++ buffer[1] = NIL;
++ }
++ else
++ {
++ /*
++ * Collect a multibyte character, by enlarging buffer until
++ * it contains a fully legal multibyte character, or the
++ * buffer is full.
++ */
++ j = 0;
++ do
++ {
++ buffer[j++] = (char)self->current;
++ buffer[j] = NIL;
++ self->InStream(self, NULL);
++ }
++ while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j));
++ }
++ if (target)
++ {
++ size = mbtowc(&wch, buffer, sizeof(buffer));
++ if (size > 0)
++ target[i] = wch;
++ }
++ amount += size;
++ self->InStream(self, NULL);
++ }
++ return amount;
++}
++#endif /* TRIO_FEATURE_WIDECHAR */
++
++/*************************************************************************
++ * TrioReadWideString
++ */
++#if TRIO_FEATURE_WIDECHAR
++TRIO_PRIVATE BOOLEAN_T
++TrioReadWideString
++TRIO_ARGS4((self, target, flags, width),
++ trio_class_t *self,
++ trio_wchar_t *target,
++ trio_flags_t flags,
++ int width)
++{
++ int i;
++ int size;
++
++ assert(VALID(self));
++ assert(VALID(self->InStream));
++
++ TrioSkipWhitespaces(self);
++
++#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
++ /* Required by TrioReadWideChar */
++ size = mblen(NULL, 0);
++#endif
++
++ /*
++ * Continue until end of string is reached, a whitespace is encountered,
++ * or width is exceeded
++ */
++ for (i = 0;
++ ((width == NO_WIDTH) || (i < width)) &&
++ (! ((self->current == EOF) || isspace(self->current)));
++ )
++ {
++ size = TrioReadWideChar(self, &target[i], flags, 1);
++ if (size == 0)
++ break; /* for */
++
++ i += size;
++ }
++ if (target)
++ target[i] = WCONST('\0');
++ return TRUE;
++}
++#endif /* TRIO_FEATURE_WIDECHAR */
++
++/*************************************************************************
++ * TrioReadGroup
++ *
++ * Reads non-empty character groups.
++ *
++ * FIXME: characterclass does not work with multibyte characters
++ */
++TRIO_PRIVATE BOOLEAN_T
++TrioReadGroup
++TRIO_ARGS5((self, target, characterclass, flags, width),
++ trio_class_t *self,
++ char *target,
++ int *characterclass,
++ trio_flags_t flags,
++ int width)
++{
++ int ch;
++ int i;
++
++ assert(VALID(self));
++ assert(VALID(self->InStream));
++
++ ch = self->current;
++ for (i = 0;
++ ((width == NO_WIDTH) || (i < width)) &&
++ (! ((ch == EOF) ||
++ (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0))));
++ i++)
++ {
++ if (target)
++ target[i] = (char)ch;
++ self->InStream(self, &ch);
++ }
++
++ if (i == 0)
++ return FALSE;
++
++ /* Terminate the string if input saved */
++ if (target)
++ target[i] = NIL;
++ return TRUE;
++}
++
++/*************************************************************************
++ * TrioReadDouble
++ *
++ * FIXME:
++ * add long double
++ * handle base
++ */
++#if TRIO_FEATURE_FLOAT
++TRIO_PRIVATE BOOLEAN_T
++TrioReadDouble
++TRIO_ARGS4((self, target, flags, width),
++ trio_class_t *self,
++ trio_pointer_t target,
++ trio_flags_t flags,
++ int width)
++{
++ int ch;
++ char doubleString[512];
++ int offset = 0;
++ int start;
++# if TRIO_FEATURE_QUOTE
++ int j;
++# endif
++ BOOLEAN_T isHex = FALSE;
++ trio_long_double_t infinity;
++
++ doubleString[0] = 0;
++
++ if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
++ width = sizeof(doubleString) - 1;
++
++ TrioSkipWhitespaces(self);
++
++ /*
++ * Read entire double number from stream. trio_to_double requires
++ * a string as input, but InStream can be anything, so we have to
++ * collect all characters.
++ */
++ ch = self->current;
++ if ((ch == '+') || (ch == '-'))
++ {
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ width--;
++ }
++
++ start = offset;
++ switch (ch)
++ {
++ case 'n':
++ case 'N':
++ /* Not-a-number */
++ if (offset != 0)
++ break;
++ /* FALLTHROUGH */
++ case 'i':
++ case 'I':
++ /* Infinity */
++ while (isalpha(ch) && (offset - start < width))
++ {
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ }
++ doubleString[offset] = NIL;
++
++ /* Case insensitive string comparison */
++ if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
++ trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
++ {
++ infinity = ((start == 1) && (doubleString[0] == '-'))
++ ? trio_ninf()
++ : trio_pinf();
++ if (flags & FLAGS_LONGDOUBLE)
++ {
++ *((trio_long_double_t *)target) = infinity;
++ }
++ else if (flags & FLAGS_LONG)
++ {
++ *((double *)target) = infinity;
++ }
++ else
++ {
++ *((float *)target) = infinity;
++ }
++ return TRUE;
++ }
++ if (trio_equal(doubleString, NAN_UPPER))
++ {
++ /* NaN must not have a preceeding + nor - */
++ if (flags & FLAGS_LONGDOUBLE)
++ {
++ *((trio_long_double_t *)target) = trio_nan();
++ }
++ else if (flags & FLAGS_LONG)
++ {
++ *((double *)target) = trio_nan();
++ }
++ else
++ {
++ *((float *)target) = trio_nan();
++ }
++ return TRUE;
++ }
++ return FALSE;
++
++ case '0':
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ if (trio_to_upper(ch) == 'X')
++ {
++ isHex = TRUE;
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ }
++ break;
++
++ default:
++ break;
++ }
++
++ while ((ch != EOF) && (offset - start < width))
++ {
++ /* Integer part */
++ if (isHex ? isxdigit(ch) : isdigit(ch))
++ {
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ }
++# if TRIO_FEATURE_QUOTE
++ else if (flags & FLAGS_QUOTE)
++ {
++ /* Compare with thousands separator */
++ for (j = 0; internalThousandSeparator[j] && self->current; j++)
++ {
++ if (internalThousandSeparator[j] != self->current)
++ break;
++
++ self->InStream(self, &ch);
++ }
++ if (internalThousandSeparator[j])
++ break; /* Mismatch */
++ else
++ continue; /* Match */
++ }
++# endif
++ else
++ break; /* while */
++ }
++ if (ch == '.')
++ {
++ /* Decimal part */
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
++ (offset - start < width))
++ {
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ }
++ }
++ if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
++ {
++ /* Exponent */
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ if ((ch == '+') || (ch == '-'))
++ {
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ }
++ while (isdigit(ch) && (offset - start < width))
++ {
++ doubleString[offset++] = (char)ch;
++ self->InStream(self, &ch);
++ }
++ }
++
++ if ((offset == start) || (*doubleString == NIL))
++ return FALSE;
++
++ doubleString[offset] = 0;
++
++ if (flags & FLAGS_LONGDOUBLE)
++ {
++ *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
++ }
++ else if (flags & FLAGS_LONG)
++ {
++ *((double *)target) = trio_to_double(doubleString, NULL);
++ }
++ else
++ {
++ *((float *)target) = trio_to_float(doubleString, NULL);
++ }
++ return TRUE;
++}
++#endif /* TRIO_FEATURE_FLOAT */
++
++/*************************************************************************
++ * TrioReadPointer
++ */
++TRIO_PRIVATE BOOLEAN_T
++TrioReadPointer
++TRIO_ARGS3((self, target, flags),
++ trio_class_t *self,
++ trio_pointer_t *target,
++ trio_flags_t flags)
++{
++ trio_uintmax_t number;
++ char buffer[sizeof(internalNullString)];
++
++ flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING);
++
++ if (TrioReadNumber(self,
++ &number,
++ flags,
++ POINTER_WIDTH,
++ BASE_HEX))
++ {
++ if (target)
++ {
++#if defined(TRIO_COMPILER_GCC) || defined(TRIO_COMPILER_MIPSPRO)
++ /*
++ * The strange assignment of number is a workaround for a compiler
++ * warning
++ */
++ *target = &((char *)0)[number];
++#else
++ *target = (trio_pointer_t)number;
++#endif
++ }
++ return TRUE;
++ }
++ else if (TrioReadString(self,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : buffer,
++ 0,
++ sizeof(internalNullString) - 1))
++ {
++ if (trio_equal_case(buffer, internalNullString))
++ {
++ if (target)
++ *target = NULL;
++ return TRUE;
++ }
++ }
++ return FALSE;
++}
++
++/*************************************************************************
++ * TrioScanProcess
++ */
++TRIO_PRIVATE int
++TrioScanProcess
++TRIO_ARGS3((data, format, parameters),
++ trio_class_t *data,
++ TRIO_CONST char *format,
++ trio_parameter_t *parameters)
++{
++ int status;
++ int assignment;
++ int ch;
++ int offset; /* Offset of format string */
++ int i; /* Offset of current parameter */
++ trio_flags_t flags;
++ int width;
++ int base;
++ trio_pointer_t pointer;
++
++ /* Return on empty format string */
++ if (format[0] == NIL)
++ return 0;
++
++ status = 0;
++ assignment = 0;
++ i = 0;
++ offset = 0;
++ data->InStream(data, &ch);
++
++ for (;;)
++ {
++ /* Skip the parameter entries */
++ while (parameters[i].type == FORMAT_PARAMETER)
++ {
++ assert(i <= MAX_PARAMETERS);
++ i++;
++ }
++
++ /* Compare non conversion-specifier part of format string */
++ while (offset < parameters[i].beginOffset)
++ {
++ if ((CHAR_IDENTIFIER == format[offset]) &&
++ (CHAR_IDENTIFIER == format[offset + 1]))
++ {
++ /* Two % in format matches one % in input stream */
++ if (CHAR_IDENTIFIER == ch)
++ {
++ data->InStream(data, &ch);
++ offset += 2;
++ continue; /* while format chars left */
++ }
++ else
++ {
++ status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ goto end;
++ }
++ }
++ else /* Not an % identifier */
++ {
++ if (isspace((int)format[offset]))
++ {
++ /* Whitespaces may match any amount of whitespaces */
++ ch = TrioSkipWhitespaces(data);
++ }
++ else if (ch == format[offset])
++ {
++ data->InStream(data, &ch);
++ }
++ else
++ {
++ status = assignment;
++ goto end;
++ }
++
++ offset++;
++ }
++ }
++
++ if (parameters[i].type == FORMAT_SENTINEL)
++ break;
++
++ if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
++ {
++ status = (assignment > 0) ? assignment : EOF;
++ goto end;
++ }
++
++ flags = parameters[i].flags;
++
++ /* Find width */
++ width = parameters[i].width;
++ if (flags & FLAGS_WIDTH_PARAMETER)
++ {
++ /* Get width from parameter list */
++ width = (int)parameters[width].data.number.as_signed;
++ }
++
++ /* Find base */
++ if (NO_BASE != parameters[i].baseSpecifier)
++ {
++ /* Base from specifier has priority */
++ base = parameters[i].baseSpecifier;
++ }
++ else if (flags & FLAGS_BASE_PARAMETER)
++ {
++ /* Get base from parameter list */
++ base = parameters[i].base;
++ base = (int)parameters[base].data.number.as_signed;
++ }
++ else
++ {
++ /* Use base from format string */
++ base = parameters[i].base;
++ }
++
++ switch (parameters[i].type)
++ {
++ case FORMAT_INT:
++ {
++ trio_uintmax_t number;
++
++ if (0 == base)
++ base = BASE_DECIMAL;
++
++ if (!TrioReadNumber(data,
++ &number,
++ flags,
++ width,
++ base))
++ {
++ status = assignment;
++ goto end;
++ }
++
++ if (!(flags & FLAGS_IGNORE))
++ {
++ assignment++;
++
++ pointer = parameters[i].data.pointer;
++#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
++ if (flags & FLAGS_SIZE_T)
++ *(size_t *)pointer = (size_t)number;
++ else
++#endif
++#if TRIO_FEATURE_PTRDIFF_T
++ if (flags & FLAGS_PTRDIFF_T)
++ *(ptrdiff_t *)pointer = (ptrdiff_t)number;
++ else
++#endif
++#if TRIO_FEATURE_INTMAX_T
++ if (flags & FLAGS_INTMAX_T)
++ *(trio_intmax_t *)pointer = (trio_intmax_t)number;
++ else
++#endif
++ if (flags & FLAGS_QUAD)
++ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
++ else if (flags & FLAGS_LONG)
++ *(long int *)pointer = (long int)number;
++ else if (flags & FLAGS_SHORT)
++ *(short int *)pointer = (short int)number;
++ else
++ *(int *)pointer = (int)number;
++ }
++ }
++ break; /* FORMAT_INT */
++
++ case FORMAT_STRING:
++#if TRIO_FEATURE_WIDECHAR
++ if (flags & FLAGS_WIDECHAR)
++ {
++ if (!TrioReadWideString(data,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : parameters[i].data.wstring,
++ flags,
++ width))
++ {
++ status = assignment;
++ goto end;
++ }
++ }
++ else
++#endif
++ {
++ if (!TrioReadString(data,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : parameters[i].data.string,
++ flags,
++ width))
++ {
++ status = assignment;
++ goto end;
++ }
++ }
++ if (!(flags & FLAGS_IGNORE))
++ assignment++;
++ break; /* FORMAT_STRING */
++
++#if TRIO_FEATURE_FLOAT
++ case FORMAT_DOUBLE:
++ {
++ if (flags & FLAGS_IGNORE)
++ {
++ pointer = NULL;
++ }
++ else
++ {
++ pointer = (flags & FLAGS_LONGDOUBLE)
++ ? (trio_pointer_t)parameters[i].data.longdoublePointer
++ : (trio_pointer_t)parameters[i].data.doublePointer;
++ }
++ if (!TrioReadDouble(data, pointer, flags, width))
++ {
++ status = assignment;
++ goto end;
++ }
++ if (!(flags & FLAGS_IGNORE))
++ {
++ assignment++;
++ }
++ break; /* FORMAT_DOUBLE */
++ }
++#endif
++
++ case FORMAT_GROUP:
++ {
++ int characterclass[MAX_CHARACTER_CLASS + 1];
++
++ /* Skip over modifiers */
++ while (format[offset] != SPECIFIER_GROUP)
++ {
++ offset++;
++ }
++ /* Skip over group specifier */
++ offset++;
++
++ memset(characterclass, 0, sizeof(characterclass));
++ status = TrioGetCharacterClass(format,
++ &offset,
++ &flags,
++ characterclass);
++ if (status < 0)
++ goto end;
++
++ if (!TrioReadGroup(data,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : parameters[i].data.string,
++ characterclass,
++ flags,
++ parameters[i].width))
++ {
++ status = assignment;
++ goto end;
++ }
++ if (!(flags & FLAGS_IGNORE))
++ assignment++;
++ }
++ break; /* FORMAT_GROUP */
++
++ case FORMAT_COUNT:
++ pointer = parameters[i].data.pointer;
++ if (NULL != pointer)
++ {
++ int count = data->processed;
++ if (ch != EOF)
++ count--; /* a character is read, but is not consumed yet */
++#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
++ if (flags & FLAGS_SIZE_T)
++ *(size_t *)pointer = (size_t)count;
++ else
++#endif
++#if TRIO_FEATURE_PTRDIFF_T
++ if (flags & FLAGS_PTRDIFF_T)
++ *(ptrdiff_t *)pointer = (ptrdiff_t)count;
++ else
++#endif
++#if TRIO_FEATURE_INTMAX_T
++ if (flags & FLAGS_INTMAX_T)
++ *(trio_intmax_t *)pointer = (trio_intmax_t)count;
++ else
++#endif
++ if (flags & FLAGS_QUAD)
++ {
++ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
++ }
++ else if (flags & FLAGS_LONG)
++ {
++ *(long int *)pointer = (long int)count;
++ }
++ else if (flags & FLAGS_SHORT)
++ {
++ *(short int *)pointer = (short int)count;
++ }
++ else
++ {
++ *(int *)pointer = (int)count;
++ }
++ }
++ break; /* FORMAT_COUNT */
++
++ case FORMAT_CHAR:
++#if TRIO_FEATURE_WIDECHAR
++ if (flags & FLAGS_WIDECHAR)
++ {
++ if (TrioReadWideChar(data,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : parameters[i].data.wstring,
++ flags,
++ (width == NO_WIDTH) ? 1 : width) == 0)
++ {
++ status = assignment;
++ goto end;
++ }
++ }
++ else
++#endif
++ {
++ if (TrioReadChar(data,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : parameters[i].data.string,
++ flags,
++ (width == NO_WIDTH) ? 1 : width) == 0)
++ {
++ status = assignment;
++ goto end;
++ }
++ }
++ if (!(flags & FLAGS_IGNORE))
++ assignment++;
++ break; /* FORMAT_CHAR */
++
++ case FORMAT_POINTER:
++ if (!TrioReadPointer(data,
++ (flags & FLAGS_IGNORE)
++ ? NULL
++ : (trio_pointer_t *)parameters[i].data.pointer,
++ flags))
++ {
++ status = assignment;
++ goto end;
++ }
++ if (!(flags & FLAGS_IGNORE))
++ assignment++;
++ break; /* FORMAT_POINTER */
++
++ case FORMAT_PARAMETER:
++ break; /* FORMAT_PARAMETER */
++
++ default:
++ status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
++ goto end;
++ }
++
++ ch = data->current;
++ offset = parameters[i].endOffset;
++ i++;
++ }
++
++ status = assignment;
++ end:
++ if (data->UndoStream)
++ data->UndoStream(data);
++ return status;
++}
++
++/*************************************************************************
++ * TrioScan
++ */
++TRIO_PRIVATE int
++TrioScan
++TRIO_ARGS7((source, sourceSize, InStream, UndoStream, format, arglist, argarray),
++ trio_pointer_t source,
++ size_t sourceSize,
++ void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
++ void (*UndoStream) TRIO_PROTO((trio_class_t *)),
++ TRIO_CONST char *format,
++ va_list arglist,
++ trio_pointer_t *argarray)
++{
++ int status;
++ trio_parameter_t parameters[MAX_PARAMETERS];
++ trio_class_t data;
++
++ assert(VALID(InStream));
++ assert(VALID(format));
++
++ memset(&data, 0, sizeof(data));
++ data.InStream = InStream;
++ data.UndoStream = UndoStream;
++ data.location = (trio_pointer_t)source;
++ data.max = sourceSize;
++ data.error = 0;
++
++#if defined(USE_LOCALE)
++ if (NULL == internalLocaleValues)
++ {
++ TrioSetLocale();
++ }
++#endif
++
++ status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
++ if (status < 0)
++ return status;
++
++ status = TrioScanProcess(&data, format, parameters);
++ if (data.error != 0)
++ {
++ status = data.error;
++ }
++ return status;
++}
++
++/*************************************************************************
++ * TrioInStreamFile
++ */
++#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
++TRIO_PRIVATE void
++TrioInStreamFile
++TRIO_ARGS2((self, intPointer),
++ trio_class_t *self,
++ int *intPointer)
++{
++ FILE *file = (FILE *)self->location;
++
++ assert(VALID(self));
++ assert(VALID(file));
++
++ self->actually.cached = 0;
++
++ /* The initial value of self->current is zero */
++ if (self->current == EOF)
++ {
++ self->error = (ferror(file))
++ ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0)
++ : TRIO_ERROR_RETURN(TRIO_EOF, 0);
++ }
++ else
++ {
++ self->processed++;
++ self->actually.cached++;
++ }
++
++ self->current = fgetc(file);
++
++ if (VALID(intPointer))
++ {
++ *intPointer = self->current;
++ }
++}
++#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
++
++/*************************************************************************
++ * TrioUndoStreamFile
++ */
++#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
++TRIO_PRIVATE void
++TrioUndoStreamFile
++TRIO_ARGS1((self),
++ trio_class_t *self)
++{
++ FILE *file = (FILE *)self->location;
++
++ assert(VALID(self));
++ assert(VALID(file));
++
++ if (self->actually.cached > 0)
++ {
++ assert(self->actually.cached == 1);
++
++ self->current = ungetc(self->current, file);
++ self->actually.cached = 0;
++ }
++}
++#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
++
++/*************************************************************************
++ * TrioInStreamFileDescriptor
++ */
++#if TRIO_FEATURE_FD
++TRIO_PRIVATE void
++TrioInStreamFileDescriptor
++TRIO_ARGS2((self, intPointer),
++ trio_class_t *self,
++ int *intPointer)
++{
++ int fd = *((int *)self->location);
++ int size;
++ unsigned char input;
++
++ assert(VALID(self));
++
++ self->actually.cached = 0;
++
++ size = read(fd, &input, sizeof(char));
++ if (size == -1)
++ {
++ self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
++ self->current = EOF;
++ }
++ else
++ {
++ self->current = (size == 0) ? EOF : input;
++ }
++ if (self->current != EOF)
++ {
++ self->actually.cached++;
++ self->processed++;
++ }
++
++ if (VALID(intPointer))
++ {
++ *intPointer = self->current;
++ }
++}
++#endif /* TRIO_FEATURE_FD */
++
++/*************************************************************************
++ * TrioInStreamCustom
++ */
++#if TRIO_FEATURE_CLOSURE
++TRIO_PRIVATE void
++TrioInStreamCustom
++TRIO_ARGS2((self, intPointer),
++ trio_class_t *self,
++ int *intPointer)
++{
++ trio_custom_t *data;
++
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ self->actually.cached = 0;
++
++ data = (trio_custom_t *)self->location;
++
++ self->current = (data->stream.in == NULL)
++ ? NIL
++ : (data->stream.in)(data->closure);
++
++ if (self->current == NIL)
++ {
++ self->current = EOF;
++ }
++ else
++ {
++ self->processed++;
++ self->actually.cached++;
++ }
++
++ if (VALID(intPointer))
++ {
++ *intPointer = self->current;
++ }
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++/*************************************************************************
++ * TrioInStreamString
++ */
++TRIO_PRIVATE void
++TrioInStreamString
++TRIO_ARGS2((self, intPointer),
++ trio_class_t *self,
++ int *intPointer)
++{
++ unsigned char **buffer;
++
++ assert(VALID(self));
++ assert(VALID(self->location));
++
++ self->actually.cached = 0;
++
++ buffer = (unsigned char **)self->location;
++ self->current = (*buffer)[0];
++ if (self->current == NIL)
++ {
++ self->current = EOF;
++ }
++ else
++ {
++ (*buffer)++;
++ self->processed++;
++ self->actually.cached++;
++ }
++
++ if (VALID(intPointer))
++ {
++ *intPointer = self->current;
++ }
++}
++
++/*************************************************************************
++ *
++ * Formatted scanning functions
++ *
++ ************************************************************************/
++
++#if defined(TRIO_DOCUMENTATION)
++# include "doc/doc_scanf.h"
++#endif
++/** @addtogroup Scanf
++ @{
++*/
++
++/*************************************************************************
++ * scanf
++ */
++
++/**
++ Scan characters from standard input stream.
++
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_STDIO
++TRIO_PUBLIC int
++trio_scanf
++TRIO_VARGS2((format, va_alist),
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioScan((trio_pointer_t)stdin, 0,
++ TrioInStreamFile,
++ TrioUndoStreamFile,
++ format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_STDIO */
++
++/**
++ Scan characters from standard input stream.
++
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_STDIO
++TRIO_PUBLIC int
++trio_vscanf
++TRIO_ARGS2((format, args),
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)stdin, 0,
++ TrioInStreamFile,
++ TrioUndoStreamFile,
++ format, args, NULL);
++}
++#endif /* TRIO_FEATURE_STDIO */
++
++/**
++ Scan characters from standard input stream.
++
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_STDIO
++TRIO_PUBLIC int
++trio_scanfv
++TRIO_ARGS2((format, args),
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)stdin, 0,
++ TrioInStreamFile,
++ TrioUndoStreamFile,
++ format, unused, args);
++}
++#endif /* TRIO_FEATURE_STDIO */
++
++/*************************************************************************
++ * fscanf
++ */
++
++/**
++ Scan characters from file.
++
++ @param file File pointer.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_FILE
++TRIO_PUBLIC int
++trio_fscanf
++TRIO_VARGS3((file, format, va_alist),
++ FILE *file,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(file));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioScan((trio_pointer_t)file, 0,
++ TrioInStreamFile,
++ TrioUndoStreamFile,
++ format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_FILE */
++
++/**
++ Scan characters from file.
++
++ @param file File pointer.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_FILE
++TRIO_PUBLIC int
++trio_vfscanf
++TRIO_ARGS3((file, format, args),
++ FILE *file,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(file));
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)file, 0,
++ TrioInStreamFile,
++ TrioUndoStreamFile,
++ format, args, NULL);
++}
++#endif /* TRIO_FEATURE_FILE */
++
++/**
++ Scan characters from file.
++
++ @param file File pointer.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_FILE
++TRIO_PUBLIC int
++trio_fscanfv
++TRIO_ARGS3((file, format, args),
++ FILE *file,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++
++ assert(VALID(file));
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)file, 0,
++ TrioInStreamFile,
++ TrioUndoStreamFile,
++ format, unused, args);
++}
++#endif /* TRIO_FEATURE_FILE */
++
++/*************************************************************************
++ * dscanf
++ */
++
++/**
++ Scan characters from file descriptor.
++
++ @param fd File descriptor.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_FD
++TRIO_PUBLIC int
++trio_dscanf
++TRIO_VARGS3((fd, format, va_alist),
++ int fd,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioScan((trio_pointer_t)&fd, 0,
++ TrioInStreamFileDescriptor,
++ NULL,
++ format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_FD */
++
++/**
++ Scan characters from file descriptor.
++
++ @param fd File descriptor.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_FD
++TRIO_PUBLIC int
++trio_vdscanf
++TRIO_ARGS3((fd, format, args),
++ int fd,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)&fd, 0,
++ TrioInStreamFileDescriptor,
++ NULL,
++ format, args, NULL);
++}
++#endif /* TRIO_FEATURE_FD */
++
++/**
++ Scan characters from file descriptor.
++
++ @param fd File descriptor.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++#if TRIO_FEATURE_FD
++TRIO_PUBLIC int
++trio_dscanfv
++TRIO_ARGS3((fd, format, args),
++ int fd,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)&fd, 0,
++ TrioInStreamFileDescriptor,
++ NULL,
++ format, unused, args);
++}
++#endif /* TRIO_FEATURE_FD */
++
++/*************************************************************************
++ * cscanf
++ */
++#if TRIO_FEATURE_CLOSURE
++TRIO_PUBLIC int
++trio_cscanf
++TRIO_VARGS4((stream, closure, format, va_alist),
++ trio_instream_t stream,
++ trio_pointer_t closure,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++ trio_custom_t data;
++
++ assert(VALID(stream));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ data.stream.in = stream;
++ data.closure = closure;
++ status = TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++#if TRIO_FEATURE_CLOSURE
++TRIO_PUBLIC int
++trio_vcscanf
++TRIO_ARGS4((stream, closure, format, args),
++ trio_instream_t stream,
++ trio_pointer_t closure,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ trio_custom_t data;
++
++ assert(VALID(stream));
++ assert(VALID(format));
++
++ data.stream.in = stream;
++ data.closure = closure;
++ return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++#if TRIO_FEATURE_CLOSURE
++TRIO_PUBLIC int
++trio_cscanfv
++TRIO_ARGS4((stream, closure, format, args),
++ trio_instream_t stream,
++ trio_pointer_t closure,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++ trio_custom_t data;
++
++ assert(VALID(stream));
++ assert(VALID(format));
++
++ data.stream.in = stream;
++ data.closure = closure;
++ return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, unused, args);
++}
++#endif /* TRIO_FEATURE_CLOSURE */
++
++/*************************************************************************
++ * sscanf
++ */
++
++/**
++ Scan characters from string.
++
++ @param buffer Input string.
++ @param format Formatting string.
++ @param ... Arguments.
++ @return Number of scanned characters.
++ */
++TRIO_PUBLIC int
++trio_sscanf
++TRIO_VARGS3((buffer, format, va_alist),
++ TRIO_CONST char *buffer,
++ TRIO_CONST char *format,
++ TRIO_VA_DECL)
++{
++ int status;
++ va_list args;
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ TRIO_VA_START(args, format);
++ status = TrioScan((trio_pointer_t)&buffer, 0,
++ TrioInStreamString,
++ NULL,
++ format, args, NULL);
++ TRIO_VA_END(args);
++ return status;
++}
++
++/**
++ Scan characters from string.
++
++ @param buffer Input string.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++TRIO_PUBLIC int
++trio_vsscanf
++TRIO_ARGS3((buffer, format, args),
++ TRIO_CONST char *buffer,
++ TRIO_CONST char *format,
++ va_list args)
++{
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)&buffer, 0,
++ TrioInStreamString,
++ NULL,
++ format, args, NULL);
++}
++
++/**
++ Scan characters from string.
++
++ @param buffer Input string.
++ @param format Formatting string.
++ @param args Arguments.
++ @return Number of scanned characters.
++ */
++TRIO_PUBLIC int
++trio_sscanfv
++TRIO_ARGS3((buffer, format, args),
++ TRIO_CONST char *buffer,
++ TRIO_CONST char *format,
++ trio_pointer_t *args)
++{
++ static va_list unused;
++
++ assert(VALID(buffer));
++ assert(VALID(format));
++
++ return TrioScan((trio_pointer_t)&buffer, 0,
++ TrioInStreamString,
++ NULL,
++ format, unused, args);
++}
++
++#endif /* TRIO_FEATURE_SCANF */
++
++/** @} End of Scanf documentation module */
++
++/*************************************************************************
++ * trio_strerror
++ */
++TRIO_PUBLIC TRIO_CONST char *
++trio_strerror
++TRIO_ARGS1((errorcode),
++ int errorcode)
++{
++#if TRIO_FEATURE_STRERR
++ /* Textual versions of the error codes */
++ switch (TRIO_ERROR_CODE(errorcode))
++ {
++ case TRIO_EOF:
++ return "End of file";
++ case TRIO_EINVAL:
++ return "Invalid argument";
++ case TRIO_ETOOMANY:
++ return "Too many arguments";
++ case TRIO_EDBLREF:
++ return "Double reference";
++ case TRIO_EGAP:
++ return "Reference gap";
++ case TRIO_ENOMEM:
++ return "Out of memory";
++ case TRIO_ERANGE:
++ return "Invalid range";
++ case TRIO_ECUSTOM:
++ return "Custom error";
++ default:
++ return "Unknown";
++ }
++#else
++ return "Unknown";
++#endif
++}
+diff -up ghostscript-9.07/trio/triodef.h.gs_sprintf ghostscript-9.07/trio/triodef.h
+--- ghostscript-9.07/trio/triodef.h.gs_sprintf 2013-05-09 17:02:39.112447283 +0100
++++ ghostscript-9.07/trio/triodef.h 2013-05-09 17:02:39.111447279 +0100
+@@ -0,0 +1,336 @@
++/*************************************************************************
++ *
++ * $Id: triodef.h,v 1.35 2009/09/20 11:37:14 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++#ifndef TRIO_TRIODEF_H
++#define TRIO_TRIODEF_H
++
++/*************************************************************************
++ * Compiler support detection
++ */
++
++#if defined(__GNUC__)
++# define TRIO_COMPILER_GCC
++#endif
++
++#if defined(__SUNPRO_CC)
++# define TRIO_COMPILER_SUNPRO __SUNPRO_CC
++#else
++# if defined(__SUNPRO_C)
++# define TRIO_COMPILER_SUNPRO __SUNPRO_C
++# endif
++#endif
++
++#if defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
++# define TRIO_COMPILER_XLC
++#else
++# if defined(_AIX) && !defined(__GNUC__)
++# define TRIO_COMPILER_XLC /* Workaround for old xlc */
++# endif
++#endif
++
++#if defined(__DECC) || defined(__DECCXX)
++# define TRIO_COMPILER_DECC
++#else
++# if defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__)
++# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */
++# endif
++#endif
++
++#if defined(__HP_aCC) || defined(__HP_cc)
++# define TRIO_COMPILER_HP
++#endif
++
++#if defined(sgi) || defined(__sgi)
++# define TRIO_COMPILER_MIPSPRO
++#endif
++
++#if defined(_MSC_VER)
++# define TRIO_COMPILER_MSVC
++#endif
++
++#if defined(__BORLANDC__)
++# define TRIO_COMPILER_BCB
++#endif
++
++/*************************************************************************
++ * Platform support detection
++ */
++
++#if defined(VMS) || defined(__VMS)
++# define TRIO_PLATFORM_VMS
++#endif
++
++#if defined(unix) || defined(__unix) || defined(__unix__)
++# define TRIO_PLATFORM_UNIX
++#endif
++
++#if defined(TRIO_COMPILER_XLC) || defined(_AIX)
++# define TRIO_PLATFORM_UNIX
++#endif
++
++#if defined(TRIO_COMPILER_DECC) || defined(__osf___)
++# if !defined(TRIO_PLATFORM_VMS)
++# define TRIO_PLATFORM_UNIX
++# endif
++#endif
++
++#if defined(__NetBSD__)
++# define TRIO_PLATFORM_UNIX
++#endif
++
++#if defined(__Lynx__)
++# define TRIO_PLATFORM_UNIX
++# define TRIO_PLATFORM_LYNX
++#endif
++
++#if defined(__APPLE__) && defined(__MACH__)
++# define TRIO_PLATFORM_UNIX
++#endif
++
++#if defined(__QNX__)
++# define TRIO_PLATFORM_UNIX
++# define TRIO_PLATFORM_QNX
++#endif
++
++#if defined(__CYGWIN__)
++# define TRIO_PLATFORM_UNIX
++#endif
++
++#if defined(AMIGA) && defined(TRIO_COMPILER_GCC)
++# define TRIO_PLATFORM_UNIX
++#endif
++
++#if defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
++# define TRIO_PLATFORM_WIN32
++#endif
++
++#if defined(_WIN32_WCE)
++# define TRIO_PLATFORM_WINCE
++#endif
++
++#if defined(mpeix) || defined(__mpexl)
++# define TRIO_PLATFORM_MPEIX
++#endif
++
++#if defined(_AIX)
++# define TRIO_PLATFORM_AIX
++#endif
++
++#if defined(__hpux)
++# define TRIO_PLATFORM_HPUX
++#endif
++
++#if defined(sun) || defined(__sun__)
++# if defined(__SVR4) || defined(__svr4__)
++# define TRIO_PLATFORM_SOLARIS
++# else
++# define TRIO_PLATFORM_SUNOS
++# endif
++#endif
++
++/*************************************************************************
++ * Standards support detection
++ */
++
++#if defined(__STDC__) \
++ || defined(_MSC_EXTENSIONS) \
++ || defined(TRIO_COMPILER_BCB)
++# define PREDEF_STANDARD_C89
++#endif
++#if defined(__STDC_VERSION__)
++# define PREDEF_STANDARD_C90
++#endif
++#if defined (__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199409L)
++# define PREDEF_STANDARD_C94
++#endif
++#if defined (__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L)
++# define PREDEF_STANDARD_C99
++#endif
++
++#if defined(TRIO_COMPILER_SUNPRO) && (TRIO_COMPILER_SUNPRO >= 0x420)
++# if !defined(PREDEF_STANDARD_C94)
++# define PREDEF_STANDARD_C94
++# endif
++#endif
++
++#if defined(__cplusplus)
++# define PREDEF_STANDARD_CXX
++#endif
++#if defined(__cplusplus) && __cplusplus - 0 >= 199711L
++# define PREDEF_STANDARD_CXX89
++#endif
++
++#if defined(TRIO_PLATFORM_UNIX)
++# include <unistd.h>
++#endif
++
++#if defined(_POSIX_VERSION)
++# define PREDEF_STANDARD_POSIX _POSIX_VERSION
++# if (_POSIX_VERSION >= 199506L)
++# define PREDEF_STANDARD_POSIX_1996
++# endif
++#endif
++
++#if (_XOPEN_VERSION - 0 >= 3) || defined(_XOPEN_XPG3)
++# define PREDEF_STANDARD_XPG3
++#endif
++#if (_XOPEN_VERSION - 0 >= 4) || defined(_XOPEN_XPG4)
++# define PREDEF_STANDARD_XPG4
++#endif
++#if (_XOPEN_VERSION - 0 > 4) \
++ || (defined(_XOPEN_UNIX) && (_XOPEN_VERSION - 0 == 4))
++# define PREDEF_STANDARD_UNIX95
++#endif
++#if (_XOPEN_VERSION - 0 >= 500)
++# define PREDEF_STANDARD_UNIX98
++#endif
++#if (_XOPEN_VERSION - 0 >= 600)
++# define PREDEF_STANDARD_UNIX03
++#endif
++
++/*************************************************************************
++ * Generic defines
++ */
++
++#if !defined(TRIO_PUBLIC)
++# define TRIO_PUBLIC
++#endif
++#if !defined(TRIO_PRIVATE)
++# define TRIO_PRIVATE static
++#endif
++
++#if !(defined(PREDEF_STANDARD_C89) || defined(PREDEF_STANDARD_CXX))
++# define TRIO_COMPILER_ANCIENT
++#endif
++
++#if defined(TRIO_COMPILER_ANCIENT)
++# define TRIO_CONST
++# define TRIO_VOLATILE
++# define TRIO_SIGNED
++typedef double trio_long_double_t;
++typedef char * trio_pointer_t;
++# define TRIO_SUFFIX_LONG(x) x
++# define TRIO_PROTO(x) ()
++# define TRIO_NOARGS
++# define TRIO_ARGS1(list,a1) list a1;
++# define TRIO_ARGS2(list,a1,a2) list a1; a2;
++# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3;
++# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4;
++# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5;
++# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6;
++# define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) list a1; a2; a3; a4; a5; a6; a7;
++# define TRIO_VARGS2(list,a1,a2) list a1; a2
++# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3
++# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4
++# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5
++# define TRIO_VA_DECL va_dcl
++# define TRIO_VA_START(x,y) va_start(x)
++# define TRIO_VA_END(x) va_end(x)
++#else /* ANSI C */
++# define TRIO_CONST const
++# define TRIO_VOLATILE volatile
++# define TRIO_SIGNED signed
++typedef long double trio_long_double_t;
++typedef void * trio_pointer_t;
++# define TRIO_SUFFIX_LONG(x) x ## L
++# define TRIO_PROTO(x) x
++# define TRIO_NOARGS void
++# define TRIO_ARGS1(list,a1) (a1)
++# define TRIO_ARGS2(list,a1,a2) (a1,a2)
++# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3)
++# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4)
++# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5)
++# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6)
++# define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) (a1,a2,a3,a4,a5,a6,a7)
++# define TRIO_VARGS2 TRIO_ARGS2
++# define TRIO_VARGS3 TRIO_ARGS3
++# define TRIO_VARGS4 TRIO_ARGS4
++# define TRIO_VARGS5 TRIO_ARGS5
++# define TRIO_VA_DECL ...
++# define TRIO_VA_START(x,y) va_start(x,y)
++# define TRIO_VA_END(x) va_end(x)
++#endif
++
++#if defined(PREDEF_STANDARD_C99) || defined(PREDEF_STANDARD_CXX)
++# define TRIO_INLINE inline
++#else
++# if defined(TRIO_COMPILER_GCC)
++# define TRIO_INLINE __inline__
++# endif
++# if defined(TRIO_COMPILER_MSVC)
++# define TRIO_INLINE _inline
++# endif
++# if defined(TRIO_COMPILER_BCB)
++# define TRIO_INLINE __inline
++# endif
++#endif
++#if !defined(TRIO_INLINE)
++# define TRIO_INLINE
++#endif
++
++/*************************************************************************
++ * Workarounds
++ */
++
++#if defined(TRIO_PLATFORM_VMS)
++/*
++ * Computations done with constants at compile time can trigger these
++ * even when compiling with IEEE enabled.
++ */
++# pragma message disable (UNDERFLOW, FLOATOVERFL)
++
++# if (__CRTL_VER < 80210001)
++/*
++ * Although the compiler supports C99 language constructs, the C
++ * run-time library does not contain all C99 functions.
++ */
++# if defined(PREDEF_STANDARD_C99)
++# undef PREDEF_STANDARD_C99
++# endif
++# endif
++#endif
++
++/*
++ * Not all preprocessors supports the LL token.
++ */
++#if defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
++#else
++# define TRIO_COMPILER_SUPPORTS_LL
++#endif
++
++#if defined(__CYGWIN__)
++/*
++ * Cygwin defines the macros for hosted C99, but does not support certain
++ * long double math functions.
++ */
++# include <cygwin/version.h>
++# define TRIO_CYGWIN_VERSION_API CYGWIN_VERSION_API_MAJOR * 1000 + \
++ CYGWIN_VERSION_API_MINOR
++/*
++ * Please change the version number below when the Cygwin API supports
++ * long double math functions (powl, fmodl, etc.)
++ */
++# if TRIO_CYGWIN_VERSION_API < 99999999
++# define TRIO_NO_FLOORL 1
++# define TRIO_NO_CEILL 1
++# define TRIO_NO_POWL 1
++# define TRIO_NO_FMODL 1
++# define TRIO_NO_LOG10L 1
++# endif
++#endif
++
++#endif /* TRIO_TRIODEF_H */
+diff -up ghostscript-9.07/trio/trio.h.gs_sprintf ghostscript-9.07/trio/trio.h
+--- ghostscript-9.07/trio/trio.h.gs_sprintf 2013-05-09 17:02:39.112447283 +0100
++++ ghostscript-9.07/trio/trio.h 2013-05-09 17:02:39.112447283 +0100
+@@ -0,0 +1,235 @@
++/*************************************************************************
++ *
++ * $Id: trio.h,v 1.19 2009/09/13 10:12:22 breese Exp $
++ *
++ * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ *************************************************************************
++ *
++ * http://ctrio.sourceforge.net/
++ *
++ ************************************************************************/
++
++#ifndef TRIO_TRIO_H
++#define TRIO_TRIO_H
++
++#if !defined(WITHOUT_TRIO)
++
++/*
++ * Use autoconf defines if present. Packages using trio must define
++ * HAVE_CONFIG_H as a compiler option themselves.
++ */
++#if defined(HAVE_CONFIG_H)
++# include <config.h>
++#endif
++
++#include "triop.h"
++
++#include <stdio.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * Error codes.
++ *
++ * Remember to add a textual description to trio_strerror.
++ */
++enum {
++ TRIO_EOF = 1,
++ TRIO_EINVAL = 2,
++ TRIO_ETOOMANY = 3,
++ TRIO_EDBLREF = 4,
++ TRIO_EGAP = 5,
++ TRIO_ENOMEM = 6,
++ TRIO_ERANGE = 7,
++ TRIO_ERRNO = 8,
++ TRIO_ECUSTOM = 9
++};
++
++/* Error macros */
++#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF)
++#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8)
++#define TRIO_ERROR_NAME(x) trio_strerror(x)
++
++typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int));
++typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t));
++
++TRIO_CONST char *trio_strerror TRIO_PROTO((int));
++
++/*************************************************************************
++ * Print Functions
++ */
++
++int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...));
++int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
++int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args));
++
++int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...));
++int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
++int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
++
++int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...));
++int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
++int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
++
++int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
++ TRIO_CONST char *format, ...));
++int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
++ TRIO_CONST char *format, va_list args));
++int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
++ TRIO_CONST char *format, void **args));
++
++int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...));
++int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args));
++int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args));
++
++int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...));
++int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
++ va_list args));
++int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
++ void **args));
++
++int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...));
++int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
++ va_list args));
++
++#if defined(TRIO_DEPRECATED)
++char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...));
++char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
++#endif
++
++int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...));
++int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args));
++int trio_asprintfv TRIO_PROTO((char **result, TRIO_CONST char *format, trio_pointer_t * args));
++
++/*************************************************************************
++ * Scan Functions
++ */
++int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...));
++int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args));
++int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args));
++
++int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...));
++int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
++int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
++
++int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...));
++int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
++int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
++
++int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
++ TRIO_CONST char *format, ...));
++int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
++ TRIO_CONST char *format, va_list args));
++int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
++ TRIO_CONST char *format, void **args));
++
++int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...));
++int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args));
++int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args));
++
++/*************************************************************************
++ * Locale Functions
++ */
++void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint));
++void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator));
++void trio_locale_set_grouping TRIO_PROTO((char *grouping));
++
++/*************************************************************************
++ * Renaming
++ */
++#ifdef TRIO_REPLACE_STDIO
++/* Replace the <stdio.h> functions */
++#ifndef HAVE_PRINTF
++# undef printf
++# define printf trio_printf
++#endif
++#ifndef HAVE_VPRINTF
++# undef vprintf
++# define vprintf trio_vprintf
++#endif
++#ifndef HAVE_FPRINTF
++# undef fprintf
++# define fprintf trio_fprintf
++#endif
++#ifndef HAVE_VFPRINTF
++# undef vfprintf
++# define vfprintf trio_vfprintf
++#endif
++#ifndef HAVE_SPRINTF
++# undef sprintf
++# define sprintf trio_sprintf
++#endif
++#ifndef HAVE_VSPRINTF
++# undef vsprintf
++# define vsprintf trio_vsprintf
++#endif
++#ifndef HAVE_SNPRINTF
++# undef snprintf
++# define snprintf trio_snprintf
++#endif
++#ifndef HAVE_VSNPRINTF
++# undef vsnprintf
++# define vsnprintf trio_vsnprintf
++#endif
++#ifndef HAVE_SCANF
++# undef scanf
++# define scanf trio_scanf
++#endif
++#ifndef HAVE_VSCANF
++# undef vscanf
++# define vscanf trio_vscanf
++#endif
++#ifndef HAVE_FSCANF
++# undef fscanf
++# define fscanf trio_fscanf
++#endif
++#ifndef HAVE_VFSCANF
++# undef vfscanf
++# define vfscanf trio_vfscanf
++#endif
++#ifndef HAVE_SSCANF
++# undef sscanf
++# define sscanf trio_sscanf
++#endif
++#ifndef HAVE_VSSCANF
++# undef vsscanf
++# define vsscanf trio_vsscanf
++#endif
++/* These aren't stdio functions, but we make them look similar */
++#undef dprintf
++#define dprintf trio_dprintf
++#undef vdprintf
++#define vdprintf trio_vdprintf
++#undef aprintf
++#define aprintf trio_aprintf
++#undef vaprintf
++#define vaprintf trio_vaprintf
++#undef asprintf
++#define asprintf trio_asprintf
++#undef vasprintf
++#define vasprintf trio_vasprintf
++#undef dscanf
++#define dscanf trio_dscanf
++#undef vdscanf
++#define vdscanf trio_vdscanf
++#endif
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* WITHOUT_TRIO */
++
++#endif /* TRIO_TRIO_H */
+diff -up ghostscript-9.07/trio/trionan.c.gs_sprintf ghostscript-9.07/trio/trionan.c
+--- ghostscript-9.07/trio/trionan.c.gs_sprintf 2013-05-09 17:02:39.112447283 +0100
++++ ghostscript-9.07/trio/trionan.c 2013-05-09 17:02:39.112447283 +0100
+@@ -0,0 +1,1257 @@
++/*************************************************************************
++ *
++ * $Id: trionan.c,v 1.33 2005/05/29 11:57:25 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************
++ *
++ * Functions to handle special quantities in floating-point numbers
++ * (that is, NaNs and infinity). They provide the capability to detect
++ * and fabricate special quantities.
++ *
++ * Although written to be as portable as possible, it can never be
++ * guaranteed to work on all platforms, as not all hardware supports
++ * special quantities.
++ *
++ * The approach used here (approximately) is to:
++ *
++ * 1. Use C99 functionality when available.
++ * 2. Use IEEE 754 bit-patterns if possible.
++ * 3. Use platform-specific techniques.
++ *
++ ************************************************************************/
++
++/*************************************************************************
++ * Include files
++ */
++#include "triodef.h"
++#include "trionan.h"
++
++#include <math.h>
++#include <string.h>
++#include <limits.h>
++#if !defined(TRIO_PLATFORM_SYMBIAN)
++# include <float.h>
++#endif
++#if defined(TRIO_PLATFORM_UNIX)
++# include <signal.h>
++#endif
++#if defined(TRIO_COMPILER_DECC)
++# include <fp_class.h>
++#endif
++#include <assert.h>
++
++#if defined(TRIO_DOCUMENTATION)
++# include "doc/doc_nan.h"
++#endif
++/** @addtogroup SpecialQuantities
++ @{
++*/
++
++/*************************************************************************
++ * Definitions
++ */
++
++#if !defined(TRIO_PUBLIC_NAN)
++# define TRIO_PUBLIC_NAN TRIO_PUBLIC
++#endif
++#if !defined(TRIO_PRIVATE_NAN)
++# define TRIO_PRIVATE_NAN TRIO_PRIVATE
++#endif
++
++#define TRIO_TRUE (1 == 1)
++#define TRIO_FALSE (0 == 1)
++
++/*
++ * We must enable IEEE floating-point on Alpha
++ */
++#if defined(__alpha) && !defined(_IEEE_FP)
++# if defined(TRIO_COMPILER_DECC)
++# if defined(TRIO_PLATFORM_VMS)
++# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
++# else
++# if !defined(_CFE)
++# error "Must be compiled with option -ieee"
++# endif
++# endif
++# else
++# if defined(TRIO_COMPILER_GCC)
++# error "Must be compiled with option -mieee"
++# endif
++# endif
++#endif /* __alpha && ! _IEEE_FP */
++
++/*
++ * In ANSI/IEEE 754-1985 64-bits double format numbers have the
++ * following properties (amoungst others)
++ *
++ * o FLT_RADIX == 2: binary encoding
++ * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
++ * to indicate special numbers (e.g. NaN and Infinity), so the
++ * maximum exponent is 10 bits wide (2^10 == 1024).
++ * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
++ * numbers are normalized the initial binary 1 is represented
++ * implicitly (the so-called "hidden bit"), which leaves us with
++ * the ability to represent 53 bits wide mantissa.
++ */
++#if defined(__STDC_IEC_559__)
++# define TRIO_IEEE_754
++#else
++# if (FLT_RADIX - 0 == 2) && (DBL_MAX_EXP - 0 == 1024) && (DBL_MANT_DIG - 0 == 53)
++# define TRIO_IEEE_754
++# endif
++#endif
++
++/*
++ * Determine which fpclassify_and_sign() function to use.
++ */
++#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
++# if defined(PREDEF_STANDARD_C99) && defined(fpclassify)
++# define TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT
++# else
++# if defined(TRIO_COMPILER_DECC)
++# define TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT
++# else
++# if defined(TRIO_COMPILER_VISUALC) || defined(TRIO_COMPILER_BORLAND)
++# define TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT
++# else
++# if defined(TRIO_COMPILER_HP) && defined(FP_PLUS_NORM)
++# define TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT
++# else
++# if defined(TRIO_COMPILER_XLC) && defined(FP_PLUS_NORM)
++# define TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT
++# else
++# define TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT
++# endif
++# endif
++# endif
++# endif
++# endif
++#endif
++
++/*
++ * Determine how to generate negative zero.
++ */
++#if defined(TRIO_FUNC_NZERO)
++# if defined(TRIO_IEEE_754)
++# define TRIO_NZERO_IEEE_754
++# else
++# define TRIO_NZERO_FALLBACK
++# endif
++#endif
++
++/*
++ * Determine how to generate positive infinity.
++ */
++#if defined(TRIO_FUNC_PINF)
++# if defined(INFINITY) && defined(__STDC_IEC_559__)
++# define TRIO_PINF_C99_MACRO
++# else
++# if defined(TRIO_IEEE_754)
++# define TRIO_PINF_IEEE_754
++# else
++# define TRIO_PINF_FALLBACK
++# endif
++# endif
++#endif
++
++/*
++ * Determine how to generate NaN.
++ */
++#if defined(TRIO_FUNC_NAN)
++# if defined(PREDEF_STANDARD_C99) && !defined(TRIO_COMPILER_DECC)
++# define TRIO_NAN_C99_FUNCTION
++# else
++# if defined(NAN) && defined(__STDC_IEC_559__)
++# define TRIO_NAN_C99_MACRO
++# else
++# if defined(TRIO_IEEE_754)
++# define TRIO_NAN_IEEE_754
++# else
++# define TRIO_NAN_FALLBACK
++# endif
++# endif
++# endif
++#endif
++
++/*
++ * Resolve internal dependencies.
++ */
++#if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT)
++# define TRIO_FUNC_INTERNAL_ISNAN
++# define TRIO_FUNC_INTERNAL_ISINF
++# if defined(TRIO_IEEE_754)
++# define TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY
++# define TRIO_FUNC_INTERNAL_IS_NEGATIVE
++# endif
++#endif
++
++#if defined(TRIO_NZERO_IEEE_754) \
++ || defined(TRIO_PINF_IEEE_754) \
++ || defined(TRIO_NAN_IEEE_754)
++# define TRIO_FUNC_INTERNAL_MAKE_DOUBLE
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_ISNAN)
++# if defined(PREDEF_STANDARD_XPG3)
++# define TRIO_INTERNAL_ISNAN_XPG3
++# else
++# if defined(TRIO_IEEE_754)
++# define TRIO_INTERNAL_ISNAN_IEEE_754
++# else
++# define TRIO_INTERNAL_ISNAN_FALLBACK
++# endif
++# endif
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_ISINF)
++# if defined(TRIO_IEEE_754)
++# define TRIO_INTERNAL_ISINF_IEEE_754
++# else
++# define TRIO_INTERNAL_ISINF_FALLBACK
++# endif
++#endif
++
++/*************************************************************************
++ * Constants
++ */
++
++#if !defined(TRIO_EMBED_NAN)
++static TRIO_CONST char rcsid[] = "@(#)$Id: trionan.c,v 1.33 2005/05/29 11:57:25 breese Exp $";
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE) \
++ || defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) \
++ || defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE)
++/*
++ * Endian-agnostic indexing macro.
++ *
++ * The value of internalEndianMagic, when converted into a 64-bit
++ * integer, becomes 0x0706050403020100 (we could have used a 64-bit
++ * integer value instead of a double, but not all platforms supports
++ * that type). The value is automatically encoded with the correct
++ * endianess by the compiler, which means that we can support any
++ * kind of endianess. The individual bytes are then used as an index
++ * for the IEEE 754 bit-patterns and masks.
++ */
++#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
++static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY)
++/* Mask for the exponent */
++static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
++ 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++
++/* Mask for the mantissa */
++static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
++ 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
++};
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE)
++/* Mask for the sign bit */
++static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
++ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++#endif
++
++#if defined(TRIO_NZERO_IEEE_754)
++/* Bit-pattern for negative zero */
++static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
++ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++#endif
++
++#if defined(TRIO_PINF_IEEE_754)
++/* Bit-pattern for infinity */
++static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
++ 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++#endif
++
++#if defined(TRIO_NAN_IEEE_754)
++/* Bit-pattern for quiet NaN */
++static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
++ 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++#endif
++
++
++/*************************************************************************
++ * Internal functions
++ */
++
++/*
++ * internal_make_double
++ */
++#if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE)
++
++TRIO_PRIVATE_NAN double
++internal_make_double
++TRIO_ARGS1((values),
++ TRIO_CONST unsigned char *values)
++{
++ TRIO_VOLATILE double result;
++ int i;
++
++ for (i = 0; i < (int)sizeof(double); i++) {
++ ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
++ }
++ return result;
++}
++
++#endif
++
++/*
++ * internal_is_special_quantity
++ */
++#if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY)
++
++TRIO_PRIVATE_NAN int
++internal_is_special_quantity
++TRIO_ARGS2((number, has_mantissa),
++ double number,
++ int *has_mantissa)
++{
++ unsigned int i;
++ unsigned char current;
++ int is_special_quantity = TRIO_TRUE;
++
++ *has_mantissa = 0;
++
++ for (i = 0; i < (unsigned int)sizeof(double); i++) {
++ current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
++ is_special_quantity
++ &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
++ *has_mantissa |= (current & ieee_754_mantissa_mask[i]);
++ }
++ return is_special_quantity;
++}
++
++#endif
++
++/*
++ * internal_is_negative
++ */
++#if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE)
++
++TRIO_PRIVATE_NAN int
++internal_is_negative
++TRIO_ARGS1((number),
++ double number)
++{
++ unsigned int i;
++ int is_negative = TRIO_FALSE;
++
++ for (i = 0; i < (unsigned int)sizeof(double); i++) {
++ is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
++ & ieee_754_sign_mask[i]);
++ }
++ return is_negative;
++}
++
++#endif
++
++#if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT)
++
++TRIO_PRIVATE_NAN TRIO_INLINE int
++c99_fpclassify_and_signbit
++TRIO_ARGS2((number, is_negative),
++ double number,
++ int *is_negative)
++{
++ *is_negative = signbit(number);
++ switch (fpclassify(number)) {
++ case FP_NAN:
++ return TRIO_FP_NAN;
++ case FP_INFINITE:
++ return TRIO_FP_INFINITE;
++ case FP_SUBNORMAL:
++ return TRIO_FP_SUBNORMAL;
++ case FP_ZERO:
++ return TRIO_FP_ZERO;
++ default:
++ return TRIO_FP_NORMAL;
++ }
++}
++
++#endif /* TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT */
++
++#if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT)
++
++TRIO_PRIVATE_NAN TRIO_INLINE int
++decc_fpclassify_and_signbit
++TRIO_ARGS2((number, is_negative),
++ double number,
++ int *is_negative)
++{
++ switch (fp_class(number)) {
++ case FP_QNAN:
++ case FP_SNAN:
++ *is_negative = TRIO_FALSE; /* NaN has no sign */
++ return TRIO_FP_NAN;
++ case FP_POS_INF:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_INFINITE;
++ case FP_NEG_INF:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_INFINITE;
++ case FP_POS_DENORM:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_SUBNORMAL;
++ case FP_NEG_DENORM:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_SUBNORMAL;
++ case FP_POS_ZERO:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_ZERO;
++ case FP_NEG_ZERO:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_ZERO;
++ case FP_POS_NORM:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_NORMAL;
++ case FP_NEG_NORM:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_NORMAL;
++ default:
++ *is_negative = (number < 0.0);
++ return TRIO_FP_NORMAL;
++ }
++}
++
++#endif /* TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT */
++
++#if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT)
++
++TRIO_PRIVATE_NAN int
++ms_fpclassify_and_signbit
++TRIO_ARGS2((number, is_negative),
++ double number,
++ int *is_negative)
++{
++ int result;
++# if defined(TRIO_COMPILER_BORLAND)
++ /*
++ * The floating-point precision may be changed by the Borland _fpclass()
++ * function, so we have to save and restore the floating-point control mask.
++ */
++ unsigned int mask;
++ /* Remember the old mask */
++ mask = _control87(0, 0);
++# endif
++
++ switch (_fpclass(number)) {
++ case _FPCLASS_QNAN:
++ case _FPCLASS_SNAN:
++ *is_negative = TRIO_FALSE; /* NaN has no sign */
++ result = TRIO_FP_NAN;
++ break;
++ case _FPCLASS_PINF:
++ *is_negative = TRIO_FALSE;
++ result = TRIO_FP_INFINITE;
++ break;
++ case _FPCLASS_NINF:
++ *is_negative = TRIO_TRUE;
++ result = TRIO_FP_INFINITE;
++ break;
++ case _FPCLASS_PD:
++ *is_negative = TRIO_FALSE;
++ result = TRIO_FP_SUBNORMAL;
++ break;
++ case _FPCLASS_ND:
++ *is_negative = TRIO_TRUE;
++ result = TRIO_FP_SUBNORMAL;
++ break;
++ case _FPCLASS_PZ:
++ *is_negative = TRIO_FALSE;
++ result = TRIO_FP_ZERO;
++ break;
++ case _FPCLASS_NZ:
++ *is_negative = TRIO_TRUE;
++ result = TRIO_FP_ZERO;
++ break;
++ case _FPCLASS_PN:
++ *is_negative = TRIO_FALSE;
++ result = TRIO_FP_NORMAL;
++ break;
++ case _FPCLASS_NN:
++ *is_negative = TRIO_TRUE;
++ result = TRIO_FP_NORMAL;
++ break;
++ default:
++ *is_negative = (number < 0.0);
++ result = TRIO_FP_NORMAL;
++ break;
++ }
++
++# if defined(TRIO_COMPILER_BORLAND)
++ /* Restore the old precision */
++ (void)_control87(mask, MCW_PC);
++# endif
++
++ return result;
++}
++
++#endif /* TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT */
++
++#if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT)
++
++TRIO_PRIVATE_NAN TRIO_INLINE int
++hp_fpclassify_and_signbit
++TRIO_ARGS2((number, is_negative),
++ double number,
++ int *is_negative)
++{
++ /*
++ * HP-UX 9.x and 10.x have an fpclassify() function, that is different
++ * from the C99 fpclassify() macro supported on HP-UX 11.x.
++ */
++ switch (fpclassify(number)) {
++ case FP_QNAN:
++ case FP_SNAN:
++ *is_negative = TRIO_FALSE; /* NaN has no sign */
++ return TRIO_FP_NAN;
++ case FP_PLUS_INF:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_INFINITE;
++ case FP_MINUS_INF:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_INFINITE;
++ case FP_PLUS_DENORM:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_SUBNORMAL;
++ case FP_MINUS_DENORM:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_SUBNORMAL;
++ case FP_PLUS_ZERO:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_ZERO;
++ case FP_MINUS_ZERO:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_ZERO;
++ case FP_PLUS_NORM:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_NORMAL;
++ case FP_MINUS_NORM:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_NORMAL;
++ default:
++ *is_negative = (number < 0.0);
++ return TRIO_FP_NORMAL;
++ }
++}
++
++#endif /* TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT */
++
++#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT)
++
++TRIO_PRIVATE_NAN TRIO_INLINE int
++xlc_fpclassify_and_signbit
++TRIO_ARGS2((number, is_negative),
++ double number,
++ int *is_negative)
++{
++ /*
++ * AIX has class() for C, and _class() for C++
++ */
++# if defined(__cplusplus)
++# define AIX_CLASS(n) _class(n)
++# else
++# define AIX_CLASS(n) class(n)
++# endif
++
++ switch (AIX_CLASS(number)) {
++ case FP_QNAN:
++ case FP_SNAN:
++ *is_negative = TRIO_FALSE; /* NaN has no sign */
++ return TRIO_FP_NAN;
++ case FP_PLUS_INF:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_INFINITE;
++ case FP_MINUS_INF:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_INFINITE;
++ case FP_PLUS_DENORM:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_SUBNORMAL;
++ case FP_MINUS_DENORM:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_SUBNORMAL;
++ case FP_PLUS_ZERO:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_ZERO;
++ case FP_MINUS_ZERO:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_ZERO;
++ case FP_PLUS_NORM:
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_NORMAL;
++ case FP_MINUS_NORM:
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_NORMAL;
++ default:
++ *is_negative = (number < 0.0);
++ return TRIO_FP_NORMAL;
++ }
++}
++
++#endif /* TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT */
++
++#if defined(TRIO_FUNC_INTERNAL_ISNAN)
++
++TRIO_PRIVATE_NAN TRIO_INLINE int
++internal_isnan
++TRIO_ARGS1((number),
++ double number)
++{
++# if defined(TRIO_INTERNAL_ISNAN_XPG3) || defined(TRIO_PLATFORM_SYMBIAN)
++ /*
++ * XPG3 defines isnan() as a function.
++ */
++ return isnan(number);
++
++# endif
++
++# if defined(TRIO_INTERNAL_ISNAN_IEEE_754)
++
++ /*
++ * Examine IEEE 754 bit-pattern. A NaN must have a special exponent
++ * pattern, and a non-empty mantissa.
++ */
++ int has_mantissa;
++ int is_special_quantity;
++
++ is_special_quantity = internal_is_special_quantity(number, &has_mantissa);
++
++ return (is_special_quantity && has_mantissa);
++
++# endif
++
++# if defined(TRIO_INTERNAL_ISNAN_FALLBACK)
++
++ /*
++ * Fallback solution
++ */
++ int status;
++ double integral, fraction;
++
++# if defined(TRIO_PLATFORM_UNIX)
++ void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
++# endif
++
++ status = (/*
++ * NaN is the only number which does not compare to itself
++ */
++ ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
++ /*
++ * Fallback solution if NaN compares to NaN
++ */
++ ((number != 0.0) &&
++ (fraction = modf(number, &integral),
++ integral == fraction)));
++
++# if defined(TRIO_PLATFORM_UNIX)
++ signal(SIGFPE, signal_handler);
++# endif
++
++ return status;
++
++# endif
++}
++
++#endif /* TRIO_FUNC_INTERNAL_ISNAN */
++
++#if defined(TRIO_FUNC_INTERNAL_ISINF)
++
++TRIO_PRIVATE_NAN TRIO_INLINE int
++internal_isinf
++TRIO_ARGS1((number),
++ double number)
++{
++# if defined(TRIO_PLATFORM_SYMBIAN)
++
++ return isinf(number);
++
++# endif
++
++# if defined(TRIO_INTERNAL_ISINF_IEEE_754)
++ /*
++ * Examine IEEE 754 bit-pattern. Infinity must have a special exponent
++ * pattern, and an empty mantissa.
++ */
++ int has_mantissa;
++ int is_special_quantity;
++
++ is_special_quantity = internal_is_special_quantity(number, &has_mantissa);
++
++ return (is_special_quantity && !has_mantissa)
++ ? ((number < 0.0) ? -1 : 1)
++ : 0;
++
++# endif
++
++# if defined(TRIO_INTERNAL_ISINF_FALLBACK)
++
++ /*
++ * Fallback solution.
++ */
++ int status;
++
++# if defined(TRIO_PLATFORM_UNIX)
++ void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
++# endif
++
++ double infinity = trio_pinf();
++
++ status = ((number == infinity)
++ ? 1
++ : ((number == -infinity) ? -1 : 0));
++
++# if defined(TRIO_PLATFORM_UNIX)
++ signal(SIGFPE, signal_handler);
++# endif
++
++ return status;
++
++# endif
++}
++
++#endif /* TRIO_FUNC_INTERNAL_ISINF */
++
++/*************************************************************************
++ * Public functions
++ */
++
++#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
++
++TRIO_PUBLIC_NAN int
++trio_fpclassify_and_signbit
++TRIO_ARGS2((number, is_negative),
++ double number,
++ int *is_negative)
++{
++ /* The TRIO_FUNC_xxx_FPCLASSIFY_AND_SIGNBIT macros are mutually exclusive */
++
++#if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT)
++
++ return c99_fpclassify_and_signbit(number, is_negative);
++
++#endif
++
++#if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT)
++
++ return decc_fpclassify_and_signbit(number, is_negative);
++
++#endif
++
++#if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT)
++
++ return ms_fpclassify_and_signbit(number, is_negative);
++
++#endif
++
++#if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT)
++
++ return hp_fpclassify_and_signbit(number, is_negative);
++
++#endif
++
++#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT)
++
++ return xlc_fpclassify_and_signbit(number, is_negative);
++
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT)
++
++ /*
++ * Fallback solution.
++ */
++ int rc;
++
++ if (number == 0.0) {
++ /*
++ * In IEEE 754 the sign of zero is ignored in comparisons, so we
++ * have to handle this as a special case by examining the sign bit
++ * directly.
++ */
++# if defined(TRIO_IEEE_754)
++ *is_negative = internal_is_negative(number);
++# else
++ *is_negative = TRIO_FALSE; /* FIXME */
++# endif
++ return TRIO_FP_ZERO;
++ }
++ if (internal_isnan(number)) {
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_NAN;
++ }
++ rc = internal_isinf(number);
++ if (rc != 0) {
++ *is_negative = (rc == -1);
++ return TRIO_FP_INFINITE;
++ }
++ if ((number > 0.0) && (number < DBL_MIN)) {
++ *is_negative = TRIO_FALSE;
++ return TRIO_FP_SUBNORMAL;
++ }
++ if ((number < 0.0) && (number > -DBL_MIN)) {
++ *is_negative = TRIO_TRUE;
++ return TRIO_FP_SUBNORMAL;
++ }
++ *is_negative = (number < 0.0);
++ return TRIO_FP_NORMAL;
++
++#endif
++}
++
++#endif
++
++/**
++ Check for NaN.
++
++ @param number An arbitrary floating-point number.
++ @return Boolean value indicating whether or not the number is a NaN.
++*/
++#if defined(TRIO_FUNC_ISNAN)
++
++TRIO_PUBLIC_NAN int
++trio_isnan
++TRIO_ARGS1((number),
++ double number)
++{
++ int dummy;
++
++ return (trio_fpclassify_and_signbit(number, &dummy) == TRIO_FP_NAN);
++}
++
++#endif
++
++/**
++ Check for infinity.
++
++ @param number An arbitrary floating-point number.
++ @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
++*/
++#if defined(TRIO_FUNC_ISINF)
++
++TRIO_PUBLIC_NAN int
++trio_isinf
++TRIO_ARGS1((number),
++ double number)
++{
++ int is_negative;
++
++ if (trio_fpclassify_and_signbit(number, &is_negative) == TRIO_FP_INFINITE)
++ {
++ return (is_negative) ? -1 : 1;
++ }
++ else
++ {
++ return 0;
++ }
++}
++
++#endif
++
++/**
++ Check for finity.
++
++ @param number An arbitrary floating-point number.
++ @return Boolean value indicating whether or not the number is a finite.
++*/
++#if defined(TRIO_FUNC_ISFINITE)
++
++TRIO_PUBLIC_NAN int
++trio_isfinite
++TRIO_ARGS1((number),
++ double number)
++{
++ int dummy;
++
++ switch (trio_fpclassify_and_signbit(number, &dummy))
++ {
++ case TRIO_FP_INFINITE:
++ case TRIO_FP_NAN:
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++#endif
++
++/**
++ Examine the sign of a number.
++
++ @param number An arbitrary floating-point number.
++ @return Boolean value indicating whether or not the number has the
++ sign bit set (i.e. is negative).
++*/
++#if defined(TRIO_FUNC_SIGNBIT)
++
++TRIO_PUBLIC_NAN int
++trio_signbit
++TRIO_ARGS1((number),
++ double number)
++{
++ int is_negative;
++
++ (void)trio_fpclassify_and_signbit(number, &is_negative);
++ return is_negative;
++}
++
++#endif
++
++/**
++ Examine the class of a number.
++
++ @param number An arbitrary floating-point number.
++ @return Enumerable value indicating the class of @p number
++*/
++#if defined(TRIO_FUNC_FPCLASSIFY)
++
++TRIO_PUBLIC_NAN int
++trio_fpclassify
++TRIO_ARGS1((number),
++ double number)
++{
++ int dummy;
++
++ return trio_fpclassify_and_signbit(number, &dummy);
++}
++
++#endif
++
++/**
++ Generate negative zero.
++
++ @return Floating-point representation of negative zero.
++*/
++#if defined(TRIO_FUNC_NZERO)
++
++TRIO_PUBLIC_NAN double
++trio_nzero(TRIO_NOARGS)
++{
++# if defined(TRIO_NZERO_IEEE_754)
++
++ return internal_make_double(ieee_754_negzero_array);
++
++# endif
++
++# if defined(TRIO_NZERO_FALLBACK)
++
++ TRIO_VOLATILE double zero = 0.0;
++
++ return -zero;
++
++# endif
++}
++
++#endif
++
++/**
++ Generate positive infinity.
++
++ @return Floating-point representation of positive infinity.
++*/
++#if defined(TRIO_FUNC_PINF)
++
++TRIO_PUBLIC_NAN double
++trio_pinf(TRIO_NOARGS)
++{
++ /* Cache the result */
++ static double pinf_value = 0.0;
++
++ if (pinf_value == 0.0) {
++
++# if defined(TRIO_PINF_C99_MACRO)
++
++ pinf_value = (double)INFINITY;
++
++# endif
++
++# if defined(TRIO_PINF_IEEE_754)
++
++ pinf_value = internal_make_double(ieee_754_infinity_array);
++
++# endif
++
++# if defined(TRIO_PINF_FALLBACK)
++ /*
++ * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
++ * as infinity. Otherwise we have to resort to an overflow
++ * operation to generate infinity.
++ */
++# if defined(TRIO_PLATFORM_UNIX)
++ void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
++# endif
++
++ pinf_value = HUGE_VAL;
++ if (HUGE_VAL == DBL_MAX) {
++ /* Force overflow */
++ pinf_value += HUGE_VAL;
++ }
++
++# if defined(TRIO_PLATFORM_UNIX)
++ signal(SIGFPE, signal_handler);
++# endif
++
++# endif
++ }
++ return pinf_value;
++}
++
++#endif
++
++/**
++ Generate negative infinity.
++
++ @return Floating-point value of negative infinity.
++*/
++#if defined(TRIO_FUNC_NINF)
++
++TRIO_PUBLIC_NAN double
++trio_ninf(TRIO_NOARGS)
++{
++ static double ninf_value = 0.0;
++
++ if (ninf_value == 0.0) {
++ /*
++ * Negative infinity is calculated by negating positive infinity,
++ * which can be done because it is legal to do calculations on
++ * infinity (for example, 1 / infinity == 0).
++ */
++ ninf_value = -trio_pinf();
++ }
++ return ninf_value;
++}
++
++#endif
++
++/**
++ Generate NaN.
++
++ @return Floating-point representation of NaN.
++*/
++#if defined(TRIO_FUNC_NAN)
++
++TRIO_PUBLIC_NAN double
++trio_nan(TRIO_NOARGS)
++{
++ /* Cache the result */
++ static double nan_value = 0.0;
++
++ if (nan_value == 0.0) {
++
++# if defined(TRIO_NAN_C99_FUNCTION) || defined(TRIO_PLATFORM_SYMBIAN)
++
++ nan_value = nan("");
++
++# endif
++
++# if defined(TRIO_NAN_C99_MACRO)
++
++ nan_value = (double)NAN;
++
++# endif
++
++# if defined(TRIO_NAN_IEEE_754)
++
++ nan_value = internal_make_double(ieee_754_qnan_array);
++
++# endif
++
++# if defined(TRIO_NAN_FALLBACK)
++ /*
++ * There are several ways to generate NaN. The one used here is
++ * to divide infinity by infinity. I would have preferred to add
++ * negative infinity to positive infinity, but that yields wrong
++ * result (infinity) on FreeBSD.
++ *
++ * This may fail if the hardware does not support NaN, or if
++ * the Invalid Operation floating-point exception is unmasked.
++ */
++# if defined(TRIO_PLATFORM_UNIX)
++ void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
++# endif
++
++ nan_value = trio_pinf() / trio_pinf();
++
++# if defined(TRIO_PLATFORM_UNIX)
++ signal(SIGFPE, signal_handler);
++# endif
++
++# endif
++ }
++ return nan_value;
++}
++
++#endif
++
++/** @} SpecialQuantities */
++
++/*************************************************************************
++ * For test purposes.
++ *
++ * Add the following compiler option to include this test code.
++ *
++ * Unix : -DSTANDALONE
++ * VMS : /DEFINE=(STANDALONE)
++ */
++#if defined(STANDALONE)
++# include <stdio.h>
++
++static TRIO_CONST char *
++getClassification
++TRIO_ARGS1((type),
++ int type)
++{
++ switch (type) {
++ case TRIO_FP_INFINITE:
++ return "FP_INFINITE";
++ case TRIO_FP_NAN:
++ return "FP_NAN";
++ case TRIO_FP_NORMAL:
++ return "FP_NORMAL";
++ case TRIO_FP_SUBNORMAL:
++ return "FP_SUBNORMAL";
++ case TRIO_FP_ZERO:
++ return "FP_ZERO";
++ default:
++ return "FP_UNKNOWN";
++ }
++}
++
++static void
++print_class
++TRIO_ARGS2((prefix, number),
++ TRIO_CONST char *prefix,
++ double number)
++{
++ printf("%-6s: %s %-15s %g\n",
++ prefix,
++ trio_signbit(number) ? "-" : "+",
++ getClassification(trio_fpclassify(number)),
++ number);
++}
++
++int main(TRIO_NOARGS)
++{
++ double my_nan;
++ double my_pinf;
++ double my_ninf;
++# if defined(TRIO_PLATFORM_UNIX)
++ void (*signal_handler) TRIO_PROTO((int));
++# endif
++
++ my_nan = trio_nan();
++ my_pinf = trio_pinf();
++ my_ninf = trio_ninf();
++
++ print_class("Nan", my_nan);
++ print_class("PInf", my_pinf);
++ print_class("NInf", my_ninf);
++ print_class("PZero", 0.0);
++ print_class("NZero", -0.0);
++ print_class("PNorm", 1.0);
++ print_class("NNorm", -1.0);
++ print_class("PSub", 1.01e-307 - 1.00e-307);
++ print_class("NSub", 1.00e-307 - 1.01e-307);
++
++ printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
++ my_nan,
++ ((unsigned char *)&my_nan)[0],
++ ((unsigned char *)&my_nan)[1],
++ ((unsigned char *)&my_nan)[2],
++ ((unsigned char *)&my_nan)[3],
++ ((unsigned char *)&my_nan)[4],
++ ((unsigned char *)&my_nan)[5],
++ ((unsigned char *)&my_nan)[6],
++ ((unsigned char *)&my_nan)[7],
++ trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan));
++ printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
++ my_pinf,
++ ((unsigned char *)&my_pinf)[0],
++ ((unsigned char *)&my_pinf)[1],
++ ((unsigned char *)&my_pinf)[2],
++ ((unsigned char *)&my_pinf)[3],
++ ((unsigned char *)&my_pinf)[4],
++ ((unsigned char *)&my_pinf)[5],
++ ((unsigned char *)&my_pinf)[6],
++ ((unsigned char *)&my_pinf)[7],
++ trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf));
++ printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
++ my_ninf,
++ ((unsigned char *)&my_ninf)[0],
++ ((unsigned char *)&my_ninf)[1],
++ ((unsigned char *)&my_ninf)[2],
++ ((unsigned char *)&my_ninf)[3],
++ ((unsigned char *)&my_ninf)[4],
++ ((unsigned char *)&my_ninf)[5],
++ ((unsigned char *)&my_ninf)[6],
++ ((unsigned char *)&my_ninf)[7],
++ trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf));
++
++# if defined(TRIO_PLATFORM_UNIX)
++ signal_handler = signal(SIGFPE, SIG_IGN);
++# endif
++
++ my_pinf = DBL_MAX + DBL_MAX;
++ my_ninf = -my_pinf;
++ my_nan = my_pinf / my_pinf;
++
++# if defined(TRIO_PLATFORM_UNIX)
++ signal(SIGFPE, signal_handler);
++# endif
++
++ printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
++ my_nan,
++ ((unsigned char *)&my_nan)[0],
++ ((unsigned char *)&my_nan)[1],
++ ((unsigned char *)&my_nan)[2],
++ ((unsigned char *)&my_nan)[3],
++ ((unsigned char *)&my_nan)[4],
++ ((unsigned char *)&my_nan)[5],
++ ((unsigned char *)&my_nan)[6],
++ ((unsigned char *)&my_nan)[7],
++ trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan));
++ printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
++ my_pinf,
++ ((unsigned char *)&my_pinf)[0],
++ ((unsigned char *)&my_pinf)[1],
++ ((unsigned char *)&my_pinf)[2],
++ ((unsigned char *)&my_pinf)[3],
++ ((unsigned char *)&my_pinf)[4],
++ ((unsigned char *)&my_pinf)[5],
++ ((unsigned char *)&my_pinf)[6],
++ ((unsigned char *)&my_pinf)[7],
++ trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf));
++ printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
++ my_ninf,
++ ((unsigned char *)&my_ninf)[0],
++ ((unsigned char *)&my_ninf)[1],
++ ((unsigned char *)&my_ninf)[2],
++ ((unsigned char *)&my_ninf)[3],
++ ((unsigned char *)&my_ninf)[4],
++ ((unsigned char *)&my_ninf)[5],
++ ((unsigned char *)&my_ninf)[6],
++ ((unsigned char *)&my_ninf)[7],
++ trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf));
++
++ return 0;
++}
++#endif
+diff -up ghostscript-9.07/trio/trionan.h.gs_sprintf ghostscript-9.07/trio/trionan.h
+--- ghostscript-9.07/trio/trionan.h.gs_sprintf 2013-05-09 17:02:39.112447283 +0100
++++ ghostscript-9.07/trio/trionan.h 2013-05-09 17:02:39.112447283 +0100
+@@ -0,0 +1,183 @@
++/*************************************************************************
++ *
++ * $Id: trionan.h,v 1.9 2005/03/27 18:52:45 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++#ifndef TRIO_TRIONAN_H
++#define TRIO_TRIONAN_H
++
++#include "triodef.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#if !defined(TRIO_PUBLIC_NAN)
++# if !defined(TRIO_PUBLIC)
++# define TRIO_PUBLIC
++# endif
++# define TRIO_PUBLIC_NAN TRIO_PUBLIC
++#endif
++
++enum {
++ TRIO_FP_INFINITE,
++ TRIO_FP_NAN,
++ TRIO_FP_NORMAL,
++ TRIO_FP_SUBNORMAL,
++ TRIO_FP_ZERO
++};
++
++/*************************************************************************
++ * Dependencies
++ */
++
++#if defined(TRIO_EMBED_NAN)
++
++/*
++ * The application that trionan is embedded in must define which functions
++ * it uses.
++ *
++ * The following resolves internal dependencies.
++ */
++
++# if defined(TRIO_FUNC_ISNAN) \
++ || defined(TRIO_FUNC_ISINF)
++# if !defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
++# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
++# endif
++# endif
++
++# if defined(TRIO_FUNC_NAN)
++# if !defined(TRIO_FUNC_PINF)
++# define TRIO_FUNC_PINF
++# endif
++# endif
++
++# if defined(TRIO_FUNC_NINF)
++# if !defined(TRIO_FUNC_PINF)
++# define TRIO_FUNC_PINF
++# endif
++# endif
++
++#else
++
++/*
++ * When trionan is not embedded all all functions are defined.
++ */
++
++# define TRIO_FUNC_NAN
++# define TRIO_FUNC_PINF
++# define TRIO_FUNC_NINF
++# define TRIO_FUNC_NZERO
++# define TRIO_FUNC_ISNAN
++# define TRIO_FUNC_ISINF
++# define TRIO_FUNC_ISFINITE
++# define TRIO_FUNC_SIGNBIT
++# define TRIO_FUNC_FPCLASSIFY
++# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
++
++#endif
++
++/*************************************************************************
++ * Functions
++ */
++
++/*
++ * Return NaN (Not-a-Number).
++ */
++#if defined(TRIO_FUNC_NAN)
++TRIO_PUBLIC_NAN double
++trio_nan
++TRIO_PROTO((void));
++#endif
++
++/*
++ * Return positive infinity.
++ */
++#if defined(TRIO_FUNC_PINF)
++TRIO_PUBLIC_NAN double
++trio_pinf
++TRIO_PROTO((void));
++#endif
++
++/*
++ * Return negative infinity.
++ */
++#if defined(TRIO_FUNC_NINF)
++TRIO_PUBLIC_NAN double
++trio_ninf
++TRIO_PROTO((void));
++#endif
++
++/*
++ * Return negative zero.
++ */
++#if defined(TRIO_FUNC_NZERO)
++TRIO_PUBLIC_NAN double
++trio_nzero
++TRIO_PROTO((TRIO_NOARGS));
++#endif
++
++/*
++ * If number is a NaN return non-zero, otherwise return zero.
++ */
++#if defined(TRIO_FUNC_ISNAN)
++TRIO_PUBLIC_NAN int
++trio_isnan
++TRIO_PROTO((double number));
++#endif
++
++/*
++ * If number is positive infinity return 1, if number is negative
++ * infinity return -1, otherwise return 0.
++ */
++#if defined(TRIO_FUNC_ISINF)
++TRIO_PUBLIC_NAN int
++trio_isinf
++TRIO_PROTO((double number));
++#endif
++
++/*
++ * If number is finite return non-zero, otherwise return zero.
++ */
++#if defined(TRIO_FUNC_ISFINITE)
++TRIO_PUBLIC_NAN int
++trio_isfinite
++TRIO_PROTO((double number));
++#endif
++
++#if defined(TRIO_FUNC_SIGNBIT)
++TRIO_PUBLIC_NAN int
++trio_signbit
++TRIO_PROTO((double number));
++#endif
++
++#if defined(TRIO_FUNC_FPCLASSIFY)
++TRIO_PUBLIC_NAN int
++trio_fpclassify
++TRIO_PROTO((double number));
++#endif
++
++#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
++TRIO_PUBLIC_NAN int
++trio_fpclassify_and_signbit
++TRIO_PROTO((double number, int *is_negative));
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TRIO_TRIONAN_H */
+diff -up ghostscript-9.07/trio/triop.h.gs_sprintf ghostscript-9.07/trio/triop.h
+--- ghostscript-9.07/trio/triop.h.gs_sprintf 2013-05-09 17:02:39.113447287 +0100
++++ ghostscript-9.07/trio/triop.h 2013-05-09 17:02:39.113447287 +0100
+@@ -0,0 +1,472 @@
++/*************************************************************************
++ *
++ * $Id: triop.h,v 1.18 2009/07/05 10:14:07 breese Exp $
++ *
++ * Copyright (C) 2000 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************
++ *
++ * Private functions, types, etc. used for callback functions.
++ *
++ * The ref pointer is an opaque type and should remain as such.
++ * Private data must only be accessible through the getter and
++ * setter functions.
++ *
++ ************************************************************************/
++
++#ifndef TRIO_TRIOP_H
++#define TRIO_TRIOP_H
++
++#include "triodef.h"
++
++#include <stdlib.h>
++#if defined(TRIO_COMPILER_ANCIENT)
++# include <varargs.h>
++#else
++# include <stdarg.h>
++#endif
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*************************************************************************
++ * Supported standards
++ */
++
++/*
++ * TRIO_C99 (=0 or =1)
++ *
++ * Define this to 0 to disable C99 format specifier extensions, or
++ * define to 1 to enable them. The format specifiers that are
++ * disabled by this switch are labelled with [C99] in the format
++ * specifier documentation.
++ */
++#if !defined(TRIO_C99)
++# define TRIO_C99 1
++#endif
++
++/*
++ * TRIO_BSD (=0 or =1)
++ *
++ * Define this to 0 to disable BSD format specifier extensions, or
++ * define to 1 to enable them. The format specifiers that are
++ * disabled by this switch are labelled with [BSD] in the format
++ * specifier documentation.
++ */
++#if !defined(TRIO_BSD)
++# define TRIO_BSD 1
++#endif
++
++/*
++ * TRIO_GNU (=0 or =1)
++ *
++ * Define this to 0 to disable GNU format specifier extensions, or
++ * define to 1 to enable them. The format specifiers that are
++ * disabled by this switch are labelled with [GNU] in the format
++ * specifier documentation.
++ */
++#if !defined(TRIO_GNU)
++# define TRIO_GNU 1
++#endif
++
++/*
++ * TRIO_MISC (=0 or =1)
++ *
++ * Define this to 0 to disable miscellaneous format specifier
++ * extensions, or define to 1 to enable them. The format specifiers
++ * that are disabled by this switch are labelled with [MISC] in the
++ * format specifier documentation.
++ */
++#if !defined(TRIO_MISC)
++# define TRIO_MISC 1
++#endif
++
++/*
++ * TRIO_UNIX98 (=0 or =1)
++ *
++ * Define this to 0 to disable UNIX98 format specifier extensions,
++ * or define to 1 to enable them. The format specifiers that are
++ * disabled by this switch are labelled with [UNIX98] in the format
++ * specifier documentation.
++ */
++#if !defined(TRIO_UNIX98)
++# define TRIO_UNIX98 1
++#endif
++
++/*
++ * TRIO_MICROSOFT (=0 or =1)
++ *
++ * Define this to 0 to disable Microsoft Visual C format specifier
++ * extensions, or define to 1 to enable them. The format specifiers
++ * that are disabled by this switch are labelled with [MSVC] in the
++ * format specifier documentation.
++ */
++#if !defined(TRIO_MICROSOFT)
++# define TRIO_MICROSOFT 1
++#endif
++
++/*
++ * TRIO_EXTENSION (=0 or =1)
++ *
++ * Define this to 0 to disable Trio-specific extensions, or define
++ * to 1 to enable them. This has two effects: it controls whether
++ * or not the Trio user-defined formating mechanism
++ * (trio_register() etc) is supported, and it enables or disables
++ * Trio's own format specifier extensions. The format specifiers
++ * that are disabled by this switch are labelled with [TRIO] in
++ * the format specifier documentation.
++ */
++#if !defined(TRIO_EXTENSION)
++# define TRIO_EXTENSION 1
++#endif
++
++/*
++ * TRIO_DEPRECATED (=0 or =1)
++ *
++ * Define this to 0 to disable deprecated functionality, or define
++ * to 1 to enable them.
++ */
++#if !defined(TRIO_DEPRECATED)
++# define TRIO_DEPRECATED 1
++#endif
++
++/*************************************************************************
++ * Features
++ */
++
++#if defined(TRIO_SNPRINTF_ONLY)
++# define TRIO_FEATURE_SCANF 0
++# define TRIO_FEATURE_FILE 0
++# define TRIO_FEATURE_STDIO 0
++# define TRIO_FEATURE_FD 0
++# define TRIO_FEATURE_DYNAMICSTRING 0
++# define TRIO_FEATURE_CLOSURE 0
++# define TRIO_FEATURE_STRERR 0
++# define TRIO_FEATURE_LOCALE 0
++# define TRIO_EMBED_NAN 1
++# define TRIO_EMBED_STRING 1
++#endif
++
++/*
++ * TRIO_FEATURE_SCANF (=0 or =1)
++ *
++ * Define this to 0 to disable all the scanf() variants, or define to 1
++ * to enable them.
++ */
++#if !defined(TRIO_FEATURE_SCANF)
++# define TRIO_FEATURE_SCANF 1
++#endif
++
++/*
++ * TRIO_FEATURE_FILE (=0 or =1)
++ *
++ * Define this to 0 to disable compilation of the trio_fprintf() and
++ * trio_fscanf() family of functions, or define to 1 to enable them.
++ *
++ * This may be useful on an embedded platform with no filesystem.
++ * Note that trio_printf() uses fwrite to write to stdout, so if you
++ * do not have an implementation of fwrite() at all then you must also
++ * define TRIO_FEATURE_STDIO to 0.
++ */
++#if !defined(TRIO_FEATURE_FILE)
++# define TRIO_FEATURE_FILE 1
++#endif
++
++/*
++ * TRIO_FEATURE_STDIO (=0 or =1)
++ *
++ * Define this to 0 to disable compilation of the trio_printf() and
++ * trio_scanf() family of functions, or define to 1 to enable them.
++ *
++ * This may be useful on an embedded platform with no standard I/O.
++ */
++#if !defined(TRIO_FEATURE_STDIO)
++# define TRIO_FEATURE_STDIO 1
++#endif
++
++/*
++ * TRIO_FEATURE_FD (=0 or =1)
++ *
++ * Define this to 0 to disable compilation of the trio_dprintf() and
++ * trio_dscanf() family of functions, or define to 1 to enable them.
++ *
++ * This may be useful on an embedded platform with no filesystem, or on
++ * a platform that supports file I/O using FILE* but not using raw file
++ * descriptors.
++ */
++#if !defined(TRIO_FEATURE_FD)
++# define TRIO_FEATURE_FD 1
++#endif
++
++/*
++ * TRIO_FEATURE_DYNAMICSTRING (=0 or =1)
++ *
++ * Define this to 0 to disable compilation of the trio_aprintf()
++ * family of functions, or define to 1 to enable them.
++ *
++ * If you define both this and TRIO_MINIMAL to 0, then Trio will never
++ * call malloc or free.
++ */
++#if !defined(TRIO_FEATURE_DYNAMICSTRING)
++# define TRIO_FEATURE_DYNAMICSTRING 1
++#endif
++
++/*
++ * TRIO_FEATURE_CLOSURE (=0 or =1)
++ *
++ * Define this to 0 to disable compilation of the trio_cprintf() and
++ * trio_cscanf() family of functions, or define to 1 to enable them.
++ *
++ * These functions are rarely needed. This saves a (small) amount of code.
++ */
++#if !defined(TRIO_FEATURE_CLOSURE)
++# define TRIO_FEATURE_CLOSURE 1
++#endif
++
++/*
++ * TRIO_FEATURE_ERRORCODE (=0 or =1)
++ *
++ * Define this to 0 to return -1 from the print and scan function on
++ * error, or define to 1 to return a negative number with debugging
++ * information as part of the return code.
++ *
++ * If enabled, the return code will be a negative number, which encodes
++ * an error code and an error location. These can be decoded with the
++ * TRIO_ERROR_CODE and TRIO_ERROR_POSITION macros.
++ */
++#if defined(TRIO_ERRORS)
++# define TRIO_FEATURE_ERRORCODE TRIO_ERRORS
++#endif
++#if !defined(TRIO_FEATURE_ERRORCODE)
++# define TRIO_FEATURE_ERRORCODE 1
++#endif
++
++/*
++ * TRIO_FEATURE_STRERR (=0 or =1)
++ *
++ * Define this to 0 if you do not use trio_strerror(), or define to 1 if
++ * you do use it.
++ *
++ * This saves a (small) amount of code.
++ */
++#if !defined(TRIO_FEATURE_STRERR)
++# define TRIO_FEATURE_STRERR 1
++#endif
++
++/*
++ * TRIO_FEATURE_FLOAT (=0 or =1)
++ *
++ * Define this to 0 to disable all floating-point support, or define
++ * to 1 to enable it.
++ *
++ * This is useful in restricted embedded platforms that do not support
++ * floating-point. Obviously you cannot use floating-point format
++ * specifiers if you define this.
++ *
++ * Do not compile trionan.c if you disable this.
++ */
++#if !defined(TRIO_FEATURE_FLOAT)
++# define TRIO_FEATURE_FLOAT 1
++#endif
++
++/*
++ * TRIO_FEATURE_LOCALE (=0 or =1)
++ *
++ * Define this to 0 to disable customized locale support, or define
++ * to 1 to enable it.
++ *
++ * This saves a (small) amount of code.
++ */
++#if !defined(TRIO_FEATURE_LOCALE)
++# define TRIO_FEATURE_LOCALE 1
++#endif
++
++/*
++ * TRIO_MINIMAL
++ *
++ * Define this to disable building the public trionan.h and triostr.h.
++ * If you define this, then you must not compile trionan.c and triostr.c
++ * separately.
++ */
++#if defined(TRIO_MINIMAL)
++# if !defined(TRIO_EMBED_NAN)
++# define TRIO_EMBED_NAN
++# endif
++# if !defined(TRIO_EMBED_STRING)
++# define TRIO_EMBED_STRING
++# endif
++#endif
++
++/* Does not work yet. Do not enable */
++#ifndef TRIO_FEATURE_WIDECHAR
++# define TRIO_FEATURE_WIDECHAR 0
++#endif
++
++/*************************************************************************
++ * Mapping standards to internal features
++ */
++
++#if !defined(TRIO_FEATURE_HEXFLOAT)
++# define TRIO_FEATURE_HEXFLOAT (TRIO_C99 && TRIO_FEATURE_FLOAT)
++#endif
++
++#if !defined(TRIO_FEATURE_LONGDOUBLE)
++# define TRIO_FEATURE_LONGDOUBLE TRIO_FEATURE_FLOAT
++#endif
++
++#if !defined(TRIO_FEATURE_ERRNO)
++# define TRIO_FEATURE_ERRNO TRIO_GNU
++#endif
++
++#if !defined(TRIO_FEATURE_QUAD)
++# define TRIO_FEATURE_QUAD (TRIO_BSD || TRIO_GNU)
++#endif
++
++#if !defined(TRIO_FEATURE_SIZE_T)
++# define TRIO_FEATURE_SIZE_T TRIO_C99
++#endif
++
++#if !defined(TRIO_FEATURE_SIZE_T_UPPER)
++# define TRIO_FEATURE_SIZE_T_UPPER TRIO_GNU
++#endif
++
++#if !defined(TRIO_FEATURE_PTRDIFF_T)
++# define TRIO_FEATURE_PTRDIFF_T TRIO_C99
++#endif
++
++#if !defined(TRIO_FEATURE_INTMAX_T)
++# define TRIO_FEATURE_INTMAX_T TRIO_C99
++#endif
++
++#if !defined(TRIO_FEATURE_FIXED_SIZE)
++# define TRIO_FEATURE_FIXED_SIZE TRIO_MICROSOFT
++#endif
++
++#if !defined(TRIO_FEATURE_POSITIONAL)
++# define TRIO_FEATURE_POSITIONAL TRIO_UNIX98
++#endif
++
++#if !defined(TRIO_FEATURE_USER_DEFINED)
++# define TRIO_FEATURE_USER_DEFINED TRIO_EXTENSION
++#endif
++
++#if !defined(TRIO_FEATURE_BINARY)
++# define TRIO_FEATURE_BINARY TRIO_EXTENSION
++#endif
++
++#if !defined(TRIO_FEATURE_QUOTE)
++# define TRIO_FEATURE_QUOTE TRIO_EXTENSION
++#endif
++
++#if !defined(TRIO_FEATURE_STICKY)
++# define TRIO_FEATURE_STICKY TRIO_EXTENSION
++#endif
++
++#if !defined(TRIO_FEATURE_VARSIZE)
++# define TRIO_FEATURE_VARSIZE TRIO_EXTENSION
++#endif
++
++#if !defined(TRIO_FEATURE_ROUNDING)
++# define TRIO_FEATURE_ROUNDING TRIO_EXTENSION
++#endif
++
++/*************************************************************************
++ * Memory handling
++ */
++#ifndef TRIO_MALLOC
++# define TRIO_MALLOC(n) malloc(n)
++#endif
++#ifndef TRIO_REALLOC
++# define TRIO_REALLOC(x,n) realloc((x),(n))
++#endif
++#ifndef TRIO_FREE
++# define TRIO_FREE(x) free(x)
++#endif
++
++
++/*************************************************************************
++ * User-defined specifiers
++ */
++
++typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t));
++
++trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name));
++void trio_unregister TRIO_PROTO((trio_pointer_t handle));
++
++TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref));
++TRIO_CONST trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref));
++
++/* Modifiers */
++int trio_get_width TRIO_PROTO((trio_pointer_t ref));
++void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width));
++int trio_get_precision TRIO_PROTO((trio_pointer_t ref));
++void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision));
++int trio_get_base TRIO_PROTO((trio_pointer_t ref));
++void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base));
++int trio_get_padding TRIO_PROTO((trio_pointer_t ref));
++void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding));
++int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */
++void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort));
++int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */
++void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short));
++int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */
++void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long));
++int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */
++void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong));
++int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */
++void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble));
++int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */
++void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative));
++int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */
++void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned));
++int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* (space) */
++void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space));
++int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */
++void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign));
++#if TRIO_FEATURE_QUOTE
++int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */
++void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote));
++#endif
++int trio_get_upper TRIO_PROTO((trio_pointer_t ref));
++void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper));
++#if TRIO_FEATURE_INTMAX_T
++int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */
++void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest));
++#endif
++#if TRIO_FEATURE_PTRDIFF_T
++int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */
++void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff));
++#endif
++#if TRIO_FEATURE_SIZE_T
++int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */
++void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size));
++#endif
++
++/* Printing */
++int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...));
++int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args));
++int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args));
++
++void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number));
++void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number));
++/* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */
++/* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */
++void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number));
++void trio_print_string TRIO_PROTO((trio_pointer_t ref, TRIO_CONST char *string));
++void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer));
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* TRIO_TRIOP_H */
+diff -up ghostscript-9.07/trio/triostr.c.gs_sprintf ghostscript-9.07/trio/triostr.c
+--- ghostscript-9.07/trio/triostr.c.gs_sprintf 2013-05-09 17:02:39.113447287 +0100
++++ ghostscript-9.07/trio/triostr.c 2013-05-09 17:02:39.113447287 +0100
+@@ -0,0 +1,2385 @@
++/*************************************************************************
++ *
++ * $Id: triostr.c,v 1.36 2010/01/26 13:02:02 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++/*************************************************************************
++ * Include files
++ */
++
++#if defined(HAVE_CONFIG_H)
++# include <config.h>
++#endif
++#include <assert.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include "triodef.h"
++#include "triostr.h"
++#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
++# define USE_MATH
++#endif
++#if defined(USE_MATH)
++# include <math.h>
++#endif
++
++/*************************************************************************
++ * Definitions
++ */
++
++#if !defined(TRIO_PUBLIC_STRING)
++# define TRIO_PUBLIC_STRING TRIO_PUBLIC
++#endif
++#if !defined(TRIO_PRIVATE_STRING)
++# define TRIO_PRIVATE_STRING TRIO_PRIVATE
++#endif
++
++#if !defined(NULL)
++# define NULL 0
++#endif
++#if !defined(NIL)
++# define NIL ((char)0)
++#endif
++#if !defined(FALSE)
++# define FALSE (1 == 0)
++# define TRUE (! FALSE)
++#endif
++#if !defined(BOOLEAN_T)
++# define BOOLEAN_T int
++#endif
++
++#if defined(USE_MATH)
++# if defined(PREDEF_STANDARD_C99)
++# if defined(TRIO_COMPILER_DECC)
++# if (TRIO_COMPILER_DECC - 0 > 80000000)
++/*
++ * The OSF/1 runtime that comes with the DECC compiler does not support
++ * hexfloats conversion.
++ */
++# define USE_STRTOD
++# define USE_STRTOF
++# endif
++# else
++# define USE_STRTOD
++# define USE_STRTOF
++# endif
++# else
++# if defined(TRIO_COMPILER_VISUALC)
++# define USE_STRTOD
++# endif
++#endif
++#endif
++
++#if defined(TRIO_PLATFORM_UNIX)
++# if defined(PREDEF_STANDARD_UNIX95)
++# define USE_STRCASECMP
++# define USE_STRNCASECMP
++# endif
++# if defined(TRIO_PLATFORM_SUNOS)
++# define USE_SYS_ERRLIST
++# else
++# define USE_STRERROR
++# endif
++# if defined(TRIO_PLATFORM_QNX)
++# define strcasecmp(x,y) stricmp(x,y)
++# define strncasecmp(x,y,n) strnicmp(x,y,n)
++# endif
++#endif
++
++#if defined(TRIO_PLATFORM_WIN32)
++# define USE_STRCASECMP
++# if defined(TRIO_PLATFORM_WINCE)
++# define strcasecmp(x,y) _stricmp(x,y)
++# else
++# define strcasecmp(x,y) strcmpi(x,y)
++# endif
++#endif
++
++#if !defined(HAVE_CONFIG_H)
++# if !(defined(TRIO_PLATFORM_SUNOS))
++# define HAVE_TOLOWER
++# define HAVE_TOUPPER
++# endif
++#endif
++
++#if defined(USE_MATH) && !defined(TRIO_NO_POWL)
++# if !defined(HAVE_POWL)
++# if defined(PREDEF_STANDARD_C99) \
++ || defined(PREDEF_STANDARD_UNIX03)
++# define HAVE_POWL
++# else
++# if defined(TRIO_COMPILER_VISUALC)
++# if defined(powl)
++# define HAVE_POWL
++# endif
++# endif
++# endif
++# endif
++#endif
++
++#if defined(HAVE_POWL)
++# define trio_powl(x,y) powl((x),(y))
++#else
++# define trio_powl(x,y) pow((double)(x),(double)(y))
++#endif
++
++#if defined(TRIO_FUNC_TO_UPPER) \
++ || (defined(TRIO_FUNC_EQUAL) && !defined(USE_STRCASECMP)) \
++ || (defined(TRIO_FUNC_EQUAL_MAX) && !defined(USE_STRNCASECMP)) \
++ || defined(TRIO_FUNC_MATCH) \
++ || defined(TRIO_FUNC_TO_LONG_DOUBLE) \
++ || defined(TRIO_FUNC_UPPER)
++# define TRIO_FUNC_INTERNAL_TO_UPPER
++#endif
++
++/*************************************************************************
++ * Structures
++ */
++
++struct _trio_string_t
++{
++ char *content;
++ size_t length;
++ size_t allocated;
++};
++
++/*************************************************************************
++ * Constants
++ */
++
++#if !defined(TRIO_EMBED_STRING)
++static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.36 2010/01/26 13:02:02 breese Exp $";
++#endif
++
++/*************************************************************************
++ * Static String Functions
++ */
++
++#if defined(TRIO_DOCUMENTATION)
++# include "doc/doc_static.h"
++#endif
++/** @addtogroup StaticStrings
++ @{
++*/
++
++/*
++ * internal_duplicate_max
++ */
++#if defined(TRIO_FUNC_DUPLICATE) \
++ || defined(TRIO_FUNC_DUPLICATE_MAX) \
++ || defined(TRIO_FUNC_STRING_DUPLICATE) \
++ || defined(TRIO_FUNC_XSTRING_DUPLICATE)
++
++TRIO_PRIVATE_STRING char *
++internal_duplicate_max
++TRIO_ARGS2((source, size),
++ TRIO_CONST char *source,
++ size_t size)
++{
++ char *target;
++
++ assert(source);
++
++ /* Make room for string plus a terminating zero */
++ size++;
++ target = trio_create(size);
++ if (target)
++ {
++ trio_copy_max(target, size, source);
++ }
++ return target;
++}
++
++#endif
++
++/*
++ * internal_string_alloc
++ */
++#if defined(TRIO_FUNC_STRING_CREATE) \
++ || defined(TRIO_FUNC_STRING_DUPLICATE) \
++ || defined(TRIO_FUNC_XSTRING_DUPLICATE)
++
++TRIO_PRIVATE_STRING trio_string_t *
++internal_string_alloc(TRIO_NOARGS)
++{
++ trio_string_t *self;
++
++ self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t));
++ if (self)
++ {
++ self->content = NULL;
++ self->length = 0;
++ self->allocated = 0;
++ }
++ return self;
++}
++
++#endif
++
++/*
++ * internal_string_grow
++ *
++ * The size of the string will be increased by 'delta' characters. If
++ * 'delta' is zero, the size will be doubled.
++ */
++#if defined(TRIO_FUNC_STRING_CREATE) \
++ || defined(TRIO_FUNC_STRING_APPEND) \
++ || defined(TRIO_FUNC_XSTRING_APPEND) \
++ || defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
++
++TRIO_PRIVATE_STRING BOOLEAN_T
++internal_string_grow
++TRIO_ARGS2((self, delta),
++ trio_string_t *self,
++ size_t delta)
++{
++ BOOLEAN_T status = FALSE;
++ char *new_content;
++ size_t new_size;
++
++ new_size = (delta == 0)
++ ? ( (self->allocated == 0) ? 1 : self->allocated * 2 )
++ : self->allocated + delta;
++
++ new_content = (char *)TRIO_REALLOC(self->content, new_size);
++ if (new_content)
++ {
++ self->content = new_content;
++ self->allocated = new_size;
++ status = TRUE;
++ }
++ return status;
++}
++
++#endif
++
++/*
++ * internal_string_grow_to
++ *
++ * The size of the string will be increased to 'length' plus one characters.
++ * If 'length' is less than the original size, the original size will be
++ * used (that is, the size of the string is never decreased).
++ */
++#if defined(TRIO_FUNC_STRING_APPEND) \
++ || defined(TRIO_FUNC_XSTRING_APPEND) \
++ || defined(TRIO_FUNC_XSTRING_APPEND_MAX)
++
++TRIO_PRIVATE_STRING BOOLEAN_T
++internal_string_grow_to
++TRIO_ARGS2((self, length),
++ trio_string_t *self,
++ size_t length)
++{
++ length++; /* Room for terminating zero */
++ return (self->allocated < length)
++ ? internal_string_grow(self, length - self->allocated)
++ : TRUE;
++}
++
++#endif
++
++#if defined(TRIO_FUNC_INTERNAL_TO_UPPER)
++
++TRIO_PRIVATE_STRING TRIO_INLINE int
++internal_to_upper
++TRIO_ARGS1((source),
++ int source)
++{
++# if defined(HAVE_TOUPPER)
++
++ return toupper(source);
++
++# else
++
++ /* Does not handle locales or non-contiguous alphabetic characters */
++ return ((source >= (int)'a') && (source <= (int)'z'))
++ ? source - 'a' + 'A'
++ : source;
++
++# endif
++}
++
++#endif
++
++
++/**
++ Create new string.
++
++ @param size Size of new string.
++ @return Pointer to string, or NULL if allocation failed.
++*/
++#if defined(TRIO_FUNC_CREATE)
++
++TRIO_PUBLIC_STRING char *
++trio_create
++TRIO_ARGS1((size),
++ size_t size)
++{
++ return (char *)TRIO_MALLOC(size);
++}
++
++#endif
++
++/**
++ Destroy string.
++
++ @param string String to be freed.
++*/
++#if defined(TRIO_FUNC_DESTROY)
++
++TRIO_PUBLIC_STRING void
++trio_destroy
++TRIO_ARGS1((string),
++ char *string)
++{
++ if (string)
++ {
++ TRIO_FREE(string);
++ }
++}
++
++#endif
++
++/**
++ Count the number of characters in a string.
++
++ @param string String to measure.
++ @return Number of characters in @p string.
++*/
++#if defined(TRIO_FUNC_LENGTH)
++
++TRIO_PUBLIC_STRING size_t
++trio_length
++TRIO_ARGS1((string),
++ TRIO_CONST char *string)
++{
++ return strlen(string);
++}
++
++#endif
++
++/**
++ Count at most @p max characters in a string.
++
++ @param string String to measure.
++ @param max Maximum number of characters to count.
++ @return The maximum value of @p max and number of characters in @p string.
++*/
++#if defined(TRIO_FUNC_LENGTH_MAX)
++
++TRIO_PUBLIC_STRING size_t
++trio_length_max
++TRIO_ARGS2((string, max),
++ TRIO_CONST char *string,
++ size_t max)
++{
++ size_t i;
++
++ for (i = 0; i < max; ++i)
++ {
++ if (string[i] == 0)
++ break;
++ }
++ return i;
++}
++
++#endif
++
++/**
++ Append @p source at the end of @p target.
++
++ @param target Target string.
++ @param source Source string.
++ @return Boolean value indicating success or failure.
++
++ @pre @p target must point to a memory chunk with sufficient room to
++ contain the @p target string and @p source string.
++ @pre No boundary checking is performed, so insufficient memory will
++ result in a buffer overrun.
++ @post @p target will be zero terminated.
++*/
++#if defined(TRIO_FUNC_APPEND)
++
++TRIO_PUBLIC_STRING int
++trio_append
++TRIO_ARGS2((target, source),
++ char *target,
++ TRIO_CONST char *source)
++{
++ assert(target);
++ assert(source);
++
++ return (strcat(target, source) != NULL);
++}
++
++#endif
++
++/**
++ Append at most @p max characters from @p source to @p target.
++
++ @param target Target string.
++ @param max Maximum number of characters to append.
++ @param source Source string.
++ @return Boolean value indicating success or failure.
++
++ @pre @p target must point to a memory chuck with sufficient room to
++ contain the @p target string and the @p source string (at most @p max
++ characters).
++ @pre No boundary checking is performed, so insufficient memory will
++ result in a buffer overrun.
++ @post @p target will be zero terminated.
++*/
++#if defined(TRIO_FUNC_APPEND_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_append_max
++TRIO_ARGS3((target, max, source),
++ char *target,
++ size_t max,
++ TRIO_CONST char *source)
++{
++ size_t length;
++
++ assert(target);
++ assert(source);
++
++ length = trio_length(target);
++
++ if (max > length)
++ {
++ strncat(target, source, max - length - 1);
++ }
++ return TRUE;
++}
++
++#endif
++
++/**
++ Determine if a string contains a substring.
++
++ @param string String to be searched.
++ @param substring String to be found.
++ @return Boolean value indicating success or failure.
++*/
++#if defined(TRIO_FUNC_CONTAINS)
++
++TRIO_PUBLIC_STRING int
++trio_contains
++TRIO_ARGS2((string, substring),
++ TRIO_CONST char *string,
++ TRIO_CONST char *substring)
++{
++ assert(string);
++ assert(substring);
++
++ return (0 != strstr(string, substring));
++}
++
++#endif
++
++/**
++ Copy @p source to @p target.
++
++ @param target Target string.
++ @param source Source string.
++ @return Boolean value indicating success or failure.
++
++ @pre @p target must point to a memory chunk with sufficient room to
++ contain the @p source string.
++ @pre No boundary checking is performed, so insufficient memory will
++ result in a buffer overrun.
++ @post @p target will be zero terminated.
++*/
++#if defined(TRIO_FUNC_COPY)
++
++TRIO_PUBLIC_STRING int
++trio_copy
++TRIO_ARGS2((target, source),
++ char *target,
++ TRIO_CONST char *source)
++{
++ assert(target);
++ assert(source);
++
++ (void)strcpy(target, source);
++ return TRUE;
++}
++
++#endif
++
++/**
++ Copy at most @p max - 1 characters from @p source to @p target.
++
++ @param target Target string.
++ @param max Maximum number of characters to append (one of which is
++ a NUL terminator). In other words @p source must point to at least
++ @p max - 1 bytes, but @p target must point to at least @p max
++ bytes.
++ @param source Source string.
++ @return Boolean value indicating success or failure.
++
++ @pre @p target must point to a memory chunk with sufficient room to
++ contain the @p source string and a NUL terminator (at most @p max
++ bytes total).
++ @pre No boundary checking is performed, so insufficient memory will
++ result in a buffer overrun.
++ @post @p target will be zero terminated.
++*/
++#if defined(TRIO_FUNC_COPY_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_copy_max
++TRIO_ARGS3((target, max, source),
++ char *target,
++ size_t max,
++ TRIO_CONST char *source)
++{
++ assert(target);
++ assert(source);
++ assert(max > 0); /* Includes != 0 */
++
++ (void)strncpy(target, source, max - 1);
++ target[max - 1] = (char)0;
++ return TRUE;
++}
++
++#endif
++
++/**
++ Duplicate @p source.
++
++ @param source Source string.
++ @return A copy of the @p source string.
++
++ @post @p target will be zero terminated.
++*/
++#if defined(TRIO_FUNC_DUPLICATE)
++
++TRIO_PUBLIC_STRING char *
++trio_duplicate
++TRIO_ARGS1((source),
++ TRIO_CONST char *source)
++{
++ return internal_duplicate_max(source, trio_length(source));
++}
++
++#endif
++
++/**
++ Duplicate at most @p max characters of @p source.
++
++ @param source Source string.
++ @param max Maximum number of characters to duplicate.
++ @return A copy of the @p source string.
++
++ @post @p target will be zero terminated.
++*/
++#if defined(TRIO_FUNC_DUPLICATE_MAX)
++
++TRIO_PUBLIC_STRING char *
++trio_duplicate_max
++TRIO_ARGS2((source, max),
++ TRIO_CONST char *source,
++ size_t max)
++{
++ size_t length;
++
++ assert(source);
++ assert(max > 0);
++
++ length = trio_length(source);
++ if (length > max)
++ {
++ length = max;
++ }
++ return internal_duplicate_max(source, length);
++}
++
++#endif
++
++/**
++ Compare if two strings are equal.
++
++ @param first First string.
++ @param second Second string.
++ @return Boolean indicating whether the two strings are equal or not.
++
++ Case-insensitive comparison.
++*/
++#if defined(TRIO_FUNC_EQUAL)
++
++TRIO_PUBLIC_STRING int
++trio_equal
++TRIO_ARGS2((first, second),
++ TRIO_CONST char *first,
++ TRIO_CONST char *second)
++{
++ assert(first);
++ assert(second);
++
++ if ((first != NULL) && (second != NULL))
++ {
++# if defined(USE_STRCASECMP)
++ return (0 == strcasecmp(first, second));
++# else
++ while ((*first != NIL) && (*second != NIL))
++ {
++ if (internal_to_upper(*first) != internal_to_upper(*second))
++ {
++ break;
++ }
++ first++;
++ second++;
++ }
++ return ((*first == NIL) && (*second == NIL));
++# endif
++ }
++ return FALSE;
++}
++
++#endif
++
++/**
++ Compare if two strings are equal.
++
++ @param first First string.
++ @param second Second string.
++ @return Boolean indicating whether the two strings are equal or not.
++
++ Case-sensitive comparison.
++*/
++#if defined(TRIO_FUNC_EQUAL_CASE)
++
++TRIO_PUBLIC_STRING int
++trio_equal_case
++TRIO_ARGS2((first, second),
++ TRIO_CONST char *first,
++ TRIO_CONST char *second)
++{
++ assert(first);
++ assert(second);
++
++ if ((first != NULL) && (second != NULL))
++ {
++ return (0 == strcmp(first, second));
++ }
++ return FALSE;
++}
++
++#endif
++
++/**
++ Compare if two strings up until the first @p max characters are equal.
++
++ @param first First string.
++ @param max Maximum number of characters to compare.
++ @param second Second string.
++ @return Boolean indicating whether the two strings are equal or not.
++
++ Case-sensitive comparison.
++*/
++#if defined(TRIO_FUNC_EQUAL_CASE_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_equal_case_max
++TRIO_ARGS3((first, max, second),
++ TRIO_CONST char *first,
++ size_t max,
++ TRIO_CONST char *second)
++{
++ assert(first);
++ assert(second);
++
++ if ((first != NULL) && (second != NULL))
++ {
++ return (0 == strncmp(first, second, max));
++ }
++ return FALSE;
++}
++
++#endif
++
++/**
++ Compare if two strings are equal.
++
++ @param first First string.
++ @param second Second string.
++ @return Boolean indicating whether the two strings are equal or not.
++
++ Collating characters are considered equal.
++*/
++#if defined(TRIO_FUNC_EQUAL_LOCALE)
++
++TRIO_PUBLIC_STRING int
++trio_equal_locale
++TRIO_ARGS2((first, second),
++ TRIO_CONST char *first,
++ TRIO_CONST char *second)
++{
++ assert(first);
++ assert(second);
++
++# if defined(LC_COLLATE)
++ return (strcoll(first, second) == 0);
++# else
++ return trio_equal(first, second);
++# endif
++}
++
++#endif
++
++/**
++ Compare if two strings up until the first @p max characters are equal.
++
++ @param first First string.
++ @param max Maximum number of characters to compare.
++ @param second Second string.
++ @return Boolean indicating whether the two strings are equal or not.
++
++ Case-insensitive comparison.
++*/
++#if defined(TRIO_FUNC_EQUAL_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_equal_max
++TRIO_ARGS3((first, max, second),
++ TRIO_CONST char *first,
++ size_t max,
++ TRIO_CONST char *second)
++{
++ assert(first);
++ assert(second);
++
++ if ((first != NULL) && (second != NULL))
++ {
++# if defined(USE_STRNCASECMP)
++ return (0 == strncasecmp(first, second, max));
++# else
++ /* Not adequately tested yet */
++ size_t cnt = 0;
++ while ((*first != NIL) && (*second != NIL) && (cnt <= max))
++ {
++ if (internal_to_upper(*first) != internal_to_upper(*second))
++ {
++ break;
++ }
++ first++;
++ second++;
++ cnt++;
++ }
++ return ((cnt == max) || ((*first == NIL) && (*second == NIL)));
++# endif
++ }
++ return FALSE;
++}
++
++#endif
++
++/**
++ Provide a textual description of an error code (errno).
++
++ @param error_number Error number.
++ @return Textual description of @p error_number.
++*/
++#if defined(TRIO_FUNC_ERROR)
++
++TRIO_PUBLIC_STRING TRIO_CONST char *
++trio_error
++TRIO_ARGS1((error_number),
++ int error_number)
++{
++# if defined(USE_STRERROR)
++
++ return strerror(error_number);
++
++# else
++# if defined(USE_SYS_ERRLIST)
++
++ extern char *sys_errlist[];
++ extern int sys_nerr;
++
++ return ((error_number < 0) || (error_number >= sys_nerr))
++ ? "unknown"
++ : sys_errlist[error_number];
++
++# else
++
++ return "unknown";
++
++# endif
++# endif
++}
++
++#endif
++
++/**
++ Format the date/time according to @p format.
++
++ @param target Target string.
++ @param max Maximum number of characters to format.
++ @param format Formatting string.
++ @param datetime Date/time structure.
++ @return Number of formatted characters.
++
++ The formatting string accepts the same specifiers as the standard C
++ function strftime.
++*/
++#if defined(TRIO_FUNC_FORMAT_DATE_MAX)
++
++TRIO_PUBLIC_STRING size_t
++trio_format_date_max
++TRIO_ARGS4((target, max, format, datetime),
++ char *target,
++ size_t max,
++ TRIO_CONST char *format,
++ TRIO_CONST struct tm *datetime)
++{
++ assert(target);
++ assert(format);
++ assert(datetime);
++ assert(max > 0);
++
++ return strftime(target, max, format, datetime);
++}
++
++#endif
++
++/**
++ Calculate a hash value for a string.
++
++ @param string String to be calculated on.
++ @param type Hash function.
++ @return Calculated hash value.
++
++ @p type can be one of the following
++ @li @c TRIO_HASH_PLAIN Plain hash function.
++*/
++#if defined(TRIO_FUNC_HASH)
++
++TRIO_PUBLIC_STRING unsigned long
++trio_hash
++TRIO_ARGS2((string, type),
++ TRIO_CONST char *string,
++ int type)
++{
++ unsigned long value = 0L;
++ char ch;
++
++ assert(string);
++
++ switch (type)
++ {
++ case TRIO_HASH_PLAIN:
++ while ( (ch = *string++) != NIL )
++ {
++ value *= 31;
++ value += (unsigned long)ch;
++ }
++ break;
++ default:
++ assert(FALSE);
++ break;
++ }
++ return value;
++}
++
++#endif
++
++/**
++ Find first occurrence of a character in a string.
++
++ @param string String to be searched.
++ @param character Character to be found.
++ @return A pointer to the found character, or NULL if character was not found.
++ */
++#if defined(TRIO_FUNC_INDEX)
++
++TRIO_PUBLIC_STRING char *
++trio_index
++TRIO_ARGS2((string, character),
++ TRIO_CONST char *string,
++ int character)
++{
++ assert(string);
++
++ return strchr(string, character);
++}
++
++#endif
++
++/**
++ Find last occurrence of a character in a string.
++
++ @param string String to be searched.
++ @param character Character to be found.
++ @return A pointer to the found character, or NULL if character was not found.
++ */
++#if defined(TRIO_FUNC_INDEX_LAST)
++
++TRIO_PUBLIC_STRING char *
++trio_index_last
++TRIO_ARGS2((string, character),
++ TRIO_CONST char *string,
++ int character)
++{
++ assert(string);
++
++ return strchr(string, character);
++}
++
++#endif
++
++/**
++ Convert the alphabetic letters in the string to lower-case.
++
++ @param target String to be converted.
++ @return Number of processed characters (converted or not).
++*/
++#if defined(TRIO_FUNC_LOWER)
++
++TRIO_PUBLIC_STRING int
++trio_lower
++TRIO_ARGS1((target),
++ char *target)
++{
++ assert(target);
++
++ return trio_span_function(target, target, trio_to_lower);
++}
++
++#endif
++
++/**
++ Compare two strings using wildcards.
++
++ @param string String to be searched.
++ @param pattern Pattern, including wildcards, to search for.
++ @return Boolean value indicating success or failure.
++
++ Case-insensitive comparison.
++
++ The following wildcards can be used
++ @li @c * Match any number of characters.
++ @li @c ? Match a single character.
++*/
++#if defined(TRIO_FUNC_MATCH)
++
++TRIO_PUBLIC_STRING int
++trio_match
++TRIO_ARGS2((string, pattern),
++ TRIO_CONST char *string,
++ TRIO_CONST char *pattern)
++{
++ assert(string);
++ assert(pattern);
++
++ for (; ('*' != *pattern); ++pattern, ++string)
++ {
++ if (NIL == *string)
++ {
++ return (NIL == *pattern);
++ }
++ if ((internal_to_upper((int)*string) != internal_to_upper((int)*pattern))
++ && ('?' != *pattern))
++ {
++ return FALSE;
++ }
++ }
++ /* two-line patch to prevent *too* much recursiveness: */
++ while ('*' == pattern[1])
++ pattern++;
++
++ do
++ {
++ if ( trio_match(string, &pattern[1]) )
++ {
++ return TRUE;
++ }
++ }
++ while (*string++);
++
++ return FALSE;
++}
++
++#endif
++
++/**
++ Compare two strings using wildcards.
++
++ @param string String to be searched.
++ @param pattern Pattern, including wildcards, to search for.
++ @return Boolean value indicating success or failure.
++
++ Case-sensitive comparison.
++
++ The following wildcards can be used
++ @li @c * Match any number of characters.
++ @li @c ? Match a single character.
++*/
++#if defined(TRIO_FUNC_MATCH_CASE)
++
++TRIO_PUBLIC_STRING int
++trio_match_case
++TRIO_ARGS2((string, pattern),
++ TRIO_CONST char *string,
++ TRIO_CONST char *pattern)
++{
++ assert(string);
++ assert(pattern);
++
++ for (; ('*' != *pattern); ++pattern, ++string)
++ {
++ if (NIL == *string)
++ {
++ return (NIL == *pattern);
++ }
++ if ((*string != *pattern)
++ && ('?' != *pattern))
++ {
++ return FALSE;
++ }
++ }
++ /* two-line patch to prevent *too* much recursiveness: */
++ while ('*' == pattern[1])
++ pattern++;
++
++ do
++ {
++ if ( trio_match_case(string, &pattern[1]) )
++ {
++ return TRUE;
++ }
++ }
++ while (*string++);
++
++ return FALSE;
++}
++
++#endif
++
++/**
++ Execute a function on each character in string.
++
++ @param target Target string.
++ @param source Source string.
++ @param Function Function to be executed.
++ @return Number of processed characters.
++*/
++#if defined(TRIO_FUNC_SPAN_FUNCTION)
++
++TRIO_PUBLIC_STRING size_t
++trio_span_function
++TRIO_ARGS3((target, source, Function),
++ char *target,
++ TRIO_CONST char *source,
++ int (*Function) TRIO_PROTO((int)))
++{
++ size_t count = 0;
++
++ assert(target);
++ assert(source);
++ assert(Function);
++
++ while (*source != NIL)
++ {
++ *target++ = Function(*source++);
++ count++;
++ }
++ return count;
++}
++
++#endif
++
++/**
++ Search for a substring in a string.
++
++ @param string String to be searched.
++ @param substring String to be found.
++ @return Pointer to first occurrence of @p substring in @p string, or NULL
++ if no match was found.
++*/
++#if defined(TRIO_FUNC_SUBSTRING)
++
++TRIO_PUBLIC_STRING char *
++trio_substring
++TRIO_ARGS2((string, substring),
++ TRIO_CONST char *string,
++ TRIO_CONST char *substring)
++{
++ assert(string);
++ assert(substring);
++
++ return strstr(string, substring);
++}
++
++#endif
++
++/**
++ Search for a substring in the first @p max characters of a string.
++
++ @param string String to be searched.
++ @param max Maximum characters to be searched.
++ @param substring String to be found.
++ @return Pointer to first occurrence of @p substring in @p string, or NULL
++ if no match was found.
++*/
++#if defined(TRIO_FUNC_SUBSTRING_MAX)
++
++TRIO_PUBLIC_STRING char *
++trio_substring_max
++TRIO_ARGS3((string, max, substring),
++ TRIO_CONST char *string,
++ size_t max,
++ TRIO_CONST char *substring)
++{
++ size_t count;
++ size_t size;
++ char *result = NULL;
++
++ assert(string);
++ assert(substring);
++
++ size = trio_length(substring);
++ if (size <= max)
++ {
++ for (count = 0; count <= max - size; count++)
++ {
++ if (trio_equal_max(substring, size, &string[count]))
++ {
++ result = (char *)&string[count];
++ break;
++ }
++ }
++ }
++ return result;
++}
++
++#endif
++
++/**
++ Tokenize string.
++
++ @param string String to be tokenized.
++ @param delimiters String containing list of delimiting characters.
++ @return Start of new token.
++
++ @warning @p string will be destroyed.
++*/
++#if defined(TRIO_FUNC_TOKENIZE)
++
++TRIO_PUBLIC_STRING char *
++trio_tokenize
++TRIO_ARGS2((string, delimiters),
++ char *string,
++ TRIO_CONST char *delimiters)
++{
++ assert(delimiters);
++
++ return strtok(string, delimiters);
++}
++
++#endif
++
++/**
++ Convert string to floating-point number.
++
++ @param source String to be converted.
++ @param endp Pointer to end of the converted string.
++ @return A floating-point number.
++
++ The following Extended Backus-Naur form is used
++ @verbatim
++ double ::= [ <sign> ]
++ ( <number> |
++ <number> <decimal_point> <number> |
++ <decimal_point> <number> )
++ [ <exponential> [ <sign> ] <number> ]
++ number ::= 1*( <digit> )
++ digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
++ exponential ::= ( 'e' | 'E' )
++ sign ::= ( '-' | '+' )
++ decimal_point ::= '.'
++ @endverbatim
++*/
++#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
++
++/* FIXME: Add EBNF for hex-floats */
++TRIO_PUBLIC_STRING trio_long_double_t
++trio_to_long_double
++TRIO_ARGS2((source, endp),
++ TRIO_CONST char *source,
++ char **endp)
++{
++# if defined(USE_STRTOLD)
++ return strtold(source, endp);
++# else
++ int isNegative = FALSE;
++ int isExponentNegative = FALSE;
++ trio_long_double_t integer = 0.0;
++ trio_long_double_t fraction = 0.0;
++ unsigned long exponent = 0;
++ trio_long_double_t base;
++ trio_long_double_t fracdiv = 1.0;
++ trio_long_double_t value = 0.0;
++
++ /* First try hex-floats */
++ if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X')))
++ {
++ base = 16.0;
++ source += 2;
++ while (isxdigit((int)*source))
++ {
++ integer *= base;
++ integer += (isdigit((int)*source)
++ ? (*source - '0')
++ : 10 + (internal_to_upper((int)*source) - 'A'));
++ source++;
++ }
++ if (*source == '.')
++ {
++ source++;
++ while (isxdigit((int)*source))
++ {
++ fracdiv /= base;
++ fraction += fracdiv * (isdigit((int)*source)
++ ? (*source - '0')
++ : 10 + (internal_to_upper((int)*source) - 'A'));
++ source++;
++ }
++ if ((*source == 'p') || (*source == 'P'))
++ {
++ source++;
++ if ((*source == '+') || (*source == '-'))
++ {
++ isExponentNegative = (*source == '-');
++ source++;
++ }
++ while (isdigit((int)*source))
++ {
++ exponent *= 10;
++ exponent += (*source - '0');
++ source++;
++ }
++ }
++ }
++ /* For later use with exponent */
++ base = 2.0;
++ }
++ else /* Then try normal decimal floats */
++ {
++ base = 10.0;
++ isNegative = (*source == '-');
++ /* Skip sign */
++ if ((*source == '+') || (*source == '-'))
++ source++;
++
++ /* Integer part */
++ while (isdigit((int)*source))
++ {
++ integer *= base;
++ integer += (*source - '0');
++ source++;
++ }
++
++ if (*source == '.')
++ {
++ source++; /* skip decimal point */
++ while (isdigit((int)*source))
++ {
++ fracdiv /= base;
++ fraction += (*source - '0') * fracdiv;
++ source++;
++ }
++ }
++ if ((*source == 'e')
++ || (*source == 'E')
++# if TRIO_MICROSOFT
++ || (*source == 'd')
++ || (*source == 'D')
++# endif
++ )
++ {
++ source++; /* Skip exponential indicator */
++ isExponentNegative = (*source == '-');
++ if ((*source == '+') || (*source == '-'))
++ source++;
++ while (isdigit((int)*source))
++ {
++ exponent *= (int)base;
++ exponent += (*source - '0');
++ source++;
++ }
++ }
++ }
++
++ value = integer + fraction;
++ if (exponent != 0)
++ {
++ if (isExponentNegative)
++ value /= trio_powl(base, (trio_long_double_t)exponent);
++ else
++ value *= trio_powl(base, (trio_long_double_t)exponent);
++ }
++ if (isNegative)
++ value = -value;
++
++ if (endp)
++ *endp = (char *)source;
++ return value;
++# endif
++}
++
++#endif
++
++/**
++ Convert string to floating-point number.
++
++ @param source String to be converted.
++ @param endp Pointer to end of the converted string.
++ @return A floating-point number.
++
++ See @ref trio_to_long_double.
++*/
++#if defined(TRIO_FUNC_TO_DOUBLE)
++
++TRIO_PUBLIC_STRING double
++trio_to_double
++TRIO_ARGS2((source, endp),
++ TRIO_CONST char *source,
++ char **endp)
++{
++#if defined(USE_STRTOD)
++ return strtod(source, endp);
++#else
++ return (double)trio_to_long_double(source, endp);
++#endif
++}
++
++#endif
++
++/**
++ Convert string to floating-point number.
++
++ @param source String to be converted.
++ @param endp Pointer to end of the converted string.
++ @return A floating-point number.
++
++ See @ref trio_to_long_double.
++*/
++#if defined(TRIO_FUNC_TO_FLOAT)
++
++TRIO_PUBLIC_STRING float
++trio_to_float
++TRIO_ARGS2((source, endp),
++ TRIO_CONST char *source,
++ char **endp)
++{
++# if defined(USE_STRTOF)
++ return strtof(source, endp);
++# else
++ return (float)trio_to_long_double(source, endp);
++# endif
++}
++
++#endif
++
++/**
++ Convert string to signed integer.
++
++ @param string String to be converted.
++ @param endp Pointer to end of converted string.
++ @param base Radix number of number.
++*/
++#if defined(TRIO_FUNC_TO_LONG)
++
++TRIO_PUBLIC_STRING long
++trio_to_long
++TRIO_ARGS3((string, endp, base),
++ TRIO_CONST char *string,
++ char **endp,
++ int base)
++{
++ assert(string);
++ assert((base >= 2) && (base <= 36));
++
++ return strtol(string, endp, base);
++}
++
++#endif
++
++/**
++ Convert one alphabetic letter to lower-case.
++
++ @param source The letter to be converted.
++ @return The converted letter.
++*/
++#if defined(TRIO_FUNC_TO_LOWER)
++
++TRIO_PUBLIC_STRING int
++trio_to_lower
++TRIO_ARGS1((source),
++ int source)
++{
++# if defined(HAVE_TOLOWER)
++
++ return tolower(source);
++
++# else
++
++ /* Does not handle locales or non-contiguous alphabetic characters */
++ return ((source >= (int)'A') && (source <= (int)'Z'))
++ ? source - 'A' + 'a'
++ : source;
++
++# endif
++}
++
++#endif
++
++/**
++ Convert string to unsigned integer.
++
++ @param string String to be converted.
++ @param endp Pointer to end of converted string.
++ @param base Radix number of number.
++*/
++#if defined(TRIO_FUNC_TO_UNSIGNED_LONG)
++
++TRIO_PUBLIC_STRING unsigned long
++trio_to_unsigned_long
++TRIO_ARGS3((string, endp, base),
++ TRIO_CONST char *string,
++ char **endp,
++ int base)
++{
++ assert(string);
++ assert((base >= 2) && (base <= 36));
++
++ return strtoul(string, endp, base);
++}
++
++#endif
++
++/**
++ Convert one alphabetic letter to upper-case.
++
++ @param source The letter to be converted.
++ @return The converted letter.
++*/
++#if defined(TRIO_FUNC_TO_UPPER)
++
++TRIO_PUBLIC_STRING int
++trio_to_upper
++TRIO_ARGS1((source),
++ int source)
++{
++ return internal_to_upper(source);
++}
++
++#endif
++
++/**
++ Convert the alphabetic letters in the string to upper-case.
++
++ @param target The string to be converted.
++ @return The number of processed characters (converted or not).
++*/
++#if defined(TRIO_FUNC_UPPER)
++
++TRIO_PUBLIC_STRING int
++trio_upper
++TRIO_ARGS1((target),
++ char *target)
++{
++ assert(target);
++
++ return trio_span_function(target, target, internal_to_upper);
++}
++
++#endif
++
++/** @} End of StaticStrings */
++
++
++/*************************************************************************
++ * Dynamic String Functions
++ */
++
++#if defined(TRIO_DOCUMENTATION)
++# include "doc/doc_dynamic.h"
++#endif
++/** @addtogroup DynamicStrings
++ @{
++*/
++
++/**
++ Create a new dynamic string.
++
++ @param initial_size Initial size of the buffer.
++ @return Newly allocated dynamic string, or NULL if memory allocation failed.
++*/
++#if defined(TRIO_FUNC_STRING_CREATE)
++
++TRIO_PUBLIC_STRING trio_string_t *
++trio_string_create
++TRIO_ARGS1((initial_size),
++ int initial_size)
++{
++ trio_string_t *self;
++
++ self = internal_string_alloc();
++ if (self)
++ {
++ if (internal_string_grow(self,
++ (size_t)((initial_size > 0) ? initial_size : 1)))
++ {
++ self->content[0] = (char)0;
++ self->allocated = initial_size;
++ }
++ else
++ {
++ trio_string_destroy(self);
++ self = NULL;
++ }
++ }
++ return self;
++}
++
++#endif
++
++/**
++ Deallocate the dynamic string and its contents.
++
++ @param self Dynamic string
++*/
++#if defined(TRIO_FUNC_STRING_DESTROY)
++
++TRIO_PUBLIC_STRING void
++trio_string_destroy
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ assert(self);
++
++ if (self)
++ {
++ trio_destroy(self->content);
++ TRIO_FREE(self);
++ }
++}
++
++#endif
++
++/**
++ Get a pointer to the content.
++
++ @param self Dynamic string.
++ @param offset Offset into content.
++ @return Pointer to the content.
++
++ @p Offset can be zero, positive, or negative. If @p offset is zero,
++ then the start of the content will be returned. If @p offset is positive,
++ then a pointer to @p offset number of characters from the beginning of the
++ content is returned. If @p offset is negative, then a pointer to @p offset
++ number of characters from the ending of the string, starting at the
++ terminating zero, is returned.
++*/
++#if defined(TRIO_FUNC_STRING_GET)
++
++TRIO_PUBLIC_STRING char *
++trio_string_get
++TRIO_ARGS2((self, offset),
++ trio_string_t *self,
++ int offset)
++{
++ char *result = NULL;
++
++ assert(self);
++
++ if (self->content != NULL)
++ {
++ if (self->length == 0)
++ {
++ (void)trio_string_length(self);
++ }
++ if (offset >= 0)
++ {
++ if (offset > (int)self->length)
++ {
++ offset = self->length;
++ }
++ }
++ else
++ {
++ offset += self->length + 1;
++ if (offset < 0)
++ {
++ offset = 0;
++ }
++ }
++ result = &(self->content[offset]);
++ }
++ return result;
++}
++
++#endif
++
++/**
++ Extract the content.
++
++ @param self Dynamic String
++ @return Content of dynamic string.
++
++ The content is removed from the dynamic string. This enables destruction
++ of the dynamic string without deallocation of the content.
++*/
++#if defined(TRIO_FUNC_STRING_EXTRACT)
++
++TRIO_PUBLIC_STRING char *
++trio_string_extract
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ char *result;
++
++ assert(self);
++
++ result = self->content;
++ /* FIXME: Allocate new empty buffer? */
++ self->content = NULL;
++ self->length = self->allocated = 0;
++ return result;
++}
++
++#endif
++
++/**
++ Set the content of the dynamic string.
++
++ @param self Dynamic String
++ @param buffer The new content.
++
++ Sets the content of the dynamic string to a copy @p buffer.
++ An existing content will be deallocated first, if necessary.
++
++ @remark
++ This function will make a copy of @p buffer.
++ You are responsible for deallocating @p buffer yourself.
++*/
++#if defined(TRIO_FUNC_XSTRING_SET)
++
++TRIO_PUBLIC_STRING void
++trio_xstring_set
++TRIO_ARGS2((self, buffer),
++ trio_string_t *self,
++ char *buffer)
++{
++ assert(self);
++
++ trio_destroy(self->content);
++ self->content = trio_duplicate(buffer);
++}
++
++#endif
++
++/*
++ * trio_string_size
++ */
++#if defined(TRIO_FUNC_STRING_SIZE)
++
++TRIO_PUBLIC_STRING int
++trio_string_size
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ assert(self);
++
++ return self->allocated;
++}
++
++#endif
++
++/*
++ * trio_string_terminate
++ */
++#if defined(TRIO_FUNC_STRING_TERMINATE)
++
++TRIO_PUBLIC_STRING void
++trio_string_terminate
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ trio_xstring_append_char(self, 0);
++}
++
++#endif
++
++/**
++ Append the second string to the first.
++
++ @param self Dynamic string to be modified.
++ @param other Dynamic string to copy from.
++ @return Boolean value indicating success or failure.
++*/
++#if defined(TRIO_FUNC_STRING_APPEND)
++
++TRIO_PUBLIC_STRING int
++trio_string_append
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ size_t length;
++
++ assert(self);
++ assert(other);
++
++ length = self->length + other->length;
++ if (!internal_string_grow_to(self, length))
++ goto error;
++ trio_copy(&self->content[self->length], other->content);
++ self->length = length;
++ return TRUE;
++
++ error:
++ return FALSE;
++}
++
++#endif
++
++
++/*
++ * trio_xstring_append
++ */
++#if defined(TRIO_FUNC_XSTRING_APPEND)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_append
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ size_t length;
++
++ assert(self);
++ assert(other);
++
++ length = self->length + trio_length(other);
++ if (!internal_string_grow_to(self, length))
++ goto error;
++ trio_copy(&self->content[self->length], other);
++ self->length = length;
++ return TRUE;
++
++ error:
++ return FALSE;
++}
++
++#endif
++
++/*
++ * trio_xstring_append_char
++ */
++#if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_append_char
++TRIO_ARGS2((self, character),
++ trio_string_t *self,
++ char character)
++{
++ assert(self);
++
++ if ((int)self->length >= trio_string_size(self))
++ {
++ if (!internal_string_grow(self, 0))
++ goto error;
++ }
++ self->content[self->length] = character;
++ self->length++;
++ return TRUE;
++
++ error:
++ return FALSE;
++}
++
++#endif
++
++/*
++ * trio_xstring_append_max
++ */
++#if defined(TRIO_FUNC_XSTRING_APPEND_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_append_max
++TRIO_ARGS3((self, other, max),
++ trio_string_t *self,
++ TRIO_CONST char *other,
++ size_t max)
++{
++ size_t length;
++
++ assert(self);
++ assert(other);
++
++ length = self->length + trio_length_max(other, max);
++ if (!internal_string_grow_to(self, length))
++ goto error;
++
++ /*
++ * Pass max + 1 since trio_copy_max copies one character less than
++ * this from the source to make room for a terminating zero.
++ */
++ trio_copy_max(&self->content[self->length], max + 1, other);
++ self->length = length;
++ return TRUE;
++
++ error:
++ return FALSE;
++}
++
++#endif
++
++/**
++ Search for the first occurrence of second parameter in the first.
++
++ @param self Dynamic string to be modified.
++ @param other Dynamic string to copy from.
++ @return Boolean value indicating success or failure.
++*/
++#if defined(TRIO_FUNC_STRING_CONTAINS)
++
++TRIO_PUBLIC_STRING int
++trio_string_contains
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_contains(self->content, other->content);
++}
++
++#endif
++
++/*
++ * trio_xstring_contains
++ */
++#if defined(TRIO_FUNC_XSTRING_CONTAINS)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_contains
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_contains(self->content, other);
++}
++
++#endif
++
++/*
++ * trio_string_copy
++ */
++#if defined(TRIO_FUNC_STRING_COPY)
++
++TRIO_PUBLIC_STRING int
++trio_string_copy
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ self->length = 0;
++ return trio_string_append(self, other);
++}
++
++#endif
++
++
++/*
++ * trio_xstring_copy
++ */
++#if defined(TRIO_FUNC_XSTRING_COPY)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_copy
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ self->length = 0;
++ return trio_xstring_append(self, other);
++}
++
++#endif
++
++/*
++ * trio_string_duplicate
++ */
++#if defined(TRIO_FUNC_STRING_DUPLICATE)
++
++TRIO_PUBLIC_STRING trio_string_t *
++trio_string_duplicate
++TRIO_ARGS1((other),
++ trio_string_t *other)
++{
++ trio_string_t *self;
++
++ assert(other);
++
++ self = internal_string_alloc();
++ if (self)
++ {
++ self->content = internal_duplicate_max(other->content, other->length);
++ if (self->content)
++ {
++ self->length = other->length;
++ self->allocated = self->length + 1;
++ }
++ else
++ {
++ self->length = self->allocated = 0;
++ }
++ }
++ return self;
++}
++
++#endif
++
++/*
++ * trio_xstring_duplicate
++ */
++#if defined(TRIO_FUNC_XSTRING_DUPLICATE)
++
++TRIO_PUBLIC_STRING trio_string_t *
++trio_xstring_duplicate
++TRIO_ARGS1((other),
++ TRIO_CONST char *other)
++{
++ trio_string_t *self;
++
++ assert(other);
++
++ self = internal_string_alloc();
++ if (self)
++ {
++ self->content = internal_duplicate_max(other, trio_length(other));
++ if (self->content)
++ {
++ self->length = trio_length(self->content);
++ self->allocated = self->length + 1;
++ }
++ else
++ {
++ self->length = self->allocated = 0;
++ }
++ }
++ return self;
++}
++
++#endif
++
++/*
++ * trio_string_equal
++ */
++#if defined(TRIO_FUNC_STRING_EQUAL)
++
++TRIO_PUBLIC_STRING int
++trio_string_equal
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal(self->content, other->content);
++}
++
++#endif
++
++
++/*
++ * trio_xstring_equal
++ */
++#if defined(TRIO_FUNC_XSTRING_EQUAL)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_equal
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal(self->content, other);
++}
++
++#endif
++
++/*
++ * trio_string_equal_max
++ */
++#if defined(TRIO_FUNC_STRING_EQUAL_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_string_equal_max
++TRIO_ARGS3((self, max, other),
++ trio_string_t *self,
++ size_t max,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal_max(self->content, max, other->content);
++}
++#endif
++
++/*
++ * trio_xstring_equal_max
++ */
++#if defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_equal_max
++TRIO_ARGS3((self, max, other),
++ trio_string_t *self,
++ size_t max,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal_max(self->content, max, other);
++}
++
++#endif
++
++/*
++ * trio_string_equal_case
++ */
++#if defined(TRIO_FUNC_STRING_EQUAL_CASE)
++
++TRIO_PUBLIC_STRING int
++trio_string_equal_case
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal_case(self->content, other->content);
++}
++
++#endif
++
++/*
++ * trio_xstring_equal_case
++ */
++#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_equal_case
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal_case(self->content, other);
++}
++
++#endif
++
++/*
++ * trio_string_equal_case_max
++ */
++#if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_string_equal_case_max
++TRIO_ARGS3((self, max, other),
++ trio_string_t *self,
++ size_t max,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal_case_max(self->content, max, other->content);
++}
++
++#endif
++
++/*
++ * trio_xstring_equal_case_max
++ */
++#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_equal_case_max
++TRIO_ARGS3((self, max, other),
++ trio_string_t *self,
++ size_t max,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_equal_case_max(self->content, max, other);
++}
++
++#endif
++
++/*
++ * trio_string_format_data_max
++ */
++#if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX)
++
++TRIO_PUBLIC_STRING size_t
++trio_string_format_date_max
++TRIO_ARGS4((self, max, format, datetime),
++ trio_string_t *self,
++ size_t max,
++ TRIO_CONST char *format,
++ TRIO_CONST struct tm *datetime)
++{
++ assert(self);
++
++ return trio_format_date_max(self->content, max, format, datetime);
++}
++
++#endif
++
++/*
++ * trio_string_index
++ */
++#if defined(TRIO_FUNC_STRING_INDEX)
++
++TRIO_PUBLIC_STRING char *
++trio_string_index
++TRIO_ARGS2((self, character),
++ trio_string_t *self,
++ int character)
++{
++ assert(self);
++
++ return trio_index(self->content, character);
++}
++
++#endif
++
++/*
++ * trio_string_index_last
++ */
++#if defined(TRIO_FUNC_STRING_INDEX_LAST)
++
++TRIO_PUBLIC_STRING char *
++trio_string_index_last
++TRIO_ARGS2((self, character),
++ trio_string_t *self,
++ int character)
++{
++ assert(self);
++
++ return trio_index_last(self->content, character);
++}
++
++#endif
++
++/*
++ * trio_string_length
++ */
++#if defined(TRIO_FUNC_STRING_LENGTH)
++
++TRIO_PUBLIC_STRING int
++trio_string_length
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ assert(self);
++
++ if (self->length == 0)
++ {
++ self->length = trio_length(self->content);
++ }
++ return self->length;
++}
++
++#endif
++
++/*
++ * trio_string_lower
++ */
++#if defined(TRIO_FUNC_STRING_LOWER)
++
++TRIO_PUBLIC_STRING int
++trio_string_lower
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ assert(self);
++
++ return trio_lower(self->content);
++}
++
++#endif
++
++/*
++ * trio_string_match
++ */
++#if defined(TRIO_FUNC_STRING_MATCH)
++
++TRIO_PUBLIC_STRING int
++trio_string_match
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_match(self->content, other->content);
++}
++
++#endif
++
++/*
++ * trio_xstring_match
++ */
++#if defined(TRIO_FUNC_XSTRING_MATCH)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_match
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_match(self->content, other);
++}
++
++#endif
++
++/*
++ * trio_string_match_case
++ */
++#if defined(TRIO_FUNC_STRING_MATCH_CASE)
++
++TRIO_PUBLIC_STRING int
++trio_string_match_case
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_match_case(self->content, other->content);
++}
++
++#endif
++
++/*
++ * trio_xstring_match_case
++ */
++#if defined(TRIO_FUNC_XSTRING_MATCH_CASE)
++
++TRIO_PUBLIC_STRING int
++trio_xstring_match_case
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_match_case(self->content, other);
++}
++
++#endif
++
++/*
++ * trio_string_substring
++ */
++#if defined(TRIO_FUNC_STRING_SUBSTRING)
++
++TRIO_PUBLIC_STRING char *
++trio_string_substring
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ trio_string_t *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_substring(self->content, other->content);
++}
++
++#endif
++
++/*
++ * trio_xstring_substring
++ */
++#if defined(TRIO_FUNC_XSTRING_SUBSTRING)
++
++TRIO_PUBLIC_STRING char *
++trio_xstring_substring
++TRIO_ARGS2((self, other),
++ trio_string_t *self,
++ TRIO_CONST char *other)
++{
++ assert(self);
++ assert(other);
++
++ return trio_substring(self->content, other);
++}
++
++#endif
++
++/*
++ * trio_string_upper
++ */
++#if defined(TRIO_FUNC_STRING_UPPER)
++
++TRIO_PUBLIC_STRING int
++trio_string_upper
++TRIO_ARGS1((self),
++ trio_string_t *self)
++{
++ assert(self);
++
++ return trio_upper(self->content);
++}
++
++#endif
++
++/** @} End of DynamicStrings */
+diff -up ghostscript-9.07/trio/triostr.h.gs_sprintf ghostscript-9.07/trio/triostr.h
+--- ghostscript-9.07/trio/triostr.h.gs_sprintf 2013-05-09 17:02:39.114447292 +0100
++++ ghostscript-9.07/trio/triostr.h 2013-05-09 17:02:39.114447292 +0100
+@@ -0,0 +1,681 @@
++/*************************************************************************
++ *
++ * $Id: triostr.h,v 1.18 2010/01/26 13:02:02 breese Exp $
++ *
++ * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
++ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
++ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
++ *
++ ************************************************************************/
++
++#ifndef TRIO_TRIOSTR_H
++#define TRIO_TRIOSTR_H
++
++/*
++ * Documentation is located in triostr.c
++ */
++
++#include <assert.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++#include "triodef.h"
++#include "triop.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++enum {
++ TRIO_HASH_NONE = 0,
++ TRIO_HASH_PLAIN,
++ TRIO_HASH_TWOSIGNED
++};
++
++#if !defined(TRIO_PUBLIC_STRING)
++# if !defined(TRIO_PUBLIC)
++# define TRIO_PUBLIC
++# endif
++# define TRIO_PUBLIC_STRING TRIO_PUBLIC
++#endif
++
++/*************************************************************************
++ * Dependencies
++ */
++
++#if defined(TRIO_EMBED_STRING)
++
++/*
++ * The application that triostr is embedded in must define which functions
++ * it uses.
++ *
++ * The following resolves internal dependencies.
++ */
++
++# if defined(TRIO_FUNC_XSTRING_SET)
++# if !defined(TRIO_FUNC_DUPLICATE)
++# define TRIO_FUNC_DUPLICATE
++# endif
++# endif
++
++# if defined(TRIO_FUNC_DUPLICATE) \
++ || defined(TRIO_FUNC_DUPLICATE_MAX) \
++ || defined(TRIO_FUNC_STRING_DUPLICATE) \
++ || defined(TRIO_FUNC_XSTRING_DUPLICATE)
++# if !defined(TRIO_FUNC_CREATE)
++# define TRIO_FUNC_CREATE
++# endif
++# if !defined(TRIO_FUNC_COPY_MAX)
++# define TRIO_FUNC_COPY_MAX
++# endif
++# endif
++
++# if defined(TRIO_FUNC_STRING_CREATE)
++# if !defined(TRIO_FUNC_STRING_DESTROY)
++# define TRIO_FUNC_STRING_DESTROY
++# endif
++# endif
++
++# if defined(TRIO_FUNC_STRING_DESTROY) \
++ || defined(TRIO_FUNC_XSTRING_SET)
++# if !defined(TRIO_FUNC_DESTROY)
++# define TRIO_FUNC_DESTROY
++# endif
++# endif
++
++# if defined(TRIO_FUNC_EQUAL_LOCALE) \
++ || defined(TRIO_FUNC_STRING_EQUAL) \
++ || defined(TRIO_FUNC_XSTRING_EQUAL)
++# if !defined(TRIO_FUNC_EQUAL)
++# define TRIO_FUNC_EQUAL
++# endif
++# endif
++
++# if defined(TRIO_FUNC_EQUAL_CASE) \
++ || defined(TRIO_FUNC_STRING_EQUAL_CASE) \
++ || defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
++# if !defined(TRIO_FUNC_EQUAL_CASE)
++# define TRIO_FUNC_EQUAL_CASE
++# endif
++# endif
++
++# if defined(TRIO_FUNC_SUBSTRING_MAX) \
++ || defined(TRIO_FUNC_STRING_EQUAL_MAX) \
++ || defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
++# if !defined(TRIO_FUNC_EQUAL_MAX)
++# define TRIO_FUNC_EQUAL_MAX
++# endif
++# endif
++
++# if defined(TRIO_FUNC_TO_DOUBLE) \
++ || defined(TRIO_FUNC_TO_FLOAT)
++# if !defined(TRIO_FUNC_TO_LONG_DOUBLE)
++# define TRIO_FUNC_TO_LONG_DOUBLE
++# endif
++# endif
++
++# if defined(TRIO_FUNC_STRING_TERMINATE)
++# if !defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
++# define TRIO_FUNC_XSTRING_APPEND_CHAR
++# endif
++# endif
++
++# if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
++# if !defined(TRIO_FUNC_STRING_SIZE)
++# define TRIO_FUNC_STRING_SIZE
++# endif
++# endif
++
++#else
++
++/*
++ * When triostr is not embedded all functions are defined.
++ */
++
++# define TRIO_FUNC_APPEND
++# define TRIO_FUNC_APPEND_MAX
++# define TRIO_FUNC_CONTAINS
++# define TRIO_FUNC_COPY
++# define TRIO_FUNC_COPY_MAX
++# define TRIO_FUNC_CREATE
++# define TRIO_FUNC_DESTROY
++# define TRIO_FUNC_DUPLICATE
++# define TRIO_FUNC_DUPLICATE_MAX
++# define TRIO_FUNC_EQUAL
++# define TRIO_FUNC_EQUAL_CASE
++# define TRIO_FUNC_EQUAL_CASE_MAX
++# define TRIO_FUNC_EQUAL_LOCALE
++# define TRIO_FUNC_EQUAL_MAX
++# define TRIO_FUNC_ERROR
++# if !defined(TRIO_PLATFORM_WINCE)
++# define TRIO_FUNC_FORMAT_DATE_MAX
++# endif
++# define TRIO_FUNC_HASH
++# define TRIO_FUNC_INDEX
++# define TRIO_FUNC_INDEX_LAST
++# define TRIO_FUNC_LENGTH
++# define TRIO_FUNC_LENGTH_MAX
++# define TRIO_FUNC_LOWER
++# define TRIO_FUNC_MATCH
++# define TRIO_FUNC_MATCH_CASE
++# define TRIO_FUNC_SPAN_FUNCTION
++# define TRIO_FUNC_SUBSTRING
++# define TRIO_FUNC_SUBSTRING_MAX
++# define TRIO_FUNC_TO_DOUBLE
++# define TRIO_FUNC_TO_FLOAT
++# define TRIO_FUNC_TO_LONG
++# define TRIO_FUNC_TO_LONG_DOUBLE
++# define TRIO_FUNC_TO_LOWER
++# define TRIO_FUNC_TO_UNSIGNED_LONG
++# define TRIO_FUNC_TO_UPPER
++# define TRIO_FUNC_TOKENIZE
++# define TRIO_FUNC_UPPER
++
++# define TRIO_FUNC_STRING_APPEND
++# define TRIO_FUNC_STRING_CONTAINS
++# define TRIO_FUNC_STRING_COPY
++# define TRIO_FUNC_STRING_CREATE
++# define TRIO_FUNC_STRING_DESTROY
++# define TRIO_FUNC_STRING_DUPLICATE
++# define TRIO_FUNC_STRING_EQUAL
++# define TRIO_FUNC_STRING_EQUAL_CASE
++# define TRIO_FUNC_STRING_EQUAL_CASE_MAX
++# define TRIO_FUNC_STRING_EQUAL_MAX
++# define TRIO_FUNC_STRING_EXTRACT
++# if !defined(TRIO_PLATFORM_WINCE)
++# define TRIO_FUNC_STRING_FORMAT_DATE_MAX
++# endif
++# define TRIO_FUNC_STRING_GET
++# define TRIO_FUNC_STRING_INDEX
++# define TRIO_FUNC_STRING_INDEX_LAST
++# define TRIO_FUNC_STRING_LENGTH
++# define TRIO_FUNC_STRING_LOWER
++# define TRIO_FUNC_STRING_MATCH
++# define TRIO_FUNC_STRING_MATCH_CASE
++# define TRIO_FUNC_STRING_SIZE
++# define TRIO_FUNC_STRING_SUBSTRING
++# define TRIO_FUNC_STRING_TERMINATE
++# define TRIO_FUNC_STRING_UPPER
++
++# define TRIO_FUNC_XSTRING_APPEND
++# define TRIO_FUNC_XSTRING_APPEND_CHAR
++# define TRIO_FUNC_XSTRING_APPEND_MAX
++# define TRIO_FUNC_XSTRING_CONTAINS
++# define TRIO_FUNC_XSTRING_COPY
++# define TRIO_FUNC_XSTRING_DUPLICATE
++# define TRIO_FUNC_XSTRING_EQUAL
++# define TRIO_FUNC_XSTRING_EQUAL_CASE
++# define TRIO_FUNC_XSTRING_EQUAL_CASE_MAX
++# define TRIO_FUNC_XSTRING_EQUAL_MAX
++# define TRIO_FUNC_XSTRING_MATCH
++# define TRIO_FUNC_XSTRING_MATCH_CASE
++# define TRIO_FUNC_XSTRING_SET
++# define TRIO_FUNC_XSTRING_SUBSTRING
++
++#endif
++
++
++/*************************************************************************
++ * String functions
++ */
++
++#if defined(TRIO_FUNC_APPEND)
++TRIO_PUBLIC_STRING int
++trio_append
++TRIO_PROTO((char *target, TRIO_CONST char *source));
++#endif
++
++#if defined(TRIO_FUNC_APPEND_MAX)
++TRIO_PUBLIC_STRING int
++trio_append_max
++TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source));
++#endif
++
++#if defined(TRIO_FUNC_CONTAINS)
++TRIO_PUBLIC_STRING int
++trio_contains
++TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring));
++#endif
++
++#if defined(TRIO_FUNC_COPY)
++TRIO_PUBLIC_STRING int
++trio_copy
++TRIO_PROTO((char *target, TRIO_CONST char *source));
++#endif
++
++#if defined(TRIO_FUNC_COPY_MAX)
++TRIO_PUBLIC_STRING int
++trio_copy_max
++TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source));
++#endif
++
++#if defined(TRIO_FUNC_CREATE)
++TRIO_PUBLIC_STRING char *
++trio_create
++TRIO_PROTO((size_t size));
++#endif
++
++#if defined(TRIO_FUNC_DESTROY)
++TRIO_PUBLIC_STRING void
++trio_destroy
++TRIO_PROTO((char *string));
++#endif
++
++#if defined(TRIO_FUNC_DUPLICATE)
++TRIO_PUBLIC_STRING char *
++trio_duplicate
++TRIO_PROTO((TRIO_CONST char *source));
++#endif
++
++#if defined(TRIO_FUNC_DUPLICATE_MAX)
++TRIO_PUBLIC_STRING char *
++trio_duplicate_max
++TRIO_PROTO((TRIO_CONST char *source, size_t max));
++#endif
++
++#if defined(TRIO_FUNC_EQUAL)
++TRIO_PUBLIC_STRING int
++trio_equal
++TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
++#endif
++
++#if defined(TRIO_FUNC_EQUAL_CASE)
++TRIO_PUBLIC_STRING int
++trio_equal_case
++TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
++#endif
++
++#if defined(TRIO_FUNC_EQUAL_CASE_MAX)
++TRIO_PUBLIC_STRING int
++trio_equal_case_max
++TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second));
++#endif
++
++#if defined(TRIO_FUNC_EQUAL_LOCALE)
++TRIO_PUBLIC_STRING int
++trio_equal_locale
++TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
++#endif
++
++#if defined(TRIO_FUNC_EQUAL_MAX)
++TRIO_PUBLIC_STRING int
++trio_equal_max
++TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second));
++#endif
++
++#if defined(TRIO_FUNC_ERROR)
++TRIO_PUBLIC_STRING TRIO_CONST char *
++trio_error
++TRIO_PROTO((int));
++#endif
++
++#if defined(TRIO_FUNC_FORMAT_DATE_MAX)
++TRIO_PUBLIC_STRING size_t
++trio_format_date_max
++TRIO_PROTO((char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime));
++#endif
++
++#if defined(TRIO_FUNC_HASH)
++TRIO_PUBLIC_STRING unsigned long
++trio_hash
++TRIO_PROTO((TRIO_CONST char *string, int type));
++#endif
++
++#if defined(TRIO_FUNC_INDEX)
++TRIO_PUBLIC_STRING char *
++trio_index
++TRIO_PROTO((TRIO_CONST char *string, int character));
++#endif
++
++#if defined(TRIO_FUNC_INDEX_LAST)
++TRIO_PUBLIC_STRING char *
++trio_index_last
++TRIO_PROTO((TRIO_CONST char *string, int character));
++#endif
++
++#if defined(TRIO_FUNC_LENGTH)
++TRIO_PUBLIC_STRING size_t
++trio_length
++TRIO_PROTO((TRIO_CONST char *string));
++#endif
++
++#if defined(TRIO_FUNC_LENGTH_MAX)
++TRIO_PUBLIC_STRING size_t
++trio_length_max
++TRIO_PROTO((TRIO_CONST char *string, size_t max));
++#endif
++
++#if defined(TRIO_FUNC_LOWER)
++TRIO_PUBLIC_STRING int
++trio_lower
++TRIO_PROTO((char *target));
++#endif
++
++#if defined(TRIO_FUNC_MATCH)
++TRIO_PUBLIC_STRING int
++trio_match
++TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern));
++#endif
++
++#if defined(TRIO_FUNC_MATCH_CASE)
++TRIO_PUBLIC_STRING int
++trio_match_case
++TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern));
++#endif
++
++#if defined(TRIO_FUNC_SPAN_FUNCTION)
++TRIO_PUBLIC_STRING size_t
++trio_span_function
++TRIO_PROTO((char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int))));
++#endif
++
++#if defined(TRIO_FUNC_SUBSTRING)
++TRIO_PUBLIC_STRING char *
++trio_substring
++TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring));
++#endif
++
++#if defined(TRIO_FUNC_SUBSTRING_MAX)
++TRIO_PUBLIC_STRING char *
++trio_substring_max
++TRIO_PROTO((TRIO_CONST char *string, size_t max, TRIO_CONST char *substring));
++#endif
++
++#if defined(TRIO_FUNC_TO_DOUBLE)
++TRIO_PUBLIC_STRING double
++trio_to_double
++TRIO_PROTO((TRIO_CONST char *source, char **endp));
++#endif
++
++#if defined(TRIO_FUNC_TO_FLOAT)
++TRIO_PUBLIC_STRING float
++trio_to_float
++TRIO_PROTO((TRIO_CONST char *source, char **endp));
++#endif
++
++#if defined(TRIO_FUNC_TO_LONG)
++TRIO_PUBLIC_STRING long
++trio_to_long
++TRIO_PROTO((TRIO_CONST char *source, char **endp, int base));
++#endif
++
++#if defined(TRIO_FUNC_TO_LOWER)
++TRIO_PUBLIC_STRING int
++trio_to_lower
++TRIO_PROTO((int source));
++#endif
++
++#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
++TRIO_PUBLIC_STRING trio_long_double_t
++trio_to_long_double
++TRIO_PROTO((TRIO_CONST char *source, char **endp));
++#endif
++
++#if defined(TRIO_FUNC_TO_UNSIGNED_LONG)
++TRIO_PUBLIC_STRING unsigned long
++trio_to_unsigned_long
++TRIO_PROTO((TRIO_CONST char *source, char **endp, int base));
++#endif
++
++#if defined(TRIO_FUNC_TO_UPPER)
++TRIO_PUBLIC_STRING int
++trio_to_upper
++TRIO_PROTO((int source));
++#endif
++
++#if defined(TRIO_FUNC_TOKENIZE)
++TRIO_PUBLIC_STRING char *
++trio_tokenize
++TRIO_PROTO((char *string, TRIO_CONST char *delimiters));
++#endif
++
++#if defined(TRIO_FUNC_UPPER)
++TRIO_PUBLIC_STRING int
++trio_upper
++TRIO_PROTO((char *target));
++#endif
++
++/*************************************************************************
++ * Dynamic string functions
++ */
++
++/*
++ * Opaque type for dynamic strings
++ */
++
++typedef struct _trio_string_t trio_string_t;
++
++#if defined(TRIO_FUNC_STRING_APPEND)
++TRIO_PUBLIC_STRING int
++trio_string_append
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_CONTAINS)
++TRIO_PUBLIC_STRING int
++trio_string_contains
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_COPY)
++TRIO_PUBLIC_STRING int
++trio_string_copy
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_CREATE)
++TRIO_PUBLIC_STRING trio_string_t *
++trio_string_create
++TRIO_PROTO((int initial_size));
++#endif
++
++#if defined(TRIO_FUNC_STRING_DESTROY)
++TRIO_PUBLIC_STRING void
++trio_string_destroy
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_STRING_DUPLICATE)
++TRIO_PUBLIC_STRING trio_string_t *
++trio_string_duplicate
++TRIO_PROTO((trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_EQUAL)
++TRIO_PUBLIC_STRING int
++trio_string_equal
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_EQUAL_MAX)
++TRIO_PUBLIC_STRING int
++trio_string_equal_max
++TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second));
++#endif
++
++#if defined(TRIO_FUNC_STRING_EQUAL_CASE)
++TRIO_PUBLIC_STRING int
++trio_string_equal_case
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX)
++TRIO_PUBLIC_STRING int
++trio_string_equal_case_max
++TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_EXTRACT)
++TRIO_PUBLIC_STRING char *
++trio_string_extract
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX)
++TRIO_PUBLIC_STRING size_t
++trio_string_format_date_max
++TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime));
++#endif
++
++#if defined(TRIO_FUNC_STRING_GET)
++TRIO_PUBLIC_STRING char *
++trio_string_get
++TRIO_PROTO((trio_string_t *self, int offset));
++#endif
++
++#if defined(TRIO_FUNC_STRING_INDEX)
++TRIO_PUBLIC_STRING char *
++trio_string_index
++TRIO_PROTO((trio_string_t *self, int character));
++#endif
++
++#if defined(TRIO_FUNC_STRING_INDEX_LAST)
++TRIO_PUBLIC_STRING char *
++trio_string_index_last
++TRIO_PROTO((trio_string_t *self, int character));
++#endif
++
++#if defined(TRIO_FUNC_STRING_LENGTH)
++TRIO_PUBLIC_STRING int
++trio_string_length
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_STRING_LOWER)
++TRIO_PUBLIC_STRING int
++trio_string_lower
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_STRING_MATCH)
++TRIO_PUBLIC_STRING int
++trio_string_match
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_MATCH_CASE)
++TRIO_PUBLIC_STRING int
++trio_string_match_case
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_SIZE)
++TRIO_PUBLIC_STRING int
++trio_string_size
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_STRING_SUBSTRING)
++TRIO_PUBLIC_STRING char *
++trio_string_substring
++TRIO_PROTO((trio_string_t *self, trio_string_t *other));
++#endif
++
++#if defined(TRIO_FUNC_STRING_TERMINATE)
++TRIO_PUBLIC_STRING void
++trio_string_terminate
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_STRING_UPPER)
++TRIO_PUBLIC_STRING int
++trio_string_upper
++TRIO_PROTO((trio_string_t *self));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_APPEND)
++TRIO_PUBLIC_STRING int
++trio_xstring_append
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
++TRIO_PUBLIC_STRING int
++trio_xstring_append_char
++TRIO_PROTO((trio_string_t *self, char character));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_APPEND_MAX)
++TRIO_PUBLIC_STRING int
++trio_xstring_append_max
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other, size_t max));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_CONTAINS)
++TRIO_PUBLIC_STRING int
++trio_xstring_contains
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_COPY)
++TRIO_PUBLIC_STRING int
++trio_xstring_copy
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_DUPLICATE)
++TRIO_PUBLIC_STRING trio_string_t *
++trio_xstring_duplicate
++TRIO_PROTO((TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_EQUAL)
++TRIO_PUBLIC_STRING int
++trio_xstring_equal
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
++TRIO_PUBLIC_STRING int
++trio_xstring_equal_max
++TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
++TRIO_PUBLIC_STRING int
++trio_xstring_equal_case
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX)
++TRIO_PUBLIC_STRING int
++trio_xstring_equal_case_max
++TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_MATCH)
++TRIO_PUBLIC_STRING int
++trio_xstring_match
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_MATCH_CASE)
++TRIO_PUBLIC_STRING int
++trio_xstring_match_case
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_SET)
++TRIO_PUBLIC_STRING void
++trio_xstring_set
++TRIO_PROTO((trio_string_t *self, char *buffer));
++#endif
++
++#if defined(TRIO_FUNC_XSTRING_SUBSTRING)
++TRIO_PUBLIC_STRING char *
++trio_xstring_substring
++TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TRIO_TRIOSTR_H */
diff --git a/source/ap/ghostscript/slack-desc b/source/ap/ghostscript/slack-desc
index 1ac40827..41ffbcbe 100644
--- a/source/ap/ghostscript/slack-desc
+++ b/source/ap/ghostscript/slack-desc
@@ -6,9 +6,9 @@
# customary to leave one space after the ':'.
|-----handy-ruler------------------------------------------------------|
-ghostscript: ghostscript (GPL Ghostscript)
+ghostscript: ghostscript (Postscript and PDF interpreter)
ghostscript:
-ghostscript: GPL Ghostscript is an interpreter of Adobe Systems' PostScript(tm)
+ghostscript: Ghostscript is an interpreter of Adobe Systems' PostScript(tm)
ghostscript: and Portable Document Format (PDF) languages. Ghostscript is an
ghostscript: essential part of the printing subsystem, taking PostScript output
ghostscript: from applications and converting it into an appropriate printer or