994
|
1 /* makepat.c */
|
|
2 #include <stdio.h>
|
|
3 #include "tools.h"
|
|
4
|
|
5 /* Make a pattern template from the strinng pointed to by arg. Stop
|
|
6 * when delim or '\000' or '\n' is found in arg. Return a pointer to
|
|
7 * the pattern template.
|
|
8 *
|
|
9 * The pattern template used here are somewhat different than those
|
|
10 * used in the "Software Tools" book; each token is a structure of
|
|
11 * the form TOKEN (see tools.h). A token consists of an identifier,
|
|
12 * a pointer to a string, a literal character and a pointer to another
|
|
13 * token. This last is 0 if there is no subsequent token.
|
|
14 *
|
|
15 * The one strangeness here is caused (again) by CLOSURE which has
|
|
16 * to be put in front of the previous token. To make this insertion a
|
|
17 * little easier, the 'next' field of the last to point at the chain
|
|
18 * (the one pointed to by 'tail) is made to point at the previous node.
|
|
19 * When we are finished, tail->next is set to 0.
|
|
20 */
|
|
21 TOKEN *
|
|
22 makepat(arg, delim)
|
|
23 char *arg;
|
|
24 int delim;
|
|
25 {
|
|
26 TOKEN *head, *tail, *ntok;
|
|
27 int error;
|
|
28
|
|
29 /* Check for characters that aren't legal at the beginning of a template. */
|
|
30
|
|
31 if (*arg == '\0' || *arg == delim || *arg == '\n' || *arg == CLOSURE)
|
|
32 return(0);
|
|
33
|
|
34 error = 0;
|
|
35 tail = head = NULL;
|
|
36
|
|
37 while (*arg && *arg != delim && *arg != '\n' && !error) {
|
|
38 ntok = (TOKEN *) malloc(TOKSIZE);
|
|
39 ntok->lchar = '\000';
|
|
40 ntok->next = 0;
|
|
41
|
|
42 switch (*arg) {
|
|
43 case ANY: ntok->tok = ANY; break;
|
|
44
|
|
45 case BOL:
|
|
46 if (head == 0) /* then this is the first symbol */
|
|
47 ntok->tok = BOL;
|
|
48 else
|
|
49 ntok->tok = LITCHAR;
|
|
50 ntok->lchar = BOL;
|
|
51 break;
|
|
52
|
|
53 case EOL:
|
|
54 if (*(arg + 1) == delim || *(arg + 1) == '\000' ||
|
|
55 *(arg + 1) == '\n') {
|
|
56 ntok->tok = EOL;
|
|
57 } else {
|
|
58 ntok->tok = LITCHAR;
|
|
59 ntok->lchar = EOL;
|
|
60 }
|
|
61 break;
|
|
62
|
|
63 case CLOSURE:
|
|
64 if (head != 0) {
|
|
65 switch (tail->tok) {
|
|
66 case BOL:
|
|
67 case EOL:
|
|
68 case CLOSURE:
|
|
69 return(0);
|
|
70
|
|
71 default:
|
|
72 ntok->tok = CLOSURE;
|
|
73 }
|
|
74 }
|
|
75 break;
|
|
76
|
|
77 case CCL:
|
|
78
|
|
79 if (*(arg + 1) == NEGATE) {
|
|
80 ntok->tok = NCCL;
|
|
81 arg += 2;
|
|
82 } else {
|
|
83 ntok->tok = CCL;
|
|
84 arg++;
|
|
85 }
|
|
86
|
|
87 if (ntok->bitmap = makebitmap(CLS_SIZE))
|
|
88 arg = dodash(CCLEND, arg, ntok->bitmap);
|
|
89 else {
|
|
90 fprintf(stderr, "Not enough memory for pat\n");
|
|
91 error = 1;
|
|
92 }
|
|
93 break;
|
|
94
|
|
95 default:
|
|
96 if (*arg == ESCAPE && *(arg + 1) == OPEN) {
|
|
97 ntok->tok = OPEN;
|
|
98 arg++;
|
|
99 } else if (*arg == ESCAPE && *(arg + 1) == CLOSE) {
|
|
100 ntok->tok = CLOSE;
|
|
101 arg++;
|
|
102 } else {
|
|
103 ntok->tok = LITCHAR;
|
|
104 ntok->lchar = esc(&arg);
|
|
105 }
|
|
106 }
|
|
107
|
|
108 if (error || ntok == 0) {
|
|
109 unmakepat(head);
|
|
110 return(0);
|
|
111 } else if (head == 0) {
|
|
112 /* This is the first node in the chain. */
|
|
113
|
|
114 ntok->next = 0;
|
|
115 head = tail = ntok;
|
|
116 } else if (ntok->tok != CLOSURE) {
|
|
117 /* Insert at end of list (after tail) */
|
|
118
|
|
119 tail->next = ntok;
|
|
120 ntok->next = tail;
|
|
121 tail = ntok;
|
|
122 } else if (head != tail) {
|
|
123 /* More than one node in the chain. Insert the
|
|
124 * CLOSURE node immediately in front of tail. */
|
|
125
|
|
126 (tail->next)->next = ntok;
|
|
127 ntok->next = tail;
|
|
128 } else {
|
|
129 /* Only one node in the chain, Insert the CLOSURE
|
|
130 * node at the head of the linked list. */
|
|
131
|
|
132 ntok->next = head;
|
|
133 tail->next = ntok;
|
|
134 head = ntok;
|
|
135 }
|
|
136 arg++;
|
|
137 }
|
|
138
|
|
139 tail->next = 0;
|
|
140 return(head);
|
|
141 }
|
|
142
|