From 35becf27e25d4d5b9b1cacf77f1d5776bc9eb350 Mon Sep 17 00:00:00 2001 From: smas Date: Fri, 28 Jul 2000 15:39:02 +0000 Subject: [PATCH] =?UTF-8?q?Premi=C3=A8re=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/libver.3 | 218 +++++++++++++++++++ doc/libver.doc | Bin 0 -> 35840 bytes lib/libver.c | 561 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/ver.h | 134 ++++++++++++ 4 files changed, 913 insertions(+) create mode 100644 doc/libver.3 create mode 100644 doc/libver.doc create mode 100644 lib/libver.c create mode 100644 lib/ver.h 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 0000000000000000000000000000000000000000..ff773644f434327f71095d80b6783ad0ada6175d GIT binary patch literal 35840 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 LS5Ny*;K2U}?HJi` literal 0 HcmV?d00001 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