|
|
1.1 root 1: /*-
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Cimarron D. Taylor of the University of California, Berkeley.
7: *
8: * Redistribution and use in source and binary forms are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: static char sccsid[] = "@(#)operator.c 5.1 (Berkeley) 4/16/90";
25: #endif /* not lint */
26:
27: #include <sys/types.h>
28: #include <stdio.h>
29: #include "find.h"
30:
31: /*
32: * find_yanknode --
33: * destructively removes the top from the plan
34: */
35: PLAN *
36: find_yanknode(planp)
37: PLAN **planp; /* pointer to top of plan (modified) */
38: {
39: PLAN *node; /* top node removed from the plan */
40:
41: if ((node = (*planp)) == NULL)
42: return(NULL);
43: (*planp) = (*planp)->next;
44: node->next = NULL;
45: return(node);
46: }
47:
48: /*
49: * find_yankexpr --
50: * Removes one expression from the plan. This is used mainly by
51: * find_squish_paren. In comments below, an expression is either
52: * a simple node or a T_EXPR node containing a list of simple nodes.
53: */
54: PLAN *
55: find_yankexpr(planp)
56: PLAN **planp; /* pointer to top of plan (modified) */
57: {
58: register PLAN *next; /* temp node holding subexpression results */
59: PLAN *node; /* pointer to returned node or expression */
60: PLAN *tail; /* pointer to tail of subplan */
61: PLAN *subplan; /* pointer to head of ( ) expression */
62: int f_expr();
63:
64: /* first pull the top node from the plan */
65: if ((node = find_yanknode(planp)) == NULL)
66: return(NULL);
67:
68: /*
69: * If the node is an '(' then we recursively slurp up expressions
70: * until we find its associated ')'. If it's a closing paren we
71: * just return it and unwind our recursion; all other nodes are
72: * complete expressions, so just return them.
73: */
74: if (node->type == T_OPENPAREN)
75: for (tail = subplan = NULL;;) {
76: if ((next = find_yankexpr(planp)) == NULL)
77: bad_arg("(", "missing closing ')'");
78: /*
79: * If we find a closing ')' we store the collected
80: * subplan in our '(' node and convert the node to
81: * a T_EXPR. The ')' we found is ignored. Otherwise,
82: * we just continue to add whatever we get to our
83: * subplan.
84: */
85: if (next->type == T_CLOSEPAREN) {
86: if (subplan == NULL)
87: bad_arg("()", "empty inner expression");
88: node->p_data[0] = subplan;
89: node->type = T_EXPR;
90: node->eval = f_expr;
91: break;
92: } else {
93: if (subplan == NULL)
94: tail = subplan = next;
95: else {
96: tail->next = next;
97: tail = next;
98: }
99: tail->next = NULL;
100: }
101: }
102: return(node);
103: }
104:
105: /*
106: * find_squish_paren --
107: * replaces "parentheisized" plans in our search plan with "expr" nodes.
108: */
109: PLAN *
110: find_squish_paren(plan)
111: PLAN *plan; /* plan with ( ) nodes */
112: {
113: register PLAN *expr; /* pointer to next expression */
114: register PLAN *tail; /* pointer to tail of result plan */
115: PLAN *result; /* pointer to head of result plan */
116:
117: result = tail = NULL;
118:
119: /*
120: * the basic idea is to have find_yankexpr do all our work and just
121: * collect it's results together.
122: */
123: while ((expr = find_yankexpr(&plan)) != NULL) {
124: /*
125: * if we find an unclaimed ')' it means there is a missing
126: * '(' someplace.
127: */
128: if (expr->type == T_CLOSEPAREN)
129: bad_arg(")", "no beginning '('");
130:
131: /* add the expression to our result plan */
132: if (result == NULL)
133: tail = result = expr;
134: else {
135: tail->next = expr;
136: tail = expr;
137: }
138: tail->next = NULL;
139: }
140: return(result);
141: }
142:
143: /*
144: * find_squish_not --
145: * compresses "!" expressions in our search plan.
146: */
147: PLAN *
148: find_squish_not(plan)
149: PLAN *plan; /* plan to process */
150: {
151: register PLAN *next; /* next node being processed */
152: register PLAN *node; /* temporary node used in T_NOT processing */
153: register PLAN *tail; /* pointer to tail of result plan */
154: PLAN *result; /* pointer to head of result plan */
155:
156: tail = result = next = NULL;
157:
158: while ((next = find_yanknode(&plan)) != NULL) {
159: /*
160: * if we encounter a ( expression ) then look for nots in
161: * the expr subplan.
162: */
163: if (next->type == T_EXPR)
164: next->p_data[0] = find_squish_not(next->p_data[0]);
165:
166: /*
167: * if we encounter a not, then snag the next node and place
168: * it in the not's subplan. As an optimization we compress
169: * several not's to zero or one not.
170: */
171: if (next->type == T_NOT) {
172: int notlevel = 1;
173:
174: node = find_yanknode(&plan);
175: while (node->type == T_NOT) {
176: ++notlevel;
177: node = find_yanknode(&plan);
178: }
179: if (node == NULL)
180: bad_arg("!", "no following expression");
181: if (node->type == T_OR)
182: bad_arg("!", "nothing between ! and -o");
183: if (notlevel % 2 != 1)
184: next = node;
185: else
186: next->p_data[0] = node;
187: }
188:
189: /* add the node to our result plan */
190: if (result == NULL)
191: tail = result = next;
192: else {
193: tail->next = next;
194: tail = next;
195: }
196: tail->next = NULL;
197: }
198: return(result);
199: }
200:
201: /*
202: * find_squish_or --
203: * compresses -o expressions in our search plan.
204: */
205: PLAN *
206: find_squish_or(plan)
207: PLAN *plan; /* plan with ors to be squished */
208: {
209: register PLAN *next; /* next node being processed */
210: register PLAN *tail; /* pointer to tail of result plan */
211: PLAN *result; /* pointer to head of result plan */
212:
213: tail = result = next = NULL;
214:
215: while ((next = find_yanknode(&plan)) != NULL) {
216: /*
217: * if we encounter a ( expression ) then look for or's in
218: * the expr subplan.
219: */
220: if (next->type == T_EXPR)
221: next->p_data[0] = find_squish_or(next->p_data[0]);
222:
223: /* if we encounter a not then look for not's in the subplan */
224: if (next->type == T_NOT)
225: next->p_data[0] = find_squish_or(next->p_data[0]);
226:
227: /*
228: * if we encounter an or, then place our collected plan in the
229: * or's first subplan and then recursively collect the
230: * remaining stuff into the second subplan and return the or.
231: */
232: if (next->type == T_OR) {
233: if (result == NULL)
234: bad_arg("-o", "no expression before -o");
235: next->p_data[0] = result;
236: next->p_data[1] = find_squish_or(plan);
237: if (next->p_data[1] == NULL)
238: bad_arg("-o", "no expression after -o");
239: return(next);
240: }
241:
242: /* add the node to our result plan */
243: if (result == NULL)
244: tail = result = next;
245: else {
246: tail->next = next;
247: tail = next;
248: }
249: tail->next = NULL;
250: }
251: return(result);
252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.