mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-06 11:50:51 -08:00
198 lines
8.6 KiB
ReStructuredText
198 lines
8.6 KiB
ReStructuredText
.. mode: -*- rst -*-
|
|
|
|
The WriteF function
|
|
===================
|
|
|
|
:Tag: design.mps.writef
|
|
:Author: Richard Brooksby
|
|
:Date: 1996-10-18
|
|
:Status: complete design
|
|
:Revision: $Id$
|
|
:Copyright: See `Copyright and License`_.
|
|
:Index terms: pair: WriteF function; design
|
|
|
|
|
|
Introduction
|
|
------------
|
|
|
|
_`.intro`: This document describes the ``WriteF()`` function, which
|
|
allows formatted output in a manner similar to ``printf()`` from the
|
|
Standard C library, but allows the Memory Pool Manager (MPM) to
|
|
operate in a freestanding environment (see design.mps.exec-env_).
|
|
|
|
.. _design.mps.exec-env: exec-env
|
|
|
|
_`.background`: The documents design.mps.exec-env_ and design.mps.lib_
|
|
describe the design of the library interface and the reason that it
|
|
exists.
|
|
|
|
.. _design.mps.lib: lib
|
|
|
|
|
|
Design
|
|
------
|
|
|
|
_`.no-printf`: There is no dependency on ``printf()``. The MPM only
|
|
depends on ``mps_io_fputc()`` and ``mps_io_fputs()``, via the library
|
|
interface (design.mps.lib_), part of the *plinth*. This makes it much
|
|
easier to deploy the MPS in a freestanding environment. This is
|
|
achieved by implementing our own output routines.
|
|
|
|
_`.writef`: Our output requirements are few, so the code is short. The
|
|
only output function which should be used in the rest of the MPM is
|
|
``WriteF()``.
|
|
|
|
``Res WriteF(mps_lib_FILE *stream, Count depth, ...)``
|
|
|
|
If ``depth`` is greater than zero, then the first output character,
|
|
and each output character after a newline in a format string, is
|
|
preceded by ``depth`` spaces.
|
|
|
|
``WriteF()`` expects a format string followed by zero or more items to
|
|
insert into the output, followed by another format string, more items,
|
|
and so on, and finally a ``NULL`` format string. For example::
|
|
|
|
res = WriteF(stream, depth,
|
|
"Hello: $A\n", (WriteFA)address,
|
|
"Spong: $U ($S)\n", (WriteFU)number, (WriteFS)string,
|
|
NULL);
|
|
if (res != ResOK)
|
|
return res;
|
|
|
|
This makes ``Describe()`` methods much easier to write. For example, ``BufferDescribe()`` contains the following code::
|
|
|
|
res = WriteF(stream, depth,
|
|
"Buffer $P ($U) {\n",
|
|
(WriteFP)buffer, (WriteFU)buffer->serial,
|
|
" class $P (\"$S\")\n",
|
|
(WriteFP)buffer->class, (WriteFS)buffer->class->name,
|
|
" Arena $P\n", (WriteFP)buffer->arena,
|
|
" Pool $P\n", (WriteFP)buffer->pool,
|
|
" ", buffer->isMutator ? "Mutator" : "Internal", " Buffer\n",
|
|
" mode $C$C$C$C (TRANSITION, LOGGED, FLIPPED, ATTACHED)\n",
|
|
(WriteFC)((buffer->mode & BufferModeTRANSITION) ? 't' : '_'),
|
|
(WriteFC)((buffer->mode & BufferModeLOGGED) ? 'l' : '_'),
|
|
(WriteFC)((buffer->mode & BufferModeFLIPPED) ? 'f' : '_'),
|
|
(WriteFC)((buffer->mode & BufferModeATTACHED) ? 'a' : '_'),
|
|
" fillSize $UKb\n", (WriteFU)(buffer->fillSize / 1024),
|
|
" emptySize $UKb\n", (WriteFU)(buffer->emptySize / 1024),
|
|
" alignment $W\n", (WriteFW)buffer->alignment,
|
|
" base $A\n", (WriteFA)buffer->base,
|
|
" initAtFlip $A\n", (WriteFA)buffer->initAtFlip,
|
|
" init $A\n", (WriteFA)buffer->ap_s.init,
|
|
" alloc $A\n", (WriteFA)buffer->ap_s.alloc,
|
|
" limit $A\n", (WriteFA)buffer->ap_s.limit,
|
|
" poolLimit $A\n", (WriteFA)buffer->poolLimit,
|
|
" alignment $W\n", (WriteFW)buffer->alignment,
|
|
" rampCount $U\n", (WriteFU)buffer->rampCount,
|
|
NULL);
|
|
if (res != ResOK)
|
|
return res;
|
|
|
|
_`.types`: For each format ``$X`` that ``WriteF()`` supports, there is
|
|
a type ``WriteFX`` defined in mpmtypes.h, which is the promoted
|
|
version of that type. These types are provided both to ensure
|
|
promotion and to avoid any confusion about what type should be used in
|
|
a cast. It is easy to check the casts against the formats to ensure
|
|
that they correspond.
|
|
|
|
_`.types.cast`: Every argument to ``WriteF()`` must be cast, because
|
|
in variable-length argument lists the "default argument promotion"
|
|
rules apply and this could cause an argument to be read incorrectly on
|
|
some platforms: for example on a 64-bit platform the ``$W`` format,
|
|
which expects a 64-bit argument, is incompatible with a 32-bit
|
|
``unsigned`` argument, which will not be promoted to 64 bits by the
|
|
default argument promotion rules. (Note that most of these casts are
|
|
unnecessary, but requiring them all makes it easy to check that the
|
|
necessary ones are all there.)
|
|
|
|
_`.types.future`: It is possibly that this type set or similar may be
|
|
used in future in some generalisation of varargs in the MPS.
|
|
|
|
_`.formats`: The formats supported are as follows.
|
|
|
|
======= =========== ================== =======================================
|
|
Code Name Type Example rendering
|
|
======= =========== ================== =======================================
|
|
``$A`` address ``Addr`` ``000000019EF60010``
|
|
``$P`` pointer ``void *`` ``000000019EF60100``
|
|
``$F`` function ``void *(*)()`` ``0001D69E01000000`` (see `.function`_)
|
|
``$S`` string ``char *`` ``hello``
|
|
``$C`` character ``char`` ``x``
|
|
``$W`` word ``ULongest`` ``0000000000109AE0``
|
|
``$U`` decimal ``ULongest`` ``42``
|
|
``$B`` binary ``ULongest`` ``00000000000000001011011110010001``
|
|
``$$`` dollar -- ``$``
|
|
======= =========== ================== =======================================
|
|
|
|
Note that ``WriteFC`` is an ``int``, because that is the default
|
|
promotion of a ``char`` (see `.types`_).
|
|
|
|
_`.snazzy`: We should resist the temptation to make ``WriteF()`` an
|
|
incredible snazzy output engine. We only need it for ``Describe()``
|
|
methods. At the moment it's a simple bit of code -- let's keep it that
|
|
way.
|
|
|
|
_`.function`: The ``F`` code is used for function pointers. ISO C
|
|
forbids casting function pointers to other types, so the bytes of
|
|
their representation are written sequentially, and may have a
|
|
different endianness to other pointers. Could be smarter, or even look
|
|
up function names, but see `.snazzy`_.
|
|
|
|
|
|
Document History
|
|
----------------
|
|
|
|
- 1996-10-18 RB_ Incomplete design.
|
|
|
|
- 2002-06-07 RB_ Converted from MMInfo database design document.
|
|
|
|
- 2013-05-22 GDR_ Converted to reStructuredText.
|
|
|
|
- 2014-04-17 GDR_ ``WriteF()`` now takes a ``depth`` parameter.
|
|
|
|
.. _RB: http://www.ravenbrook.com/consultants/rb/
|
|
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
|
|
|
|
|
Copyright and License
|
|
---------------------
|
|
|
|
Copyright © 2013-2015 Ravenbrook Limited. All rights reserved.
|
|
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
|
Ravenbrook for commercial licensing options.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
#. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
#. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
#. Redistributions in any form must be accompanied by information on how
|
|
to obtain complete source code for this software and any
|
|
accompanying software that uses this software. The source code must
|
|
either be included in the distribution or be available for no more than
|
|
the cost of distribution plus a nominal fee, and must be freely
|
|
redistributable under reasonable conditions. For an executable file,
|
|
complete source code means the source code for all modules it contains.
|
|
It does not include source code for modules or files that typically
|
|
accompany the major components of the operating system on which the
|
|
executable file runs.
|
|
|
|
**This software is provided by the copyright holders and contributors
|
|
"as is" and any express or implied warranties, including, but not
|
|
limited to, the implied warranties of merchantability, fitness for a
|
|
particular purpose, or non-infringement, are disclaimed. In no event
|
|
shall the copyright holders and contributors be liable for any direct,
|
|
indirect, incidental, special, exemplary, or consequential damages
|
|
(including, but not limited to, procurement of substitute goods or
|
|
services; loss of use, data, or profits; or business interruption)
|
|
however caused and on any theory of liability, whether in contract,
|
|
strict liability, or tort (including negligence or otherwise) arising in
|
|
any way out of the use of this software, even if advised of the
|
|
possibility of such damage.**
|