amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (05/18/91)
Submitted-by: "J. Spencer" <bhgs@utcs.utoronto.ca> Posting-number: Volume 91, Issue 108 Archive-name: libraries/sregexp-9.4/part02 #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 2)." # Contents: sregexp.c sregexp.doc # Wrapped by tadguy@ab20 on Fri May 17 21:56:59 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'sregexp.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sregexp.c'\" else echo shar: Extracting \"'sregexp.c'\" \(16596 characters\) sed "s/^X//" >'sregexp.c' <<'END_OF_FILE' X X/* This is a routine to test if a string matches a regular expression. X * X * X * The regular expression sytax is a slight extension of the regular X * AmigaDos wildcard patterns. Apparently 2.0 has added a few new things X * (well, at least a not operator) to the game. This may or may not X * be consistant with those additions (it's the way they otta done it.) X * X * Here it is: X * X * ? matches any one character X * X * #(pat) matches zero or more occurances of the pattern pat. X * X * (pat) seperates out a piece of the pattern. X * X * pat1|pat2 matches to either pat1 or pat2 X * X * ' escapes the special meaning of these symbols. X * X * % matches the null string. X * X * EXTENSIONS X * X * [chars] will match any single character in the set chars, X * specified as single characters or ranges seperated X * by a -. Ex. [af-i+] would match a, f, g, h, i, and X * +. If ~ is the first character in the set then the X * set matched is the complement of the set specified. X * Ex. [~a-z] would match any one character that is X * not a (lower case if case sensitivity is on) letter. X * Note that a [~a] is NOT the same as a ~[a]. The former X * would match a 'b' but not a 'ab', whereas the latter X * would match both. X * X * ~(pat) will match anything that doesn't match the pattern. X * Note: it is illegal to repeat a not. ie #~a is illegal. X * (So is #(~(a)) so don't even try it.) You can repeat X * something with a not IN it, as long as it can't be X * reduced to the form #~(pattern). (A #[~a] is OK.) X * However ~#a has the expected effect (matches any X * non-null string not composed entirely of a's.) X * X * * same as #?. X * X * X */ X X#include "sregexp.h" X Xconst char wilds[] = { /* string of the wildcards, for easy access */ X CHR_REPEAT, X CHR_NOT, X CHR_OPENBRACE, X CHR_CLOSEBRACE, X CHR_OPENSET, X CHR_CLOSESET, X CHR_ANYCHAR, X CHR_NULL, X CHR_OR, X CHR_ESCAPE, X/* CHR_RANGE, <--- special case */ X CHR_STAR, X 0 X}; X X#ifdef __DEBUG__ Xextern void puts(char *); Xextern void printf(char *, ...); X#endif X X Xstruct SregExp * Xparsesregexp(expr) Xchar *expr; X/* This is the entry point into the parsing subroutines. */ X{ X return parsesub(&expr,0); X} X Xstatic struct SregExp * Xparsesub(p,end) Xchar **p,end; X/* This routine will parse a sub expression up until the character X 'end' is encontered. This is 0 for the whole pattern and ')' X for a subpattern */ X{ X struct SregList *list,*head=NULL,*orlist,*orhead=NULL; X struct SregExp *sreg; X int num = 0,ornum = 0; X X if (**p == end) { X char *q; X X q = "%"; X return parseone(&q,TRUE); X } X X while (**p != end) { X if (!(sreg = parseone(p,TRUE))) /* parse on wildcard */ X goto cleanup; X if (head) { /* if there's already a list, just stick it on */ X if (!(list = (list->srl_next = getmem(sizeof(struct SregList))))) { X report(MEM_ERROR); X goto cleanup; X } X } else { /* otherwise, make a new list */ X if (!(list = (head = getmem(sizeof(struct SregList))))) { X report(MEM_ERROR); X goto cleanup; X } X } X list->srl_sreg = sreg; X list->srl_next = NULL; X num++; X if (**p == CHR_OR) { /* deal with an or */ X if (!(sreg = makesum(head,num))) X goto cleanup; X if (orhead) { /* either add onto the or list */ X if (!(orlist = (orlist->srl_next = getmem(sizeof(struct SregList))))) { X report(MEM_ERROR); X goto cleanup; X } X } else { /* or make a new or list */ X if (!(orlist = (orhead = getmem(sizeof(struct SregList))))) { X report(MEM_ERROR); X goto cleanup; X } X } X orlist->srl_sreg = sreg; X orlist->srl_next = NULL; X ornum++; X (*p)++; X head = NULL; X num = 0; X } X } X if (!(sreg = makesum(head,num))) X goto cleanup; X if (orhead) { /* if this expression had an or, clean it up */ X if (!(orlist = (orlist->srl_next = getmem(sizeof(struct SregList))))) { X report(MEM_ERROR); X goto cleanup; X } X orlist->srl_sreg = sreg; X orlist->srl_next = NULL; X ornum++; X if (!(sreg = makeor(orhead,ornum))) X goto cleanup; X } X X return sreg; /* sub expression successfully matched. */ X Xcleanup: /* troubles all head here to clean up */ X X list = head; X while (list) { /* free all the bits of the current sum */ X head = list->srl_next; X freesregexp(list->srl_sreg); X FreeMem(list,sizeof(struct SregList)); X list = head; X } X list = orhead; X while (list) { /* and all of the current or parts */ X head = list->srl_next; X freesregexp(list->srl_sreg); X FreeMem(list,sizeof(struct SregList)); X list = head; X } X X return NULL; /* return the failure */ X} X Xstatic struct SregExp * Xmakesum(list,num) Xstruct SregList *list; Xint num; X/* This routine takes a linked list of sreg's and joins them together X Under the auspices of one big SRP_SUM type sreg */ X{ X struct SregList *lnk; X struct SregExp *sreg; X int i,len=0; X char fixed = SRF_FIXLEN; X X if (num == 0) { X report(ILLEGAL_ERR); X return NULL; X } else if (num == 1) { X sreg = list->srl_sreg; X FreeMem(list,sizeof(struct SregList)); X return sreg; X } if (!(sreg = getmem(sizeof(struct SregExp) + num*sizeof(struct SregExp *)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Type = SRP_SUM; X sreg->sre_Flag = 0; X sreg->sre_Data.number = num; X for (i = 0; i < num; i++) { X len += realen(list->srl_sreg); X fixed &= isfixed(list->srl_sreg) ? SRF_FIXLEN : 0; X sreg->sre_List[i] = list->srl_sreg; X lnk = list->srl_next; X FreeMem(list,sizeof(struct SregList)); X list = lnk; X } X sreg->sre_MinLen = len; X sreg->sre_Flag |= fixed; X return sreg; X} X Xstatic struct SregExp * Xmakeor(list,num) Xstruct SregList *list; Xint num; X/* This does basically the same thing as makesum, except it makes X an SRP_OR type sreg to join the list and doesn't deal with some X special cases */ X{ X struct SregList *lnk; X struct SregExp *sreg; X int i,len; X char fixed = SRF_FIXLEN; X X if (!(sreg = getmem(sizeof(struct SregExp) + num*sizeof(struct SregExp *)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Type = SRP_OR; X sreg->sre_Flag = 0; X sreg->sre_Data.number = num; X for (i = 0; i < num; i++) { X if (i == 0) X len = realen(list->srl_sreg); X else if (len != realen(list->srl_sreg)) { X fixed = 0; X if (len > realen(list->srl_sreg)) X len = realen(list->srl_sreg); X } X fixed &= isfixed(list->srl_sreg) ? SRF_FIXLEN : 0; X sreg->sre_List[i] = list->srl_sreg; X lnk = list->srl_next; X FreeMem(list,sizeof(struct SregList)); X list = lnk; X } X sreg->sre_MinLen = len; X sreg->sre_Flag |= fixed; X return sreg; X} X Xstatic struct SregExp * Xparseone(p,cat) Xchar **p,cat; X/* This routine parses one wildcard character from the string *p, X leaving it set up pointing to the begining of the next X wildcard. If 'cat' is true then a string of characters will X be grouped together as a SRP_STRING type sreg. It may be X false because of the scope rules of ~ and #, which only X repeat the very next pattern. */ X{ X struct SregExp *sreg; X X switch (**p) { X case (CHR_REPEAT) : X (*p)++; X if (!(sreg = parseone(p,FALSE))) X return NULL; X if (sreg->sre_Flag & SRF_NOT) { X report(ILLEGAL_ERR); X freesregexp(sreg); X return NULL; X } X sreg->sre_Flag |= SRF_REPEAT; X break; X case (CHR_NOT) : X (*p)++; X if (!(sreg = parseone(p,FALSE))) X return NULL; X sreg->sre_Flag |= SRF_NOT; X break; X case (CHR_OPENBRACE) : X (*p)++; X sreg = parsesub(p,CHR_CLOSEBRACE); X (*p)++; X break; X case (CHR_OPENSET) : X (*p)++; X if (!(sreg = getmem(sizeof(struct SregExp)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Type = SRP_SETCHAR; X sreg->sre_Flag = SRF_FIXLEN; X sreg->sre_MinLen = 1; X if (!(sreg->sre_Data.setchar = makeset(p))) { X FreeMem(sreg,sizeof(sreg)); X return NULL; X } X (*p)++; X break; X case (CHR_ANYCHAR) : X (*p)++; X if (!(sreg = getmem(sizeof(struct SregExp)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Type = SRP_ANYCHAR; X sreg->sre_Flag = SRF_FIXLEN; X sreg->sre_MinLen = 1; X break; X case (CHR_STAR) : X (*p)++; X if (!(sreg = getmem(sizeof(struct SregExp)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Type = SRP_ANYCHAR; X sreg->sre_Flag = SRF_FIXLEN | SRF_REPEAT; X sreg->sre_MinLen = 1; X break; X case (CHR_NULL) : X (*p)++; X if (!(sreg = getmem(sizeof(struct SregExp)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Type = SRP_NULL; X sreg->sre_Flag = SRF_FIXLEN; X sreg->sre_MinLen = 0; X break; X case (CHR_CLOSEBRACE) : X case (CHR_CLOSESET) : X case (CHR_OR) : X case (0) : X report(ILLEGAL_ERR); X return NULL; X default : X if (!(sreg = getmem(sizeof(struct SregExp)))) { X report(MEM_ERROR); X return NULL; X } X sreg->sre_Flag = SRF_FIXLEN; X if (!cat) { X sreg->sre_Data.onechar = onechar(p,FALSE); X sreg->sre_Type = SRP_ONECHAR; X sreg->sre_MinLen = 1; X } else { X char *q=*p; X int len=0; X X while (onechar(&q,FALSE)) X len++; X sreg->sre_MinLen = len; X if (len == 1) { X sreg->sre_Data.onechar = onechar(p,FALSE); X sreg->sre_Type = SRP_ONECHAR; X } else { X sreg->sre_Type = SRP_STRING; X if (!(q = sreg->sre_Data.string = getmem(len+1))) { X report(MEM_ERROR); X FreeMem(sreg,sizeof(sreg)); X return NULL; X } X while (*q++ = onechar(p,FALSE)) ; X *q = 0; X } X } X } X return sreg; X} X Xstatic char Xonechar(p,minus) Xchar **p,minus; X/* this routine picks one character off the string *p. It handles X escaping the special meaning of the wildcard characters, and X returns 0 if we're at the end of the string or the next X char is a wildcard. if 'minus' is true, then the '-' is X treated as a wildcard, otherwise it isn't */ X{ X if (**p == CHR_ESCAPE) X (*p)++; X else if (strchr(wilds,**p) || (minus && **p == CHR_RANGE)) X return 0; X return *(*p)++; X} X Xstatic char * Xmakeset(p) Xchar **p; X/* this makes a table of match flags from the character specifier X that goes in between [ and ]. It handles a leading '~' and X leaves *p pointing to the closing brace. Note: This routine X checks to make sure the specifier ends in a ] and fails if X it doesn't */ X{ X char *set,not=FALSE,ok=FALSE,s,e; X X if (**p == CHR_NOT) { X (*p)++; X not = TRUE; X } X if (!(set = getmem(32))) { X report(MEM_ERROR); X return NULL; X } X for (s = 0; s < 32; s++) X set[s] = 0; X while (s = onechar(p,TRUE)) { X ok = TRUE; X if (**p == CHR_RANGE) { X (*p)++; X if (!(e = onechar(p,TRUE))) { X report(ILLEGAL_ERR); X FreeMem(set,32); X return NULL; X } X for ( ; s <= e; s++) X set[s/8] |= 1 << (s % 8); X } else X set[s/8] |= 1 << (s % 8); X } X if (!ok || **p != CHR_CLOSESET) { X report(ILLEGAL_ERR); X FreeMem(set,32); X return NULL; X } X if (not) { X for(s = 0; s < 32; s++) X set[s] = ~set[s]; X } X return set; X} X Xvoid Xfreesregexp(sreg) Xstruct SregExp *sreg; X/* this routine frees up a sreg. It correctly handles freeing the X subpattern elements in a SRP_SUM or SRP_OR sreg and frees the X match table or string from a SRP_SETCHAR or SRP_STRING sreg. X This is one of the externally visible routines. */ X{ X int add = 0; X X if (sreg->sre_Type == SRP_SUM || sreg->sre_Type == SRP_OR) { X int i; X X add = sreg->sre_Data.number * sizeof(struct SregExp *); X for (i = 0; i < sreg->sre_Data.number; i++) X freesregexp(sreg->sre_List[i]); X X } else if (sreg->sre_Type == SRP_STRING) X FreeMem(sreg->sre_Data.string,strlen(sreg->sre_Data.string)+1); X else if (sreg->sre_Type == SRP_SETCHAR) X FreeMem(sreg->sre_Data.setchar,32); X FreeMem(sreg,sizeof(struct SregExp) + add); X} X Xint Xmatchsregexp(p,sreg,up) Xchar *p; Xstruct SregExp *sreg; Xint up; X/* This is the externally visible stub to the pattern matching part X of sreg. 'p' is the string to match to, sreg is the preparsed X sreg, and up indicates if the match is case sensitive. */ X{ X return matchnsregexp(p,sreg,up,strlen(p)); X} X Xint Xmatchnsregexp(p,sreg,up,len) Xchar *p; Xstruct SregExp *sreg; Xint up,len; X/* This routine will match a sreg to a string of length 'len'. */ X/* The length, rather than NULL terminated is used to make a X lot of things a lot simpler */ X{ X int res,i; X X if (sreg->sre_Flag & SRF_REPEAT) { /* deal with repeaters. */ X char not,*h; X X if (len == 0 || sreg->sre_Type == SRP_ANYCHAR) { /* always true */ X res = TRUE; X goto end; X } X /* check if the lengths match up */ X if (len < sreg->sre_MinLen || (sreg->sre_Flag & SRF_FIXLEN && X (sreg->sre_MinLen == 0 || len % sreg->sre_MinLen != 0))) { X res = FALSE; X goto end; X } X not = sreg->sre_Flag & SRF_NOT; X sreg->sre_Flag &= ~(SRF_REPEAT | SRF_NOT); X if (sreg->sre_Flag & SRF_FIXLEN) { /* handle fixed lenght matches */ X h = p; X while (h-p < len) { X if (!(res = matchnsregexp(h,sreg,up,sreg->sre_MinLen))) X goto end; X h += sreg->sre_MinLen; X } X } else { /* and variable length ones */ X for (i = len; i >= (sreg->sre_MinLen ? sreg->sre_MinLen : 1); i--) { X if (res = matchnsregexp(p,sreg,up,i)) { X sreg->sre_Flag |= SRF_REPEAT; X if (res = matchnsregexp(p+i,sreg,up,len-i)) X break; X sreg->sre_Flag &= ~SRF_REPEAT; X } X } X } X sreg->sre_Flag |= SRF_REPEAT | not; X goto end; X } X X /* check the lengths first for quick rejection */ X if (len < sreg->sre_MinLen || (sreg->sre_Flag & SRF_FIXLEN && len != sreg->sre_MinLen)) { X res = FALSE; X goto end; X } X X switch (sreg->sre_Type) { X case (SRP_SUM) : X res = matchsum(&(sreg->sre_List[0]),sreg->sre_Data.number,p,len,up); X break; X case (SRP_ONECHAR) : X res = len == 1 && (up ? *p == sreg->sre_Data.onechar : X toupper(*p) == toupper(sreg->sre_Data.onechar)); X break; X case (SRP_SETCHAR) : X res = len == 1 && matchset(sreg,*p) || (up ? FALSE : X (isupper(*p) ? matchset(sreg,tolower(*p)) : X matchset(sreg,toupper(*p)))); X break; X case (SRP_ANYCHAR) : X res = len == 1; X break; X case (SRP_STRING) : X if (up) X res = !strncmp(p,sreg->sre_Data.string,len); X else X res = !strnicmp(p,sreg->sre_Data.string,len); X break; X case (SRP_NULL) : X res = len == 0; X break; X case (SRP_OR) : X for (i = 0; i < sreg->sre_Data.number; i++) X if (res = matchnsregexp(p,sreg->sre_List[i],up,len)) { X break; X } X break; X } X Xend: X X if (sreg->sre_Flag & SRF_NOT) X return !res; X else X return res; X} X Xstatic int Xmatchsum(list,num,p,len,up) Xstruct SregExp *list[]; Xint num,len,up; Xchar *p; X/* This routine is called by match to match the elements of a sum X of sregs. It tries to be as effecient as possible, and keep X recursion to a minimum. It will match any fixed length peices X at the begining and end first, then match any fixed length X peices in the middle to break the string up. Only then does X it do the tiresome matches to the non-fixed length peices. */ X{ X int i,res,o; X X while (num && isfixed(list[0])) { X if (!(res = matchnsregexp(p,list[0],up,list[0]->sre_MinLen))) X return FALSE; X p += list[0]->sre_MinLen; X len -= list[0]->sre_MinLen; X list++; X num--; X } X while (num && isfixed(list[num-1])) { X if (!(res = matchnsregexp(p+len-list[num-1]->sre_MinLen,list[num-1],up, X list[num-1]->sre_MinLen))) X return FALSE; X len -= list[num-1]->sre_MinLen; X num--; X } X if (num == 0) X return TRUE; X X o = 0; X for (i = 1; i < num-1; i++) { X if (isfixed(list[i])) { X for ( ; len-o >= list[i]->sre_MinLen; o++) { X if (res = matchnsregexp(p+o,list[i],up,list[i]->sre_MinLen)) { X if (!(res = matchsum(list,i,p,o,up))) X return FALSE; X if (!(res = matchsum(list+(i+1),num-i-1, X p+o+list[i]->sre_MinLen,len-o-list[i]->sre_MinLen,up))) X return FALSE; X return TRUE; X } X } X return FALSE; X } else X o += realen(list[i]); X } X X if (num == 1) X return matchnsregexp(p,list[0],up,len); X X for (o = len; o >= list[0]->sre_MinLen; o--) X if (matchnsregexp(p,list[0],up,o) && matchsum(list+1,num-1,p+o,len-o,up)) X return TRUE; X X return FALSE; X} X Xint Xiswild(p) Xchar *p; X/* this is a very simple routine, but it is externally visible. Returns X true if the string has wildcard characters (unescaped) false if X not */ X{ X while (onechar(&p,FALSE)) ; X return *p != 0; X} X Xvoid Xreport(i) Xint i; X/* This routine now does set the IoErr value to more information. X For now it does nothing. */ X{ X struct Process *myself; X X if (myself = (struct Process *)FindTask(0)) X myself->pr_Result2 = i; X} END_OF_FILE if test 16596 -ne `wc -c <'sregexp.c'`; then echo shar: \"'sregexp.c'\" unpacked with wrong size! fi # end of 'sregexp.c' fi if test -f 'sregexp.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sregexp.doc'\" else echo shar: Extracting \"'sregexp.doc'\" \(13775 characters\) sed "s/^X//" >'sregexp.doc' <<'END_OF_FILE' XTABLE OF CONTENTS X Xsregexp.library/AnchorPath Xsregexp.library/BuildPath Xsregexp.library/FreeSpathInfo Xsregexp.library/FreeSregExp Xsregexp.library/IsWild Xsregexp.library/ParseSregExp Xsregexp.library/MatchNSregExp Xsregexp.library/MatchSregExp Xsregexp.library/NextFile X Xsregexp.library/AnchorPath sregexp.library/AnchorPath X X NAME X AnchorPath -- get set up to match a wildcard path. X X SYNOPSIS X spath = AnchorPath(anc, wld) X D0 A0 A1 X struct SpathInfo *AnchorPath(char *, char *); X X FUNCTION X This is the first step in matching a wildcarded path. This routine X will preparse all of the wildcard elements in the path and set X everything up for subsequent calls to NextFile. X X If NULL is returned, then IoErr can be examined to find out more on X whatever went wrong. X X The wildcarded path is made up of (almost, see bug note) any legal X AmigaDOS path name, with wildcard expressions in the place of file X and directory names. There is one additional syntax: '.../' means X recursively search all sub-directories. so: X DH0:.../fred X would search all of DH0 for a (file or directory or either, see X NextFile) named fred. X X One pretty nifty feature is that wildcards are legal in the volume X node part of the path. This will match to any file system device or X assigned directory or volume node that the system currently has X mounted. So to match all of the hard drive partitions in your system X you would use 'DH?:.../fred'. The root of your current device will X be matched only if the pattern explicitly matches a null string (ie X either just ':' or '%:') X X INPUTS X anc - a null terminated string which is the name of a X directory. All paths returned by BuildPath and NextFile X will be relative to this directory. X X wld - the wildcarded path to be matched. X X RESULTS X spath - a pointer to a SpathInfo structure ready for calls to X NextFile. X X NOTES X It will be most usual to pass a pointer to a null string for anc, X this will make all paths relative to the current working directory. X X If the wildcarded path ends in a '/' then the search will match only X directories, and the '/' will be appended to all paths returned by X BuildPath and NextFile. If you specify a path ending in '/' and then X ask NextFile to look for only files the search will fail. If the X path does not end in a '/' then no '/' will be appended to the path X returned, regardless of whether the match is to a file or a X directory. X X BUGS X (well, possible bugs actually) If one of the elements of the path X explicitly matches a null string (ie. either /%/ or just //) then X the routine will match to the parent directory. This works in all of X the cases I have tried (and the only important use, which is at the X beginning of the path.) I am just not terribly confident with the X way it's done, so if funny bugs creep up, look here first. X X SEE ALSO X ParseSregExp, NextFile, BuildPath, FreeSpathInfo X Xsregexp.library/BuildPath sregexp.library/BuildPath X X NAME X BuildPath -- build the path to the current match to a SpathInfo X structure X X SYNOPSIS X len = BuildPath(spi,buff,len) X D0 A0 A1 D0 X int BuildPath(Struct SpathInfo *, char *, int); X X FUNCTION X The path to the current match of the SpathInfo structure is copied X into the buffer and null terminated. This will have unpredictable X results, possibly including fireworks, if it is called before the X first call to NextFile. X X This routine will mainly be used to try again with a bigger buffer X if NextPath failed with SPE_BUFF_FULL. X X INPUTS X spi - The pointer returned by a call to AnchorPath X X buff - a buffer length len long to copy the path name into. X X len - the length of the buffer, buff. X X X RESULTS X len - exactly the same as returned by NextFile. X X SEE ALSO X NextFile, AnchorPath. X Xsregexp.library/FreeSpathInfo sregexp.library/FreeSpathInfo X X NAME X FreeSpathInfo -- free up all of the resources locked by calls X to AnchorPath and NextFile X X SYNOPSIS X FreeSpathInfo(spi) X A0 X void FreeSpathInfo(struct SpathInfo *); X X FUNCTION X This will free all of the memory and file locks currently wrapped up X in the SpathInfo structure. This is the ONLY way you should try to X free up these resources. X X This routine can be called at any point, either immediately after X the call to AnchorPath, or after any calls to NextFile or BuildPath. X X INPUTS X spi - A pointer to a SpathInfo structure to be freed. X X SEE ALSO X AnchorPath. X Xsregexp.library/FreeSregExp sregexp.library/FreeSregExp X X NAME X FreeSregExp -- free up a preparsed wildcard created by ParseSregExp X X SYNOPSIS X FreeSregExp(sreg) X A0 X void FreeSregExp(struct SregExp *); X X FUNCTION X This routine will free all of the resources associated with a X preparsed wildcard expression. This is the only legal way to free X the object created by ParseSregExp, and you should not try to do it X yourself. X X INPUTS X sreg - a pointer to the preparsed wildcard expression returned X by ParseSregExp. X X SEE ALSO X ParseSregExp, MatchNSregExp, MatchSregExp. X Xsregexp.library/IsWild sregexp.library/IsWild X X NAME X IsWild -- test if a string has any unescaped wildcard characters. X X SYNOPSIS X bool = IsWild(wildcard); X D0 A0 X int IsWild(char *); X X FUNCTION X This routine merely checks if the string contains any unescaped X wildcard characters. It does not actually test if the string is X wild. For example, it would fail on '(this is a test)' because of X the round brackets, which are wildcard characters. X X INPUTS X wildcard - a pointer to a wildcard string. X X RESULTS X bool - non-zero if any unescaped wildcard characters were X found. X X NOTES X This routine has very little merit, and is not really all that X useful. I will probably add a routine in future versions that does X the same thing but takes the preparsed wildcard expression and X returns the unique string which it will match, or NULL. X X SEE ALSO X ParseSregExp. X Xsregexp.library/ParseSregExp sregexp.library/ParseSregExp X X NAME X ParseSregExp -- preparse a wildcard expression for matching. X X SYNOPSIS X sreg = ParseSregExp(wildcard) X D0 A0 X struct SregExp *ParseSregExp(char *); X X FUNCTION X A wildcard string must be preparsed before it can be passed to X MatchSregExp or MatchNSregExp to actually test if it matches a given X target string. X X This function returns a pointer to the successfully created X structure, or NULL on failure. On failure, IoErr() can be examined X to get more information on the cause of the trouble. X ERROR_INVALID_COMPONENT_NAME is returned if the wildcard string is X illegal and ERROR_NO_FREE_STORE is returned if memory allocation X failed. X X WILDCARD SYNTAX X The wildcard syntax accepted is an extension of the usual AmigaDOS X wildcards. Any 1.3 wildcard expression should be ok. Apparently X under 2.0 they have added a not operator, and the one here may or X may not be compatible with the way they have done it. (They SHOULD X have done it this way.) X X Here is a synopsis: X X ? matches any one character X X #(pat) matches zero or more occurrences of the pattern pat. X X (pat) separates out a piece of the pattern. X X pat1|pat2 matches to either pat1 or pat2 X X ' escapes the special meaning of these symbols. X X % matches the null string. X X These are the extensions: X X [chars] will match any single character in the set chars, X specified as single characters or ranges separated by a X -. Ex. [af-i+] would match a, f, g, h, i, and +. If ~ X is the first character in the set then the set matched X is the complement of the set specified. Ex. [~a-z] would X match any one character that is not a (lower case if X case sensitivity is on) letter. Note that a [~a] is NOT X the same as a ~[a]. The former would match a 'b' but not X a 'ab', whereas the latter would match both. Special X care should be taken when using this wildcard in case X insensitive matches. As expected, [a] would match either X 'a' or 'A' in a case insensitive search, but [~a] would X match anything, since it doesn't match 'a', but would X match a 'A'. X X ~(pat) will match anything that doesn't match the pattern. X Note: it is illegal to repeat a not. ie #~a is illegal. X (So is #(~(a)) so don't even try it.) You can repeat X something with a not IN it, as long as it can't be X reduced to the form #~(pattern). (A #[~a] is OK.) X However ~#a has the expected effect (matches any X non-null string not composed entirely of a's.) X X * same as #?. X X INPUTS X wildcard - a pointer to the null terminated wildcard expression X string. X X RETURNS X sreg - a preparsed version of the wildcard expression. X X SEE ALSO X FreeSregExp, MatchNSregExp, MatchSregExp. X Xsregexp.library/MatchNSregExp sregexp.library/MatchNSregExp X X NAME X MatchNSregExp - match a preparsed wildcard expression to a target X X SYNOPSIS X bool = MatchNSregExp(target,sreg,case,len) X D0 A0 A1 D0 D1 X int MatchNSregExp(char *, struct SregExp *, int int); X X FUNCTION X This function tests if the given fixed length target string matches X the preparsed wildcard expression. X X This routine is identical to MatchSregExp, except it takes a pointer X to a string and its length, rather than a null terminated string. X X INPUTS X target - the null terminated target string you wish to test X against the wildcard expression. X X sreg - the preparsed wildcard expression. X X case - if this is non-zero then the match is case sensitive, X otherwise it is case insensitive. X X len - the length of the string pointed to by target. X X RESULTS X bool - non-zero if the target matches the expression, zero X otherwise. X X NOTES X See ParseSregExp for a discussion of the wildcard expression and the X tricky behaviour of character sets (ie. [...]) when the search is X case insensitive. X X This routine is handy for matching BCPL strings. If p is a c X pointer (byte, not longword address) of a BCPL string then X X MatchNSregExp(p+1,sreg,case,*p) X X will test the BCPL string for a match. X X SEE ALSO X FreeSregExp, ParseSregExp, MatchSregExp. X Xsregexp.library/MatchSregExp sregexp.library/MatchSregExp X X NAME X MatchSregExp - match a preparsed wildcard expression to a target X X SYNOPSIS X bool = MatchSregExp(target,sreg,case) X D0 A0 A1 D0 X int MatchSregExp(char *, struct SregExp *, int); X X FUNCTION X This function tests if the given null terminated target string X matches the preparsed wildcard expression. X X This routine is identical to MatchNSregExp, except it takes a X pointer to a null terminated string, rather than a string and its X length. X X INPUTS X target - the null terminated target string you wish to test X against the wildcard expression. X X sreg - the preparsed wildcard expression. X X case - if this is non-zero then the match is case sensitive, X otherwise it is case insensitive. X X RESULTS X bool - non-zero if the target matches the expression, zero X otherwise. X X NOTES X See ParseSregExp for a discussion of the wildcard expression and the X tricky behaviour of character sets (ie. [...]) when the search is X case insensitive. X X This call currently just results in the call: X X MatchNSregExp(target,sreg,case,strlen(target)); X X but this may change in future version. X X SEE ALSO X FreeSregExp, ParseSregExp, MatchNSregExp. X Xsregexp.library/NextFile sregexp.library/NextFile X X NAME X NextFile -- return the next (or first) file matching the path. X X SYNOPSIS X len = NextFile(spi,buff,len,dirs) X D0 A0 A1 D0 D1 X int NextFile(struct SpathInfo *, char *, int int); X X FUNCTION X This routine copies the path to the next (or first, if this is the X first call) file or directory matching the wildcard in the SpathInfo X structure created by a call to AnchorPath. X X The usual calling sequence would be: X AnchorPath X repeat while no errors and more files X NextFile X FreeSpathInfo X X The length of the path is returned, or if there is an error or there X are no more matches a negative result is returned. Both the X negative number and the Value if IoErr will give more information X about why the routine returned. X X INPUTS X spi - The pointer returned by a call to AnchorPath X X buff - a buffer length len long to copy the path name into. X X len - the length of the buffer, buff. X X dirs - if this is greater than zero, only directories will X match; if it is zero, both files and directories will X match; if it is less than zero, only files will match. X See the defines in the include file. X X RESULTS X len - on success this will be the length of the path copied X into the buffer. If it is less than zero, some kind of X special event is signalled. X SPE_ALL_DONE - This signals there are no more matches X to the path. IoErr will also be set to X ERROR_NO_MORE_ENTRIES X SPE_ERROR - Some error happened, see IoErr. X SPE_BUFF_FULL - The buffer you suplied was not big X enough for the path name. Get a bigger X one and call BuildPath. X SPE_SIGBREAK - One of the dos break signals was X received by your process. This does not X clear the signals, but since some X searches can take a while it checks X every now and again. You can just clear X the signal and call NextPath again to X ignore the signal. X X NOTES X It is meaningless to mix calls with a different value of dirs. X Anything passed by in a call in which you did not ask for objects of X a given type will not reappear in subsequent calls in which you do X ask for that type. X X SEE ALSO X AnchorPath, BuildPath. X END_OF_FILE if test 13775 -ne `wc -c <'sregexp.doc'`; then echo shar: \"'sregexp.doc'\" unpacked with wrong size! fi # end of 'sregexp.doc' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.misc.