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