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.