source: trunk/athena/etc/synctree/regexp.c @ 10510

Revision 10510, 4.8 KB checked in by ghudson, 27 years ago (diff)
Assume POSIX.
  • Property svn:executable set to *
Line 
1/*
2 * Copyright 1986,1989 by Richard P. Basch
3 * All Rights Reserved.
4 */
5
6/*
7 * Regular expression parser
8 *
9 * Function:
10 *    int regexp(pattern, string)
11 *
12 * Synopsis:
13 *    This routine will determine if the "string" matches the "pattern".
14 *    The pattern is similar to that of UNIX /bin/csh filename globbing.
15 *    The only differences between this and the csh parser are:
16 *      - Double negation in ranges is allowed
17 *        eg.  [a-z^m-q^n]  would represent any character
18 *             between a and z (inclusive), except for the characters
19 *             m through q, but still allowing n
20 *      - {} has not yet been implemented.
21 *
22 * Return values:
23 *    This routine returns 0 if the string did not match the pattern
24 *    and non-zero if the string did match.
25 */
26
27#include "regexp.h"
28
29int reg_matchrange(range,testc)
30char *range, testc;
31{
32    /*
33     * Arguments:
34     *    range = range expression
35     *    testc = character to test to see if it within the range
36     *
37     * Variables:
38     *    found     = was there a match (either negated or normal)
39     *    r_start   = beginning of a range
40     *    r_end     = end of a range
41     *    not       = toggle for whether to negate the expression
42     *    reg_chars = non-zero if there are non-negated characters/ranges
43     *    c         = temporary character
44     *    r_state   = 0 for first char of range, 1 for last char of range
45     */
46   
47    int found=0, not=0, reg_chars=0, r_state = 0, literal = 0;
48    unsigned char r_start, r_end, c;
49
50    while(c = *range++) {
51        literal = 0;
52       
53        switch(c) {
54        case NOTCHAR:
55        case LITERAL:
56            if (c == NOTCHAR && *range) {
57                not = (! not);
58                break;
59            }
60            if (c == LITERAL && *range) {
61                c = *range++;
62                literal++;
63            }
64        default:
65            reg_chars += !not;
66
67            if (!r_state) {             /* This is the beginning of a range */
68                if (c == RANGETO && !literal && *range) {
69                    r_start = r_end =  '\0';
70                    range--;
71                } else
72                    r_start = r_end = c;
73
74                if (*range == RANGETO) {
75                    range++;            /* Skip the RANGETO character */
76
77                    switch (*range) {   /* What comes next? */
78                    case NOTCHAR:       /* If NOTCHAR or no more characters */
79                    case '\0':          /* set the range-end and process    */
80                        r_end = '\377';
81                        break;
82                    default:            /* Ok, to process range-end normally */
83                        r_state++;      /* Set the flag */
84                        break;
85                    }
86
87                    if (r_state)
88                        break;          /* Go ahead and get the range-end */
89                }
90            } else
91                r_end = c;
92
93            if (testc >= r_start && testc <= r_end)
94                found = not ? -1 : 1;
95            break;
96        }
97    }
98    return((found > 0) || (!reg_chars && !found));
99}
100
101int regexp(pattern, string)             /* returns 1 if string fits */
102char *pattern, *string;                 /* pattern, 0 otherwise.    */
103{
104    int good = 1;
105    char range[128], *temp, c, lastc;
106
107    while(*pattern && good) {
108        switch(*pattern) {
109        case WILDCHAR:
110            pattern++;
111            good = (*string++ != '\0');
112            break;
113        case LITERAL:
114            pattern++;
115            good = (*pattern++ == *string++);
116            break;
117        case WILDCARD:
118            pattern++;
119            while ((!regexp(pattern, string)) && *string != '\0')
120                string++;
121            break;
122        case RANGEBEG:
123            lastc = *pattern++;
124            for (temp = range;
125                 (c = *pattern++) && !(c == RANGEEND && lastc != LITERAL);
126                 lastc = *temp++ = c) ;
127            *temp = '\0';
128            temp = string++;
129            while (!(good = regexp(pattern, string)) && *string != '\0')
130                string++;
131            for ( ; temp<string && good; good=reg_matchrange(range, *temp++)) ;
132            break;
133        default:
134            good = (*pattern++ == *string++);
135            break;
136        }
137    }
138    return(good && *pattern == '\0' && *string == '\0');
139}
140
141
142
143
144#if 0
145char *strindex(string1,string2)         /* find first occurrence */
146char *string1, *string2;                /* of string2 in string1 */
147{
148    char *t1, *t2, *t3;
149
150    for (t1=string1; *t1 != '\0'; t1++) {
151        for (t2=string2, t3=t1; *t2 != '\0' && *t2 == *t3; t2++, t3++) ;
152        if (*t2 == '\0') return (t1);
153    }
154    return(NULL);
155}
156
157char *bstrindex(string1, string2)       /* Find last occurrence  */
158char *string1, *string2;                /* of string2 in string1 */
159{
160    char *t1, *t2;
161
162    t1 = strindex(string1, string2);
163    if (t1 != NULL)
164        while ((t2 = strindex(t1+1, string2)) != NULL) t1=t2;
165    return(t1);
166}
167
168stoupper(string)                        /* Convert string to uppercase */
169char *string;
170{
171   while(*string != NULL)
172      *string++ = toupper(*string);
173}
174#endif /* 0 */
175
176
177#ifdef TEST
178#include <stdio.h>
179#include <signal.h>
180
181void cleanup()
182{
183    exit(1);
184}
185main()
186{
187    char s1[80], s2[80];
188    int s3;
189    struct sigaction sa;
190
191    (void) sigemptyset(&sa.sa_mask);
192    sa.sa_flags = 0;
193    sa.sa_handler = cleanup;
194    (void) sigaction(SIGINT, &sa, (struct sigaction *)0);
195loop:
196    printf("Pattern ==> ");
197    if (!gets(s1))
198        exit (0);
199    if (! strcmp(s1,"quit"))
200        exit(0);
201
202    printf("String  ==> ");
203    if (!gets(s2))
204        exit(0);
205
206    s3 = regexp(s1,s2);
207    printf("%s\n\n", s3 ? "Pattern matched" : "Pattern failed");
208    goto loop;
209}
210#endif /* test */
Note: See TracBrowser for help on using the repository browser.