2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Pattern matching and parsing functionality
9 #include <exec/memory.h>
10 #include <proto/exec.h>
11 #include <proto/utility.h>
12 #include <proto/dos.h>
13 #include <dos/dosextens.h>
14 #include <dos/dosasl.h>
16 #include "dos_intern.h"
19 A simple method for pattern matching with multiple wildcards:
20 I use markers that consist of both a pointer into the string
21 and one into the pattern. The marker simply follows the string
22 and everytime it hits a wildcard it's split into two new markers
23 (one to assume that the wildcard match has ended and one to assume
24 that it continues). If a marker doesn't fit any longer it's
25 removed and if all of them are gone the pattern mismatches.
26 OTOH if any of the markers reaches the end of both the string
27 and the pattern simultaneously the pattern matches the string.
33 * pat -- Pattern string (as returned by ParsePatternXXXX())
34 * str -- The string to match against the pattern 'pat'
35 * case -- Determines if the case is important or not
36 * DOSBase -- dos.library base
41 BOOL
patternMatch(CONST_STRPTR pat
, CONST_STRPTR str
, BOOL useCase
,
42 struct DosLibrary
*DOSBase
)
47 struct markerarray ma
;
48 struct markerarray
*macur
= &ma
;
49 struct markerarray
*cur2
;
60 #define ERROR(a) { error = (a); goto end; }
62 ma
.next
= ma
.prev
= NULL
;
68 case P_REPBEG
: /* _#(_a), _#a_ or _#[_a] */
80 else if(c
== P_REPEND
)
90 case P_REPEND
: /* #(a_)_ */
101 else if(c
== P_REPBEG
)
111 case P_NOT
: /* _~(_a) */
123 else if(c
== P_NOTEND
)
135 case P_NOTEND
: /* ~(a_)_ */
148 }while(!cur2
->marker
[cnt2
].type
);
155 else if(str
> cur2
->marker
[cnt2
].str
)
157 cur2
->marker
[cnt2
].str
= str
;
164 PUSH(1, pat
, str
+ 1);
169 case P_ORSTART
: /* ( */
181 else if(c
== P_ORNEXT
)
188 else if(c
== P_OREND
)
199 case P_ORNEXT
: /* | */
211 else if(c
== P_OREND
)
222 case P_OREND
: /* ) */
226 case P_SINGLE
: /* ? */
239 PUSH(1, pat
, str
+ 1);
245 case P_CLASS
: /* [ */
258 PUSH(1, pat
, str
+ 1);
287 while(*pat
++ != P_CLASS
)
296 case P_NOTCLASS
: /* [~ */
303 PUSH(1, pat
, str
+ 1);
346 PUSH(1, pat
, str
+ 1);
356 /* This often used pattern has extra treatment to be faster */
359 PUSH(0, pat
, str
+ 1);
377 PUSH(1, pat
, str
+ 1);
405 PUSH(1, pat
, str
+ 1);
421 struct markerarray
*next
= macur
->next
;
423 FreeMem(macur
, sizeof(struct markerarray
));
433 LONG
patternParse(CONST_STRPTR Source
, STRPTR Dest
, LONG DestLength
,
434 BOOL useCase
, struct DosLibrary
*DOSBase
)
442 #define ERROR(a) { SetIoErr(a); return -1; }
443 stack
= end
= Dest
+ DestLength
;
444 #define PUT(a) { if(Dest >= stack) ERROR(ERROR_BUFFER_OVERFLOW); *Dest++ = (a); }
468 ERROR(ERROR_BAD_TEMPLATE
);
484 PUT(useCase
? a
: ToUpper(a
));
488 ERROR(ERROR_BAD_TEMPLATE
);
515 ERROR(ERROR_BAD_TEMPLATE
);
518 while(!(*stack
== P_OREND
|| stack
== end
))
527 while(!(stack
== end
|| *stack
== P_OREND
))
534 ERROR(ERROR_BAD_TEMPLATE
);
560 ERROR(ERROR_BAD_TEMPLATE
);
570 PUT(useCase
? a
: ToUpper(a
));
575 ERROR(ERROR_BAD_TEMPLATE
);
583 if (DOSBase
->dl_Root
->rn_Flags
& RNF_WILDSTAR
)
620 PUT(useCase
? a
: ToUpper(a
));
624 while(stack
!= end
&& *stack
!= P_OREND
)
632 ERROR(ERROR_BAD_TEMPLATE
);