[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Jitter] Print contexts, generalised

From: Luca Saiu
Subject: [Jitter] Print contexts, generalised
Date: Sun, 15 Nov 2020 20:09:13 +0100
User-agent: Gnus (Gnus v5.13), GNU Emacs 27.0.50, x86_64-pc-linux-gnu


I am now happy with the state of print contexts, which in their current
shape should be a good mix of expressive power and ease of use.

Before print contexts in the rest of the Jitter codebase and pushing to
the master branch, I would like to hear your comment.

The full code is in the print-context branch.  The jitter-print.h
header, whose comments should explain the entire user API, is attached.

Please tell me what you think.  Regards,

Example use:

  jitter_print_context cx = jitter_print_context_make_fd (1);
  //jitter_print_context cx = jitter_print_context_make_string ();
  jitter_print_char_star (cx, "===========\n");
  jitter_print_char_star (cx, "main is at "); jitter_print_pointer (cx, main);
  jitter_print_char_star (cx, "\n===========\n");
  jitter_print_int (cx, 10, 0); jitter_print_char_star (cx, "\n");

  jitter_print_char_star (cx, "This has a hyperlink: ");
  jitter_print_begin_hyperlink (cx, "http://ageinghacker.net";);
  jitter_print_char_star (cx, "foo");
  jitter_print_end_hyperlink (cx);
  jitter_print_char_star (cx, "\n");

  jitter_print_begin_class (cx, "interesting");
  jitter_print_int (cx, 2, 14);
  jitter_print_end_class (cx);
  jitter_print_char_star (cx, "\n");

  jitter_print_char_star (cx, "Look at this: ");
  jitter_print_begin_class (cx, "beautiful");
  jitter_print_char (cx, 'q');
  //jitter_print_end_class (cx);
  jitter_print_char_star (cx, "\n");

  jitter_print_int (cx, 10, 1234567); jitter_print_char_star (cx, "\n");
  jitter_print_ulong_long (cx, 10, 1234567); jitter_print_char_star (cx, "\n");
  jitter_print_long_long (cx, 10, -123456789012345LL); jitter_print_char_star 
(cx, "\n");

  //char *s = jitter_print_context_get_string (cx, NULL);  printf ("%s", s); 
free (s);

  jitter_print_destroy_context (cx);

Luca Saiu
* My personal web site:  http://ageinghacker.net
* GNU epsilon:           http://www.gnu.org/software/epsilon
* Jitter:                http://ageinghacker.net/projects/jitter

I support everyone's freedom of mocking any opinion or belief, no
matter how deeply held, with open disrespect and the same unrelented
enthusiasm of a toddler who has just learned the word "poo".
/* Jitter: custom contextual printing.

   Copyright (C) 2020 Luca Saiu
   Written by Luca Saiu

   This file is part of Jitter.

   Jitter is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   Jitter is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with Jitter.  If not, see <http://www.gnu.org/licenses/>. */


#include <stdio.h> /* For the definition of FILE. */

#include <jitter/jitter.h>
#include <jitter/jitter-dynamic-buffer.h>


/* Introduction.
 * ************************************************************************** */

/* This header defines an extensible output abstraction called "print context"
   allowing the user to print data along with user-specified "decorations" to an
   underlying channel such as a file descriptor, libc stream or socket, or a
   string in memory.  A "print context kind" describes the behaviour of
   operations, including the way decorations are handled; every print context
   has a print context kind, plus an underlying channel on which to write.  A
   few print context kinds are provided here; other use cases are possible for
   the user to define using this documented API (pretty-printing comes to mind),
   and might be directly provided here in the future.

   "Decorations" may express semantic attributes such as the nesting level of a
   program form or encode cosmetic features such as fonts, colours or
   hyperlinks, for example as implemented by GNU libtextstyle .  Some (or all)
   decorations will have no effect in some context kinds; a user is still free
   to write any decoration to any print context, and to reuse the same code for
   printing to different contexts -- for example on a terminal supporting
   colours and fonts, to a file, into a string in memory.

   The API is meant to be expressive enough for wrapping the functionality of
   GNU libtextstyle for printed colour or font attributes and hyperlinks where
   the library is available, while ignoring such functionality otherwise.
   If the underlying channel abstraction does not support such facilities then
   the additional styling and hyperlinking operations will have no effect, but
   the main input/output operation will still behave as intended.  A
   libtextstyle print context kind is currently *not* predefined here, in order
   not to have libtextstyle as a dependency for libjitter.  Such code might be
   provided in the future, either as an example or possibly as part of a small
   separate library.

   It is possible in general to interleave other input/output operations on the
   underlying channel (for example file seeking, or reading) with print context
   operations, as long as the print context is explicitly flushed before each
   explicit access to the underlying channel.

   The Jitter runtime library prints VM routines and native code disassemblies
   through this facility, generating output to a print context provided by the
   user. */

/* Every function with return type int in this API returns 0 to signify success,
   while any other result signifies failure.
   In case of error these functions may print an unspecified number of
   characters before failing; there is currently no support for error recovery.
   Depending on the definition of the context kind, some of the functions
   defined below may have no effect on the output, and simply return 0.  When
   the context kind in question defines the operation as having any effect, any
   operation is subject to failure.
   Notice that beginning or ending a declaration may well be output operations,
   subject to failure. */

/* A print context is a pointer to a structure which the user should treat as
   opaque, to be defined further down. */
typedef struct jitter_print_context_private *


/* Context initialisation.
 * ************************************************************************** */

/* Functions making new contexts are specific to each context kind, and a few
   can be found below.  Any context returned by a context-making function will
   have initially no class and no hyperlink destination. */


/* Printing with contexts.
 * ************************************************************************** */

/* A formatted output function in the style of printf , while easy to define on
   GNU and a few other platforms thanks to aprintf , is unfortunately
   impractical to define using standard C only and a generic libc, and is
   therefore omitted in the interest of portability.  Of course the user is free
   to employ aprintf , sprintf or any other facility in order to compose a
   string in memory to be then printed by calling jitter_print_char_star . */

/* Print a char object in the given context. */
jitter_print_char (jitter_print_context ct, char x)
  __attribute__ ((nonnull (1)));

/* Print char_no char objects read from memory starting at the address p,
   including any '\0' chars.  This function is intended for binary output. */
jitter_print_chars (jitter_print_context ct, char *p, size_t char_no)
  __attribute__ ((nonnull (1, 2)));

/* Print the pointed string in the given context, up to and not including its
   first '\0' character.  Undefined behaviour is the string is NULL or not
   '\0'-terminated. */
jitter_print_char_star (jitter_print_context ct, char *x)
  __attribute__ ((nonnull (1, 2)));

/* Print a pointer in the given context, using the same syntax as printf's
   "%p" output format. */
jitter_print_pointer (jitter_print_context ct, void *x)
  __attribute__ ((nonnull (1)));

/* Print an integer in the given context, using the given radix.  The minimum
   supported radix is 2, and the maximum is 36.  Undefined behaviour for
   unsupported radixes. */
jitter_print_short (jitter_print_context ct, int radix, short x)
  __attribute__ ((nonnull (1)));
jitter_print_int (jitter_print_context ct, int radix, int x)
  __attribute__ ((nonnull (1)));
jitter_print_long (jitter_print_context ct, int radix, long x)
  __attribute__ ((nonnull (1)));
jitter_print_long_long (jitter_print_context ct, int radix, jitter_long_long x)
  __attribute__ ((nonnull (1)));
jitter_print_ushort (jitter_print_context ct, int radix, unsigned short x)
  __attribute__ ((nonnull (1)));
jitter_print_uint (jitter_print_context ct, int radix, unsigned int x)
  __attribute__ ((nonnull (1)));
jitter_print_ulong (jitter_print_context ct, int radix, unsigned long x)
  __attribute__ ((nonnull (1)));
jitter_print_ulong_long (jitter_print_context ct, int radix,
                         jitter_ulong_long x)
  __attribute__ ((nonnull (1)));

/* Print an floating-point number in the given context.  Right now only the
   equivalent of printf's "%f" output format is currently supported; for
   printing in other formats the user will have to resort to sprintf or
   custom alternatives. */
jitter_print_float (jitter_print_context ct, float x)
  __attribute__ ((nonnull (1)));
jitter_print_double (jitter_print_context ct, double x)
  __attribute__ ((nonnull (1)));
jitter_print_long_double (jitter_print_context ct, long double x)
  __attribute__ ((nonnull (1)));
#endif // #if defined (JITTER_HAVE_LONG_DOUBLE)

/* Convenience aliases for printing integer or floating-point data having Jitter
   types.  Each of these definition is just a macro resolving to one of the
   previous integer-printing function names, according to the configuration. */
  /* This will not happen on GNU, but one check costs almost nothing. */
# define  jitter_print_jitter_int jitter_print_short
# define  jitter_print_jitter_uint jitter_print_ushort
# define  jitter_print_jitter_int jitter_print_int
# define  jitter_print_jitter_uint jitter_print_uint
# define  jitter_print_jitter_int jitter_print_long
# define  jitter_print_jitter_uint jitter_print_ulong
#elif defined (JITTER_HAVE_LONG_LONG_INT) \
# define  jitter_print_jitter_int jitter_print_long_long
# define  jitter_print_jitter_uint jitter_print_ulong_long
# error "this should never happen: sizeof (void *) has an unexpected value"
# define  jitter_print_jitter_float jitter_print_float
# define  jitter_print_jitter_float jitter_print_double
#elif  defined (JITTER_HAVE_LONG_DOUBLE) \
# define  jitter_print_jitter_float jitter_print_long_double
# error "this should never happen: no floating-point type is defined with the"
# error "same size as void *."


/* Decorations.
 * ************************************************************************** */

/* Each decoration has a name, a type and a value.  Decoration may be nested
   inside each other, and have to be "begun" or "ended" in a strictly LIFO
   order.  The topmost decoration with a given name is the "active" one.
   Decoration values are dynamically typed. */

/* The name of a decoration is a string.  User functions may pass temporary
   strings to this API, for example always reusing the same memory; decoration
   names (and string values: see below) are copied into internally managed
   memory as needed. */
typedef char *

/* An indicator of which supported type a decoration currently has. */
enum jitter_print_decoration_type
    /* The decoration value is integer. */

    /* The decoration value is floating-point. */

    /* The decoration value is a text string (copied into local memory) by
       the print context subsystem. */

    /* The decoration value is a pointer to arbitrary user memory. */

/* The value of a particular decoration.  Each field is associated to one
   value of enum jitter_print_decoration_type , defined above. */
union jitter_print_decoration_value
  /* A signed integer value. */
  jitter_int integer;

  /* A floating-point value. */
  double floating_point;

  /* A '\0'-terminated string.  Any value given by the user is copied
     into locally managed memory, and the user should not attempt to
     free the copy pointed by this field. */
  char *string;

  /* A pointer to arbitrary data supplied by the user.  Differently
     from the string field this pointer refers user data, which is
     the user's responsibility to keep alive until the decoration
     remains in use. */
  void *pointer;


/* Decoration beginning.
 * ************************************************************************** */

/* Begin an integer-type decoration in the pointed context, having
   the given name and the given value. */
jitter_print_begin_decoration_integer (jitter_print_context ct,
                                       jitter_print_decoration_name name,
                                       jitter_int value)
  __attribute__ ((nonnull (1, 2)));

/* Begin an floating-point-type decoration in the pointed context, having the
   given name and the given value. */
jitter_print_begin_decoration_floating_point (jitter_print_context ct,
                                              jitter_print_decoration_name name,
                                              double value)
  __attribute__ ((nonnull (1, 2)));

/* Begin an string-type decoration in the pointed context, having the given name
   and the given value.  The value is copied into internally managed memory, and
   it is the user's responsibility to dispose of her original copy. */
jitter_print_begin_decoration_string (jitter_print_context ct,
                                      jitter_print_decoration_name name,
                                      char *value)
  __attribute__ ((nonnull (1, 2, 3)));

/* Begin an pointer-type decoration in the pointed context, having the given
   name and the given value.  This function, differently from
   jitter_print_begin_decoration_string , never derefenreces the value pointer
   but simply copies it; it is the user's responsibility to keep the pointed
   data alive until the decoration is ended by a matching
   jitter_print_end_decoration call. */
jitter_print_begin_decoration_pointer (jitter_print_context ct,
                                       jitter_print_decoration_name name,
                                       void *value)
  __attribute__ ((nonnull (1, 2)));


/* Decoration ending.
 * ************************************************************************** */

/* End the last started decoration, which must have the given name.  Undefined
   behaviour if no matching decoration was began, or if beginning and end
   of multiple decorations do not follow a LIFO order. */
jitter_print_end_decoration (jitter_print_context ct,
                             jitter_print_decoration_name name)
  __attribute__ ((nonnull (1, 2)));


/* Decoration introspection.
 * ************************************************************************** */

/* Check the currently active most recent declaration in the given context.  If
   any exists then set the memory pointed from name, type and value to pointers
   to relevant decoration attributes in internal memory, which will remain valid
   as long as no further declaration is begun or ended.  Set the memory pointed
   by the three pointers to NULL otherwise. */
jitter_print_get_decoration (jitter_print_context ct,
                             jitter_print_decoration_name *name_p,
                             enum jitter_print_decoration_type **type_pp,
                             union jitter_print_decoration_value **value_pp)
  __attribute__ ((nonnull (1, 2, 3, 4)));

/* Like jitter_print_get_decoration , but only consider decorations with the
   given name.  There is no user pointer name to set in this case.*/
jitter_print_get_decoration_named (jitter_print_context ct,
                                   jitter_print_decoration_name name,
                                   enum jitter_print_decoration_type **type_pp,
                                   union jitter_print_decoration_value
  __attribute__ ((nonnull (1, 2, 3, 4)));


/* Convenience functions for known decorations: classes.
 * ************************************************************************** */

/* "Classes" describe the cosmetic look of text output.  Libtextstyle uses
   string values for classes. */

/* The name of class decorations. */

/* The name of a class, as used by libtextstyle.  Class names are not copied
   into print context data structures, and must have a lifetime at least as
   long as their use by print contexts: in other words, if class names are
   allocated in memory, such memory must not be overwritten until after the
   last use of the class is ended by jitter_print_end_class call. */
typedef char *

/* Switch to using the given class for the forthcoming output, until the
   next call to jitter_print_begin_class or to jitter_print_end_class.  Class
   uses nest in a LIFO style: after ending a class use the previously "began"
   class, if any, comes back into effect. */
jitter_print_begin_class (jitter_print_context ct, jitter_print_class c)
  __attribute__ ((nonnull (1, 2)));

/* Stop using the last class given in jitter_print_begin_class, and switch back
   to the class defined by the previoys jitter_print_begin_class call (or no
   class, if the outermost call was matched) for the following.  Undefined
   behaviour if there is no previous jitter_print_begin_class call to match. */
jitter_print_end_class (jitter_print_context ct)
  __attribute__ ((nonnull (1)));

/* If any class is currently active in the pointed context return its value,
   using internal memory managed internally by the print context system; return
   NULL otherwise.  Undefined behaviour if the current class is set to a
   non-string value. */
char *
jitter_print_get_class (jitter_print_context ct)
  __attribute__ ((returns_nonnull,
                  nonnull (1)));


/* Convenience functions for known decorations: hyperlinks.
 * ************************************************************************** */

/* In Libtextstyle a "hyperlink" is a string formatted like a URL associated to
   output text; some recent terminal emulator actually render URLs as
   interactive clickable links.
   Libtextstyle hyperlinks are not nestable.  This non-nestability in Jitter
   print contexts, along with the value type, is only enforced when using the
   convenience functions in this section: normally decorations are dynamically
   typed, and can nest. */

/* A hyperlink destination, as used by libtextstyle.  A hyperlink does not share
   the strict lifetime requirement of class names, and the user is allowed to
   free or overwrite its memory immediately after the
   jitter_print_begin_hyperlink call using it. */
typedef char *

/* Mark the current output as the beginning of a hyperlink to the given URL,
   which must be a valid '\0'-terminated string.
   Undefined behaviour if a hyperlink is already set at the time of the call. */
jitter_print_begin_hyperlink (jitter_print_context ct, jitter_print_url url)
  __attribute__ ((nonnull (1, 2)));

/* Mark the current output as the end of the hyperlink which was started before
   with jitter_print_begin_hyperlink.  Undefined behaviour if there is no
   previous jitter_print_begin_hyperlink call to match.  At the end of the
   call the context has no longer any current hyperlink. */
jitter_print_end_hyperlink (jitter_print_context ct)
  __attribute__ ((nonnull (1)));

/* If any hyperlink is currently active in the pointed context return its value,
   using internal memory managed internally by the print context system; return
   NULL otherwise.  Undefined behaviour if the current hyperlink is set to a
   non-string value. */
char *
jitter_print_get_hyperlink (jitter_print_context ct)
  __attribute__ ((returns_nonnull,
                  nonnull (1)));


/* Other functionality available in every context.
 * ************************************************************************** */

/* Functions making new contexts are specific to each context kind, and
   are not defined here.  Any context returned by a context-making function
   will have initially no class and no hyperlink destination. */

/* Flush the output.  Return 0 on success, a non-zero value on error. */
jitter_print_flush (jitter_print_context ct)
  __attribute__ ((nonnull (1)));

/* End any still open decoration, flush the output then destroy the given
   context.  Undefined behaviour if the context is not valid or has already
   been destroyed.  Return 0 if all of the close and flush operations succeed,
   a non-zero result otherwise; destroy the data structure in either case.
   Notice that, for every reasonable print context type, destroying the
   context should *not* close the underlying channel: it may be useful
   for the user to perform additional input/output even after the print
   context has been finalised. */
jitter_print_destroy_context (jitter_print_context ct)
  __attribute__ ((nonnull (1)));


/* Predefined print context kinds: FILE * and file descriptor.
 * ************************************************************************** */

/* Return a fresh print context printing to the pointed libc buffered stream,
   ignoring decorations. */
jitter_print_context_make_file_star (FILE *f)
  __attribute__ ((warn_unused_result, returns_nonnull,
                  nonnull (1)));

/* Return a fresh print context printing to the given libc unbuffered file
   descriptor, ignoring flushing and decorations. */
jitter_print_context_make_fd (int fd)
  __attribute__ ((warn_unused_result, returns_nonnull));


/* Predefined print context kinds: string.
 * ************************************************************************** */

/* Return a fresh print context "printing" into a string in memory which
   automatically grows to fit the output.  Such a context ignores flushing
   and decorations. */
jitter_print_context_make_string (void)
  __attribute__ ((warn_unused_result, returns_nonnull));

/* Given a print context made by jitter_print_context_make_string, return
   a malloc-allocated copy of its current string, also including any '\0'
   chars previously printed by the user, terminated by a further '\0' char.
   It is the user's responsibility to eventually dispose of the copied string
   by calling free .
   If the supplied length pointer is not NULL write the length of the printed
   string (not counting the one added trailing '\0') into its pointed memory.

   Notice that the returned string will contain '\0' chars *before* the
   trailing one which is appended by this function, if any were printed as
   single chars (printing using char_star functions does not copy any '\0'
   char to the output).  This feature is intended for binary formats, in
   which case the user should pass a non-NULL value for length_p . */
char *
jitter_print_context_get_string (jitter_print_context c, size_t *length_p)
  __attribute__ ((warn_unused_result, returns_nonnull,
                  nonnull (1)));


/* Defining new print context kinds.
 * ************************************************************************** */

/* The user may define a custom context kind by providing functions associated
   to fundamental operations and storing pointers to them in memory as fields
   of a structure of type struct jitter_print_context_kind_struct.
   Each print context contains a pointer to user-provided data, which the
   functions within the struct jitter_print_context_kind_struct object may
   Since more fields within struct jitter_print_context_kind_struct may be
   added in the future the user is strongly advised to dynamically initialise
   such structures using jitter_print_context_kind_make_trivial , and then only
   set the fields associated to implemented operations. */
struct jitter_print_context_kind_struct;
typedef struct jitter_print_context_kind_struct *

/* A pointer to any data needed for the context.  The user is free to cast this
   pointer to any other kind of applicable pointer; an example is the file_star
   context defined in jitter-print.c , whose functions cast
   jitter_print_context_data to FILE * in order to keep track of the underlying
   libc stream. */
typedef void *

/* Return a new context kind, with the still undefined function pointers all set
   to NULL.  The caller is supposed to set the fields she is interested in, and
   leave the rest as NULL so that the undefined operations do nothing. */
jitter_print_context_kind_make_trivial (void)
  __attribute__ ((warn_unused_result, returns_nonnull));

/* Destroy the pointed context kind.  This is mostly provided for symmetry's
   sake, and to silence valgrind: in practice context kinds will be allocated
   globally and there is no real need to destroy them at finalisation.  After
   calling this it becomes invalid to use any context of the destroyed kind. */
jitter_print_context_kind_destroy (jitter_print_context_kind k)
  __attribute__ ((nonnull (1)));

/* It is the user's responsibility to provide a convenient function for making a
   context of her new custom kind.  The context kinds defined in the section
   above may serve as examples: see the definition of jitter_print_initialize,
   with the caveat that the user should use
   jitter_print_context_kind_make_trivial rather than
   jitter_print_context_kind_initialize_trivial .

   Every context-making function should use this function and return its result;
   the final user working on context, however, does not need to ever see this,
   and should instead allocate each context with a function appropriate for its
   kind such as jitter_print_context_make_file_star for file_star contexts. */
jitter_print_context_make (jitter_print_context_kind k,
                           jitter_print_context_data d)
  __attribute__ ((warn_unused_result, returns_nonnull,
                  nonnull (1, 2)));

/* The fields within the struct below, along with its total size, may change in
   future versions and the user should treat the structure as containing unknown
   fields, by first allocating an instance through
   jitter_print_context_kind_make_trivial and then setting its known non-NULL
   fields. */
struct jitter_print_context_kind_struct
  /* All the functions here return 0 on success and a non-zero result on

     If a field is NULL within a specific context kind then the corresponding
     operation does nothing and always returns 0, with one exception: either one
     of print_char and print_chars, or both, may be non-NULL.  If only one is
     defined then the missing operation is emulated via the other as described
     below. */

  /* Print the given character to the pointed underlying channel.  If the
     underlying primitive is interrupted by a recoverable error (for example
     of the kind where errno is set to EAGAIN) retry until success.
     If this field is NULL but print_chars is not then the single character
     is printed via print_chars , reading one char's worth of memory from
     a temporary copy. */
  int (* print_char) (jitter_print_context_data d, char c);

  /* Print char_no char objects read from memory starting at the address p
     and including any '\0' characters found in the interval to the underlying
     channel.  If the underlying primitive is interrupted by a recoverable
     error (of the  kind where errno is set to EAGAIN) retry until success.
     If this field is NULL but print_char is not then strings are printed in a
     loop by multiple calls to the function pointed by the print_char field. */
  int (* print_chars) (jitter_print_context_data d, char *p, size_t char_no);

  /* Begin a decoration with the name, value type and value, in the pointed
     underlying channel.  The pointers received here point to local copies, in
     the cases copy are made (decoration name and string value). */
  int (* begin_decoration) (jitter_print_context_data d,
                            const jitter_print_decoration_name name,
                            enum jitter_print_decoration_type type,
                            const union jitter_print_decoration_value *value);

  /* End a decoration with the given name, value type and value, in the pointed
     underlying channel.  This is always called on the last begun decoration
     in LIFO style.  Locally copied buffers (decoration name and string value)
     are freed automatically, out of this user function. */
  int (* end_decoration) (jitter_print_context_data d,
                          const jitter_print_decoration_name name,
                          enum jitter_print_decoration_type type,
                          const union jitter_print_decoration_value *value);

  /* Flush the pointed underlying channel. */
  int (* flush) (jitter_print_context_data d);

  /* Destroy the pointed print context data, without closing the underlying
     channel.  No flushing is necessary here; the function pointed by the
     flush field, if any, will be called at destruction time when appropriate. 
  int (* destroy_without_flushing) (jitter_print_context_data d);

/* What a context consists of in memory.  This type should be treated as
   opaque by the final user, and even by users defining new context kinds. */
struct jitter_print_context_private
  /* The stack of currently active decorations, the most current on the top.
     The stack is empty at initialisation.  Items are all of type
     struct jitter_print_decoration. */
  struct jitter_dynamic_buffer stack;

  /* The context kind.  This is a pointer. */
  jitter_print_context_kind kind;

  /* The context data, as appropriate for its kind.  This is a pointer. */
  jitter_print_context_data data;


/* Global initialisation.
 * ************************************************************************** */

/* This function, which makes the predefined context kinds available, is
   automatically called the first time any VM is initialised.  There is no
   matching finalisation.  Not for the user. */
jitter_print_initialize (void);

#endif // #ifndef JITTER_PRINT_H_

Attachment: signature.asc
Description: PGP signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]