File: wild.c

package info (click to toggle)
xmake 1.06-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 124 kB
  • ctags: 120
  • sloc: ansic: 1,372; makefile: 60
file content (123 lines) | stat: -rw-r--r-- 2,613 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

/*
 *  WILD.C
 */

#include "defs.h"

#define MAXLEVELS   10

Prototype int  WildConvert(char *, char **, char *, char *);

int appendDst(char **pbase, int di, int dl, char *s, int slen);

/*
 *  Run srcBuf through the srcMat pattern matcher and if it matches
 *  convert it via dstMat into dstBuf, else dstBuf \0 len.
 */

int
WildConvert(char *srcBuf, char **pdstBuf, char *srcMat, char *dstMat)
{
    short r = 0;
    long i;
    int di = 0;
    int dl = 0;
    static short Index;
    static short SubLen[MAXLEVELS];
    static char *SubStr[MAXLEVELS];

    if (Index == MAXLEVELS)
	fatal(NULL, "maximum recursion reached in WildConvert (%s,%s,%s)", srcBuf, srcMat, dstMat);

    /*
     *	skip non-wildcards, srcBuf must match srcMat
     */

    while (*srcMat && *srcMat != '*' && *srcMat != '?') {
	if (*srcBuf != *srcMat)
	    return(-1);
	++srcBuf;
	++srcMat;
    }

    switch(*srcMat) {
    case '\0':                      /*  match end, terminating case */
	if (*srcBuf)                /*  buf srcBuf not exhausted!   */
	    r = -1;
	break;
    case '?':                       /*  match 1 */
	if (*srcBuf == 0)           /*  match failed against srcbuf  */
	    return(-1);
	SubStr[Index] = srcBuf;
	SubLen[Index] = 1;
	++Index;
	r = WildConvert(srcBuf + 1, NULL, srcMat + 1, NULL);
	--Index;
	break;
    case '*':                       /*  match any   */
	/*
	 *  strangeness in loop is so \0 (nil string) is checked for,
	 *  it is perfectly valid for the remainder to be nil.
	 *
	 *  note: bug in NeXT's GCC -O/-O2, had to reorder r == -1 to
	 *  the right side of the &&
	 */

	r = -1;
	for (i = 0; (i == 0 || srcBuf[i-1]) && r == -1; ++i) {
	    SubStr[Index] = srcBuf;
	    SubLen[Index] = i;
	    ++Index;
	    r = WildConvert(srcBuf + i, NULL, srcMat + 1, NULL);
	    --Index;
	}
	break;
    }
    if (r == 0 && dstMat) {
	short k = 0;
	short n = -1;

	while (*dstMat) {
	    switch(*dstMat) {
	    case '%':
		n = (dstMat[1] - '1');
	    case '*':
	    case '?':
		if (*dstMat == '%')
		    ++dstMat;
		else
		    n = k++;

		if (n >= 0 && n < MAXLEVELS) {
		    dl = appendDst(pdstBuf, di, dl, SubStr[n], SubLen[n]);
		    di += SubLen[n];
		}
		break;
	    default:
		dl = appendDst(pdstBuf, di, dl, dstMat, 1);
		++di;
		break;
	    }
	    ++dstMat;
	}
	dl = appendDst(pdstBuf, di, dl, "", 1);
    }
    return(r);
}

int
appendDst(char **pbase, int di, int dl, char *s, int slen)
{
    if (dl == 0) {
	*pbase = malloc(16);
	dl = 16;
    }
    if (di + slen > dl) {
	dl = (di + slen + 15) & ~15;
	*pbase = realloc(*pbase, dl);
    }
    bcopy(s, *pbase + di, slen);
    return(dl);
}