Première version

This commit is contained in:
smas 2000-07-28 15:39:02 +00:00
commit 35becf27e2
4 changed files with 913 additions and 0 deletions

218
doc/libver.3 Normal file
View File

@ -0,0 +1,218 @@
'\" t
'." @(#)LIBVER.3 2.0 00/06/30 SMA;
.TH LIBVER 3 "01 Apr 2000"
.SH NOM
LIBVER (utilitaires divers)
.SH SYNOPSIS
.LP
.B cc [flag ...] file ... -lver [library ...]
.LP
.BI "#include <ver.h>"
.LP
.BI "VER_INFO_EXPORT( " Object_Name ", " Version ", " CVS_Tag ", " Src_File ", " Author " )"
.LP
.BI "VERT_Status VER_Object_Print ( FILE * " Stream ", VERT_Print_Mode " Print_Mode " );"
.LP
.BI "VERT_Status VER_Info_Next_Get(VERT_Info_Container ** " Container ", VERT_Object * " Object ", VERT_Index * " Index " );"
.LP
.BI "VERT_Status VER_Info_Print(FILE * " Out ", VERT_Info_Container * " Container ", VERT_Print_Mode " Print_Mode " );"
.LP
.SH DESCRIPTION
.LP
La librairie
.B LIBVER
permet a un objet (programme ou librairie) de partager ses informations concernant :
.LP
.RS 3
- son nom
.LP
- sa version
.LP
- son tag CVS
.LP
- le nom de son fichier source
.LP
- l'auteur de son fichier source
.RS -3¨
.LP
La librairie fournit aussi des fonctions d'acces aux informations partagees
par tous les objets (statiques (.o) ou partages (.so)) dont depend l'objet courant.
.LP
.SH "FONCTIONS & MACRO"
.LP
.BI "VER_INFO_EXPORT(" Object_Name ", " Version ", " CVS_Tag ", " Src_File ", " Author " )"
.RS 3
.LP
Cette macro est interpretee par le preprocesseur C.
Elle permet de generer une fonction C qui exporte les informations de l'objet courant via les API internes de la librairie.
.LP
Cette macro doit recevoir les parametres suivants :
.LP
.RS 3
- (In)
.I Object_Name
: le nom de l'objet (sans guillemets car utilise pour generer le nom de la fonction)
.LP
- (In)
.I Version
: la version de l'objet (entre guillemets)
.LP
- (In)
.I CVS_Tag
: le tag CVS (entre guillemets)
.LP
- (In)
.I Src_File
: le nom du fichier source (entre guillemets)
.LP
- (In)
.I Author
: le nom de l'auteur du fichier (entre guillemets)
.RS -3
.LP
.I NB
: la macro attend des parametres separes par des virgules.
.LP
Chaque fichier voulant exporter ses informations doit definir une instruction ressemblant a ce qui suit :
.LP
.RS 3
VER_INFO_EXPORT(terminator, "1.0", "tag-schwartzy-1_0_0-1", "terminator.c", "Sarah Connors")
.RS -3
.LP
L'instruction pourra se baser sur des mots-cle du preprocesseur ou sur ceux de CVS :
.LP
.RS 3
VER_INFO_EXPORT(monobjet, "$ Revision $", "$ Name $", __FILE__, "$ Author $")
.RS -3
.LP
.RS -3
.LP
.BI "VERT_Status VER_Object_Print ( FILE * " Out ", VERT_Print_Mode " Print_Mode " );"
.RS 3
.LP
Cette fonction permet d'afficher les informations concernant l'objet appelant:
.LP
Elle doit recevoir les parametres suivants :
.LP
.RS 3
- (In)
.I Out
: le flux de sortie de l'affichage
.LP
- (In)
.I Print_Mode
: le mode d'affichage :
.LP
.RS 3
-
.B VERD_MINIMAL
: affichage du nom, de la version et du tag CVS de l'objet appelant.
.LP
-
.B VERD_VERBOSE
: affichage sous forme de tableau de toutes les informations de l'objet appelant et de tous les objets dont il depend.
.LP
.RS -3
.RS -3
.RS -3
.LP
.BI "VERT_Status VER_Info_Next_Get(VERT_Info_Container ** " Container ", VERT_Object * " Object ", VERT_Index * " Index " );"
.RS 3
.LP
Cette fonction permet de recuperer un conteneur d'informations.
.LP
Elle doit recevoir les parametres suivants :
.LP
.RS 3
- (Out)
.I Container
: l'adresse d'un pointeur sur le conteneur a recuperer
.LP
- (In Out)
.I Object
: un pointeur sur l'objet a partir duquel on recherche le conteneur
.LP
- (In Out)
.I Index
: un pointeur sur l'index a partir duquel on recherche le conteneur
.LP
.RS -3
.LP
.I NB
: un objet peut avoir plusieurs conteneurs s'il a ete construit a partir de plusieurs objets statiques (.o).
.LP
L'index permet de distinguer les differents conteneurs d'un meme objet. Il commence a 0.
.LP
Le premier objet correspond a l'objet appelant (deuxieme parametre valorise a NULL).
.LP
Les objets suivants sont des objets partages (.so) dont depend l'objet appelant.
.LP
Si un conteneur a pu etre trouve, l'objet et l'index correspondant a ce conteneur sont alors mis a jour.
.LP
.RS -3
.BI "VERT_Status VER_Info_Print(FILE * " Out ", VERT_Info_Container * " Container ", VERT_Print_Mode " Print_Mode " );"
.RS 3
.LP
Cette fonction permet d'afficher les informations d'un conteneur :
.LP
Elle doit recevoir les parametres suivants :
.LP
.RS 3
- (In)
.I Out
: le flux de sortie de l'affichage
.LP
- (In)
.I Container
: un pointeur sur le conteneur a afficher
.LP
- (In)
.I Print_Mode
: le mode d'affichage :
.LP
.RS 3
-
.B VERD_MINIMAL
: affichage du nom, de la version et du tag CVS du conteneur
.LP
-
.B VERD_VERBOSE
: affichage de toutes les informations du conteneur
.LP
.RS -3
.RS -3
.RS -3
.SH CODES RETOUR
.LP
Toutes les fonctions constituant l'API de la librairie LIBVER retournent un code de type
.B VERT_Status
:
.LP
.RS 3
-
.B VERS_OK
: la fonction s'est correctement executee et a produit un resultat
.LP
-
.B VERS_KO
: la fonction s'est correctement executee mais n'a pas produit de resultat
.LP
-
.B VERS_ERRAPI
: la fonction a ete appelee avec des arguments de valeur incorrecte
.LP
-
.B VERS_ERRMEM
: la fonction ne s'est pas correctement executee pour un probleme d'allocation memoire
.RS -3
.LP
La macro
.B VER_ERROR(rc)
permet de tester si un code retour correspond a une erreur.
.LP
En cas d'erreur, la variable VER_Error_Msg contient un message du type :
.LP
.RS 3
Error <Nom fonction> : <message d'erreur>
.RS -3
.LP

BIN
doc/libver.doc Normal file

Binary file not shown.

561
lib/libver.c Normal file
View File

@ -0,0 +1,561 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef LINUX
#else
#include <libelf.h>
#endif
#include <dlfcn.h>
#include <ver.h>
VER_INFO_EXPORT (libver, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $")
void VER_Error_Print (void);
void * VER_Symbol_Next_Find (const char *, VERT_Object *, VERT_Index *);
extern char * strdup (const char *);
#ifdef LINUX
extern struct r_scope_elem *_dl_global_scope [2];
#endif
/*------------------------------------------------------------------------------*/
/* Création d'un conteneur d'informations */
/*------------------------------------------------------------------------------*/
/* (O) Contanier : adresse d'un pointeur sur le container à créer */
/* (I) Object_Name : nom de l'objet */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Init (VERT_Info_Container ** Container, const char * Object_Name)
{
*Container = (VERT_Info_Container *) malloc (sizeof (VERT_Info_Container));
if (*Container == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_Init : unable to allocate memory for a container");
VER_Error_Print ();
return VERS_ERRMEM;
}
if (Object_Name != NULL)
(*Container)->name = strdup (Object_Name);
else
(*Container)->name = NULL;
(*Container)->version = NULL;
(*Container)->tag = NULL;
(*Container)->srcfile = NULL;
(*Container)->author = NULL;
return VERS_OK;
}
/*------------------------------------------------------------------------------*/
/* Mise à jour d'une information */
/*------------------------------------------------------------------------------*/
/* (I) Container : pointeur sur le conteneur d'informations */
/* (I) Info_Type : type d'information à mettre à jour */
/* (I) Value : valeur de l'information */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Set (VERT_Info_Container * Container, VERT_Info Info_Type, const char * Value)
{
char * tmp;
if (Container == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_Set : the container is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
if (Value == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_Set : the value is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
switch ((int)Info_Type)
{
case VERD_VERSION:
if (!strncmp (Value, "$Revision: ", 11))
{
char * ptr;
tmp = strdup (Value + 11);
if ((ptr = strchr (tmp, ' ')) != NULL) *ptr = '\0';
}
else
tmp = strdup (Value);
if (!tmp) return VERS_ERRMEM;
if (Container->version != NULL) free (Container->version);
Container->version = tmp;
break;
case VERD_TAG:
if (!strncmp (Value, "$Name: ", 7))
{
char * ptr;
tmp = strdup (Value + 7);
if ((ptr = strchr (tmp, ' ')) != NULL) *ptr = '\0';
}
else
tmp = strdup (Value);
if (!tmp) return VERS_ERRMEM;
if (Container->tag != NULL) free (Container->tag);
Container->tag = tmp;
break;
case VERD_SRCFILE:
tmp = strdup (Value);
if (!tmp) return VERS_ERRMEM;
if (Container->srcfile != NULL) free (Container->srcfile);
Container->srcfile = tmp;
break;
case VERD_AUTHOR:
if (!strncmp (Value, "$Author: ", 9))
{
char * ptr;
tmp = strdup (Value + 9);
if (!tmp) return VERS_ERRMEM;
if ((ptr = strchr (tmp, ' ')) != NULL) *ptr = '\0';
}
else
tmp = strdup (Value);
if (!tmp) return VERS_ERRMEM;
if (Container->author != NULL) free (Container->author);
Container->author = tmp;
break;
default:
sprintf (VER_Error_Msg, "Error VER_Info_Set : unexpected type %d", (int)Info_Type);
VER_Error_Print ();
return VERS_ERRAPI;
}
return VERS_OK;
}
/*------------------------------------------------------------------------------*/
/* Effacement d'une information */
/*------------------------------------------------------------------------------*/
/* (I) Container : pointeur sur le conteneur d'informations */
/* (I) Info_Type : type d'information à effacer */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Clean (VERT_Info_Container * Container, VERT_Info Info_Type)
{
if (Container == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_Clean : the container is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
switch ((int)Info_Type)
{
case VERD_VERSION:
if (Container->version != NULL) free (Container->version);
break;
case VERD_TAG:
if (Container->tag != NULL) free (Container->tag);
break;
case VERD_SRCFILE:
if (Container->srcfile != NULL) free (Container->srcfile);
break;
case VERD_AUTHOR:
if (Container->author != NULL) free (Container->author);
break;
default:
sprintf (VER_Error_Msg, "Error VER_Info_Clean : unexpected type %d", (int)Info_Type);
VER_Error_Print ();
return VERS_ERRAPI;
}
return VERS_ERRAPI;
}
/*------------------------------------------------------------------------------*/
/* Destruction d'un container d'informations */
/*------------------------------------------------------------------------------*/
/* (I) Container : pointeur sur le conteneur d'informations */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_End (VERT_Info_Container * Container)
{
if (Container == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_End : the container is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
if (Container->name != NULL) free (Container->name);
if (Container->version != NULL) free (Container->version);
if (Container->tag != NULL) free (Container->tag);
if (Container->srcfile != NULL) free (Container->srcfile);
if (Container->author != NULL) free (Container->author);
free (Container);
return VERS_OK;
}
/*------------------------------------------------------------------------------*/
/* Affichage des informations d'un conteneur */
/*------------------------------------------------------------------------------*/
/* (I) Stream : pointeur sur le flux de sortie */
/* (I) Container : pointeur sur le conteneur d'informations */
/* (I) Mode : mode d'affichage */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Print (FILE * Stream, VERT_Info_Container * Container, VERT_Print_Mode Mode)
{
if (Stream == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_Print : the file descriptor is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
if (Container == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Info_Print : the container is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
if (Mode == VERD_MINIMAL)
fprintf (Stream, "%-20s%-20s%-30s\n",
Container->name ? Container->name : "???",
Container->version ? Container->version : "",
Container->tag ? Container->tag : "");
else
fprintf (Stream, "%-20s%-20s%-30s%-30s%-20s\n",
Container->name ? Container->name : "???",
Container->version ? Container->version : "",
Container->tag ? Container->tag : "",
Container->srcfile ? Container->srcfile : "",
Container->author ? Container->author : "");
return VERS_OK;
}
/*------------------------------------------------------------------------------*/
/* Récupération d'un conteneur d'informations */
/*------------------------------------------------------------------------------*/
/* (O) Container : adresse d'un pointeur sur le conteneur d'informations */
/* (I) Object : objet dans lequel on effectue la recherche */
/* (I) Index : pointeur d'index à partir duquel on effectue la recherche */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Next_Get (VERT_Info_Container ** Container, VERT_Object * Object, VERT_Index * Index)
{
void * Ptr = VER_Symbol_Next_Find (VER_FCN_NAME, Object, Index);
VERT_Fcn * Ptr_Fcn = (VERT_Fcn *)Ptr;
if (Ptr == NULL) return VERS_KO;
*Container = (VERT_Info_Container *)(*Ptr_Fcn)();
if (*Container == NULL) return VERS_ERRMEM;
return VERS_OK;
}
/*------------------------------------------------------------------------------*/
/* Affichage des informations exportées par l'objet courant */
/*------------------------------------------------------------------------------*/
/* (I) Stream : pointeur sur le flux de sortie */
/* (I) Mode : mode d'affichage */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Object_Print (FILE * Stream, VERT_Print_Mode Mode)
{
VERT_Status Nb_Object = 0;
VERT_Info_Container * Container;
VERT_Object * Object;
char sep [120];
VERT_Index Index;
void * Handle;
if (Stream == NULL)
{
sprintf (VER_Error_Msg, "Error VER_Object_Print : the file descriptor is null");
VER_Error_Print ();
return VERS_ERRAPI;
}
/* Affichage sous forme de tableau en option 'verbose' */
if (Mode == VERD_VERBOSE)
{
memset (sep, '-', sizeof (sep));
sep [sizeof (sep) -1] = '\0';
fprintf (stdout, "%-20s%-20s%-30s%-30s%-20s\n%s\n", "OBJECT NAME", "VERSION", "TAG", "SOURCE FILE", "AUTHOR", sep);
}
/* Info : on distingue deus types d'objets :
- un premier objet (objet principal) qui correspond à ce qui est chargé par le loader
au lancement du programme : programme principal + objets statiques (.o)
- autant d'objets qui ont chargés dynamiquement par le linker (.so)
*/
/* On commence par récupèrer l'objet principal */
Handle = dlopen (NULL, RTLD_LAZY);
#ifdef LINUX
/*
Sous LINUX, le linker définit une variable globale bien pratique qui référence
la liste des objets linkés dynamiquement.
*/
Object = ((struct r_scope_elem *)(_dl_global_scope [0]))->r_list [0];
#else
/*
Sous SOLARIS, on doit faire appel à la fonction dlinfo() pour obtenir
les informations de link pour l'objet principal.
NB : cette fonction n'existe pas sous LINUX.
*/
Object = (VERT_Object *)malloc (sizeof (VERT_Object));
dlinfo (Handle, RTLD_DI_LINKMAP, &Object);
#endif
/* Recherche d'informations dans tous les objets linkés */
Index = 0;
while (Object != NULL)
{
if (VER_Info_Next_Get (&Container, Object, &Index) == VERS_OK)
{
Nb_Object++;
/*
Définition du nom de l'objet : on ajoute '.o' ou '.so'
selon qu'il s'agit du premier objet chargé ou non.
*/
if (Container->name)
{
if (Object->l_prev != NULL)
{
if ((Container->name = (char *)realloc (Container->name, strlen (Container->name) + 4)) != NULL)
sprintf (Container->name, "%s.so", Container->name);
}
else
{
if ((Container->name = (char *)realloc (Container->name, strlen (Container->name) + 3)) != NULL)
sprintf (Container->name, "%s.o", Container->name);
}
}
/* Affichage complet des informations récupérées */
VER_Info_Print (Stream, Container, Mode);
/* Désallocation des informations */
VER_Info_End (Container);
/* Recherche du symbole suivant dans le même objet */
Index++;
}
else
{
/* En mode affichage minimal, on s'arrête après l'objet principal */
if (Object->l_prev == NULL && Mode == VERD_MINIMAL)
Object = NULL;
else
{
/* Recherche dans l'objet suivant */
Object = Object->l_next;
Index = 0;
}
}
}
return Nb_Object;
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonctions privées */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Recherche d'un symbole dans les tables de symboles des objets linkés : */
/* */
/* (I) Symbol_Name : nom de symbole à rechercher */
/* (O) Object : objet dans lequel on recherche le symbole */
/* (I) Index : pointeur sur l'index à partir duquel on recherche */
/* */
/* Retourne la référence du symbole trouvé, NULL si non trouvé. */
/*------------------------------------------------------------------------------*/
void * VER_Symbol_Next_Find (const char * Symbol_Name, VERT_Object * Object, VERT_Index * Index)
{
unsigned long Offset;
/* Recherche dans l'objet passé en paramètre */
if (Object != NULL)
{
VERT_Index * Hash_Table, Nb_Symbol;
Elf32_Sym * Symbol_Table;
char * String_Table;
Elf32_Sym * Symbol;
int i, Found;
/* Définition de l'offset pour interpréter les adresses virtuelles */
/*
Les adresses données dans les sections sont virtuelles : on doit leur ajouter
un offset défini dans l'entête de l'objet. Ceci n'est toutefois pas vrai pour l'objet principal.
*/
if (Object->l_prev == NULL)
Offset = 0; /* Pas d'offset pour l'objet principal */
else
Offset = Object->l_addr; /* Offset non nul pour les objets partagés */
/* Recherche des sections relatives aux symboles */
#ifdef LINUX
/* Sous LINUX, les sections sont directement accessibles par le champs <l_info> de l'entête de l'objet */
Symbol_Table = (Elf32_Sym *)(Object->l_info [DT_SYMTAB]->d_un.d_ptr);
String_Table = (char *)(Object->l_info [DT_STRTAB]->d_un.d_ptr);
/*
Le nombre de symboles peut lui-aussi être retrouvé à partir de l'entête de l'objet.
En effet, l'entête contient un champ <l_buckets> qui pointe sur la donnée <bucket> de la section HASH.
Connaissant la structure de l'entête de la section HASH, on retrouve facilement la donnée <nchain>.
*/
Nb_Symbol = *(VERT_Index *)((size_t)(Object->l_buckets) - sizeof (VERT_Index));
#else
/*
Sous SOLARIS, le champs <l_info> n'existe pas.
Il faut donc parcourir toutes les sections pour trouver celles qui nous intéressent.
*/
i = 0;
Found = 0;
while (Found < 3)
{
switch ((int)Object->l_ld [i].d_tag)
{
case DT_HASH:
/* La section HASH nous intéressent car elle contient le nombre de symboles */
Hash_Table = (VERT_Index *)(Object->l_ld [i].d_un.d_ptr + Offset);
Nb_Symbol = Hash_Table [1]; /* Donnée <nchain> */
Found++;
break;
case DT_SYMTAB:
/* La section SYMTAB référence les symboles de l'objet courant */
Symbol_Table = (Elf32_Sym *)(Object->l_ld [i].d_un.d_ptr + Offset);
Found++;
break;
case DT_STRTAB:
/*
La section STRTAB contient les chaînes de caractères qui sont référencées
par les autres sections (notamment les noms de symboles).
*/
String_Table = (char *)(Object->l_ld [i].d_un.d_ptr + Offset);
Found++;
break;
default:
/* Les autres sections ne nous intéressent pas */
}
i++;
}
#endif
/* Recherche dans la table des symboles à partir de l'index passé en paramètre */
while ((*Index) < Nb_Symbol)
{
Symbol = &Symbol_Table [*Index];
/* On recherche une fonction qui correspond au nom passé en paramètre */
if (Symbol->st_value != 0 && ELF32_ST_TYPE (Symbol->st_info) <= STT_FUNC && !strncmp (String_Table + Symbol->st_name, Symbol_Name, strlen (Symbol_Name)))
return (void *)(Symbol->st_value + Offset);
(*Index)++;
}
/* Aucun symbole n'a été trouvé */
return NULL;
}
return NULL;
}
/*------------------------------------------------------------------------------*/
/* Routine d'affichage d'un message d'erreur */
/*------------------------------------------------------------------------------*/
void VER_Error_Print (void)
{
fprintf (stderr, VER_Error_Msg);
}

134
lib/ver.h Normal file
View File

@ -0,0 +1,134 @@
#ifndef _LIBVER
#define _LIBVER
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LINUX
#include <link.h>
#else
#include <sys/link.h>
#endif
typedef int VERT_Info;
#define VERD_VERSION 1
#define VERD_TAG 2
#define VERD_SRCFILE 3
#define VERD_AUTHOR 4
typedef int VERT_Print_Mode;
#define VERD_VERBOSE 1
#define VERD_MINIMAL 2
typedef int VERT_Status;
#define VER_ERROR(s) (s < 0) /* Tous les codes retour négatifs correspondent à des erreurs */
#define VERS_OK 1
#define VERS_KO 0
#define VERS_ERRMEM -1 /* Problème d'allocation mémoire */
#define VERS_ERRAPI -2 /* Utilisation incorrecte des API */
typedef struct {
char * name;
char * version;
char * tag;
char * srcfile;
char * author;
} VERT_Info_Container;
typedef VERT_Info_Container * VERT_Fcn (void);
typedef struct link_map VERT_Object;
typedef unsigned int VERT_Index;
#define VER_FCN_NAME "VER_Info_Export"
#define INIT(x) VERT_Info_Container * Container; VER_Info_Init (&Container, x);
#define VERSION(x) if (Container) VER_Info_Set(Container,VERD_VERSION, x);
#define TAG(x) if (Container) VER_Info_Set(Container,VERD_TAG, x);
#define SRCFILE(x) if (Container) VER_Info_Set(Container,VERD_SRCFILE, x);
#define AUTHOR(x) if (Container) VER_Info_Set(Container,VERD_AUTHOR, x);
#define VER_INFO_EXPORT(obj,ver,tag,file,author) \
VERT_Info_Container * VER_Info_Export_##obj (void); \
VERT_Info_Container * VER_Info_Export_##obj (void) \
{ \
INIT(#obj) \
VERSION(ver) \
TAG(tag) \
SRCFILE(file) \
AUTHOR(author) \
return (Container); \
}
char VER_Error_Msg [256];
/*------------------------------------------------------------------------------*/
/* Affichage des informations exportées par l'objet courant */
/*------------------------------------------------------------------------------*/
/* (I) Stream : pointeur sur le flux de sortie */
/* (I) Mode : mode d'affichage */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Object_Print (FILE * Stream, VERT_Print_Mode Mode);
/*------------------------------------------------------------------------------*/
/* Récupération d'un conteneur d'informations */
/*------------------------------------------------------------------------------*/
/* (O) Container : adresse d'un pointeur sur le conteneur d'informations */
/* (I) Object : objet dans lequel on effectue la recherche */
/* (I) Index : pointeur d'index à partir duquel on effectue la recherche */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Next_Get (VERT_Info_Container ** Container, VERT_Object * Object, VERT_Index * Index);
/*------------------------------------------------------------------------------*/
/* Affichage des informations d'un conteneur */
/*------------------------------------------------------------------------------*/
/* (I) Stream : pointeur sur le flux de sortie */
/* (I) Container : pointeur sur le conteneur d'informations */
/* (I) Mode : mode d'affichage */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Print (FILE * Stream, VERT_Info_Container * Container, VERT_Print_Mode Mode);
/*------------------------------------------------------------------------------*/
/* Création d'un conteneur d'informations */
/*------------------------------------------------------------------------------*/
/* (O) Contanier : adresse d'un pointeur sur le container à créer */
/* (I) Object_Name : nom de l'objet */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Init (VERT_Info_Container ** Container, const char * Object_Name);
/*------------------------------------------------------------------------------*/
/* Mise à jour d'une information */
/*------------------------------------------------------------------------------*/
/* (I) Container : pointeur sur le conteneur d'informations */
/* (I) Info_Type : type d'information à mettre à jour */
/* (I) Value : valeur de l'information */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Set (VERT_Info_Container * Container, VERT_Info Info_Type, const char * Value);
/*------------------------------------------------------------------------------*/
/* Effacement d'une information */
/*------------------------------------------------------------------------------*/
/* (I) Container : pointeur sur le conteneur d'informations */
/* (I) Info_Type : type d'information à effacer */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_Clean (VERT_Info_Container * Container, VERT_Info Info_Type);
/*------------------------------------------------------------------------------*/
/* Destruction d'un container d'informations */
/*------------------------------------------------------------------------------*/
/* (I) Container : pointeur sur le conteneur d'informations */
/*------------------------------------------------------------------------------*/
VERT_Status VER_Info_End (VERT_Info_Container * Container);
/*------------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif