	Fonction de recherche avec sous rpertoires
	*******************************************

	Il y a des fois ou on aimerait inclure une petite fonction de
recherche de fichiers qui prend en compte les sous-rpertoires et leur
contenu. Vous pouvez ainsi calculer la taille du contenu d'un dossier,
afficher l'arborescence d'un disque, rechercher des extensions
particulires et que sais-je encore...

L'aide du systme
-----------------
	Deux fonctions du GEMDOS vont tre utilises: FSFIRST (file
search first = cherche premier fichier) et FSNEXT (file search next =
cherche fichier suivant). La premire, comme son nom l'indique, doit tre
appele en premier: c'est  elle qu'on passe les arguments de recherche.
La seconde ne fait qu'avancer dans le rpertoire en reprenant les
arguments de la premire.
	En sortie, ces deux fonctions renvoient soit code d'erreur ngatif
soit zro si un fichier existe et remplissent la DTA. La description se
trouve en figure 1.

Le principe de recherche
------------------------
	Vous en trouverez une description sommaire dans la figure n2
quelque part sur cette page....


Il y a un os...
---------------
	Prenons un rpertoire GLOUGLOU contenant un rpertoire TOTO.
Lorsque j'ouvre TOTO, je dois rappeler FSFIRST pour me placer au dbut de
son contenu mais alors... le FSFIRST dans TOTO a recouvert les
informations du FSFIRST de GLOUGLOU. Il arrive un moment ou FSNEXT me
renvoit "Plus d'objet", je dois alors refermer TOTO. Pourtant, j'ai beau
en sortir, le FSNEXT suivant continue  travailler comme si il tait
encore dans TOTO: je vais recevoir systmatiquement "Plus d'objets" car
le lien avec les infos de GLOUGLOU est perdu! Malheureusement, il y a de
grandes chances pour que mon rpertoire GLOUGLOU ne soit pas termin.

...qu'on peut contourner!
-------------------------
        Il suffit de conserver les informations de la DTA telle qu'elle
tait juste avant d'ouvrir TOTO. En la restaurant  la fermeture de
celui-ci, je reprend mon travail l o je l'avais laiss.
	Sachant que cette zone contient 44 octets, on peut en caser 23
dans un simple kilo octet: c'est largement suffisant! Mme sur un CD, il
est rare de trouver un rpertoire inclus dans un autre, inclus dans un
autre, inclus dans un autre.... avec 23 niveaux de profondeur.
	La fonction utilse pour modifier l'adresse de la DTA est FSETDTA,
toujours dans la partie GEMDOS.

Le programme
------------

	On l'appelle avec un pointeur sur une chaine donnant le chemin
d'accs au rpertoire qu'on veut explorer:

Entree:
A3: adresse d'une chaine "X:\xxx\xxx\",0

	En sortie, on obtient les valeurs n_dossiers et n_fichiers
indiquant le nombre total de dossiers et de fichiers traits. Cette partie
peut tre enleve, mais c'est toujours plaisant de faire des statistiques.
Vous verrez qu'un CD contient ENORMMENT de choses.

	DATA

	; masque de recherche
masque: dc.b "*.*",0
	; nom pour remonter au dossier parent
parent: dc.b "..",0
	even

n_dossiers: dc.l 0
n_fichiers: dc.l 0

	BSS
	; de la place pour 23 niveaux!!
dtas: dc.b 23*44

	Voici les quelques macros dcrivant les fonctions GEMDOS. Je les
ai simplifies afin qu'elles n'utilisent pas les passages de paramtres
propres  mon assembleur.

DSETDRV macro
	move #14,-(sp)
	trap #1
	addq.l #4,sp
	endm

DSETPATH macro
	move #59,-(sp)
	trap #1
	addq.l #6,sp
	endm

FSETDTA macro
	move #26,-(sp)
	trap #1
	addq.l #6,sp
	endm

FSFIRST macro
	move #78,-(sp)
	trap #1
	addq.l #8,sp
	endm

FSNEXT macro
	move #79,-(sp)
	trap #1
	addq.l #2,sp
	endm

	Le programme en lui mme, voici l'utilisation des registres:

D6: niveau de profondeur (D6+1 quand on ouvre un dossier, D6-1 quand on
remonte). Il sert de critre de fin, en effet, lorsque D6=-1, c'est que
j'ai tout explor.

A4: pointeur sur les DTAs successives, il varie comme D6 mais par paquet de
44 octets.

	Au dpart, on vrifie si le chemin contient un nom de lecteur (la
prsence de ":" en seconde position le confirme), si oui, on fixe d'abord
le lecteur avec DSETDRV. En suite, on fixe le chemin de ce lecteur avec
la fonction DSETPATH: si le code renvoy est ngatif (path not found), on
sort immdiatement.
	Remarquez D6 qui est initialis  0 et A4  DTAS.

	TEXT

recherche:
	moveq #0,d6
	move (a3),d0
	cmp.b #":",d0
	bne.s .setpath
	lsr #8,d0
	sub #"A",d0
	move d0,-(sp)
	DSETDRV
	addq.l #2,a3
.setpath:
	move.l a3,-(sp)
	DSETPATH
	tst.l d0
	bmi .fin
	lea dtas,a4


	Vient ensuite le traitement du dbut d'un dossier. On met  jour
nos variables de statistiques, on fixe la DTA courante (pointe par A4) et
on appelle FSFIRST avec "*.*" comme masque afin d'obtenir tous les
dossiers possibles.

.debut_dossier:
	addq.l #1,n_dossiers
	move.l a4,-(sp)
	FSETDTA
	move #-1,-(sp)
	pea masque(pc)
	FSFIRST
	bra.s .autre

	On arrive  l'tiquette ".autre" soit par FSFIRST au dbut du
dossier, soit directement par FSNEXT en milieu de dossier. On teste sur D0
la prsence d'un autre objet (il faut D0=0). Dans le cas ou D0 est
ngatif, on sait qu'on a atteint la fin du dossier en cours.

.next:
	FSNEXT
.autre:
	tst.l d0
	bmi .fin_dossier

	Ds qu'un objet est prsent dans la DTA, on lit sont attribut afin
de sparer Dossiers et Fichiers. C'est le bit 4 de l'attribut qui indique
un dossier:

	move.b 21(a4),d0
	btst #4,d0
	bne.s .dossier

	Si le bit est  zro, on a  faire  un Fichier. On met  jour les
statistiques et au saute  la routine de traitement. C'est ici mme que
vous pouvez ajouter la routine de votre choix, j'ai choisi de faire le
total des tailles des fichiers dans mon exemple de "traiter_fichier". Au
retour de ce traitement, on continue sur le fichier suivant:

	addq.l #1,n_fichiers
	bsr traiter_fichier
	bra.s .next

	Si c'est un dossier, j'en lis d'abord les 2 premiers caractres.
Il y a deux cas particuliers, les dossiers "." et ".." qui reprsentent
respectivement les "dossier courant" et "dossier parent". On les voit
systmatiquement dans un listing sous MS-DOS. Ces deux l sont ignors
(saut  "next"). Un dernier cas a du tre ajout: je suis tomb sur des
dossiers dont le nom est vide (un CD pas Atari...) qui ne s'ouvrent pas
mais pour lesquels DSETPATH ne signale pas d'erreur. Si on ne les saute
pas, on tourne en boucle dans le mme dossier!

.dossier:
	move 30(a4),d0
	cmp #"..",d0
	beq.s .next
	cmp #$2e00,d0
	beq.s .next
	and #$FF00,d0
	beq.s .next

	Une fois les cas particuliers limins, j'ouvre le dossier trouv
dont le nom est au 30me octet de la DTA. Si l'ouverture est un chec (D0
ngatif), j'ignore ce dossier:

	pea 30(a4)
	DSETPATH
	tst.l d0
	bmi .next

	Dans le cas d'un succs, je prserve la DTA en augmentant A4 de 44
octets. D6 est lui aussi augment car on avance d'un cran dans
l'arborescence:

	add #44,a4
	addq #1,d6
	bra .debut_dossier

	Voici pour finir le traitement de la fin d'un dossier. Le niveau
D6 est dcrment et on vrifie que D6 n'est pas gal  -1 avant de
continuer. Si tout est Ok, je modifie A4 pour rcuprer la DTA prcdente
et je remonte d'un cran avec DSETPATH "..". Ceci correspond au "cd.." du
MS Dos ou d'autres interprteurs de commande.

.fin_dossier:
	subq #1,d6
	bmi.s .fin
	sub #44,a4
	pea parent(pc)
	DSETPATH

	Si cette opration est un chec, on sort immdiatement afin de ne
pas faire tourner la routine en boucle. Sinon, l'ancienne DTA est fixe et
on retourne  FSNEXT comme si de rien n'tait:

	tst.l d0
	bmi.s .fin
	move.l a4,-(sp)
	FSETDTA
	bra .next
.fin:
	rts

	Voici l'exemple de traitement de fichier. Je n'utilise que
l'entre "taille du fichier" de la DTA que je cumule dans ma variable
"taille". Ainsi, au sortir de la fonction j'aurai la somme des tailles de
tous les fichiers inclus dans un rpertoire et ses sous-rpertoires.

	DATA
taille: dc.l 0

	TEXT
traiter_fichier:
	move.l 26(a4),d0
	add.l d0,taille
	rts

Les extensions possibles
------------------------
	La DTA amne pas mal de renseignements. Vous pouvez faire un tri
ou une slection sur la date ou l'heure du fichier, sur sa taille. Vous
pouvez chercher tous les fichiers *.BAK de sauvegarde et les effacer pour
faire de la place. Vous pouvez rechercher tous les *.PRG, *.TOS, *.TTP et
fixer leur flag "fast load" afin d'acclrer les chargements. Enfin,
une foule de petites ides que je vous laisse dvelopper.
	Pour ma part, j'ai inclu cette routine dans M_Player afin de
regrouper toutes les animations d'un dossier ou d'un CD dans un seul
fichier batch, ensuite, j'utilise ce batch pour lire en continu toutes les
animations ainsi trouves.

	Nous voil arrivs au terme de cet article,  la prochaine fois!

	Guillaume Tello
	gtello@wanadoo.fr