2010-07-29 3 views
2

J'utilise une bibliothèque tierce qui a beaucoup de différents codes d'erreur. Un inclure des fichiers contient un tas de lignes comme:extraire des messages de chaîne de l'ensemble de #define

#define ABC_INVALID_BUFFER_SIZE 101 
#define ABC_INVALID_COMMAND 102 

etc.

Lors de l'exécution, je suis obtenir différents codes d'erreur que je développe ma demande. Je veux, à l'exécution, que l'application imprime des messages comme "error: ABC_INVALID_COMMAND", au lieu de l'imprimer "error: 102". Je veux avoir une carte de traduction de sortes qui me permet de convertir les nombres en texte en utilisant map [code]. Donc, ce que je cherche est un mécanisme qui me permet, au moment de la compilation, d'analyser le fichier include et de le convertir en map [102] = string ("ABC_INVALID_COMMAND"). Je peux le faire en utilisant un script awk, mais je me demande s'il existe un mécanisme qui existe déjà. Sûrement je ne peux pas être le premier qui veut/doit faire ceci? Quelque chose d'évident que je n'ai pas encore découvert?

+1

Je pense que vous feriez mieux d'écrire (à la main) une fonction qui traduit les codes dans un message d'erreur lisible par l'homme. Cela peut être aussi simple qu'une instruction switch() qui renvoie une chaîne de caractères constante. De nombreuses bibliothèques fournissent déjà une telle chose (par exemple, ldap_err2string() pour LDAP); mais si votre bibliothèque tierce ne vous l'offre pas, il vaut peut-être mieux passer un peu de temps à en coder une à la main. –

+0

1000 de messages, la plupart d'entre eux je ne sais pas ce qu'ils signifient? – Mike

Répondre

1

Vous n'êtes certainement pas le premier à vouloir cette fonction, je l'aurais aimé aussi.

Malheureusement, vous devrez continuer à utiliser votre script. Je voudrais avoir un script qui a fait make et ensuite votre script à chaque fois.

Même si le c morceaux pré-processeur les #define étiquette de, vous pouvez toujours y accéder:

cpp -dM foo.h 

Retours:

(some others) 
#define A 1 
#define B 2 

Vous constaterez que vous aurez toujours besoin de jouer avec les valeurs de retour.

Plus d'infos sur http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Preprocessor-Options.html#Preprocessor-Options

0

Il ne peut se faire par la langue, le pré-processeur réaffecte les chaînes à leurs valeurs avant que le compilateur voit.

Les solutions communes sont:
1, Un script pour générer la liste des constantes avec un ensemble correspondant de chaînes définies #.
Ou générer une fonction avec une grosse instruction switch pour renvoyer des valeurs de chaîne.

2, remplacer les valeurs d'un tableau de structs

struct { 
    int value; 
    char *name; 
} values; 

et l'initialiser avec des paires de constante, "description". Selon la façon dont vous utilisez les #defines, cela pourrait ne pas être possible.

Je voudrais écrire un script (awk/python/etc) pour lire un fichier texte:

AVALUE 12 
BVALUE 23 
CVALUE 45 

Et cracher un fichier .h

#define AVALUE_S "AVALUE" 
#define AVALUE 12 
#define BVALUE_S "BVALUE" 
#define BVALUE 23 

Ensuite, dans votre code, vous pouvez utilisez simplement AVALUE_S partout où vous avez besoin de la chaîne lisible par un humain.

+0

Partiellement utile. Cpp montrerait ce que définit a fini par être exécuté (en fonction d'autres ifdefs). Encore besoin de mon script awk. – Mike

1

Absolument!Cela peut être fait avec X-Macros en utilisant le préprocesseur pour le compilateur. Je l'utilise beaucoup pour associer des codes d'erreur avec des chaînes.

Description complète: What is a good reference documenting patterns of use of X-Macros in C (or possibly C++)?

Pour votre question:

/* 
* X Macro() data list 
* - Add all new values here (and only here!) 
* Format: Enum, Value 
*/ 
#define X_ABC_ERROR \ 
    X(ABC_INVALID_BUFFER_SIZE, 101) \ 
    X(ABC_INVALID_COMMAND,  102) \ 
    X(ABC_SOME_OTHER_ERROR,  200) 

/* 
* Build an array of error return values 
* e.g. {101,102} 
*/ 
static int ErrorVal[] = 
{ 
    #define X(Enum,Val)  Val, 
    X_ABC_ERROR 
    #undef X 
}; 

/* 
* Build an array of error enum names 
* e.g. {"ABC_INVALID_BUFFER_SIZE","ABC_INVALID_COMMAND"} 
*/ 
static char * ErrorName[] = { 
    #define X(Enum,Val)  #Enum, 
    X_ABC_ERROR 
    #undef X 
}; 

/* 
* Create an enumerated list of error indexes 
* e.g. IDX_ABC_INVALID_BUFFER_SIZE = 0, IDX_ABC_INVALID_COMMAND = 1, ... 
*/ 
enum { 
    #define X(Enum,Val)  IDX_##Enum, 
    X_ABC_ERROR 
    #undef X 
    IDX_MAX /* Array size */ 
}; 

/* 
* Sample function to show error codes/names 
*/ 
static void showErrorInfo(void) 
{ 
    int i; 

    /* 
    * Access the values 
    */ 
    for (i=0; i<IDX_MAX; i++) 
     printf(" %s == %d\n", ErrorName[i], ErrorVal[i]); 
} 
+0

Solution élégante très intéressante si vous avez le contrôle sur les constantes que vous définissez, mais c'est une bibliothèque tierce (pour un matériel dédié spécial), qui définit des milliers de messages et de codes d'erreur ... – Mike

Questions connexes