commit 35becf27e25d4d5b9b1cacf77f1d5776bc9eb350 Author: smas Date: Fri Jul 28 15:39:02 2000 +0000 Première version diff --git a/doc/libver.3 b/doc/libver.3 new file mode 100644 index 0000000..ac5e3b6 --- /dev/null +++ b/doc/libver.3 @@ -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 " +.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 : +.RS -3 +.LP diff --git a/doc/libver.doc b/doc/libver.doc new file mode 100644 index 0000000..ff77364 Binary files /dev/null and b/doc/libver.doc differ diff --git a/lib/libver.c b/lib/libver.c new file mode 100644 index 0000000..45094d5 --- /dev/null +++ b/lib/libver.c @@ -0,0 +1,561 @@ +#include +#include +#include +#ifdef LINUX +#else +#include +#endif +#include +#include + +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 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 qui pointe sur la donnée de la section HASH. + Connaissant la structure de l'entête de la section HASH, on retrouve facilement la donnée . + */ + + Nb_Symbol = *(VERT_Index *)((size_t)(Object->l_buckets) - sizeof (VERT_Index)); +#else + /* + Sous SOLARIS, le champs 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 */ + 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); +} + diff --git a/lib/ver.h b/lib/ver.h new file mode 100644 index 0000000..2c3a8e3 --- /dev/null +++ b/lib/ver.h @@ -0,0 +1,134 @@ +#ifndef _LIBVER +#define _LIBVER + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LINUX +#include +#else +#include +#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