IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Parsing de fichiers C


Sujet :

Langage Perl

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Points : 53
    Points
    53
    Par défaut Parsing de fichiers C
    Salut à tous!

    Je suis débutant en Perl et je dois dévelloper un parser de fichiers d'entête en C:
    Ce parser devra extraire les constantes d'énumérations déclarées dans des fichiers *.h

    exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef enum
    {
       constante1 = valeur1,
       constante2
    }
    Nom_enum;
    Pour le moment, j'arrive à extraire ces noms de constante.
    Mais le but maintenant est de pouvoir extraire le Nom_enum afin de pouvoir trier (car le fichier d'en tête est rempli d'enum et de constantes :p ) puis enfin incrémenter la valeur1.
    Voici mon code (merci à Djibril pour l'aide):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    #!/usr/bin/perl
    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 les define
    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;
     
    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";
     
    #  Bloc typedef
    my @typedef = $CodeFichierC =~ m/
       (?:
       enum[^{]+{        # Ligne typedef avec accolade
       ([^;]+)			 # contenu tout sauf accolade fermante
       }				 # accolade fermante                     
       )
       /mgix;
     
    my $CodeTypedef = join( '', @typedef );
    $CodeTypedef =~ s{\n}{}g;
     
    my %Constante = $CodeTypedef =~ m{
       (\w+)\s*    # variable
       =*          # Egual ou non
       \s*(\S+)\s*  # valeur (tout sauf un espace)
       }mxig;
     
    my $valeur_enum;
    my $nom_enum;
     
    foreach my $test($CodeFichierC)
    {
     
    	if($test=~ m/(\s*enum\n{)(.*)(})([\w]+);/)#essais pour choper le nom de l'énum mais ne fonctionne pas
    	{
     
    	   $nom_enum = ($test =~ m/(\s*enum\n{)(.*)(})([\w]+);/);	
    	   print WRITER "\n===\n";
               print WRITER "$4\n";
               print WRITER "\n===\n";
    	}
    }
     
    print WRITER "Constantes definies dans les typedef: \n\n";
    foreach my $var ( keys %Constante ) 
    {
       $Constante{$var} =~ s{,}{}g;
     
       if ( exists $VariableDefine{ $Constante{$var} } ) 
       {
          print WRITER "$var = $VariableDefine{$Constante{$var}} <===($Constante{$var})\n";
     
       }
       else 
       {
          print WRITER "$var =";
          print WRITER $valeur_enum++;
          print WRITER "\n"; 
       }
    }
     
     
    close(WRITER);
    Si quelqu'un à des conseils à me donner, je suis preneur

    Merci d'avance

  2. #2
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Donne un exemple de fichier C plus conséquent s'il te plait et correct, pas des blabblabla.

    Avec des defines, contantes, enum bien déclarés, etc etc

    Merci

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Points : 53
    Points
    53
    Par défaut
    La forme est correcte:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    typedef enum
      {
        NO_CARD = 0    ,
        CARD_INSERTED  ,
        CARD_REMOVED   ,
        CARD_DETECTED  ,
        CARD_JAM       ,
        CARD_SCANNED
      }
      CARD_STATUS;

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define TOP_CAD_PRIVATE_COMMAND   254
    #define MAX_COMMAND_NUM           255


    Pour les define ca roule

    Le soucis est pour les enums

  4. #4
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Bon Ton soucis est que tu n'as pas compris le script que je t'ai fais et tu ne maitrises pas les expressions régulières.

    Bon, je vais te réécrire ton code avec plus de commentaires. Tu prendras le soins de le lire et d'essayer de comprendre tout ce qui est marqué dedans, sinon ça ne t'apportera absolument rien.

  5. #5
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Je suis pas sûr d'avoir tout pigé dans le source fourni (car les traitements des différents éléments du fichier header s'enchevêtrent, semble-t-il), mais dans ce qui suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #  Bloc typedef
    my @typedef = $CodeFichierC =~ m/
       (?:
       enum[^{]+{        # Ligne typedef avec accolade
       ([^;]+)			 # contenu tout sauf accolade fermante
       }				 # accolade fermante                     
       )
       /mgix;
    J'aurais tendance à dire qu'il serait plus intéressant de construire un hash dont la clé serait le nom de l'enum et la valeur, le contenu de l'enum, et ensuite, parcourir cette table pour extraire la constante et incrémenter les autres valeurs à partir de cette constante.

    Ceci doit être possible grâce à quelque chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    my %typedef = ();
    while ($CodeFichierC =~ m/
            (?:
            enum[^{]+{        # Ligne typedef avec accolade
            ([^}]+)           # contenu tout sauf accolade fermante
            }                 # accolade fermante                     
            ([^;]+)           # Nom de l'enum avant le ;
            )
            /mgix); {
      $typedef{$2} = $1;
    }
    Au passage, l'expression régulière initiale contenait une erreur (par rapport au commentaire qu'elle mentionne) : le contenu de l'enum allait jusqu'au ; et non jusqu'à l'accolade fermante comme indiqué dans le commentaire.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    C'est absolument ce que je suis en train de lui faire, avec plus de commentaires dans le code.

  7. #7
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Une autre idée serait peut-être de regarder du coté du CPAN : C::Scan::Constants
    Here's a brief overview of the module:

    * Provides a function, "extract_constants_from()", that extracts a list of information relating to #define constants and "#typedef enum" style constants found in a supplied list of C header (.h) files.
    ...
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  8. #8
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Bonne pioche, A creuser aussi, je vais le tester de suite.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Points : 53
    Points
    53
    Par défaut
    Wow je vai reluquer un coup ce module aussi, merci pour vos conseils en tout cas c'est vraiment super

    Et merci Djibril pour tes conseils, je vai les suivres

  10. #10
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    A première vue, je suis pas sur qu'il soit bien abouti (et il n'est pas très souple, car il faut lui fournir des noms de fichier, impossible de fournir un variable contenu le header déjà lu) : j'ai pas réussi à l'utiliser avec mon exemple simplissime qui fonctionnait avec le bout de code que j'ai donné plus haut.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  11. #11
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    C::Scan::Constants nécessite l'installation de mod_perl, de plus, le package d'installation n'est pas très futé donc on a pas mal de souci car nécessite l'installation de plusieurs modules. De plus après, test, il n'a pas l'air de fonctionner correctement sous windows
    Donc je ne le conseil pas pour l'instant pour un débutant.

    Donc je termine le script à ma sauce et ça ira, ça permettra à Fabien25C de mieux apprendre Perl

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Points : 53
    Points
    53
    Par défaut
    D'accord ca me va merci beaucoup

  13. #13
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Hum... chez moi, il s'est installé sans problème (cygwin). Par contre, même s'il n'est pas utilisable en tant que module, il peut contenir des choses intéressantes dans son source. A voir.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  14. #14
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Je crois avoir trouvé une raison pour laquelle il peut ne pas fonctionner sous Windows :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        # Create a temp directory here.
        my $temp_scan_dir = tempdir( 'c_scan_const_XXXXX',
                                     DIR     => '/tmp',
                                     CLEANUP => 1 )
            or die "Internal error: failed to create temp dir";
    Pas sur que /tmp existe sur tous les systèmes.
    Il eu sans doute été plus portable de ne pas préciser l'argument DIR
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  15. #15
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Bon Voici le script remis à jour.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #!/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;
        foreach my $Enumerateur ( split( ',', $ContenuBloc, -1 ) ) {
            my ( $Nomvariable, $Valeur ) = split( '=', $Enumerateur, -1 );
            $Constante{$Nomvariable} = $Valeur || 0;
        }
     
        # 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);
    Pour un fichier de type :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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

    tu as ceci en sorti :
    Defines:

    MAX_COMMAND_NUM = 255
    TOP_CAD_PRIVATE_COMMAND = 254

    ============

    Constantes definies dans les typedef:

    CARD_STATUS
    - CARD_DETECTED = 0
    - CARD_REMOVED = 0
    - CARD_SCANNED = 0
    - CARD_INSERTED = 0
    - CARD_JAM = 0
    - NO_CARD = 1
    Essaye de comprendre le script, si tu as besoin d'explication, n'hésite pas.
    NB: La regex pour récupérer les blocs enum considère que le nom de l'enum est après l'accolade fermante, comme dans ton exemple, s'il ne le trouve pas, il ne récupérera pas le bloc.

    Voilà

  16. #16
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Je crois avoir trouvé une raison pour laquelle il peut ne pas fonctionner sous Windows :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        # Create a temp directory here.
        my $temp_scan_dir = tempdir( 'c_scan_const_XXXXX',
                                     DIR     => '/tmp',
                                     CLEANUP => 1 )
            or die "Internal error: failed to create temp dir";
    Pas sur que /tmp existe sur tous les systèmes.
    Il eu sans doute été plus portable de ne pas préciser l'argument DIR
    C'est sûr , quand j'aurais un peu plus de temps, je me pencherais dessus afin d'envoyer un patch de correction.

  17. #17
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Djibril, je crois qu'il faut incrémenter les enums après celui qui est initialisé avec une valeur
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  18. #18
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Ok, correctif.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #!/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;
        foreach my $Enumerateur ( split( ',', $ContenuBloc, -1 ) ) {
            my ( $Nomvariable, $Valeur ) = split( '=', $Enumerateur, -1 );
            # si la valeur existe, on l'incremente, sinon on la met à 0
            if ( defined $Valeur) {
              $Valeur++;
            }
            else {
              $Valeur = 0;
            }
            $Constante{$Nomvariable} = $Valeur;
        }
     
        # 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);
    On obtient donc
    Defines:

    MAX_COMMAND_NUM = 255
    TOP_CAD_PRIVATE_COMMAND = 254

    ============

    Constantes definies dans les typedef:

    CARD_STATUS
    - CARD_DETECTED = 0
    - CARD_REMOVED = 0
    - CARD_SCANNED = 0
    - CARD_INSERTED = 0
    - CARD_JAM = 0
    - NO_CARD = 2
    S'il y a d'autres modifs, je pense qu'il peut se pencher dessus, je lui ai déjà mâché pas mal le boulot.

  19. #19
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Désolé Djibril, j'aurais dû être plus complet en t'indiquant l'erreur (en fournissant la correction par exemple), car ta nouvelle correction ne donne pas le bon résultat.
    Je corrige et je reposte... dans quelques minutes.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Points : 53
    Points
    53
    Par défaut
    Tout d'abord, merci beaucoup, vraiment c'est sympa

    Ensuite, il y a quelques points que je ne comprend pas bien dans ton script:

    1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    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;
    Ici, je ne comprend pas porquoi on fait "enum[^{]+{" c'est le "+{" que je ne comprend pas puis a quoi sert "/mgix".

    2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    foreach my $Enumerateur ( split( ',', $ContenuBloc, -1 ) ) 
        {
           my ( $Nomvariable, $Valeur ) = split( '=', $Enumerateur, -1 );
           $Constante{$Nomvariable} = $Valeur || 0;
        }
    Ici, je ne comprend pas les "-1".


    Je vai me replonger dans les table de hachage aussi j'ai pas mal de lacunes

    En tout cas merci beaucoup pour votre aide

Discussions similaires

  1. Parsing de fichier XML en C
    Par longbeach dans le forum XML
    Réponses: 12
    Dernier message: 12/12/2006, 16h31
  2. Parsing gros fichier performant ?
    Par jaggy19 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 09/11/2006, 13h11
  3. parsing de fichier texte
    Par robert_trudel dans le forum Access
    Réponses: 4
    Dernier message: 03/06/2006, 17h45
  4. [DOM] [DocumentBuilder] Problème de parsing de fichier
    Par tck-lt dans le forum Format d'échange (XML, JSON...)
    Réponses: 9
    Dernier message: 13/04/2006, 17h18
  5. Parsing de fichier en C++ : Au secours :(
    Par Triqueur dans le forum C++
    Réponses: 4
    Dernier message: 16/02/2006, 14h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo