C'est à peu de chose près, ce qui j'ai dit plus haut, sauf pour LANGUAGE_UNKNOWN pour lequel je ne suis pas d'accord.
En C, si l'enum est écrit LANGUAGE_UNKWOWN = 255, sa valeur vaut 255, pas 256 (voir l'énoncé de djibril).
Version imprimable
C'est à peu de chose près, ce qui j'ai dit plus haut, sauf pour LANGUAGE_UNKNOWN pour lequel je ne suis pas d'accord.
En C, si l'enum est écrit LANGUAGE_UNKWOWN = 255, sa valeur vaut 255, pas 256 (voir l'énoncé de djibril).
hum autant pour moi j'ai fait une faute de frappe :p
Donc si tu reprends un peu mieux le patch que j'avais fourni, tu devrais obtenir ce résultat, sans oublier de corriger l'usage de %VariableDefine.
yes, sauf que je comprend pas pour l'inversion de l'increment :?
bon le C, ça fait des lustres que j'en ai pas fait.
L'idéal c'est de se mettre d'accord.
Pour ce fichier :
Voici ce que j'obtiens, j'espère que c'est OK pour vousCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 typedef enum { NO_CARD = 1 , CARD_INSERTED , CARD_REMOVED , CARD_DETECTED , CARD_JAM , CARD_SCANNED } CARD_STATUS; #define TOP_CAD_PRIVATE_COMMAND 254 #define MAX_COMMAND_NUM 255 #define TOP_GENERIC_COMMAND 254 typedef enum { CARD_ON = TOP_GENERIC_COMMAND, CARD_OFF } CARD_STATUS; typedef enum { LANGUAGE_NONE = 0, LANGUAGE_DUTCH, LANGUAGE_ENGLISH, LANGUAGE_FRENCH, LANGUAGE_GERMAN, LANGUAGE_ITALIAN, LANGUAGE_SPANISH, LANGUAGE_UNKNOWN = 255 } LANGUAGE;
Par rapport à vous résultat, pourquoi CARD_OFF = 255 et non 0 vu qu'on commenceCitation:
Defines:
TOP_GENERIC_COMMAND = 254
MAX_COMMAND_NUM = 255
TOP_CAD_PRIVATE_COMMAND = 254
============
Constantes definies dans les typedef:
LANGUAGE
- LANGUAGE_ENGLISH = 2
- LANGUAGE_DUTCH = 1
- LANGUAGE_UNKNOWN = 255
- LANGUAGE_ITALIAN = 5
- LANGUAGE_FRENCH = 3
- LANGUAGE_NONE = 0
- LANGUAGE_GERMAN = 4
- LANGUAGE_SPANISH = 6
CARD_STATUS
- CARD_OFF = 0
- CARD_ON = 254
l'incrémentation pour chaque enum à 0 ?
Voici le code
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 #!/usr/bin/perl # But : Parsing d'un fichier de type C use warnings; use strict; use Regexp::Common qw /comment/; use Perl6::Slurp; # Englobe le fichier .h my $CodeFichierC = slurp "pub_serv.h"; #ouverture du fichier *.txt en mode Ecriture open WRITER, '>', "decode2.txt" or die "Le fichier ne peut être édité !\n"; # Suppression des commentaires C my $RegexComment = $RE{comment}{'C++'}; #C++ pour supprimer /* */ ET // $CodeFichierC =~ s{$RegexComment}{}g; # Recupère tous les define du fichier my @define = $CodeFichierC =~ m{ ^\s* # La ligne commence par un espace ou non \#define # suivi de #define \s* # espace ou non ([^\n]+)\s* # contenu define \n # se termine par un retour chariot }mgix; # Dans le hash, la cle sera le nom d'un define et la valeur celle du define. my %VariableDefine; foreach my $Define (@define) { my ( $var, $value ) = split( /\s+/, $Define ); $VariableDefine{$var} = $value || ''; } print WRITER "Defines: \n\n"; foreach my $var ( keys %VariableDefine ) { print WRITER "$var = $VariableDefine{$var}\n"; } print WRITER "\n============\n\n"; # Recupère tous les bloc enum avec le nom de l'enum (le tout dans @typedef) # Si le bloc ne match pas avec la regex, il ne sera pas dans @BlocEnum my @BlocEnum = $CodeFichierC =~ m/ ( enum[^{]+{ # Ligne enum suivi de tous sauf une accolade + accolade [^}]+ # contenu tout sauf accolade fermante } # accolade fermante [^;]+; # suivi du nom de l'enum plus virgule ) /mgix; # On va maintenant traiter chaque bloc enum my %EnumData; foreach my $DonneeEnum (@BlocEnum) { my ( $ContenuBloc, $NomEnum ) = $DonneeEnum =~ m/ { ([^}]+) # contenu du bloc (tout sauf accolade) } ([^;]+);$ # Nom enum /mgix; # On enleve les retour chariot et espace $NomEnum =~ s{[\n\s]}{}g; $ContenuBloc =~ s{[\n\s]}{}g; # Recupération des constances dans $ContenuBloc my %Constante; my $Valeur = 0; foreach my $Enumerateur ( split( ',', $ContenuBloc ) ) { my ( $Nomvariable, $test ) = split( '=', $Enumerateur ); # si la valeur existe, on l'incremente, sinon on la met à 0 if ( defined $test) { # On vérifie qu'il est present dans define ou non if ( defined $VariableDefine{$test} ) { $test = $VariableDefine{$test}; } else { $Valeur++; } } else { $test = $Valeur; $Valeur++; } $Constante{$Nomvariable} = $test; } # A chaque enum, on associ un hash contenant ces constance $EnumData{$NomEnum} = \%Constante; } # Affichage des enum avec cnostances print WRITER "Constantes definies dans les typedef: \n\n"; while ( my ( $Enum, $RefConstances ) = each %EnumData ) { print WRITER "$Enum\n"; while ( my ( $constante, $valeur ) = each %{$RefConstances} ) { print WRITER "\t- $constante = $valeur \n"; } } close(WRITER);
Djibril, dans un enum en C, lorsque tu commences à définir un énuméré, tous ceux qui suivent et qui ne sont pas définis avec une valeur sont simplement incrémentés par rapport au précédent.
Lorsque tu ne définis AUCUNE valeur dans l'énuméré, le premier énuméré commence à 0. C'est donc seulement dans ce cas qu'il faut initialiser $Valeur à 0. Dans tous les autres cas, soit on incrémente la valeur précédente, soit on prend la valeur spécifiée telle qu'elle.
Donc pour le cas de CARD_OFF, comme il est défini après CARD_ON et qu'il n'a pas de valeur définie, CARD_OFF vaudra CARD_ON + 1.
Ok, merci pour l'explication.
Donc ça change un peu la logique du code car pour le premier enum on obtient un bon résultat par chance l'initialisation de $valeur à 0 coincide avec le faite que LANGUAGE_NONE = 0, mais s'il était égal à 10, ce ne serait pas bon. D'ou l'importance d'avoir des exemples clairs sinon on tourne en rond et chacun perd son temps. :?
Exemple :
donneCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 typedef enum { LANGUAGE_NONE = 10, LANGUAGE_DUTCH, LANGUAGE_ENGLISH, LANGUAGE_FRENCH, LANGUAGE_GERMAN, LANGUAGE_ITALIAN, LANGUAGE_SPANISH, LANGUAGE_UNKNOWN = 255 } LANGUAGE;
au lieu deCitation:
LANGUAGE
- LANGUAGE_ENGLISH = 2
- LANGUAGE_DUTCH = 1
- LANGUAGE_UNKNOWN = 255
- LANGUAGE_ITALIAN = 5
- LANGUAGE_FRENCH = 3
- LANGUAGE_NONE = 10
- LANGUAGE_GERMAN = 4
- LANGUAGE_SPANISH = 6
si j'ai bien comprisCitation:
LANGUAGE
- LANGUAGE_ENGLISH = 12
- LANGUAGE_DUTCH = 11
- LANGUAGE_UNKNOWN = 255
- LANGUAGE_ITALIAN = 15
- LANGUAGE_FRENCH = 13
- LANGUAGE_NONE = 10
- LANGUAGE_GERMAN = 14
- LANGUAGE_SPANISH = 16
bon modification
en rajoutant en début de scriptCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 foreach my $Enumerateur ( split( ',', $ContenuBloc ) ) { my ( $Nomvariable, $test ) = split( '=', $Enumerateur ); # si la valeur existe, on l'incremente, sinon on la met à 0 if ( defined $test) { # On vérifie qu'il est present dans define ou non if ( defined $VariableDefine{$test} ) { $test = $VariableDefine{$test}; $Valeur = List::Util::max($Valeur,$test) +1; } else { $Valeur ++; } } else { $Valeur = List::Util::max( values %Constante ) + 1 || $Valeur; $test = $Valeur; $Valeur++; } $Constante{$Nomvariable} = $test; }
ainsi :Code:use List::Util;
donneCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 typedef enum { NO_CARD = 1 , CARD_INSERTED , CARD_REMOVED , CARD_DETECTED , CARD_JAM , CARD_SCANNED } CARD_STATUS; #define TOP_CAD_PRIVATE_COMMAND 254 #define MAX_COMMAND_NUM 255 #define TOP_GENERIC_COMMAND 254 typedef enum { CARD_ON = TOP_GENERIC_COMMAND, CARD_OFF } CARD_STATUS; typedef enum { LANGUAGE_NONE = 10, LANGUAGE_DUTCH, LANGUAGE_ENGLISH, LANGUAGE_FRENCH, LANGUAGE_GERMAN, LANGUAGE_ITALIAN, LANGUAGE_SPANISH, LANGUAGE_UNKNOWN = 255 } LANGUAGE;
Voilà, bon courage pour la suite.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 Defines: TOP_GENERIC_COMMAND = 254 MAX_COMMAND_NUM = 255 TOP_CAD_PRIVATE_COMMAND = 254 ============ Constantes definies dans les typedef: LANGUAGE - LANGUAGE_ENGLISH = 12 - LANGUAGE_DUTCH = 11 - LANGUAGE_UNKNOWN = 255 - LANGUAGE_ITALIAN = 15 - LANGUAGE_FRENCH = 13 - LANGUAGE_NONE = 10 - LANGUAGE_GERMAN = 14 - LANGUAGE_SPANISH = 16 CARD_STATUS - CARD_OFF = 255 - CARD_ON = 254
Ton dernier résultat est effectivement ce qu'il faut obtenir (pas comme dans le message précédent, où je crois que tu as inversé).
Par contre, j'ai dit une bêtise plus tôt en parlant de l'usage de %VariableDefine : il est correctement utilisé.
Comme je l'ai fait remarquer plus haut, cela ne règle pas l'ensemble des formes grammaticales possibles en C pour la définition des énumérés, comme celle d'utiliser une valeur d'un énuméré comme base de calcul pour un autre... mais ceci est une autre histoire (CARD_ON = CARD_OFF + 10 par exemple).
Rebonjour :)
Merci pour votre aide :)
Bon je tente quand même d'exposer une chose que je ne comprend pas:
Dans ton code Djibril, Eclipse me dit pour la ligne :
Code:
1
2 $Valeur = List::Util::max(values %Constante) +1 || $Valeur;
Et je ne comprend pas du tout ça en fait...Code:Use of uninitialized value in addition (+)
Désolé si je n'ai pas été assez clair sur certains points, mais c'est pas évident de déceler toutes les particularité d'un header de plus de 2000 lignes (en tout cas moi j'y arrive pas :p )
ps: j'ai bien rajouté en début de script
Code:
1
2use List::Util;
cela veut dire qu'à un moment où Perl est en train de faire
, il y a une valeur qui est non initialisée, probablement %Constante.Code:$Valeur = List::Util::max(values %Constante) +1 || $Valeur;
Remplace
parCode:$Valeur = List::Util::max( values %Constante ) + 1 || $Valeur;
Peux tu nous montrer ton fichier de 2000 lignes histoire qu'on le test si c pas discretCode:
1
2
3 if ( my @Values = values %Constante ) { $Valeur = List::Util::max( @Values ) + 1; }
Pour le header de 2000 lignes, je ne peux pas le distribuer comme ca, il est soumis à un copyright dsl :oops:
ok
Je prefere pas prendre de risques...
Merci de ta compréhension ;)
Mmmm... je me dis que cette ligne
étant exécutée inconditionnellement (donc y compris si $test est indéfini), il est possible que %Constante contienne des clés pour lesquelles les valeurs sont indéfinies.Code:$Constante{$Nomvariable} = $test;
Ca n'a pas l'air d'avoir d'influence sur la fonction max, qui semble ignorer ces valeurs, mais il me semble qu'il sera sain pour éviter tout autre effet de bord que le hash %Constante ne contienne que des variables valides.
Salut!
Désolé pour cette période d'absence j'étais assez occupé.
De retour dans le perl je rajoute un nouveau problème au palamarès de mes problèmes que j'arrive pas à résoudre.
La ca me paraît assez simple à résoudre, mais j'ai beau essayer de chercher etc... je trouve pas du tout.
Donc voila:
J'ai des define de "forme normale" dans mon header.
Et j'en ai d'autres d'une autre forme:
Le problème est que dans la recherche du define, je fais ([^\n]*) donc il est censé prendre tout jusqu'a un retour chariot, hors après execution du script, j'obtiens seulementCode:
1
2#define ICCIS_CARD_STATUS_FLD ((DWORD)(1UL << 0))
Je ne comprend pas pourquoi il s'arrête là alors qu'il ne rencontre pas de retour chariot.Code:
1
2 ICCIS_CARD_STATUS_FLD = ((DWORD)(1UL
Une idée?
ps: si vous en avez marre aucun soucis, je comprend tout à fait, mais sachez juste que je ne fais pas ça pour un projet quelcquonque, c'est juste pour m'améliorer en Perl, et j'ai un peux de mal avec ce language. Libre à vous de continuer à m'aider ;)
En tout cas merci déja pour votre aide :)
Si tu nous mettez ta vraie regex ;)
Alors je me suis dis si il va pas jusqu'au retour de chariot alors qu'il est censé le faire je me suis dit qu'il aille au moins jusqu'au 2 parenthèses fermantes donc à la place de ([^\n]*) j'ai tenté ([^\)\)]*) mais ca ne fonctionne pas.
Mais je comprend vraiment pas pourquoi il ne prend pas la fin du define. Il s'arrete alors qu'il n'y a pas de retour chariot et ca je comprend pas du tout :p
Code:
1
2
3
4
5
6
7
8
9 my @define = $CodeFichierC =~ m{ ^\s* # La ligne commence par un espace ou non \#define # suivi de #define \s* # espace ou non ([^\)\)]*) # contenu define jusqu'au parenthèses fermantes \n # se termine par un retour chariot }mgix;
Dans un groupe [ ], tu mets une liste de caractère admissible, mais il n'est pas possible d'y introduire des groupes de caractère.
Sinon, j'ai simplement utilisé ([^\n]*) et je peux capturer sans problème la fin du define :
Au lieu de matcher "\n", je préfère utiliser $.Citation:
$ echo "#define ICCIS_CARD_STATUS_FLD ((DWORD)(1UL << 0))" | perl -e '$a = <STDIN>;@a = $a =~ /^\s*\#define\s*([^\n]*)\n/mgix;print join " : ", @a'
ICCIS_CARD_STATUS_FLD ((DWORD)(1UL << 0))
La regexp suivante fonctionne donc égalementCode:/^\s*\#define\s*(.*)$/mgix