bump version
[AROS.git] / test / matchtest.c
blob6e219a73cef02f3670ac7d11f3526a9490cc019f
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Test of the DOS functions MatchFirst, MatchNext and MatchEnd.
6 */
8 #include <proto/dos.h>
9 #include <proto/exec.h>
10 #include <dos/dos.h>
11 #include <dos/dosasl.h>
12 #include <exec/types.h>
13 #include <exec/memory.h>
15 #include <stdio.h>
16 #include <string.h>
19 /*
20 Uncomment the following defines and function prototypes
21 if you want to use the code for the Match*-functions that
22 is in this file.
26 #undef MatchFirst
27 #undef MatchNext
28 #undef MatchEnd
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);
39 int main (void)
41 BOOL error;
42 int strlength=160;
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. */
56 scanf("%s",Pattern);
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);
74 else
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);
84 MatchEnd(AP);
85 FreeVec(AP);
86 FreeVec(Pattern);
87 //CurrentDir(oldlock);
89 //UnLock(dirlock);
91 return 0;
94 #undef MatchFirst
95 #undef MatchNext
96 #undef MatchEnd
99 LONG MyMatchFirst(STRPTR pat, struct AnchorPath * AP)
101 struct AChain * AC;
102 struct AChain * AC_Prev = NULL;
103 LONG PatLength;
104 STRPTR ParsedPattern;
105 BPTR firstlock;
107 if (!pat)
108 return FALSE;
110 PatLength = 2*strlen(pat)+2;
112 ParsedPattern = AllocMem(PatLength, MEMF_ANY);
113 if (NULL != ParsedPattern)
115 LONG PatStart = 0;
116 LONG PatEnd = 0;
117 BOOL AllDone = FALSE;
118 LONG index;
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.
130 while (TRUE)
132 if (ParsedPattern[PatEnd] == ':')
134 success = TRUE;
135 break;
137 else
139 if ( ParsedPattern[PatEnd] == '/' ||
140 ParsedPattern[PatEnd] == '\0' ||
141 (ParsedPattern[PatEnd] & 0x80) != 0
142 /* a token or nonprintable letter */)
144 PatEnd = 0;
145 break;
148 PatEnd++;
151 /* Only if success == TRUE an assigned dir was found. */
152 if (TRUE == success)
154 /* try to create a lock to that assigned dir. */
155 char Remember = ParsedPattern[PatEnd+1];
156 PatEnd++;
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;
169 PatStart=PatEnd;
171 else
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
189 while (TRUE)
191 if (ParsedPattern[PatEnd] == '\0')
193 AllDone = TRUE;
194 PatEnd--;
195 break;
197 if (ParsedPattern[PatEnd] == '/')
199 PatEnd--;
200 break;
202 PatEnd++;
205 AC = AllocMem(sizeof(struct AChain)+(PatEnd-PatStart+2), MEMF_CLEAR);
206 if (NULL == AC)
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
212 you. - sorry */
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;
221 break;
224 if (NULL == AP->ap_Base)
226 AP->ap_Base = AC;
227 AP->ap_Current = AC;
230 if (NULL != AC_Prev)
232 AC_Prev->an_Child = AC;
234 AC->an_Parent = AC_Prev;
235 AC_Prev = AC;
237 /* copy the part of the pattern to the end of the AChain. */
238 index = 0;
239 while (PatStart <= PatEnd)
241 AC->an_String[index] = ParsedPattern[PatStart];
242 index++;
243 PatStart++;
245 /* Put PatStart and PetEnd behind the '/' that was found. */
246 PatStart = PatEnd + 2;
247 PatEnd += 2;
249 the trailing '\0' is there automatically as I allocated enough store
250 with MEMF_CLEAR
253 } /* while () */
255 /* The AnchorChain to work with is the very first one. */
256 AC = AP->ap_Base;
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;
282 return 0;
285 else
287 return ERROR_NO_FREE_STORE;
290 return 0;
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;
299 BOOL success;
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);
313 AC = AC->an_Child;
314 Examine(AC->an_Lock, &AC->an_Info);
318 AP->ap_Flags &= ~(BYTE)(APF_DODIR|APF_DIDDIR);
320 /* AC points to the current AnchorChain */
321 while (TRUE)
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)
340 UnLock(AC->an_Lock);
343 AC->an_Lock = BNULL;
344 /* Are there any previous directories??? */
345 if (NULL != AC->an_Parent)
347 /* Step back to this directory and go on searching here */
348 AC = AC->an_Parent;
349 AP->ap_Current = AC;
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;
359 return 0;
361 else
363 /* No previous directory, so I am done here... */
364 return ERROR_NO_MORE_ENTRIES;
367 else
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;
376 return 0;
378 } /* while (TRUE) */
379 return 0;
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 */
388 if (NULL == AC)
390 while (AC != AP->ap_Base)
392 UnLock(AC->an_Lock);
393 AC = AC->an_Parent;
395 /* AC points to the very first AChain obj. in the list */
397 /* Free the AChain List */
398 while (NULL != AC)
400 AC_tmp = AC->an_Child;
401 FreeVec(AC);
402 AC = AC_tmp;
404 /* Cleanup AP */
405 AP->ap_Base = NULL;
406 AP->ap_Current = NULL;
409 BOOL writeFullPath(struct AnchorPath * AP)
411 struct AChain * AC = AP->ap_Base;
412 BOOL end = FALSE;
413 char * LastPos = (char *)&AP->ap_Buf;
414 int copied = 0;
416 while (FALSE == end)
418 int len = strlen(AC->an_Info.fib_FileName);
419 if (copied+len > AP->ap_Strlen)
421 return FALSE;
423 strcpy(&LastPos[copied], AC->an_Info.fib_FileName);
424 copied += len;
426 if (AC != AP->ap_Current)
428 /* also add a '/' */
429 if (copied+1 > AP->ap_Strlen)
431 return FALSE;
433 LastPos[copied]='/';
434 copied++;
436 else
438 if (copied+1 > AP->ap_Strlen)
440 return FALSE;
442 LastPos[copied]='\0';
443 end = TRUE;
446 AC = AC->an_Child;
448 return TRUE;