1 /* Test of the DOS functions MatchFirst MatchNext and MatchEnd.
5 #include <proto/exec.h>
7 #include <dos/dosasl.h>
8 #include <exec/types.h>
9 #include <exec/memory.h>
16 Uncomment the following defines and function prototypes
17 if you want to use the code for the Match*-functions that
25 #define MatchFirst MyMatchFirst
26 #define MatchNext MyMatchNext
27 #define MatchEnd MyMatchEnd
28 LONG MyMatchFirst(STRPTR pat, struct AnchorPath * AP);
29 LONG MyMatchNext(struct AnchorPath *AP);
30 void MyMatchEnd(struct AnchorPath *AP);
33 BOOL
writeFullPath(struct AnchorPath
*AP
);
39 struct AnchorPath
* AP
= AllocVec(sizeof(struct AnchorPath
) + strlength
,MEMF_CLEAR
);
40 char * Pattern
= AllocVec(80,MEMF_ANY
);
42 //dirlock = Lock("sys:",ACCESS_READ);
43 //oldlock = CurrentDir(dirlock);
45 AP
->ap_BreakBits
= SIGBREAKF_CTRL_C
;
46 AP
->ap_Flags
= 0;//APF_DODIR;
47 AP
->ap_Strlen
= strlength
;
49 printf("Give me a pattern to serach for: ");
50 /* the following line breaks AROS in MatchEnd() when calling FreeVec()
51 the second time the program is run. I have no idea why, though. */
53 printf("Pattern to search for: %s\n",Pattern
);
55 for(error
= MatchFirst(Pattern
,AP
); error
== 0;
56 error
= MatchNext(AP
))
58 if (AP
->ap_Flags
& APF_DIDDIR
)
60 AP
->ap_Flags
&= ~APF_DIDDIR
;
61 printf(" leaving \033[32m%s\033[39m\n",AP
->ap_Buf
);
63 else /* if dir then enter it! */
65 if (AP
->ap_Info
.fib_DirEntryType
>= 0)
67 AP
->ap_Flags
|=APF_DODIR
;
68 printf("entering \033[33m%s\033[39m\n",AP
->ap_Buf
);
72 //BPTR fl = CurrentDir(AP->ap_Current->an_Lock);
73 //(void)CurrentDir(fl);
75 printf(" %s\n",AP
->ap_Buf
);
79 printf("error = %i \n",error
);
83 //CurrentDir(oldlock);
95 LONG
MyMatchFirst(STRPTR pat
, struct AnchorPath
* AP
)
98 struct AChain
* AC_Prev
= NULL
;
100 STRPTR ParsedPattern
;
106 PatLength
= 2*strlen(pat
)+2;
108 ParsedPattern
= AllocMem(PatLength
, MEMF_ANY
);
109 if (NULL
!= ParsedPattern
)
113 BOOL AllDone
= FALSE
;
115 BOOL success
= FALSE
;
116 /* put the preparsed string to some memory */
117 /* If there are any wildcards then leave info */
118 if (1 == ParsePatternNoCase(pat
, ParsedPattern
, PatLength
))
119 AP
->ap_Flags
= (BYTE
)APF_ITSWILD
;
121 /* First I search for the very first ':'. If a '/' comes along
122 before that I quit. The string before and including the ':'
123 is assumed to be an assigned director, for example 'libs:'.
124 So I will start looking for the pattern in that directory.
128 if (ParsedPattern
[PatEnd
] == ':')
135 if ( ParsedPattern
[PatEnd
] == '/' ||
136 ParsedPattern
[PatEnd
] == '\0' ||
137 (ParsedPattern
[PatEnd
] & 0x80) != 0
138 /* a token or nonprintable letter */)
147 /* Only if success == TRUE an assigned dir was found. */
150 /* try to create a lock to that assigned dir. */
151 char Remember
= ParsedPattern
[PatEnd
+1];
153 ParsedPattern
[PatEnd
] = '\0';
155 firstlock
= Lock(ParsedPattern
, ACCESS_READ
);
156 /* check whether an error occurred */
157 if (BNULL
== firstlock
)
159 FreeMem(ParsedPattern
, PatLength
);
160 return ERROR_DIR_NOT_FOUND
; /* hope that's the right one... */
163 /* I have the correct lock. */
164 ParsedPattern
[PatEnd
] = Remember
;
169 /* Create a lock to the current dir. */
170 firstlock
= CurrentDir(BNULL
);
171 firstlock
= DupLock(firstlock
);
172 (void)CurrentDir(firstlock
);
175 /* Build the Anchor Chain. For every subdirector I allocate
176 a AChain structure and link them all together */
177 while (FALSE
== AllDone
)
182 Search for the next '/' in the pattern and everything behind
183 the previous '/' and before this '/' will go to an_String
187 if (ParsedPattern
[PatEnd
] == '\0')
193 if (ParsedPattern
[PatEnd
] == '/')
201 AC
= AllocMem(sizeof(struct AChain
)+(PatEnd
-PatStart
+2), MEMF_CLEAR
);
204 /* not so bad if this was not the very first AC. */
205 if (NULL
== AP
->ap_Base
)
207 /* oops, it was the very first one. I really cannot do anything for
209 FreeMem(ParsedPattern
, PatLength
);
210 return ERROR_NO_FREE_STORE
;
213 /* let me out of here. I will at least try to do something for you.
214 I can check the first few subdirs but that's gonna be it.
216 AP
->ap_Flags
|= APF_NOMEMERR
;
220 if (NULL
== AP
->ap_Base
)
228 AC_Prev
->an_Child
= AC
;
230 AC
->an_Parent
= AC_Prev
;
233 /* copy the part of the pattern to the end of the AChain. */
235 while (PatStart
<= PatEnd
)
237 AC
->an_String
[index
] = ParsedPattern
[PatStart
];
241 /* Put PatStart and PetEnd behind the '/' that was found. */
242 PatStart
= PatEnd
+ 2;
245 the trailing '\0' is there automatically as I allocated enough store
251 /* The AnchorChain to work with is the very first one. */
253 AC
->an_Lock
= firstlock
;
255 /* look for the first file that matches the given pattern */
256 success
= Examine(AC
->an_Lock
, &AC
->an_Info
);
257 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
258 while (DOSTRUE
== success
&&
259 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
260 AC
->an_Info
.fib_FileName
))
262 /* I still haven't found what I've been looking for ... */
263 success
= ExNext(AC
->an_Lock
, &AC
->an_Info
);
266 if (DOSFALSE
== success
)
268 return ERROR_NO_MORE_ENTRIES
;
271 /* Hooray! A matching file was found. Also show the data in AP */
272 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
273 if (0 != AP
->ap_Strlen
)
275 if (FALSE
== writeFullPath(AP
))
276 return ERROR_BUFFER_OVERFLOW
;
283 return ERROR_NO_FREE_STORE
;
290 LONG
MyMatchNext(struct AnchorPath
* AP
)
292 /* If the user says I am supposed to enter the directory then I first check
293 whether it is a directory... */
294 struct AChain
* AC
= AP
->ap_Current
;
296 if (0 != (AP
->ap_Flags
& APF_DODIR
))
298 if (AC
->an_Info
.fib_DirEntryType
>= 0 /* &&
299 AC->an_Info.fib_DirEntryType != ST_SOFTLINK */)
301 /* Ok, it seems to be a directory so I will enter it. */
302 /* See whether there's a AnchorChain for that dir... */
303 if (NULL
!= AC
->an_Child
)
305 /* Ok, we're all set. */
306 /* Lock the director by it's name. */
307 AP
->ap_Current
= AC
->an_Child
;
308 AC
->an_Child
->an_Lock
= Lock(AC
->an_Info
.fib_FileName
, ACCESS_READ
);
310 Examine(AC
->an_Lock
, &AC
->an_Info
);
314 AP
->ap_Flags
&= ~(BYTE
)(APF_DODIR
|APF_DIDDIR
);
316 /* AC points to the current AnchorChain */
319 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
320 while (DOSTRUE
== success
&&
321 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
322 AC
->an_Info
.fib_FileName
))
324 success
= ExNext(AC
->an_Lock
, &AC
->an_Info
);
327 if (DOSFALSE
== success
)
329 /* No more entries in this dir that match. So I might have to
330 step back one directory. Unlock the current dir first,
331 !!!!!???? but only if it is not the one from where I started
332 Otherwise AROS crashes...
335 if (NULL
!= AC
->an_Parent
)
340 /* Are there any previous directories??? */
341 if (NULL
!= AC
->an_Parent
)
343 /* Step back to this directory and go on searching here */
346 CurrentDir(AC
->an_Lock
);
347 /* I show this dir again as I come back from searching it */
348 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
349 AP
->ap_Flags
|= APF_DIDDIR
;
350 if (0 != AP
->ap_Strlen
)
352 if (FALSE
== writeFullPath(AP
))
353 return ERROR_BUFFER_OVERFLOW
;
359 /* No previous directory, so I am done here... */
360 return ERROR_NO_MORE_ENTRIES
;
365 /* Alright, I found a match... */
366 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
367 if (0 != AP
->ap_Strlen
)
369 if (FALSE
== writeFullPath(AP
))
370 return ERROR_BUFFER_OVERFLOW
;
378 void MyMatchEnd(struct AnchorPath
* AP
)
380 /* Free the AChain and unlock all locks that are still there */
381 struct AChain
* AC
= AP
->ap_Current
;
382 struct AChain
* AC_tmp
;
383 /* Unlock everything */
386 while (AC
!= AP
->ap_Base
)
391 /* AC points to the very first AChain obj. in the list */
393 /* Free the AChain List */
396 AC_tmp
= AC
->an_Child
;
402 AP
->ap_Current
= NULL
;
405 BOOL
writeFullPath(struct AnchorPath
* AP
)
407 struct AChain
* AC
= AP
->ap_Base
;
409 char * LastPos
= (char *)&AP
->ap_Buf
;
414 int len
= strlen(AC
->an_Info
.fib_FileName
);
415 if (copied
+len
> AP
->ap_Strlen
)
419 strcpy(&LastPos
[copied
], AC
->an_Info
.fib_FileName
);
422 if (AC
!= AP
->ap_Current
)
425 if (copied
+1 > AP
->ap_Strlen
)
434 if (copied
+1 > AP
->ap_Strlen
)
438 LastPos
[copied
]='\0';