Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : GFA Basic - Lire le catalogue d'une disquette
(Article écrit par Stéphane Schreiber et extrait d'Amiga News Tech - décembre 1990)
|
|
Dir-moi et List-me sont dans un bateau...
Parmi tout le courrier que nous recevons à l'ANT, plusieurs lettres posent toujours plus ou moins
la même question : "comment lire le catalogue entier d'une disquette, comme le fait la commande "DIR ALL" ?
Intéressante question, je me remercie de l'avoir posée.
Ce n'est pas tant que le but fixé soit très difficile à atteindre, mais cela demande de connaître un
tout petit peu le système, et plus particulièrement AmigaDOS. Je tiens ici à rappeler que notre célèbre
Max avait déjà donné, dans le cadre de sa rubrique "assembleur", une routine
permettant de lire le catalogue d'un répertoire. Le sous-programme GFA que je vous propose ce mois-ci
est donc en quelque sorte et comme qui dirait, une extension de la routine de Max. Mais nous allons de plus
utiliser les facilités qu'offre le BASIC dans le traitement des chaînes de caractères pour
éliminer impitoyablement les fichiers ".info" de notre répertoire, toujours sources de confusion de
l'éléphant. Notez que l'on aurait également pu éliminer les "fastdir", rejetons les outils tels que
CLIMate ou DiskMaster, mais bon, si on va par là, on peut carrément éliminer de la liste tous les fichiers,
donc ne pas écrire de routine du tout et par là-même, me mettre au chômage technique. Ce qui est loin d'être
le but recherché.
Le bon DOS
Avant de parler strictement GFA Basic, abordons, si vous le voulez bien, les quelques fonctions
d'AmigaDOS qui vont nous aider à accomplir notre tâche. Ce que je trouve le plus boulversifiant
dans tout cela, c'est qu'elles ne sont qu'au nombre de quatre :
Lock(pointeur sur le nom, mode d'accès) permet d'obtenir un "lock" (verrou) sur le répertoire à
examiner. En d'autres termes, il s'agit de demander à AmigaDOS la permission de farfouiller dans les
entrailles dudit répertoire. Ceci est nécessaire car dans un système multitâche, un autre programme peut
accéder également à ce même répertoire pour en changer le contenu ; les "locks" permettent à AmigaDOS
de s'y retrouver dans sa petite cuisine et de ne pas communiquer d'informations fausses au demandeur,
en l'occurrence nous. Le paramètre "mode d'accès" précise si l'on désire accéder à ce répertoire en lecture
(-2) ou en écriture (-1). Un accès en écriture interdit à d'autres tâches d'accéder à ce même répertoire,
tant qu'il n'a pas été libéré (voir la fonction UnLock() ci-dessous).
Lock() renvoie l'adresse d'une structure Lock qui sera nécessaire par la suite, mais dont on
n'a pas besoin de connaître le contenu. Reportez-vous aux RKRM: Includes & Autodocs si la curiosité
vous démange par trop.
UnLock(lock) est la fonction inverse de Lock() : elle signifie à AmigaDOS que l'on en a terminé
avec le répertoire que l'on avait précédemment verrouillé.
Le paramètre "lock" est l'adresse de la structure Lock renvoyée par Lock().
Examine(lock, fib) permet de lire le nom du premier fichier - ou répertoire - contenu dans le
répertoire en cours d'examen. Encore une fois, le paramètre "lock" est celui renvoyé par Lock().
Quant à "fib", il s'agit de l'adresse d'une structure FileInfoBlock longue de 260 octets qu'Examine()
remplira avec tous les renseignements dont nous avons besoin. Il est préférable qu'elle soit entièrement
remplie de 0 avant l'appel à Examine() et indispensable que son adresse soit multiple de 4, pour de vagues
raisons de BCPL à la noix. Le meilleur moyen de réunir ces deux conditions est de la créer dynamiquement
par un appel à AllocMem(). Il ne faudra alors pas oublier le FreeMem() correspondant,
complémentaire et indispensable à la fois. Examine() retourne en réponse une valeur qui, si elle est nulle,
indique une erreur, par exemple si le répertoire à examiner est vide.
ExNext(lock, fib), permet, enfin, au sein d'une boucle, de lire le nom de tous les fichiers suivants
dans le répertoire. Le paramètre "lock" est toujours le même, ainsi que "fib" - qui ne doit bien entendu
pas être réinitialisée entre temps. De même qu'Examine(), ExNext() renvoie une valeur nulle en cas
d'erreur.
Voyons maintenant de plus près le contenu de la structure FileInfoBlock, dans laquelle nous allons piocher
les informations qui nous seront utiles :
Structure FileInfoBlock (Longueur : 260 octets)
Décalage |
Nom |
Signification |
0 |
Diskkey |
Numéro de la disquette |
§ |
DirEntryType |
Type d'entrée <0 si fichier, >0 si répertoire |
8 |
FileName |
108 octets pour le nom (30 utilisés) |
116 |
Protection |
Attributs (voir la commande Protect) |
120 |
EntryType |
Type d'entrée |
124 |
Size |
Taille du fichier |
128 |
NumBlocks |
Nombre de blocs occupés |
132 |
Days |
Date de création |
136 |
Minutes |
Heure de création (minutes) |
140 |
Ticks |
Heure de création (secondes) |
144 |
Comment |
80 octets pour le commentaire |
224 |
Reserved |
36 octets réservés au DOS |
Lorsque l'on sait tout cela, l'écriture d'une routine de lecture du répertoire entier d'une disquette
devient chose simple. La preuve.
Où l'on récursive à souhait
Or donc, la routine présentée ici l'est sous forme de fonction retournant un paramètre :
le nombre de fichiers répertoriés (tiroirs compris). Ce sera peut-être gadget pour certains, mais
utiles à d'autres. Néanmoins, la transformation en procédure standard est des plus faciles.
Le principe retenu est celui de la récursivité. Il s'agit de l'une des facilités du GFA Basic les
moins souvent employées, alors qu'elle peut faire des merveilles. Je ne vous ferai pas l'affront de vous
rappeler qu'une procédure ou une fonction est récursive lorsqu'elle peut s'appeler elle-même sans perdre
le contenu de ses variables. Pour schématiser le fonctionnement, on appelle une première fois la
fonction qui commence à lire le catalogue du répertoire dont le nom a été passé en paramètre. Si l'entrée
lue est un fichier, on affiche son nom, sinon, si c'est un répertoire, on appelle récursivement la fonction
avec pour paramètre le nom de ce répertoire, qui sera à son tour examiné jusqu'au plus profond de ses
entrailles, etc. Une fois toutes les entrées de ce sous-répertoire traitées, on remonte d'un niveau dans
la récursivité et on continue jusqu'à ce que toute la disquette ait été examinée. Vous avez le droit
de relire plusieurs fois ce paragraphe si vous n'avez pas tout bien compris.
Certains se demanderont sûrement ce à quoi peut bien servir la variable "prof&" initialisée à 1 en
début de programme : tout simplement à comptabiliser le niveau de récursivité de manière à indenter
joliment la sortie à l'écran, c'est tout. Ce n'est pas parce qu'on est fainéant qu'il ne faut pas faire
les choses proprement.
Extensions possibles
Il est évidemment possible d'améliorer cette routine de moult manières, par exemple en y ajoutant un tri
des noms de fichiers, comme le fait la commande Dir du CLI, ou bien en sortant également les attributs
des fichiers, leur commentaire, etc. C'est à vous de voir. Il est même possible de la modifier pour en
faire une fonction de recherche d'un fichier sur la disquette ou un effaceur de ".BAK" global... Ce ne
sont pas les idées qui manquent.
|