Lecture et affichage du contenu des fichiers res (résident)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Lecture et affichage du contenu des fichiers res (résident)

Message par Anonyme2 »

Voici un code d'analyse des fichiers résidents PureBasic.
Je n'ai pas encore fait la partie des interfaces, mais bientôt j'espère.

J'ai fait beaucoup de tests, et je n'ai pas trouvé d'erreur (j'ai surtout testé les structures).

Si vous en trouvez, dites-le moi.

Code : Tout sélectionner

; Auteur : Denis
; Version de PB : 3.92
; Librairie utilisée : Aucune
; Date : 13 janvier 2005
;
; Explication du code :
; Affiche le contenu des fichiers résidents PB et utilisateurs, constantes et structures
; Les interfaces ne sont pas analysées, ça pourrait planter, c'est la prochaine étape
; Les constantes sont dans une liste chainée nommée Constantes
; Pour chaque constante, on retrouve :
;- le nom de la constante
;- le nom du fichier ou est déclarée la constantes
;- la valeur numérique dans Valeur ou la chaine dans Valeur$ lorsqu'il s'agit d'une constante chaine
; Pour savoir si c'est un constantes chaine il faut tester la longueur de la chaine

; Les structures sont en suivants dans la liste chainées, y compris les mots Structure, Endstructure
; StructureUnion et EndStructureUnion
;
; J'ai mis en commentaire l'offset de chaque élément, ca peut servir pour ceux qui voudraient utiliser
; ce code.
;
; il reste des champs dont je n'ai pas saisi l'utilité (mais pour mon besoin ce n'est pas grave)
;

Enumeration
  #Fenetre_Principale
  #ListIconConstantes
  #ListIconStructures
EndEnumeration

Structure Constante
  Nom$
  FichierResident$
  Valeur.l
  Valeur$ ; cas des constantes de texte
EndStructure

Structure Structures
  Nom$
EndStructure

NewList Constantes.Constante()
NewList Structures.Structures()

Global Nb_Structures ; comptabilise le nombre total de structures de tous les fichiers

;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
Procedure.s CheminPureBasic()
  Buffer$ = Space(260) : BufferSize = 259
  If GetVersion_() & $FF0000 ; Windows NT/XP
    clef = #HKEY_CLASSES_ROOT
    Adresse = @"Applications\PureBasic.exe\shell\open\command"
  Else ; La même chose pour Win9x
    clef = #HKEY_LOCAL_MACHINE
    Adresse = @"Software\Classes\PureBasic.exe\shell\open\command"
  EndIf
  
  If RegOpenKeyEx_(clef, Adresse, 0, #KEY_ALL_ACCESS, @Key) = #ERROR_SUCCESS
    If RegQueryValueEx_(Key, "", 0, @type, @Buffer$, @BufferSize) = #ERROR_SUCCESS
      OutputDirectory$ = GetPathPart(Mid(Buffer$, 2, Len(Buffer$) - 7))
    EndIf
    RegCloseKey_(Key)
  EndIf
  ProcedureReturn OutputDirectory$
EndProcedure
;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
Procedure LectureResident()
  PbConstantFolder$ = CheminPureBasic() + "Residents\"
  If ExamineDirectory(0, PbConstantFolder$, "")
    CheminDir = NextDirectoryEntry()
    While CheminDir
      ; les interfaces pas pris en compte, on passe les fichiers
      If CheminDir = 1 And LCase(DirectoryEntryName()) <> "interface.res"And LCase(DirectoryEntryName()) <> "interfacedx.res"
        If ReadFile(0, PbConstantFolder$ + DirectoryEntryName())
          TailleFichier = Lof()
          *ConstantsHeader = AllocateMemory(TailleFichier)
          ; *ConstantsHeader est un pointeur sur le début du texte en mémoire
          ReadData(*ConstantsHeader, TailleFichier)
          CloseFile(0)
          *ConstantsEnd = *ConstantsHeader + TailleFichier
          *SymbolCourant = *ConstantsHeader
          ; *SymbolCourant va permettre de lire les symboles en suivant
          ; Le fichier commmence par les 16 caractères suivant, si Ok on continue
          ; 'ERUP'+0,0,0,0+'3SER'+'TCRS'
          If PeekL(*SymbolCourant) = 'PURE' And PeekL(*SymbolCourant + 4) = 0 And PeekL(*SymbolCourant + 8) = 'RES3' And PeekL(*SymbolCourant + 12) = 'SRCT'
            *SymbolCourant = *ConstantsHeader + 16
            ; le fichier commence par des structures s'il y en a sinon par les constantes
            Select PeekL(*SymbolCourant)
              Case 0 ; il n'y a que des constantes, pas de structures ou interfaces
                If PeekL(*SymbolCourant + 4) = 'CNST'
                  *SymbolCourant + 12
                  While *SymbolCourant < * ConstantsEnd
                    If Len(PeekS(*SymbolCourant)) = 0
                      ; on sort s'il n'y a plus de chaines à traiter
                      Break
                    EndIf
                    If Right(PeekS(*SymbolCourant), 1) = "$" ; je ne sais pas pourquoi on retrouve
                      ; une copie de la chaine avec $ à la fin mais pas toujours (?)
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                    Else
                      AddElement(Constantes())
                      Constantes()\nom$ = PeekS(*SymbolCourant) ; lecture nom constante
                      Constantes()\FichierResident$ = DirectoryEntryName()
                      *SymbolCourant + Len(Constantes()\nom$) ; déplacement du pointeur
                      If PeekW(*SymbolCourant)
                        ; ici le word qui suit est égal à 800 au lieu de 0, c'est une valeur
                        ; alphanumérique
                        *SymbolCourant + 2
                        Constantes()\Valeur$ = PeekS(*SymbolCourant)
                        *SymbolCourant + Len(Constantes()\Valeur$) + 1
                      Else
                        ; ici c'est une valeur et pas une chaine
                        *SymbolCourant + 2
                        Constantes()\Valeur = PeekL(*SymbolCourant)
                        *SymbolCourant + 4 ; on arrive sur la nouvelle chaine
                      EndIf
                    EndIf
                  Wend
                Else
                  MessageRequester("Erreur1", "Le fichier " + DirectoryEntryName() + " n'est pas au format resident PureBasic", 16)
                EndIf
                
              Default ; on débute par les structures
                Debug "Fichier :   " + DirectoryEntryName()
                ; TotalCaracteresToutesStructures est la longueur total utilisée dans le fichier res
                ; pour stocker toutes les infos des structures
                TotalCaracteresToutesStructures = PeekL(*SymbolCourant)
                *SymbolCourant + 4 ; on avance le pointeur
                *DernierSymbol = *SymbolCourant + TotalCaracteresToutesStructures
                ; les 4 caractères qui commences à *SymbolCourant+TotalCaracteresToutesStructures
                ; sont TSNC  --> les constantes s'il y en a ou sinon une autre chaine
                
                Repeat
                  ; le champ suivant est le nom de la structure sous forme de string classique
                  Nom_Structure$ = PeekS(*SymbolCourant)
                  *SymbolCourant + Len(Nom_Structure$) + 1 ; on avance le pointeur
                  Nb_Structures + 1 ; on incrémente le compteur de structure
                  ; le champ suivant est un long donnant la taille de la structure
                  TailleStructure = PeekL(*SymbolCourant)
                  *SymbolCourant + 4 ; on avance le pointeur
                  ; le champ suivant est un word donnant le nombre d'éléments de la structure
                  Nombre_Elements = PeekW(*SymbolCourant)
                  *SymbolCourant + 3 ; on avance le pointeur (à vérifier vers Fred pour la taille du Nb_Elements)
                  AddElement(Structures())
                  ; les lignes suivantes c'est pour mettre ou non un s à la fin des mots (pluriel)
                  If Nombre_Elements > 1
                    If TailleStructure > 1
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : " + Str(TailleStructure) + " octets,  constituée de " + Str(Nombre_Elements) + " éléments"
                    Else
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : 1 octet,  constituée de " + Str(Nombre_Elements) + " éléments"
                    EndIf
                  Else
                    If TailleStructure > 1
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : " + Str(TailleStructure) + " octets,  constituée d'un élément"
                    Else
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : 1 octet,  constituée d'un élément"
                    EndIf
                  EndIf
                  Structures()\Nom$ + "  -  déclaré dans le fichier "+DirectoryEntryName()+")"
                  ; le champ suivant est un Long donnant le nombre de caractères jusqu'au 0 de fin de chaine inclus
                  ; chaine représentant le type de l'élément
                  FinStructureCourante = *SymbolCourant + PeekL(*SymbolCourant) + 4 - 1
                  Decale$ = ""
                  StructureUnion_Courante = #false ; permet d'inclure les mots StructureUnion ou EndStructureUnion
                  Offset = 0 ; Offset de l'élément courant par rapport à l'origine
                  OffsetMax = 0 ; OffsetMax va être modifié dans la boucle for suivante si pas une StructureUnion
                  ; OffsetMax mémorise l'offset max en cours, on lit pour chaque élément son offset respectif
                  ; situé dans le fichier et on compare, si offset > OffsetMax alors OffsetMax = Offset
                  ; si Offset > OffsetMax on n'est pas dans une StructureUnion, sinon c'est un élément de la StructureUnion
                  For i = 1 To Nombre_Elements
                    ; on va lire à "rebrousse poil" d'abord le type de l'élément puis son nom
                    *SymbolCourant = FinStructureCourante - 1
                    Type$ = ""
                    Char.b = PeekB(*SymbolCourant)
                    While Char
                      Type$ = Chr(Char) + Type$
                      *SymbolCourant - 1
                      Char = PeekB(*SymbolCourant)
                    Wend
                    ; normalement ici Char vaut 0 et Type$ vaut le nom du type de l'élément
                    ; on on va lire à "rebrousse poil" le nom de l'élément et le caractère
                    ; d'arrêt est soit 255 ($FF) soit 0 donc > 0
                    ; si c'est $FF ce n'est pas un tableau ($FF = -1 sur 1 octet)
                    *SymbolCourant - 1 ; on remonte avant le 0 de fin de chaine
                    Char = PeekB(*SymbolCourant)
                    While Char > 0
                      *SymbolCourant - 1
                      Char = PeekB(*SymbolCourant)
                    Wend
                    *SymbolCourant + 1
                    AddElement(Structures())
                    If Char = -1 ; ce n'est pas un tableau
                      Offset = PeekL(*SymbolCourant - 12) ; lecture de l'offset par rapport à l'adrese de base
                      ; on comparare à la valeur précédante pour déterminer ou non la StructureUnion
                      If Offset <= OffsetMax And i > 1 ; c'est une StructureUnion, on ne modifie pas OffsetMax
                        If StructureUnion_Courante = #false ; on va écrire le mot StructureUnion
                          StructureUnion_Courante = #true
                          Decale$ = "  "
                          ; il faut insérer un élément avant l'élément courant
                          SelectElement(Structures(), ListIndex(Structures()) - 2)
                          AddElement(Structures())
                          Structures()\Nom$ = Decale$ + " StructureUnion"
                          NextElement(Structures()) ; on va ajouter 3 espaces devant l'élément qui n'était pas dans la structureUnion
                          Structures()\Nom$ = Decale$ + Structures()\Nom$
                          LastElement(Structures())
                     ;   Else ; on est déjà dans la StructureUnion
                        EndIf
                      Else
                        OffsetMax = Offset
                        ; on vérifie si on est dans une StructureUnion,
                        ; si oui on écrit "EndStructureUnion"
                        If StructureUnion_Courante = #true
                          StructureUnion_Courante = #false
                          Structures()\Nom$ = Decale$ + " EndStructureUnion"
                          Decale$ = ""
                          AddElement(Structures())
                        EndIf
                      EndIf
                      Structures()\Nom$ = Decale$ + "   " + PeekS(*SymbolCourant) + "." + Type$ ; + "     Offset élément : "+Str(OffsetMax)
                    Else ; sinon c'est un tableau, le long précédant est <> de $FFFF
                      ; la valeur du tableau est située à *SymbolCourant-4 juste avant le nom de l'élément
                      ; l'oofset de l'élément est situé à *SymbolCourant-12
                      Offset = PeekL(*SymbolCourant - 12) ; lecture de l'offset par rapport à l'adrese de base
                      ; on comparare à la valeur précédante pour déterminer ou non la StructureUnion
                      If Offset <= OffsetMax And i > 1 ; c'est une StructureUnion
                        If StructureUnion_Courante = #false ; on va écrire le mot StructureUnion
                          StructureUnion_Courante = #true
                          Decale$ = "  "
                          ; il faut insérer un élément avant l'élément courant
                          If ListIndex(Structures()) - 2 >= 0 ; on teste que l'élément existe
                            SelectElement(Structures(), ListIndex(Structures()) - 2)
                          Else
                            FirstElement(Structures())
                          EndIf
                          AddElement(Structures())
                          Structures()\Nom$ = Decale$ + " StructureUnion"
                          NextElement(Structures()) ; on va ajouter 3 espaces devant l'élément qui n'était pas dans la structureUnion
                          Structures()\Nom$ = Decale$ + Structures()\Nom$
                          LastElement(Structures())
                     ;   Else ; on est déjà dans la StructureUnion
                          
                        EndIf
                      Else
                        ; on vérifie si on est dans une StructureUnion,
                        ; si oui on écrit "EndStructureUnion"
                        OffsetMax = Offset
                        If StructureUnion_Courante = #true
                          StructureUnion_Courante = #false
                          Structures()\Nom$ = Decale$ + " EndStructureUnion"
                          Decale$ = ""
                          AddElement(Structures())
                        EndIf
                      EndIf
                      Structures()\Nom$ = Decale$ + "   " + PeekS(*SymbolCourant) + "." + Type$ + "[" + Str(PeekL(*SymbolCourant - 4)) + "]" ; + "     Offset élément : "+Str(OffsetMax)
                    EndIf
                    If i < Nombre_Elements
                      FinStructureCourante + PeekL(FinStructureCourante + 1) + 4
                    EndIf
                  Next i
                  AddElement(Structures())
                  If StructureUnion_Courante = #true
                    Structures()\Nom$ = Decale$ + " EndStructureUnion"
                    Decale$ = ""
                    AddElement(Structures())
                  EndIf
                  Structures()\Nom$ = "EndStructure"
                  AddElement(Structures())
                  AddElement(Structures())
                  *SymbolCourant = FinStructureCourante + 1
                Until *SymbolCourant >= *DernierSymbol
                ; ici on en a fini avec les structures, on regarde s'il y a des constantes
                ; en arrivant ici, les 4 premiers octets de la chaine que l'on va lire doivent
                ; valoir TSNC, on teste
                *SymbolCourant = *DernierSymbol ; on positionne le pointeur
                If PeekL(*SymbolCourant) = 'CNST'
                  ; il peut y avoir plus de deux 0, donc on supprime tous les 0
                  *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                  Char.b = PeekB(*SymbolCourant)
                  While Char = 0
                    *SymbolCourant + 1
                    Char = PeekB(*SymbolCourant)
                  Wend
                  While *SymbolCourant < * ConstantsEnd
                    If Len(PeekS(*SymbolCourant)) = 0
                      ; on sort s'il n'y a plus de chaines à traiter
                      Break
                    EndIf
                    If Right(PeekS(*SymbolCourant), 1) = "$"
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                    Else
                      AddElement(Constantes())
                      Constantes()\nom$ = PeekS(*SymbolCourant) ; lecture nom constante
                      Constantes()\FichierResident$ = DirectoryEntryName()
                      *SymbolCourant + Len(Constantes()\nom$) ; déplacement du pointeur
                      If PeekW(*SymbolCourant)
                        ; ici le word qui suit est égal à 800 au lieu de 0, c'est une valeur
                        ; alphanumérique
                        *SymbolCourant + 2
                        Constantes()\Valeur$ = PeekS(*SymbolCourant)
                        *SymbolCourant + Len(Constantes()\Valeur$) + 1
                      Else
                        ; ici c'est une valeur et pas une chaîne
                        *SymbolCourant + 2
                        Constantes()\Valeur = PeekL(*SymbolCourant)
                        *SymbolCourant + 4 ; on arrive sur la nouvelle chaine
                      EndIf
                    EndIf
                  Wend
                EndIf
            EndSelect
          Else
            MessageRequester("Erreur", "Le fichier " + DirectoryEntryName() + " n'est pas au format resident PureBasic", 16)
          EndIf
          FreeMemory(*ConstantsHeader)
        EndIf
      EndIf
      CheminDir = NextDirectoryEntry()
    Wend
  EndIf
EndProcedure
;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
If OpenWindow(#Fenetre_Principale, 0, 0, 660, 408, #PB_Window_MinimizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Lecture des fichiers résidents PureBasic")
  If CreateGadgetList(WindowID(#Fenetre_Principale))
    Nb_Structures = 0
    LectureResident()
    Debug CountList(Constantes())
    ; Tri des constantes
    Dim Cst.s(CountList(Constantes()) - 1)
    ForEach Constantes()
      If Len(Constantes()\Valeur$)
        Cst.s(ListIndex(Constantes())) = Right(Constantes()\Nom$, Len(Constantes()\Nom$)) + "£" + Constantes()\Valeur$ + "£" + Constantes()\FichierResident$
      Else
        Cst.s(ListIndex(Constantes())) = Right(Constantes()\Nom$, Len(Constantes()\Nom$)) + "£$" + Hex(Constantes()\Valeur) + "£" + Constantes()\FichierResident$
      EndIf
    Next
    ; on trie; Méthode du soldat inconnu
    SortArray(Cst.s(), 2)
    
    If ListIconGadget(#ListIconConstantes, 0, 0, 660, 204, " Constante  (" + Str(CountList(Constantes())) + " références)", 270)
      AddGadgetColumn(#ListIconConstantes, 1, " Valeur", 188)
      AddGadgetColumn(#ListIconConstantes, 21, " Fichier résident", 180)
      HideGadget(#ListIconConstantes, 1)
      For i = 0 To ListIndex(Constantes()) ; Affichage  des constantes
        AddGadgetItem(#ListIconConstantes, -1, StringField(Cst.s(i), 1, "£") + Chr(10) + StringField(Cst.s(i), 2, "£") + Chr(10) + StringField(Cst.s(i), 3, "£"))
      Next
      HideGadget(#ListIconConstantes, 0)
    EndIf
    Dim cst.s(0)
    If ListIconGadget(#ListIconStructures, 0, 205, 660, 204, " Structures   (" + Str(Nb_Structures) + " références)", 640)
      HideGadget(#ListIconStructures, 1)
      
      If ListIndex(Structures()) > 0
        ForEach Structures() ; Affichage  des structures
          AddGadgetItem(#ListIconStructures, -1, Structures()\nom$)
          A$ = A$ + Structures()\nom$ + Chr(10)
        Next
        SetClipboardText(A$)
      EndIf
      HideGadget(#ListIconStructures, 0)
    EndIf
    
  EndIf
  Repeat
    If WaitWindowEvent() = #PB_EventCloseWindow : quit + 1
    EndIf
  Until quit
  
EndIf
Dernière modification par Anonyme2 le jeu. 13/janv./2005 20:49, modifié 2 fois.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

C'est génial ce prog car on a souvent des problèmes de doublons ou seulement vérifier les valeurs des constantes et des structures.

Il me dit que ces fichiers ne sont pas au format résident:
udpnetwork.res
ThreadSync.res
DnLoglib.res
SRGET.RES
Color.res
SQLite.res
MoreListIconGadget.res


Par contre, ce serait bien de pouvoir les lister dans l'ordre alphabétique.

:D
Dernière modification par nico le jeu. 13/janv./2005 19:48, modifié 1 fois.
gansta93
Messages : 1448
Inscription : jeu. 26/févr./2004 11:17
Localisation : Le Village
Contact :

Message par gansta93 »

Salut,

Bien pratique comme programme!
Un truc qui serait bien, ça serait de savoir de quel fichier vien la stricture affichée... il me semble que ça n'y est pas sinon... autant pour moi :oops:.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

gansta93 a écrit :Salut,

Bien pratique comme programme!
Un truc qui serait bien, ça serait de savoir de quel fichier vien la stricture affichée... il me semble que ça n'y est pas sinon... autant pour moi :oops:.
Oui, c'est pas trop difficile, je verrais ce que je peux faire. :D
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

nico a écrit :C'est génial ce prog car on a souvent des problèmes de doublons ou seulement vérifier les valeurs des constantes et des structures.

Il me dit que ces fichiers ne sont pas au format résident:
Fichier : PureTools_I.RES
Fichier : Variant_inc.res
Fichier : PureBasic_x86.res
Fichier : Windows.res
Fichier : PureCOLOR.res
Fichier : TB_GadgetExtension.res

Par contre, ce serait bien de pouvoir les lister dans l'ordre alphabétique.

:D
Bizzare Nico :?:

j'ai les résidents suivants
Fichier : PureBasic_x86.res
Fichier : Windows.res
Fichier : PureTools_I.RES
Fichier : TB_GadgetExtension.res
et ceux de mes libs perso

et ça ne m'affiche pas cette erreur. :roll:

Tous les fichiers que j'ai regardé et ceux que j'ai créé pour mes tests commencent par les 16 octets suivants et toujours les mêmes (en prenant un éditeur hexa, ce sont les valeurs hexa en suivant). J'affiche le message sur le format lorsque je ne trouve pas cette chaine , le test est à la ligne 85 du code

45 52 55 50 00 00 00 00 33 53 45 52 54 43 52 53

Si tu as cette erreur, c'est que tu n'as pas ces valeurs, mais je trouve ça bizarre, à moins que Fred ait mis des valeurs variables en fonction de licences, mais bon...

Tu pourrais regarder avec un éditeur hexa les 16 premières valeurs et me les donner.

Sinon pour le classement, ça devrait pouvoir se faire facilement. Je vais regarder.

J'ai environ plus de 9140 constantes et le gros de la troupe est dans le fichier Windows.res :roll:
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je n'ai pas copier les bonnes valeurs, je viens de les corriger.
il y a un résident de ta librairie qui n'est pas conforme, je précise que je n'ai pas la dernière version.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

nico a écrit :Je n'ai pas copier les bonnes valeurs, je viens de les corriger.
il y a un résident de ta librairie qui n'est pas conforme, je précise que je n'ai pas la dernière version.
Ouf, :D
des heures et des heures de prises de têtes, j'aime mieux ça

Sinon c'est quel résident ? (là encore c'est bizarre car c'est PureBasic qui les fait), mais peut-être qu'il est fait avec une ancienne version de PB....
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Je viens de remplacer le code par un code amélioré, c'est-à-dire que les constantes sont triées par nom (méthode du soldat inconnue qui fonctionne très bien) et j'ai mis le fichier d'appartenance des structures.

J'ai supprimé le # devant le nom, c'est plus lisible
gansta93
Messages : 1448
Inscription : jeu. 26/févr./2004 11:17
Localisation : Le Village
Contact :

Message par gansta93 »

Oué, trop bien !
J'ai plus rien à dire, bravo...
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Je viens de me rendre compte que lorsque les variables sont des pointeurs, ce n'est pas pris en compte par mon code.

Je suis dessus et dès que c'est prêt, je met le code ici.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Voilà le code modifié qui affiche l'élément avec le * si c'est un pointeur.

Encore quelques zones d'ombres, mais les tests que j'ai fait sont concluants.

Code : Tout sélectionner

; Auteur : Denis
; Version de PB : 3.92
; Librairie utilisée : Aucune
; Date : 13 janvier 2005
;
; Explication du code :
; Affiche le contenu des fichiers résidents PB et utilisateurs, constantes et structures
; Les interfaces ne sont pas analysées, ça pourrait planter, c'est la prochaine étape
; Les constantes sont dans une liste chainée nommée Constantes
; Pour chaque constante, on retrouve :
;- le nom de la constante
;- le nom du fichier ou est déclarée la constantes
;- la valeur numérique dans Valeur ou la chaine dans Valeur$ lorsqu'il s'agit d'une constante chaine
; Pour savoir si c'est un constantes chaine il faut tester la longueur de la chaine

; Les structures sont en suivants dans la liste chainées, y compris les mots Structure, Endstructure
; StructureUnion et EndStructureUnion
;
; J'ai mis en commentaire l'offset de chaque élément, ca peut servir pour ceux qui voudraient utiliser
; ce code.
;
; il reste des champs dont je n'ai pas saisi l'utilité (mais pour mon besoin ce n'est pas grave)

Enumeration
  #Fenetre_Principale
  #ListIconConstantes
  #ListIconStructures
EndEnumeration


; codage des éléments des structures du fichier res
; pour différencier un élément qui est un tableau d'un élément qui
; ne l'est pas, on lit le long précédant le nom de la structure (valeur collée
; au nom de l'élément). Si le long vaut -1 (=$FFFFFFFF) ce n'est pas un tableau
; on a donc 2 long pour différencier par exemple un #byte d'un #Tableau_byte
; les codes suivants correspondent au codage des éléments en fonction de leur type
; j'ai eu dans tous mes tests un valeur hexa qui revenait mais je ne suis pas arrivé 
; à savoir pourquoi. Parfois j'avais $207 au lieu de $7, mais si c'est un pointeur
; j'avais de toute façon $107, je teste si la valeur appartient à l'intervalle 
; $100 <--> $10A et si oui c'est un pointeur. Avec les byte, long etc je n'ai pas cette
; valeur $200 ajouté au code de base


;  byte                        = $1
;  word                        = $3
;  long                        = $5
;  Structure                   = $7
;  String                      = $8
;  flottant                    = $9
; 
;  Tableau_byte                = $1
;  Tableau_word                = $3
;  Tableau_long                = $5
;  Tableau_Structure           = $7
;  Tableau_String              = $8
;  Tableau_flottant            = $9
; 
;  Pointeur_byte               = $101  --> 257 en déci
;  Pointeur_word               = $103
;  Pointeur_long               = $105
;  Pointeur_Structure          = $107
;  Pointeur_String             = $108
;  Pointeur_flottant           = $109  --> 265 en déci
; 
;  Pointeur_Tableau_byte       = $101
;  Pointeur_Tableau_word       = $103
;  Pointeur_Tableau_long       = $105
;  Pointeur_Tableau_Structure  = $107
;  Pointeur_Tableau_String     = $108
;  Pointeur_Tableau_flottant   = $109

Structure Constante
  Nom$
  FichierResident$
  Valeur.l
  Valeur$ ; cas des constantes de texte
EndStructure

Structure Structures
  Nom$
EndStructure

NewList Constantes.Constante()
NewList Structures.Structures()

Global Nb_Structures ; comptabilise le nombre total de structures de tous les fichiers

;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
Procedure.s CheminPureBasic()
  Buffer$ = Space(260) : BufferSize = 259
  If GetVersion_() & $FF0000 ; Windows NT/XP
    clef = #HKEY_CLASSES_ROOT
    Adresse = @"Applications\PureBasic.exe\shell\open\command"
  Else ; La même chose pour Win9x
    clef = #HKEY_LOCAL_MACHINE
    Adresse = @"Software\Classes\PureBasic.exe\shell\open\command"
  EndIf
  
  If RegOpenKeyEx_(clef, Adresse, 0, #KEY_ALL_ACCESS, @Key) = #ERROR_SUCCESS
    If RegQueryValueEx_(Key, "", 0, @type, @Buffer$, @BufferSize) = #ERROR_SUCCESS
      OutputDirectory$ = GetPathPart(Mid(Buffer$, 2, Len(Buffer$) - 7))
    EndIf
    RegCloseKey_(Key)
  EndIf
  ProcedureReturn OutputDirectory$
EndProcedure
;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
Procedure LectureResident()
  PbConstantFolder$ = CheminPureBasic() + "Residents\"
  If ExamineDirectory(0, PbConstantFolder$, "")
    CheminDir = NextDirectoryEntry()
    While CheminDir
      ; les interfaces pas pris en compte, on passe les fichiers
      If CheminDir = 1 And LCase(DirectoryEntryName()) <> "interface.res"And LCase(DirectoryEntryName()) <> "interfacedx.res"
        If ReadFile(0, PbConstantFolder$ + DirectoryEntryName())
          TailleFichier = Lof()
          *ConstantsHeader = AllocateMemory(TailleFichier)
          ; *ConstantsHeader est un pointeur sur le début du texte en mémoire
          ReadData(*ConstantsHeader, TailleFichier)
          CloseFile(0)
          *ConstantsEnd = *ConstantsHeader + TailleFichier
          *SymbolCourant = *ConstantsHeader
          ; *SymbolCourant va permettre de lire les symboles en suivant
          ; Le fichier commmence par les 16 caractères suivant, si Ok on continue
          ; 'ERUP'+0,0,0,0+'3SER'+'TCRS'
          If PeekL(*SymbolCourant) = 'PURE' And PeekL(*SymbolCourant + 4) = 0 And PeekL(*SymbolCourant + 8) = 'RES3' And PeekL(*SymbolCourant + 12) = 'SRCT'
            *SymbolCourant + 16
            ; le fichier commence par des structures s'il y en a sinon par les constantes
            Select PeekL(*SymbolCourant)
              Case 0 ; il n'y a que des constantes, pas de structures ou interfaces
                If PeekL(*SymbolCourant + 4) = 'CNST'
                  *SymbolCourant + 12
                  While *SymbolCourant < * ConstantsEnd
                    If Len(PeekS(*SymbolCourant)) = 0
                      ; on sort s'il n'y a plus de chaines à traiter
                      Break
                    EndIf
                    If Right(PeekS(*SymbolCourant), 1) = "$" ; je ne sais pas pourquoi on retrouve
                      ; une copie de la chaine avec $ à la fin mais pas toujours (?)
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                    Else
                      AddElement(Constantes())
                      Constantes()\nom$ = PeekS(*SymbolCourant) ; lecture nom constante
                      Constantes()\FichierResident$ = DirectoryEntryName()
                      *SymbolCourant + Len(Constantes()\nom$) ; déplacement du pointeur
                      If PeekW(*SymbolCourant)
                        ; ici le word qui suit est égal à 800 au lieu de 0, c'est une valeur
                        ; alphanumérique
                        *SymbolCourant + 2
                        Constantes()\Valeur$ = PeekS(*SymbolCourant)
                        *SymbolCourant + Len(Constantes()\Valeur$) + 1
                      Else
                        ; ici c'est une valeur et pas une chaine
                        *SymbolCourant + 2
                        Constantes()\Valeur = PeekL(*SymbolCourant)
                        *SymbolCourant + 4 ; on arrive sur la nouvelle chaine
                      EndIf
                    EndIf
                  Wend
                Else
                  MessageRequester("Erreur1", "Le fichier " + DirectoryEntryName() + " n'est pas au format resident PureBasic", 16)
                EndIf
                
              Default ; on débute par les structures
                Debug "Fichier :   " + DirectoryEntryName()
                ; TotalCaracteresToutesStructures est la longueur total utilisée dans le fichier res
                ; pour stocker toutes les infos des structures
                TotalCaracteresToutesStructures = PeekL(*SymbolCourant)
                *SymbolCourant + 4 ; on avance le pointeur
                *DernierSymbol = *SymbolCourant + TotalCaracteresToutesStructures
                ; les 4 caractères qui commences à *SymbolCourant+TotalCaracteresToutesStructures
                ; sont TSNC  --> les constantes s'il y en a ou sinon une autre chaine
                
                Repeat
                  ; le champ suivant est le nom de la structure sous forme de string classique
                  Nom_Structure$ = PeekS(*SymbolCourant)
                  *SymbolCourant + Len(Nom_Structure$) + 1 ; on avance le pointeur
                  Nb_Structures + 1 ; on incrémente le compteur de structure
                  ; le champ suivant est un long donnant la taille de la structure
                  TailleStructure = PeekL(*SymbolCourant)
                  *SymbolCourant + 4 ; on avance le pointeur
                  ; le champ suivant est un word donnant le nombre d'éléments de la structure
                  Nombre_Elements = PeekW(*SymbolCourant)
                  *SymbolCourant + 3 ; on avance le pointeur (à vérifier vers Fred pour la taille du Nb_Elements)
                  AddElement(Structures())
                  ; les lignes suivantes c'est pour mettre ou non un s à la fin des mots (pluriel)
                  If Nombre_Elements > 1
                    If TailleStructure > 1
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : " + Str(TailleStructure) + " octets,  constituée de " + Str(Nombre_Elements) + " éléments"
                    Else
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : 1 octet,  constituée de " + Str(Nombre_Elements) + " éléments"
                    EndIf
                  Else
                    If TailleStructure > 1
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : " + Str(TailleStructure) + " octets,  constituée d'un élément"
                    Else
                      Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : 1 octet,  constituée d'un élément"
                    EndIf
                  EndIf
                  Structures()\Nom$ + "  -  déclaré dans le fichier "+DirectoryEntryName()+")"
                  ; le champ suivant est un Long donnant le nombre de caractères jusqu'au 0 de fin de chaine inclus
                  ; chaine représentant le type de l'élément
                  FinStructureCourante = *SymbolCourant + PeekL(*SymbolCourant) + 4 - 1
                  Decale$ = ""
                  StructureUnion_Courante = #false ; permet d'inclure les mots StructureUnion ou EndStructureUnion
                  Offset = 0 ; Offset de l'élément courant par rapport à l'origine
                  OffsetMax = 0 ; OffsetMax va être modifié dans la boucle for suivante si pas une StructureUnion
                  ; OffsetMax mémorise l'offset max en cours, on lit pour chaque élément son offset respectif
                  ; situé dans le fichier et on compare, si offset > OffsetMax alors OffsetMax = Offset
                  ; si Offset > OffsetMax on n'est pas dans une StructureUnion, sinon c'est un élément de la StructureUnion
                  For i = 1 To Nombre_Elements
                    ; on va lire à "rebrousse poil" d'abord le type de l'élément puis son nom
                    *SymbolCourant = FinStructureCourante - 1
                    Type$ = ""
                    Char.b = PeekB(*SymbolCourant)
                    While Char
                      Type$ = Chr(Char) + Type$
                      *SymbolCourant - 1
                      Char = PeekB(*SymbolCourant)
                    Wend
                    ; normalement ici Char vaut 0 et Type$ vaut le nom du type de l'élément
                    ; on on va lire à "rebrousse poil" le nom de l'élément et le caractère
                    ; d'arrêt est soit 255 ($FF) soit 0 donc > 0
                    ; si c'est $FF ce n'est pas un tableau ($FF = -1 sur 1 octet)
                    *SymbolCourant - 1 ; on remonte avant le 0 de fin de chaine
                    Char = PeekB(*SymbolCourant)
                    While Char > 0
                      *SymbolCourant - 1
                      Char = PeekB(*SymbolCourant)
                    Wend
                    *SymbolCourant + 1
                    AddElement(Structures())
                    If Char = -1 ; ce n'est pas un tableau
                      Offset = PeekL(*SymbolCourant - 12) ; lecture de l'offset par rapport à l'adrese de base
                      ; on comparare à la valeur précédante pour déterminer ou non la StructureUnion
                      If Offset <= OffsetMax And i > 1 ; c'est une StructureUnion, on ne modifie pas OffsetMax
                        If StructureUnion_Courante = #false ; on va écrire le mot StructureUnion
                          StructureUnion_Courante = #true
                          Decale$ = "  "
                          ; il faut insérer un élément avant l'élément courant
                          SelectElement(Structures(), ListIndex(Structures()) - 2)
                          AddElement(Structures())
                          Structures()\Nom$ = Decale$ + " StructureUnion"
                          NextElement(Structures()) ; on va ajouter 3 espaces devant l'élément qui n'était pas dans la structureUnion
                          Structures()\Nom$ = Decale$ + Structures()\Nom$
                          LastElement(Structures())
                     ;   Else ; on est déjà dans la StructureUnion
                        EndIf
                      Else
                        OffsetMax = Offset
                        ; on vérifie si on est dans une StructureUnion,
                        ; si oui on écrit "EndStructureUnion"
                        If StructureUnion_Courante = #true
                          StructureUnion_Courante = #false
                          Structures()\Nom$ = Decale$ + " EndStructureUnion"
                          Decale$ = ""
                          AddElement(Structures())
                        EndIf
                      EndIf
                      If PeekW(*SymbolCourant-16)>= 256 And PeekW(*SymbolCourant-16) <= 266  ; c'est un pointeur
                         Point$="*"
                      Else
                         Point$=""
                      EndIf
                      Structures()\Nom$ = Decale$ + "   " +  Point$+ PeekS(*SymbolCourant) + "." + Type$ ; + "     Offset élément : "+Str(OffsetMax)
                    Else ; sinon c'est un tableau, le long précédant est <> de $FFFF
                      ; la valeur du tableau est située à *SymbolCourant-4 juste avant le nom de l'élément
                      ; l'offset de l'élément est situé à *SymbolCourant-12
                      ; le codage pointeur est un long situé à *SymbolCourant-16, si = 5 pointeur
                      Offset = PeekL(*SymbolCourant - 12) ; lecture de l'offset par rapport à l'adrese de base
                      ; on comparare à la valeur précédante pour déterminer ou non la StructureUnion
                      If Offset <= OffsetMax And i > 1 ; c'est une StructureUnion
                        If StructureUnion_Courante = #false ; on va écrire le mot StructureUnion
                          StructureUnion_Courante = #true
                          Decale$ = "  "
                          ; il faut insérer un élément avant l'élément courant
                          If ListIndex(Structures()) - 2 >= 0 ; on teste que l'élément existe
                            SelectElement(Structures(), ListIndex(Structures()) - 2)
                          Else
                            FirstElement(Structures())
                          EndIf
                          AddElement(Structures())
                          Structures()\Nom$ = Decale$ + " StructureUnion"
                          NextElement(Structures()) ; on va ajouter 3 espaces devant l'élément qui n'était pas dans la structureUnion
                          Structures()\Nom$ = Decale$ + Structures()\Nom$
                          LastElement(Structures())
                     ;   Else ; on est déjà dans la StructureUnion
                          
                        EndIf
                      Else
                        ; on vérifie si on est dans une StructureUnion,
                        ; si oui on écrit "EndStructureUnion"
                        OffsetMax = Offset
                        If StructureUnion_Courante = #true
                          StructureUnion_Courante = #false
                          Structures()\Nom$ = Decale$ + " EndStructureUnion"
                          Decale$ = ""
                          AddElement(Structures())
                        EndIf
                      EndIf

                      If PeekW(*SymbolCourant-16)>= 256 And PeekW(*SymbolCourant-16) <= 266  ; c'est un pointeur
                         Point$="*"
                      Else
                         Point$=""
                      EndIf
                      Structures()\Nom$ = Decale$ + "   " + Point$+PeekS(*SymbolCourant) + "." + Type$ + "[" + Str(PeekL(*SymbolCourant - 4)) + "]" ; + "     Offset élément : "+Str(OffsetMax)
                    EndIf
                    If i < Nombre_Elements
                      FinStructureCourante + PeekL(FinStructureCourante + 1) + 4
                    EndIf
                  Next i
                  AddElement(Structures())
                  If StructureUnion_Courante = #true
                    Structures()\Nom$ = Decale$ + " EndStructureUnion"
                    Decale$ = ""
                    AddElement(Structures())
                  EndIf
                  Structures()\Nom$ = "EndStructure"
                  AddElement(Structures())
                  AddElement(Structures())
                  *SymbolCourant = FinStructureCourante + 1
                Until *SymbolCourant >= *DernierSymbol
                ; ici on en a fini avec les structures, on regarde s'il y a des constantes
                ; en arrivant ici, les 4 premiers octets de la chaine que l'on va lire doivent
                ; valoir TSNC, on teste
                *SymbolCourant = *DernierSymbol ; on positionne le pointeur
                If PeekL(*SymbolCourant) = 'CNST'
                  ; il peut y avoir plus de deux 0, donc on supprime tous les 0
                  *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                  Char.b = PeekB(*SymbolCourant)
                  While Char = 0
                    *SymbolCourant + 1
                    Char = PeekB(*SymbolCourant)
                  Wend
                  While *SymbolCourant < * ConstantsEnd
                    If Len(PeekS(*SymbolCourant)) = 0
                      ; on sort s'il n'y a plus de chaines à traiter
                      Break
                    EndIf
                    If Right(PeekS(*SymbolCourant), 1) = "$"
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                      *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                    Else
                      AddElement(Constantes())
                      Constantes()\nom$ = PeekS(*SymbolCourant) ; lecture nom constante
                      Constantes()\FichierResident$ = DirectoryEntryName()
                      *SymbolCourant + Len(Constantes()\nom$) ; déplacement du pointeur
                      If PeekW(*SymbolCourant)
                        ; ici le word qui suit est égal à 800 au lieu de 0, c'est une valeur
                        ; alphanumérique
                        *SymbolCourant + 2
                        Constantes()\Valeur$ = PeekS(*SymbolCourant)
                        *SymbolCourant + Len(Constantes()\Valeur$) + 1
                      Else
                        ; ici c'est une valeur et pas une chaîne
                        *SymbolCourant + 2
                        Constantes()\Valeur = PeekL(*SymbolCourant)
                        *SymbolCourant + 4 ; on arrive sur la nouvelle chaine
                      EndIf
                    EndIf
                  Wend
                EndIf
            EndSelect
          Else
            MessageRequester("Erreur", "Le fichier " + DirectoryEntryName() + " n'est pas au format resident PureBasic", 16)
          EndIf
          FreeMemory(*ConstantsHeader)
        EndIf
      EndIf
      CheminDir = NextDirectoryEntry()
    Wend
  EndIf
EndProcedure
;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
If OpenWindow(#Fenetre_Principale, 0, 0, 660, 408, #PB_Window_MinimizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Lecture des fichiers résidents PureBasic")
  If CreateGadgetList(WindowID(#Fenetre_Principale))
    Nb_Structures = 0
    LectureResident()
    Debug CountList(Constantes())
    ; Tri des constantes
    Dim Cst.s(CountList(Constantes()) - 1)
    ForEach Constantes()
      If Len(Constantes()\Valeur$)
        Cst.s(ListIndex(Constantes())) = Right(Constantes()\Nom$, Len(Constantes()\Nom$)) + "£" + Constantes()\Valeur$ + "£" + Constantes()\FichierResident$
      Else
        Cst.s(ListIndex(Constantes())) = Right(Constantes()\Nom$, Len(Constantes()\Nom$)) + "£$" + Hex(Constantes()\Valeur) + "£" + Constantes()\FichierResident$
      EndIf
    Next
    ; on trie; Méthode du soldat inconnu
    SortArray(Cst.s(), 2)
    
    If ListIconGadget(#ListIconConstantes, 0, 0, 660, 204, " Constante  (" + Str(CountList(Constantes())) + " références)", 270)
      AddGadgetColumn(#ListIconConstantes, 1, " Valeur", 188)
      AddGadgetColumn(#ListIconConstantes, 21, " Fichier résident", 180)
      HideGadget(#ListIconConstantes, 1)
      For i = 0 To ListIndex(Constantes()) ; Affichage  des constantes
        AddGadgetItem(#ListIconConstantes, -1, StringField(Cst.s(i), 1, "£") + Chr(10) + StringField(Cst.s(i), 2, "£") + Chr(10) + StringField(Cst.s(i), 3, "£"))
      Next
      HideGadget(#ListIconConstantes, 0)
    EndIf
    Dim cst.s(0)
    If ListIconGadget(#ListIconStructures, 0, 205, 660, 204, " Structures   (" + Str(Nb_Structures) + " références)", 640)
      HideGadget(#ListIconStructures, 1)
      
      If ListIndex(Structures()) > 0
        ForEach Structures() ; Affichage  des structures
          AddGadgetItem(#ListIconStructures, -1, Structures()\nom$)
          A$ = A$ + Structures()\nom$ + Chr(10)
        Next
        SetClipboardText(A$)
      EndIf
      HideGadget(#ListIconStructures, 0)
    EndIf
    
  EndIf
  Repeat
    If WaitWindowEvent() = #PB_EventCloseWindow : quit + 1
    EndIf
  Until quit
  
EndIf
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Une petite précison

Il y a 3 formats de resident , ou plutot 3 versions dont le codage diffère (Fred me l'a dit).

Le code ci-dessus ne lit que les résidents version 3.
Si j'arrive à coder pour les 2 autres versions, je poste le code. :roll:
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

J'ai modifié le code pour le support des résident version 1, j'ai plusieurs fichiers de ce type (lib utilisateurs)

Je pense que les versions ont évolué en fonction d'ajout des interfaces (passage de la version 2 à 3 ?), de l'ajout des StructuresUnion (passage de la version 1 à la version 2 ?) , enfin c'est ce que je comprend en étudiant les fichiers résidents.

Pour les résidents version 2 je n'en ai pas mais je vais télécharger toutes les librairies de Purearea et il doit bien y en avoir :roll:

D'ici quelque temps, il y aura une version améliorée avec les interfaces et une sélection possible des structures et interfaces, mais ça fait partie d'un code beaucoup plus conséquent.

Code : Tout sélectionner

; Auteur : Denis
; Version de PB : 3.93
; Librairie utilisée : Aucune
; Date : 13 janvier 2005  
; Modifié le 10 mars pour le support résident version 1
;
; Explication du code :
; Affiche le contenu des fichiers résidents PB et utilisateurs, constantes et structures
; Les interfaces ne sont pas analysées, ça pourrait planter, c'est la prochaine étape
; Les constantes sont dans une liste chainée nommée Constantes
; Pour chaque constante, on retrouve :
;- le nom de la constante
;- le nom du fichier ou est déclarée la constantes
;- la valeur numérique dans Valeur ou la chaine dans Valeur$ lorsqu'il s'agit d'une constante chaine
; Pour savoir si c'est un constantes chaine il faut tester la longueur de la chaine

; Les structures sont en suivants dans la liste chainées, y compris les mots Structure, Endstructure
; StructureUnion et EndStructureUnion
;
; J'ai mis en commentaire l'offset de chaque élément, ca peut servir pour ceux qui voudraient utiliser
; ce code.
;
; il reste des champs dont je n'ai pas saisi l'utilité (mais pour mon besoin ce n'est pas grave)

Enumeration
   #Fenetre_Principale
   #ListIconConstantes
   #ListIconStructures
EndEnumeration

#res1 = 1 ; format resident version 1
#res2 = 2 ; format resident version 2
#res3 = 3 ; format resident version 3

; codage des éléments des structures du fichier res
; pour différencier un élément qui est un tableau d'un élément qui
; ne l'est pas, on lit le long précédant le nom de la structure (valeur collée
; au nom de l'élément). Si le long vaut -1 (=$FFFFFFFF) ce n'est pas un tableau
; on a donc 2 long pour différencier par exemple un #byte d'un #Tableau_byte
; les codes suivants correspondent au codage des éléments en fonction de leur type
; j'ai eu dans tous mes tests un valeur hexa qui revenait mais je ne suis pas arrivé
; à savoir pourquoi. Parfois j'avais $207 au lieu de $7, mais si c'est un pointeur
; j'avais de toute façon $107, je teste si la valeur appartient à l'intervalle
; $100 <--> $10A et si oui c'est un pointeur. Avec les byte, long etc je n'ai pas cette
; valeur $200 ajouté au code de base


; byte                        = $1
; word                        = $3
; long                        = $5
; Structure                   = $7
; String                      = $8
; flottant                    = $9
;

; Tableau_byte                = $1
; Tableau_word                = $3
; Tableau_long                = $5
; Tableau_Structure           = $7
; Tableau_String              = $8
; Tableau_flottant            = $9
;
; Pointeur_byte               = $101  --> 257 en déci
; Pointeur_word               = $103
; Pointeur_long               = $105
; Pointeur_Structure          = $107
; Pointeur_String             = $108
; Pointeur_flottant           = $109  --> 265 en déci
;
; Pointeur_Tableau_byte       = $101
; Pointeur_Tableau_word       = $103
; Pointeur_Tableau_long       = $105
; Pointeur_Tableau_Structure  = $107
; Pointeur_Tableau_String     = $108
; Pointeur_Tableau_flottant   = $109

Structure Constante
   Nom$
   FichierResident$
   Valeur.l
   Valeur$ ; cas des constantes de texte
EndStructure

Structure Structures
   Nom$
EndStructure

NewList Constantes.Constante()
NewList Structures.Structures()

Global Nb_Structures ; comptabilise le nombre total de structures de tous les fichiers

;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
Procedure.s CheminPureBasic()
   Buffer$ = Space(260) : BufferSize = 259
   If GetVersion_() & $FF0000 ; Windows NT/XP
      clef = #HKEY_CLASSES_ROOT
      Adresse = @"Applications\PureBasic.exe\shell\open\command"
   Else ; La même chose pour Win9x
      clef = #HKEY_LOCAL_MACHINE
      Adresse = @"Software\Classes\PureBasic.exe\shell\open\command"
   EndIf
   
   If RegOpenKeyEx_(clef, Adresse, 0, #KEY_ALL_ACCESS, @Key) = #ERROR_SUCCESS
      If RegQueryValueEx_(Key, "", 0, @type, @Buffer$, @BufferSize) = #ERROR_SUCCESS
         OutputDirectory$ = GetPathPart(Mid(Buffer$, 2, Len(Buffer$) - 7))
      EndIf
      RegCloseKey_(Key)
   EndIf
   ProcedureReturn OutputDirectory$
EndProcedure
;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
Procedure LectureResident()
   PbConstantFolder$ = CheminPureBasic() + "Residents\"
   If ExamineDirectory(0, PbConstantFolder$, "*.res")
      CheminDir = NextDirectoryEntry()
      While CheminDir
         ; les interfaces pas pris en compte, on passe les fichiers
         If CheminDir = 1 And LCase(DirectoryEntryName()) <> "interface.res"And LCase(DirectoryEntryName()) <> "interfacedx.res"
            If ReadFile(0, PbConstantFolder$ + DirectoryEntryName())
               TailleFichier = Lof()
               *ConstantsHeader = AllocateMemory(TailleFichier)
               ; *ConstantsHeader est un pointeur sur le début du texte en mémoire
               ReadData(*ConstantsHeader, TailleFichier)
               CloseFile(0)
               *ConstantsEnd = *ConstantsHeader + TailleFichier
               *SymbolCourant = *ConstantsHeader
               ; *SymbolCourant va permettre de lire les symboles en suivant
               ; Le fichier commmence par les 16 caractères suivant, si Ok on continue
               ; 'ERUP'+0,0,0,0+'3SER'+'TCRS' ou 'ERUP'+0,0,0,0+'1SER'+'TCRS'
               If CompareMemory(*SymbolCourant, ?Fichier_Res3, 16)
                  RES = #res3
               ElseIf CompareMemory(*SymbolCourant, ?Fichier_Res1, 16)
                  RES = #res1
               Else
                  RES = 0
               EndIf
               If RES
                  *SymbolCourant + 16
                  ; le fichier commence par des structures s'il y en a sinon par les constantes
                  Select PeekL(*SymbolCourant)
                     Case 0 ; il n'y a que des constantes, pas de structures ou interfaces
                        If PeekL(*SymbolCourant + 4) = 'CNST'
                           *SymbolCourant + 12
                           While *SymbolCourant < * ConstantsEnd
                              If Len(PeekS(*SymbolCourant)) = 0
                                 ; on sort s'il n'y a plus de chaines à traiter
                                 Break
                              EndIf
                              If Right(PeekS(*SymbolCourant), 1) = "$" ; je ne sais pas pourquoi on retrouve
                                 ; une copie de la chaine avec $ à la fin mais pas toujours (?)
                                 *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                                 *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                              Else
                                 AddElement(Constantes())
                                 Constantes()\nom$ = PeekS(*SymbolCourant) ; lecture nom constante
                                 Constantes()\FichierResident$ = DirectoryEntryName()
                                 *SymbolCourant + Len(Constantes()\nom$) ; déplacement du pointeur
                                 If RES <> #res1
                                 If PeekW(*SymbolCourant)
                                    ; ici le word qui suit est égal à 800 au lieu de 0, c'est une valeur
                                    ; alphanumérique
                                    *SymbolCourant + 2
                                    Constantes()\Valeur$ = PeekS(*SymbolCourant)
                                    *SymbolCourant + Len(Constantes()\Valeur$) + 1
                                 Else
                                    ; ici c'est une valeur et pas une chaine
                                    *SymbolCourant + 2
                                    Constantes()\Valeur = PeekL(*SymbolCourant)
                                    *SymbolCourant + 4 ; on arrive sur la nouvelle chaine
                                 EndIf
                                    Else
                                       Constantes()\Valeur = PeekL(*SymbolCourant + 1)
                                       *SymbolCourant + 5
                                    EndIf
                              EndIf
                           Wend
                        Else
                           MessageRequester("Erreur1", "Le fichier " + DirectoryEntryName() + " n'est pas au format resident PureBasic", 16)
                        EndIf
                        
                     Default ; on débute par les structures
;                         Debug "Fichier :   " + DirectoryEntryName()
                        ; TotalCaracteresToutesStructures est la longueur total utilisée dans le fichier res
                        ; pour stocker toutes les infos des structures
                        TotalCaracteresToutesStructures = PeekL(*SymbolCourant)
                        *SymbolCourant + 4 ; on avance le pointeur
                        *DernierSymbol = *SymbolCourant + TotalCaracteresToutesStructures
                        ; les 4 caractères qui commences à *SymbolCourant+TotalCaracteresToutesStructures
                        ; sont TSNC  --> les constantes s'il y en a ou sinon une autre chaine
                        
                        Repeat
                           ; le champ suivant est le nom de la structure sous forme de string classique
                           Nom_Structure$ = PeekS(*SymbolCourant)
                           *SymbolCourant + Len(Nom_Structure$) + 1 ; on avance le pointeur
                           Nb_Structures + 1 ; on incrémente le compteur de structure
                           ; le champ suivant est un long donnant la taille de la structure
                           TailleStructure = PeekL(*SymbolCourant)
                           *SymbolCourant + 4 ; on avance le pointeur
                           ; le champ suivant est un word donnant le nombre d'éléments de la structure
                           Nombre_Elements = PeekW(*SymbolCourant)
                           If RES = #res1
                              *SymbolCourant + 4 ; on avance le pointeur
                           Else
                              *SymbolCourant + 3 ; on avance le pointeur
                           EndIf
                           
                           AddElement(Structures())
                           ; les lignes suivantes c'est pour mettre ou non un s à la fin des mots (pluriel)
                           If Nombre_Elements > 1
                              If TailleStructure > 1
                                 Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : " + Str(TailleStructure) + " octets,  constituée de " + Str(Nombre_Elements) + " éléments"
                              Else
                                 Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : 1 octet,  constituée de " + Str(Nombre_Elements) + " éléments"
                              EndIf
                           Else
                              If TailleStructure > 1
                                 Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : " + Str(TailleStructure) + " octets,  constituée d'un élément"
                              Else
                                 Structures()\Nom$ = "Structure  " + Nom_Structure$ + "   (taille : 1 octet,  constituée d'un élément"
                              EndIf
                           EndIf
                           Structures()\Nom$ + "  -  déclaré dans le fichier " + DirectoryEntryName() + ")"
                           ; le champ suivant est un Long donnant le nombre de caractères jusqu'au 0 de fin de chaine inclus
                           ; chaine représentant le type de l'élément
                           FinStructureCourante = *SymbolCourant + PeekL(*SymbolCourant) + 4 - 1
                           Decale$ = ""
                           StructureUnion_Courante = #false ; permet d'inclure les mots StructureUnion ou EndStructureUnion
                           Offset = 0 ; Offset de l'élément courant par rapport à l'origine
                           OffsetMax = 0 ; OffsetMax va être modifié dans la boucle for suivante si pas une StructureUnion
                           ; OffsetMax mémorise l'offset max en cours, on lit pour chaque élément son offset respectif
                           ; situé dans le fichier et on compare, si offset > OffsetMax alors OffsetMax = Offset
                           ; si Offset > OffsetMax on n'est pas dans une StructureUnion, sinon c'est un élément de la StructureUnion
                           For i = 1 To Nombre_Elements
                              ; on va lire à "rebrousse poil" d'abord le type de l'élément puis son nom
                              *SymbolCourant = FinStructureCourante - 1
                              Type$ = ""
                              Char.b = PeekB(*SymbolCourant)
                              While Char
                                 Type$ = Chr(Char) + Type$
                                 *SymbolCourant - 1
                                 Char = PeekB(*SymbolCourant)
                              Wend
                              ; normalement ici Char vaut 0 et Type$ vaut le nom du type de l'élément
                              ; on on va lire à "rebrousse poil" le nom de l'élément et le caractère
                              ; d'arrêt est soit 255 ($FF) soit 0 donc > 0
                              ; si c'est $FF ce n'est pas un tableau ($FF = -1 sur 1 octet)
                              *SymbolCourant - 1 ; on remonte avant le 0 de fin de chaine
                              Char = PeekB(*SymbolCourant)
                              While Char > 0
                                 *SymbolCourant - 1
                                 Char = PeekB(*SymbolCourant)
                              Wend
                              *SymbolCourant + 1
                              AddElement(Structures())
                              If Char = -1 ; ce n'est pas un tableau
                                 If RES > #res1 ; structureunion seulement si version > 1
                                    Offset = PeekL(*SymbolCourant - 12) ; lecture de l'offset par rapport à l'adrese de base
                                    ; on comparare à la valeur précédante pour déterminer ou non la StructureUnion
                                    If Offset <= OffsetMax And i > 1 ; c'est une StructureUnion, on ne modifie pas OffsetMax
                                       If StructureUnion_Courante = #false ; on va écrire le mot StructureUnion
                                          StructureUnion_Courante = #true
                                          Decale$ = "  "
                                          ; il faut insérer un élément avant l'élément courant
                                          SelectElement(Structures(), ListIndex(Structures()) - 2)
                                          AddElement(Structures())
                                          Structures()\Nom$ = Decale$ + " StructureUnion"
                                          NextElement(Structures()) ; on va ajouter 3 espaces devant l'élément qui n'était pas dans la structureUnion
                                          Structures()\Nom$ = Decale$ + Structures()\Nom$
                                          LastElement(Structures())
                                          ; Else ; on est déjà dans la StructureUnion
                                       EndIf
                                    Else
                                       OffsetMax = Offset
                                       ; on vérifie si on est dans une StructureUnion,
                                       ; si oui on écrit "EndStructureUnion"
                                       If StructureUnion_Courante = #true
                                          StructureUnion_Courante = #false
                                          Structures()\Nom$ = Decale$ + " EndStructureUnion"
                                          Decale$ = ""
                                          AddElement(Structures())
                                       EndIf
                                    EndIf
                                 EndIf
                                 If RES = #res1
                                    type = PeekB(*SymbolCourant - 12)
                                 Else
                                    type = PeekW(*SymbolCourant - 16)
                                 EndIf
                                 If type >= 256 And type <= 266 ; c'est un pointeur
                                    Point$ = "*"
                                 Else
                                    Point$ = ""
                                 EndIf
                                 Structures()\Nom$ = Decale$ + "   " + Point$ + PeekS(*SymbolCourant) + "." + Type$
                              Else ; sinon c'est un tableau, le long précédant est <> de $FFFF
                                 ; la valeur du tableau est située à *SymbolCourant-4 juste avant le nom de l'élément
                                 ; l'offset de l'élément est situé à *SymbolCourant-12
                                 ; le codage pointeur est un long situé à *SymbolCourant-16, si = 5 pointeur
                                 Offset = PeekL(*SymbolCourant - 12) ; lecture de l'offset par rapport à l'adrese de base
                                 If RES > #res1 ; structureunion seulement si version > 1
                                    ; on comparare à la valeur précédante pour déterminer ou non la StructureUnion
                                    If Offset <= OffsetMax And i > 1 ; c'est une StructureUnion
                                       If StructureUnion_Courante = #false ; on va écrire le mot StructureUnion
                                          StructureUnion_Courante = #true
                                          Decale$ = "  "
                                          ; il faut insérer un élément avant l'élément courant
                                          If ListIndex(Structures()) - 2 >= 0 ; on teste que l'élément existe
                                             SelectElement(Structures(), ListIndex(Structures()) - 2)
                                          Else
                                             FirstElement(Structures())
                                          EndIf
                                          AddElement(Structures())
                                          Structures()\Nom$ = Decale$ + " StructureUnion"
                                          NextElement(Structures()) ; on va ajouter 3 espaces devant l'élément qui n'était pas dans la structureUnion
                                          Structures()\Nom$ = Decale$ + Structures()\Nom$
                                          LastElement(Structures())
                                          ; Else ; on est déjà dans la StructureUnion
                                       EndIf
                                    Else
                                       ; on vérifie si on est dans une StructureUnion,
                                       ; si oui on écrit "EndStructureUnion"
                                       OffsetMax = Offset
                                       If StructureUnion_Courante = #true
                                          StructureUnion_Courante = #false
                                          Structures()\Nom$ = Decale$ + " EndStructureUnion"
                                          Decale$ = ""
                                          AddElement(Structures())
                                       EndIf
                                    EndIf
                                 EndIf
                                 If RES = #res1
                                    TailleTableau = PeekW(*SymbolCourant - 2)
                                    type = PeekB(*SymbolCourant - 12)
                                 Else
                                    TailleTableau = PeekL(*SymbolCourant - 4)
                                    type = PeekW(*SymbolCourant - 16)
                                 EndIf
                                 If type >= 256 And type <= 266 ; c'est un pointeur
                                    Point$ = "*"
                                 Else
                                    Point$ = ""
                                 EndIf
                                 Structures()\Nom$ = Decale$ + "   " + Point$ + PeekS(*SymbolCourant) + "." + Type$ + "[" + Str(TailleTableau) + "]"
                              EndIf
                              If i < Nombre_Elements
                                 FinStructureCourante + PeekL(FinStructureCourante + 1) + 4
                              EndIf
                           Next i
                           AddElement(Structures())
                           If StructureUnion_Courante = #true
                              Structures()\Nom$ = Decale$ + " EndStructureUnion"
                              Decale$ = ""
                              AddElement(Structures())
                           EndIf
                           Structures()\Nom$ = "EndStructure"
                           AddElement(Structures())
                           AddElement(Structures())
                           *SymbolCourant = FinStructureCourante + 1
                        Until *SymbolCourant >= *DernierSymbol
                        ; ici on en a fini avec les structures, on regarde s'il y a des constantes
                        ; en arrivant ici, les 4 premiers octets de la chaine que l'on va lire doivent
                        ; valoir TSNC, on teste
                        *SymbolCourant = *DernierSymbol ; on positionne le pointeur
                        If PeekL(*SymbolCourant) = 'CNST'
                           ; il peut y avoir plus de deux 0, donc on supprime tous les 0
                           If RES = #res1
                              *SymbolCourant + Len(PeekS(*SymbolCourant)) + 3
                           Else
                              *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                              Char.b = PeekB(*SymbolCourant)
                              While Char = 0
                                 *SymbolCourant + 1
                                 Char = PeekB(*SymbolCourant)
                              Wend
                           EndIf
                           While *SymbolCourant < * ConstantsEnd
                              If Len(PeekS(*SymbolCourant)) = 0
                                 ; on sort s'il n'y a plus de chaines à traiter
                                 Break
                              EndIf
                              If Right(PeekS(*SymbolCourant), 1) = "$"
                                 *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                                 *SymbolCourant + Len(PeekS(*SymbolCourant)) + 1
                              Else
                                 AddElement(Constantes())
                                 Constantes()\nom$ = PeekS(*SymbolCourant) ; lecture nom constante
                                 Constantes()\FichierResident$ = DirectoryEntryName()
                                 *SymbolCourant + Len(Constantes()\nom$) ; déplacement du pointeur
                                 If RES <> #res1
                                 If PeekW(*SymbolCourant)
                                    ; ici le word qui suit est égal à 800 au lieu de 0, c'est une valeur
                                    ; alphanumérique
                                    *SymbolCourant + 2
                                    Constantes()\Valeur$ = PeekS(*SymbolCourant)
                                    *SymbolCourant + Len(Constantes()\Valeur$) + 1
                                 Else
                                    ; ici c'est une valeur et pas une chaîne
                                    *SymbolCourant + 2
                                    Constantes()\Valeur = PeekL(*SymbolCourant)
                                    *SymbolCourant + 4 ; on arrive sur la nouvelle chaine
                                 EndIf
                                 Else
                                    Constantes()\Valeur = PeekL(*SymbolCourant + 1)
                                    *SymbolCourant + 5
                                 EndIf
                              EndIf
                           Wend
                        EndIf
                  EndSelect
               Else
                  MessageRequester("Erreur", "Le fichier " + DirectoryEntryName() + " n'est pas au format resident PureBasic", 16)
               EndIf
               FreeMemory(*ConstantsHeader)
            EndIf
         EndIf
         CheminDir = NextDirectoryEntry()
      Wend
   EndIf
EndProcedure
;/ /\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
If OpenWindow(#Fenetre_Principale, 0, 0, 660, 408, #PB_Window_MinimizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Lecture des fichiers résidents PureBasic")
   If CreateGadgetList(WindowID(#Fenetre_Principale))
      Nb_Structures = 0
      LectureResident()
      ; Tri des constantes
      Dim Cst.s(CountList(Constantes()) - 1)
      ForEach Constantes()
         If Len(Constantes()\Valeur$)
            Cst.s(ListIndex(Constantes())) = Right(Constantes()\Nom$, Len(Constantes()\Nom$)) + "£" + Constantes()\Valeur$ + "£" + Constantes()\FichierResident$
         Else
            Cst.s(ListIndex(Constantes())) = Right(Constantes()\Nom$, Len(Constantes()\Nom$)) + "£$" + Hex(Constantes()\Valeur) + "£" + Constantes()\FichierResident$
         EndIf
      Next
      ; on trie; Méthode du soldat inconnu
      SortArray(Cst.s(), 2)
      
      If ListIconGadget(#ListIconConstantes, 0, 0, 660, 204, " Constante  (" + Str(CountList(Constantes())) + " références)", 270)
         AddGadgetColumn(#ListIconConstantes, 1, " Valeur", 188)
         AddGadgetColumn(#ListIconConstantes, 21, " Fichier résident", 180)
         HideGadget(#ListIconConstantes, 1)
         For i = 0 To ListIndex(Constantes()) ; Affichage  des constantes
            AddGadgetItem(#ListIconConstantes, -1, StringField(Cst.s(i), 1, "£") + Chr(10) + StringField(Cst.s(i), 2, "£") + Chr(10) + StringField(Cst.s(i), 3, "£"))
         Next
         HideGadget(#ListIconConstantes, 0)
      EndIf
      Dim cst.s(0)
      If ListIconGadget(#ListIconStructures, 0, 205, 660, 204, " Structures   (" + Str(Nb_Structures) + " références)", 640)
         HideGadget(#ListIconStructures, 1)
         
         If ListIndex(Structures()) > 0
            ForEach Structures() ; Affichage  des structures
               AddGadgetItem(#ListIconStructures, -1, Structures()\nom$)
               A$ = A$ + Structures()\nom$ + Chr(10)
            Next
            SetClipboardText(A$)
         EndIf
         HideGadget(#ListIconStructures, 0)
      EndIf
      
   EndIf
   Repeat
      If WaitWindowEvent() = #PB_EventCloseWindow : quit + 1
      EndIf
   Until quit
   
EndIf

DataSection
   Fichier_Res3 :
      Data .b $45, $52, $55, $50, $00, $00, $00, $00, $33, $53, $45, $52, $54, $43, $52, $53
   Fichier_Res2 :
      Data .b $45, $52, $55, $50, $00, $00, $00, $00, $32, $53, $45, $52, $54, $43, $52, $53
   Fichier_Res1 :
      Data .b $45, $52, $55, $50, $00, $00, $00, $00, $31, $53, $45, $52, $54, $43, $52, $53
EndDataSection ;}
bernard13
Messages : 1221
Inscription : mer. 05/janv./2005 21:30

Message par bernard13 »

je vois pas l'interet de faire ça
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Et quel est l'intérêt de ta réponse :twisted: franchement, va falloir respecter un peu plus le travail des autres parce que des répliques du genre, on s'en moque complètement :evil:
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre