2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
5 Desc: Test of the DOS functions MatchFirst, MatchNext and MatchEnd.
9 #include <proto/exec.h>
11 #include <dos/dosasl.h>
12 #include <exec/types.h>
13 #include <exec/memory.h>
20 Uncomment the following defines and function prototypes
21 if you want to use the code for the Match*-functions that
29 #define MatchFirst MyMatchFirst
30 #define MatchNext MyMatchNext
31 #define MatchEnd MyMatchEnd
32 LONG MyMatchFirst(STRPTR pat, struct AnchorPath * AP);
33 LONG MyMatchNext(struct AnchorPath *AP);
34 void MyMatchEnd(struct AnchorPath *AP);
37 BOOL
writeFullPath(struct AnchorPath
*AP
);
43 struct AnchorPath
* AP
= AllocVec(sizeof(struct AnchorPath
) + strlength
,MEMF_CLEAR
);
44 char * Pattern
= AllocVec(80,MEMF_ANY
);
46 //dirlock = Lock("sys:",ACCESS_READ);
47 //oldlock = CurrentDir(dirlock);
49 AP
->ap_BreakBits
= SIGBREAKF_CTRL_C
;
50 AP
->ap_Flags
= 0;//APF_DODIR;
51 AP
->ap_Strlen
= strlength
;
53 printf("Give me a pattern to search for: ");
54 /* the following line breaks AROS in MatchEnd() when calling FreeVec()
55 the second time the program is run. I have no idea why, though. */
57 printf("Pattern to search for: %s\n",Pattern
);
59 for(error
= MatchFirst(Pattern
,AP
); error
== 0;
60 error
= MatchNext(AP
))
62 if (AP
->ap_Flags
& APF_DIDDIR
)
64 AP
->ap_Flags
&= ~APF_DIDDIR
;
65 printf(" leaving \033[32m%s\033[39m\n",AP
->ap_Buf
);
67 else /* if dir then enter it! */
69 if (AP
->ap_Info
.fib_DirEntryType
>= 0)
71 AP
->ap_Flags
|=APF_DODIR
;
72 printf("entering \033[33m%s\033[39m\n",AP
->ap_Buf
);
76 //BPTR fl = CurrentDir(AP->ap_Current->an_Lock);
77 //(void)CurrentDir(fl);
79 printf(" %s\n",AP
->ap_Buf
);
83 printf("error = %i \n",error
);
87 //CurrentDir(oldlock);
99 LONG
MyMatchFirst(STRPTR pat
, struct AnchorPath
* AP
)
102 struct AChain
* AC_Prev
= NULL
;
104 STRPTR ParsedPattern
;
110 PatLength
= 2*strlen(pat
)+2;
112 ParsedPattern
= AllocMem(PatLength
, MEMF_ANY
);
113 if (NULL
!= ParsedPattern
)
117 BOOL AllDone
= FALSE
;
119 BOOL success
= FALSE
;
120 /* put the preparsed string to some memory */
121 /* If there are any wildcards then leave info */
122 if (1 == ParsePatternNoCase(pat
, ParsedPattern
, PatLength
))
123 AP
->ap_Flags
= (BYTE
)APF_ITSWILD
;
125 /* First I search for the very first ':'. If a '/' comes along
126 before that I quit. The string before and including the ':'
127 is assumed to be an assigned director, for example 'libs:'.
128 So I will start looking for the pattern in that directory.
132 if (ParsedPattern
[PatEnd
] == ':')
139 if ( ParsedPattern
[PatEnd
] == '/' ||
140 ParsedPattern
[PatEnd
] == '\0' ||
141 (ParsedPattern
[PatEnd
] & 0x80) != 0
142 /* a token or nonprintable letter */)
151 /* Only if success == TRUE an assigned dir was found. */
154 /* try to create a lock to that assigned dir. */
155 char Remember
= ParsedPattern
[PatEnd
+1];
157 ParsedPattern
[PatEnd
] = '\0';
159 firstlock
= Lock(ParsedPattern
, ACCESS_READ
);
160 /* check whether an error occurred */
161 if (BNULL
== firstlock
)
163 FreeMem(ParsedPattern
, PatLength
);
164 return ERROR_DIR_NOT_FOUND
; /* hope that's the right one... */
167 /* I have the correct lock. */
168 ParsedPattern
[PatEnd
] = Remember
;
173 /* Create a lock to the current dir. */
174 firstlock
= CurrentDir(BNULL
);
175 firstlock
= DupLock(firstlock
);
176 (void)CurrentDir(firstlock
);
179 /* Build the Anchor Chain. For every subdirector I allocate
180 a AChain structure and link them all together */
181 while (FALSE
== AllDone
)
186 Search for the next '/' in the pattern and everything behind
187 the previous '/' and before this '/' will go to an_String
191 if (ParsedPattern
[PatEnd
] == '\0')
197 if (ParsedPattern
[PatEnd
] == '/')
205 AC
= AllocMem(sizeof(struct AChain
)+(PatEnd
-PatStart
+2), MEMF_CLEAR
);
208 /* not so bad if this was not the very first AC. */
209 if (NULL
== AP
->ap_Base
)
211 /* oops, it was the very first one. I really cannot do anything for
213 FreeMem(ParsedPattern
, PatLength
);
214 return ERROR_NO_FREE_STORE
;
217 /* let me out of here. I will at least try to do something for you.
218 I can check the first few subdirs but that's gonna be it.
220 AP
->ap_Flags
|= APF_NOMEMERR
;
224 if (NULL
== AP
->ap_Base
)
232 AC_Prev
->an_Child
= AC
;
234 AC
->an_Parent
= AC_Prev
;
237 /* copy the part of the pattern to the end of the AChain. */
239 while (PatStart
<= PatEnd
)
241 AC
->an_String
[index
] = ParsedPattern
[PatStart
];
245 /* Put PatStart and PetEnd behind the '/' that was found. */
246 PatStart
= PatEnd
+ 2;
249 the trailing '\0' is there automatically as I allocated enough store
255 /* The AnchorChain to work with is the very first one. */
257 AC
->an_Lock
= firstlock
;
259 /* look for the first file that matches the given pattern */
260 success
= Examine(AC
->an_Lock
, &AC
->an_Info
);
261 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
262 while (DOSTRUE
== success
&&
263 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
264 AC
->an_Info
.fib_FileName
))
266 /* I still haven't found what I've been looking for ... */
267 success
= ExNext(AC
->an_Lock
, &AC
->an_Info
);
270 if (DOSFALSE
== success
)
272 return ERROR_NO_MORE_ENTRIES
;
275 /* Hooray! A matching file was found. Also show the data in AP */
276 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
277 if (0 != AP
->ap_Strlen
)
279 if (FALSE
== writeFullPath(AP
))
280 return ERROR_BUFFER_OVERFLOW
;
287 return ERROR_NO_FREE_STORE
;
294 LONG
MyMatchNext(struct AnchorPath
* AP
)
296 /* If the user says I am supposed to enter the directory then I first check
297 whether it is a directory... */
298 struct AChain
* AC
= AP
->ap_Current
;
300 if (0 != (AP
->ap_Flags
& APF_DODIR
))
302 if (AC
->an_Info
.fib_DirEntryType
>= 0 /* &&
303 AC->an_Info.fib_DirEntryType != ST_SOFTLINK */)
305 /* Ok, it seems to be a directory so I will enter it. */
306 /* See whether there's a AnchorChain for that dir... */
307 if (NULL
!= AC
->an_Child
)
309 /* Ok, we're all set. */
310 /* Lock the director by it's name. */
311 AP
->ap_Current
= AC
->an_Child
;
312 AC
->an_Child
->an_Lock
= Lock(AC
->an_Info
.fib_FileName
, ACCESS_READ
);
314 Examine(AC
->an_Lock
, &AC
->an_Info
);
318 AP
->ap_Flags
&= ~(BYTE
)(APF_DODIR
|APF_DIDDIR
);
320 /* AC points to the current AnchorChain */
323 success
= ExNext (AC
->an_Lock
, &AC
->an_Info
);
324 while (DOSTRUE
== success
&&
325 DOSFALSE
== MatchPatternNoCase(AC
->an_String
,
326 AC
->an_Info
.fib_FileName
))
328 success
= ExNext(AC
->an_Lock
, &AC
->an_Info
);
331 if (DOSFALSE
== success
)
333 /* No more entries in this dir that match. So I might have to
334 step back one directory. Unlock the current dir first,
335 !!!!!???? but only if it is not the one from where I started
336 Otherwise AROS crashes...
339 if (NULL
!= AC
->an_Parent
)
344 /* Are there any previous directories??? */
345 if (NULL
!= AC
->an_Parent
)
347 /* Step back to this directory and go on searching here */
350 CurrentDir(AC
->an_Lock
);
351 /* I show this dir again as I come back from searching it */
352 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
353 AP
->ap_Flags
|= APF_DIDDIR
;
354 if (0 != AP
->ap_Strlen
)
356 if (FALSE
== writeFullPath(AP
))
357 return ERROR_BUFFER_OVERFLOW
;
363 /* No previous directory, so I am done here... */
364 return ERROR_NO_MORE_ENTRIES
;
369 /* Alright, I found a match... */
370 CopyMem(&AC
->an_Info
, &AP
->ap_Info
, sizeof(struct FileInfoBlock
));
371 if (0 != AP
->ap_Strlen
)
373 if (FALSE
== writeFullPath(AP
))
374 return ERROR_BUFFER_OVERFLOW
;
382 void MyMatchEnd(struct AnchorPath
* AP
)
384 /* Free the AChain and unlock all locks that are still there */
385 struct AChain
* AC
= AP
->ap_Current
;
386 struct AChain
* AC_tmp
;
387 /* Unlock everything */
390 while (AC
!= AP
->ap_Base
)
395 /* AC points to the very first AChain obj. in the list */
397 /* Free the AChain List */
400 AC_tmp
= AC
->an_Child
;
406 AP
->ap_Current
= NULL
;
409 BOOL
writeFullPath(struct AnchorPath
* AP
)
411 struct AChain
* AC
= AP
->ap_Base
;
413 char * LastPos
= (char *)&AP
->ap_Buf
;
418 int len
= strlen(AC
->an_Info
.fib_FileName
);
419 if (copied
+len
> AP
->ap_Strlen
)
423 strcpy(&LastPos
[copied
], AC
->an_Info
.fib_FileName
);
426 if (AC
!= AP
->ap_Current
)
429 if (copied
+1 > AP
->ap_Strlen
)
438 if (copied
+1 > AP
->ap_Strlen
)
442 LastPos
[copied
]='\0';