int pmatch_quot(const char **P_PtrPtr, const char **S_PtrPtr, int *Flags) { int result=MATCH_FAIL, OldFlags; char P_Char, S_Char; const char *OldPos, *ptr; P_Char=**P_PtrPtr; S_Char=**S_PtrPtr; result=pmatch_quot_analyze(P_Char, S_Char); switch (result) { case MATCH_ONE: (*P_PtrPtr)++; break; case MATCH_HEX: if (! pmatch_ascii((*P_PtrPtr)+1,S_Char,MATCH_HEX)) return(MATCH_FAIL); (*P_PtrPtr)+=2; break; case MATCH_OCTAL: if (! pmatch_ascii((*P_PtrPtr)+1,S_Char,MATCH_OCTAL)) return(MATCH_FAIL); (*P_PtrPtr)+=3; break; case MATCH_SWITCH_ON: case MATCH_SWITCH_OFF: //some switches need to be applied in order for a pattern to match //(like the case-insensitive switch) others should only be applied if //it matches. So we apply the switch, but if the subsequent pmatch_char fails //we unapply it OldFlags=*Flags; OldPos=*P_PtrPtr; (*P_PtrPtr)++; //go past the + or - to the actual type pmatch_switch(**P_PtrPtr, result, Flags); (*P_PtrPtr)++; result=pmatch_char(P_PtrPtr, S_PtrPtr, Flags); if (result==MATCH_FAIL) { *P_PtrPtr=OldPos; *Flags=OldFlags; } return(result); break; case MATCH_FAIL: return(MATCH_FAIL); break; } return(MATCH_ONE); }
int pmatch_quot(char **P_PtrPtr, char **S_PtrPtr, int *Flags) { int result=MATCH_FAIL, OldFlags; char P_Char, S_Char, *OldPos; P_Char=**P_PtrPtr; S_Char=**S_PtrPtr; switch (P_Char) { case 'b': if (S_Char=='\b') result=MATCH_ONE; break; case 'e': if (S_Char==27) result=MATCH_ONE; break; //escape case 'n': if (S_Char=='\n') result=MATCH_ONE; break; case 'r': if (S_Char=='\r') result=MATCH_ONE; break; case 't': if (S_Char==' ') result=MATCH_ONE; break; case 'l': if (islower(S_Char)) result=MATCH_ONE; break; case 'x': result=MATCH_HEX; break; case 'A': if (isalpha(S_Char)) result=MATCH_ONE; break; case 'B': if (isalnum(S_Char)) result=MATCH_ONE; break; case 'D': if (isdigit(S_Char)) result=MATCH_ONE; break; case 'S': if (isspace(S_Char)) result=MATCH_ONE; break; case 'P': if (ispunct(S_Char)) result=MATCH_ONE; break; case 'X': if (isxdigit(S_Char)) result=MATCH_ONE; break; case 'U': if (isupper(S_Char)) result=MATCH_ONE; break; case '+': result=MATCH_SWITCH_ON; break; case '-': result=MATCH_SWITCH_OFF; break; default: if (S_Char==P_Char) result=MATCH_ONE; break; } switch (result) { case MATCH_ONE: (*P_PtrPtr)++; break; case MATCH_HEX: if (! pmatch_ascii((*P_PtrPtr)+1,S_Char,MATCH_HEX)) return(MATCH_FAIL); (*P_PtrPtr)+=2; break; case MATCH_OCTAL: if (! pmatch_ascii((*P_PtrPtr)+1,S_Char,MATCH_OCTAL)) return(MATCH_FAIL); (*P_PtrPtr)+=3; break; case MATCH_SWITCH_ON: case MATCH_SWITCH_OFF: //some switches need to be applied in order for a pattern to match //(like the case-insensitive switch) others should only be applied if //it matches. So we apply the switch, but if the subsequent pmatch_char fails //we unapply it OldFlags=*Flags; OldPos=*P_PtrPtr; (*P_PtrPtr)++; //go past the + or - to the actual type pmatch_switch(**P_PtrPtr, result, Flags); (*P_PtrPtr)++; result=pmatch_char(P_PtrPtr, S_PtrPtr, Flags); if ((result==MATCH_FAIL) || (result==MATCH_CONT)) { *P_PtrPtr=OldPos; *Flags=OldFlags; } return(result); break; case MATCH_FAIL: if (*Flags & PMATCH_SUBSTR) return(MATCH_CONT); return(MATCH_FAIL); break; } return(MATCH_ONE); }
int pmatch_process(char *Pattern, char *String, char **Start, char **End, int Flags) { char *P_Ptr, *S_Ptr, *ptr; int result; P_Ptr=Pattern; S_Ptr=String; if (Start) *Start=NULL; if (End) *End=NULL; result=pmatch_char(&P_Ptr, &S_Ptr, &Flags); while (*S_Ptr) { switch (result) { case MATCH_FAIL: return(FALSE); break; //Match failed, but we're looking for a substring of 'String' so continue searching for match case MATCH_CONT: P_Ptr=Pattern; if (Start) *Start=NULL; if (End) *End=NULL; break; case MATCH_START: if (S_Ptr != String) return(FALSE); if (Flags & PMATCH_NOTSTART) return(FALSE); if (! (Flags & PMATCH_NOEXTRACT)) { if (Start && (! *Start)) *Start=S_Ptr; } S_Ptr--; //naughty, were are now pointing before String, but the //S_Ptr++ below will correct this break; case MATCH_FOUND: if (End && (! (Flags & PMATCH_NOEXTRACT))) { *End=S_Ptr; } return(TRUE); break; //Match many is a special case. We have too look ahead to see if the next char //Matches, and thust takes us out of 'match many' howerver, If the call to pmatch_char //fails then we have to rewind the pattern pointer to match many's '*' and go round again case MATCH_MANY: ptr=P_Ptr; P_Ptr++; result=pmatch_char(&P_Ptr, &S_Ptr, &Flags); if (result==MATCH_FAIL) P_Ptr=ptr; else if (result==MATCH_CONT) P_Ptr=ptr; else if (! (Flags & PMATCH_NOEXTRACT)) { if (Start && (! *Start)) *Start=S_Ptr; } break; case MATCH_ONE: if (! (Flags & PMATCH_NOEXTRACT)) { if (Start && (! *Start)) *Start=S_Ptr; } break; } S_Ptr++; if ((End) && (! (Flags & PMATCH_NOEXTRACT))) *End=S_Ptr; result=pmatch_char(&P_Ptr, &S_Ptr, &Flags); } //if pattern not exhausted then we didn't get a match if (*P_Ptr) return(FALSE); return(TRUE); }
//Somewhat ugly, as we need to iterate through the string, so we need it passed as a ** int pmatch_search(char *Pattern, char **S_PtrPtr, char *S_End, char **MatchStart, char **MatchEnd, int *Flags) { int result; char *P_Ptr, *ptr, *S_Start; if (MatchStart) *MatchStart=NULL; if (MatchEnd) *MatchEnd=NULL; P_Ptr=Pattern; S_Start=*S_PtrPtr; result=pmatch_char(&P_Ptr, S_PtrPtr, Flags); while (*S_PtrPtr <= S_End) { switch (result) { case MATCH_FAIL: if (*Flags & PMATCH_SUBSTR) return(MATCH_CONT); return(MATCH_FAIL); break; //Match failed, but we're looking for a substring of 'String' so continue searching for match case MATCH_CONT: if (! (*Flags & PMATCH_SUBSTR)) return(MATCH_FAIL); //if we were some ways through a pattern before hitting the character //that failed the match, then we must rewind to reconsider that character //as a fresh match //if ((*P_Ptr != *Pattern) && (*Pattern != '^')) (*S_PtrPtr)--; if ((*P_Ptr != *Pattern) ) (*S_PtrPtr)--; P_Ptr=Pattern; break; case MATCH_START: if (*Flags & PMATCH_NOTSTART) return(MATCH_FAIL); (*S_PtrPtr)--; //naughty, were are now pointing before String, but the //S_Ptr++ below will correct this break; case MATCH_FOUND: if (*Flags & PMATCH_NOEXTRACT) { //This is to prevent returning NULL strings in 'MatchStart' and 'MatchEnd' if (MatchStart && (! *MatchStart)) *MatchStart=S_Start; if (MatchEnd && (! *MatchEnd)) *MatchEnd=*MatchStart; } //else if (MatchEnd) *MatchEnd=*S_PtrPtr; return(MATCH_ONE); break; //Match many is a special case. We have too look ahead to see if the next char //Matches, and thus takes us out of 'match many' howerver, If the call to pmatch_char //fails then we have to rewind the pattern pointer to match many's '*' and go round again case MATCH_MANY: ptr=P_Ptr; P_Ptr++; //pmatch_char will think that if we've reached the end of the pattern, then we've got //a match, regardless of where we are in the string. However, this is the one case where //'*' needs to be a little 'greedy'. If the last item in the pattern was '*' (match many) //then we need to continue until we read the end of the string if (*P_Ptr=='\0') { if (*S_PtrPtr == S_End) result=MATCH_FOUND; else result=MATCH_FAIL; } else { if (*S_PtrPtr == S_End) result=MATCH_FAIL; else result=pmatch_char(&P_Ptr, S_PtrPtr, Flags); } if ((result==MATCH_FAIL) || (result==MATCH_CONT)) P_Ptr=ptr; break; case MATCH_REPEAT: result=pmatch_repeat(&P_Ptr, S_PtrPtr, S_End, Flags); if (result==MATCH_FAIL) { if (*Flags & PMATCH_SUBSTR) return(MATCH_CONT); return(MATCH_FAIL); } break; } if ((result==MATCH_CONT) ) { if (MatchStart) *MatchStart=NULL; if (MatchEnd) *MatchEnd=NULL; } else if (! (*Flags & PMATCH_NOEXTRACT)) { if (MatchStart && (*S_PtrPtr >= S_Start) && (! *MatchStart)) *MatchStart=*S_PtrPtr; if (MatchEnd && ((*(S_PtrPtr)+1) < S_End)) *MatchEnd=(*S_PtrPtr)+1; } //Handle 'MATCH_FOUND' in the switch statement, don't iterate further through Pattern or String if (result==MATCH_FOUND) continue; (*S_PtrPtr)++; //if (*S_PtrPtr > S_End) break; result=pmatch_char(&P_Ptr, S_PtrPtr, Flags); } //if pattern not exhausted then we didn't get a match if (*P_Ptr !='\0') return(MATCH_CONT); return(MATCH_ONE); }
//Somewhat ugly, as we need to iterate through the string, so we need it passed as a ** int pmatch_search(const char **P_PtrPtr, const char **S_PtrPtr, const char *S_End, const char **MatchStart, const char **MatchEnd, int *Flags) { const char *ptr, *S_Start, *P_tmp, *S_tmp; int result; if (MatchStart) *MatchStart=NULL; if (MatchEnd) *MatchEnd=NULL; if (*Flags & PMATCH_SUBSTR) { (*Flags) &= ~PMATCH_SUBSTR; (*Flags) |= PMATCH_SHORT; } S_Start=*S_PtrPtr; result=pmatch_char(P_PtrPtr, S_PtrPtr, Flags); while (*S_PtrPtr < S_End) { switch (result) { case MATCH_FAIL: return(MATCH_FAIL); break; case MATCH_START: if (*Flags & PMATCH_NOTSTART) return(MATCH_FAIL); (*S_PtrPtr)--; //naughty, were are now pointing before String, but the //S_Ptr++ below will correct this break; //Match many is a special case. We have too look ahead to see if the next char //Matches, and thus takes us out of 'match many' howerver, If the call to pmatch_char //fails then we have to rewind the pattern pointer to match many's '*' and go round again case MATCH_MANY: result=pmatch_many(P_PtrPtr, S_PtrPtr, S_End, MatchStart, MatchEnd, Flags); if (result==MATCH_FAIL) return(MATCH_FAIL); break; case MATCH_FOUND: if (! (*Flags & PMATCH_NOEXTRACT) ) { //This is to prevent returning NULL strings in 'MatchStart' and 'MatchEnd' if (MatchStart && (! *MatchStart)) *MatchStart=S_Start; if (MatchEnd && (! *MatchEnd)) *MatchEnd=*MatchStart; } return(MATCH_ONE); break; case MATCH_REPEAT: result=pmatch_repeat(P_PtrPtr, S_PtrPtr, S_End, Flags); if (result==MATCH_FAIL) return(MATCH_FAIL); break; } if (result==MATCH_NEXT) /*do nothing */ ; else if (result==MATCH_FOUND) continue; else if (! (*Flags & PMATCH_NOEXTRACT)) { if (MatchStart && (*S_PtrPtr >= S_Start) && (! *MatchStart)) *MatchStart=*S_PtrPtr; if (MatchEnd && ((*(S_PtrPtr)+1) < S_End)) *MatchEnd=(*S_PtrPtr)+1; } //Handle 'MATCH_FOUND' in the switch statement, don't iterate further through Pattern or String if (**S_PtrPtr != '\0') (*S_PtrPtr)++; result=pmatch_char(P_PtrPtr, S_PtrPtr, Flags); } //any number of '*' at the end of the pattern don't count once we've run out of string //? however does, because '?' is saying 'one character' whereas '*' is zero or more //while (*P_Ptr=='*') P_Ptr++; //if pattern not exhausted then we didn't get a match if (**P_PtrPtr !='\0') return(MATCH_FAIL); return(MATCH_ONE); }