|
|
1.1 root 1: /* guide.c - Search Guide handling */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/dsap/common/RCS/guide.c,v 7.0 89/11/23 21:42:17 mrose Rel $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/dsap/common/RCS/guide.c,v 7.0 89/11/23 21:42:17 mrose Rel $
9: *
10: *
11: * $Log: guide.c,v $
12: * Revision 7.0 89/11/23 21:42:17 mrose
13: * Release 6.0
14: *
15: */
16:
17: /*
18: * NOTICE
19: *
20: * Acquisition, use, and distribution of this module and related
21: * materials are subject to the restrictions of a license agreement.
22: * Consult the Preface in the User's Manual for the full terms of
23: * this agreement.
24: *
25: */
26:
27: /*
28: SYNTAX:
29: Guide ::= [<objectclass> '#'] <Criteria>
30: Criteria ::= CriteriaItem | CriteriaSet | '!' Criteria
31: CrtieriaSet ::= ['('] Criteria '@' CriteriaSet [')'] |
32: ['('] Criteria '|' CriteriaSet [')']
33: CriteriaItem ::= ['('] <attributetype> '$' <matchType> [')']
34: matchType ::= "EQ" | "SUBSTR" | "GE" | "LE" | "APPROX"
35:
36: EXAMPLES:
37:
38: Person # commonName $ APPROX
39: ( organization $ EQ ) @ (commonName $ SUBSTR)
40: ( organization $ EQ ) @ ((commonName $ SUBSTR) | (commonName $ EQ))
41:
42: NOTE:
43: Use of @ for "and" as '&' get filtered out earlier!!!
44: */
45:
46: /* LINTLIBRARY */
47:
48: #include "quipu/util.h"
49: #include "quipu/attrvalue.h"
50: #include "cmd_srch.h"
51:
52: static Criteria_free (arg)
53: struct Criteria *arg;
54: {
55: struct Criteria *parm = arg;
56:
57: if (parm == NULL)
58: return;
59:
60: switch (parm -> offset) {
61: case Criteria_type:
62: if (parm -> un.type)
63: free_CriteriaItem (parm -> un.type),
64: parm -> un.type = NULL;
65: break;
66:
67: case Criteria_and:
68: case Criteria_or:
69: {
70: struct and_or_set *and_or_set;
71:
72: for (and_or_set = parm -> un.and_or; and_or_set;) {
73: struct and_or_set *f_and_or_set = and_or_set -> and_or_next;
74:
75: if (and_or_set -> and_or_comp)
76: Criteria_free (and_or_set -> and_or_comp),
77: and_or_set -> and_or_comp = NULL;
78:
79: if (and_or_set)
80: free ((char *) and_or_set);
81: and_or_set = f_and_or_set;
82: }
83:
84: parm -> un.and_or = NULL;
85: }
86: break;
87:
88: case Criteria_not:
89: if (parm -> un.not)
90: Criteria_free (parm -> un.not),
91: parm -> un.not = NULL;
92: break;
93: }
94:
95: free ((char *) arg);
96: }
97:
98: static free_CriteriaItem (arg)
99: struct CriteriaItem *arg;
100: {
101: struct CriteriaItem *parm = arg;
102:
103: if (parm == NULL)
104: return;
105:
106: free ((char *) arg);
107: }
108:
109:
110: static guidefree (arg)
111: struct Guide * arg;
112: {
113: if (arg == NULL)
114: return;
115:
116: if (arg->objectClass)
117: oid_free (arg->objectClass);
118:
119: Criteria_free (arg->criteria);
120:
121: free ((char *)arg);
122: }
123:
124: static struct CriteriaItem * CriteriaItem_cpy (arg)
125: struct CriteriaItem *arg;
126: {
127: struct CriteriaItem *parm = arg;
128: struct CriteriaItem *res;
129:
130: if (parm == NULL)
131: return NULL;
132:
133: res = (struct CriteriaItem *) smalloc (sizeof(struct CriteriaItem));
134:
135: res->offset = parm->offset;
136: res->attrib = AttrT_cpy (parm->attrib);
137:
138: return (res);
139: }
140:
141:
142: static struct Criteria * Criteria_cpy (a)
143: struct Criteria * a;
144: {
145: struct Criteria *b;
146:
147: if (a == NULL)
148: return NULL;
149:
150: b = (struct Criteria *) smalloc (sizeof(struct Criteria));
151: b-> offset = a->offset;
152:
153: switch (a -> offset) {
154: case Criteria_type:
155: b->un.type = CriteriaItem_cpy (a->un.type);
156: break;
157:
158: case Criteria_and:
159: case Criteria_or:
160: {
161: struct and_or_set *and_or_set;
162: struct and_or_set *ao_res = (struct and_or_set *)NULL;
163: struct and_or_set *ao_tmp;
164:
165: ao_tmp = ao_res; /* OK lint ? */
166:
167: for (and_or_set = a -> un.and_or; and_or_set; and_or_set = and_or_set->and_or_next) {
168: struct and_or_set *tmp;
169:
170: tmp = (struct and_or_set *) smalloc (sizeof(struct and_or_set));
171: tmp->and_or_comp = Criteria_cpy(and_or_set->and_or_comp);
172: tmp->and_or_next = (struct and_or_set *)NULL;
173: if (ao_res == ((struct and_or_set *)NULL))
174: ao_res = tmp;
175: else
176: ao_tmp->and_or_next = tmp;
177: ao_tmp = tmp;
178: }
179:
180: b->un.and_or = ao_res;
181: }
182: break;
183:
184: case Criteria_not:
185: b->un.not = Criteria_cpy (a->un.not);
186: break;
187: }
188:
189: return (b);
190: }
191:
192: static struct Guide * guidecpy (a)
193: struct Guide * a;
194: {
195: struct Guide * b;
196:
197: b = (struct Guide * ) smalloc (sizeof(struct Guide));
198:
199: if (a->objectClass)
200: b->objectClass = oid_cpy (a->objectClass);
201: else
202: b->objectClass = NULLOID;
203:
204: b->criteria = Criteria_cpy (a->criteria);
205:
206: return (b);
207: }
208:
209: #define NOCHOICE 255
210:
211: static CMD_TABLE guide_tab [] = {
212: "EQ", choice_equality,
213: "SUBSTR", choice_substrings,
214: "GE", choice_greaterOrEqual,
215: "LE", choice_lessOrEqual,
216: "APPROX", choice_approximateMatch,
217: 0, NOCHOICE
218: };
219:
220: static struct CriteriaItem * CriteriaItem_parse (str)
221: char * str;
222: {
223: struct CriteriaItem * res;
224: char * ptr;
225: if ((str == NULLCP) || (*str == 0))
226: return ((struct CriteriaItem *) NULL);
227:
228: res = (struct CriteriaItem *) smalloc (sizeof(struct CriteriaItem));
229:
230: if ((ptr = index (str,'$')) == NULLCP) {
231: parse_error ("Seperator missing in CriteriaItem %s",str);
232: return ((struct CriteriaItem *) NULL);
233: }
234: *ptr-- = 0;
235: if (isspace (*ptr))
236: *ptr = 0;
237: ptr++;
238: if ((res -> attrib = AttrT_new (str)) == NULLAttrT) {
239: parse_error ("Unknown attribute type in CriteriaItem %s",str);
240: return ((struct CriteriaItem *) NULL);
241: }
242: *ptr++ = '$';
243:
244: if ((res -> offset = cmd_srch(SkipSpace(ptr),guide_tab)) == NOCHOICE) {
245: parse_error ("Unknown search type in CriteriaItem %s",ptr);
246: return ((struct CriteriaItem *) NULL);
247: }
248:
249: return (res);
250:
251: }
252:
253:
254:
255: static getop (str, ch)
256: char *str,
257: *ch;
258: {
259: int i,
260: bracket = 0;
261:
262: for (i = 0; i < strlen (str); i++) {
263: if (bracket == 0 && (str[i] == '@' || str[i] == '|')) {
264: *ch = str[i];
265: return (i);
266: }
267: if (str[i] == '(')
268: ++bracket;
269: if (str[i] == ')')
270: --bracket;
271: if (bracket < 0) {
272: parse_error ("Too many close brackets",NULLCP);
273: return (-2);
274: }
275: }
276: return (-1);
277: }
278:
279:
280: static struct Criteria * Criteria_parse (str)
281: char *str;
282: {
283: int gotit,
284: bracketed;
285: char ch,
286: och = '\0';
287: char * TidyString();
288: struct Criteria * result;
289:
290: struct and_or_set * ao = (struct and_or_set *)NULL;
291: struct and_or_set * ao_ptr;
292:
293: result = (struct Criteria *) smalloc (sizeof(struct Criteria));
294:
295: str = TidyString (str);
296:
297: /* Got a multiple-component string for parsing */
298:
299: do {
300: bracketed = FALSE;
301: if ((gotit = getop (str, &ch)) == -2)
302: return ((struct Criteria *)NULL);
303:
304: if (gotit < 0) {/* Match an open bracket. */
305: if (*str == '(')
306: if (str[strlen (str) - 1] == ')') {
307: str[strlen (str) - 1] = '\0';
308: ++str;
309: bracketed = TRUE;
310: } else {
311: parse_error ("Too many open brackets",NULLCP);
312: return ((struct Criteria *)NULL);
313: }
314:
315: if (och == '\0') {
316: if (bracketed == TRUE) {
317: gotit = 0; /* Stop 'while' loop
318: * falling */
319: continue; /* Parse the internals */
320: } else
321: break; /* Single item only */
322: } else
323: ch = och; /* Use last operation */
324: }
325: if (och == '\0')/* Remember last operation */
326: och = ch;
327: else if (och != ch) {
328: parse_error ("Can't Mix Operations.",NULLCP);
329: return ((struct Criteria *)NULL);
330: }
331: if (gotit >= 0) /* If got an op, make it null */
332: str[gotit] = '\0';
333: /* Recurse on the 'first' string */
334: ao_ptr = (struct and_or_set*) smalloc (sizeof(struct and_or_set));
335: if ((ao_ptr->and_or_comp = Criteria_parse (str)) == (struct Criteria *)NULL)
336: return ((struct Criteria *)NULL);
337:
338: ao_ptr->and_or_next = (struct and_or_set*) NULL;
339: if (ao != (struct and_or_set *)NULL)
340: ao_ptr->and_or_next = ao;
341: ao = ao_ptr;
342: str += gotit + 1;
343:
344: if (gotit >= 0) { /* Match an and symbol */
345: if (och == '@') {
346: result->offset = Criteria_and;
347: } else {/* Match an or symbol */
348: result->offset = Criteria_or;
349: }
350: }
351: result->un.and_or = ao;
352: }
353: while (gotit >= 0);
354: if (och == '\0') {
355: if (*str == '!') { /* Match a not symbol */
356: result->offset = Criteria_not;
357: if ((result->un.not = Criteria_parse (str + 1)) == (struct Criteria *)NULL)
358: return ((struct Criteria *)NULL);
359: } else {
360: result->offset = Criteria_type;
361: if ((result->un.type = CriteriaItem_parse(str)) == (struct CriteriaItem *)NULL)
362: return ((struct Criteria *)NULL);
363: }
364: }
365: return (result);
366: }
367:
368: static struct Guide * guideparse (str)
369: char *str;
370: {
371: char *ptr;
372: struct Guide * res;
373:
374: res = (struct Guide *) smalloc (sizeof (struct Guide));
375:
376: if ((ptr = index (str,'#')) != NULLCP) {
377: *ptr-- = 0;
378: if (isspace (*ptr))
379: *ptr = 0;
380: ptr++;
381: if (( res->objectClass = name2oid(str)) == NULLOID) {
382: parse_error ("Unknown class in Guide %s",str);
383: return ((struct Guide *)NULL);
384: }
385: res->objectClass = oid_cpy (res->objectClass);
386: *ptr++ = '#';
387: str = ptr;
388: }
389:
390: if ((res->criteria = Criteria_parse (SkipSpace(str))) == (struct Criteria *)NULL)
391: return ((struct Guide *)NULL);
392:
393: return (res);
394: }
395:
396:
397: static CriteriaItem_print(ps,parm,format)
398: PS ps;
399: struct CriteriaItem * parm;
400: int format;
401: {
402: char *ptr;
403:
404: if (parm == NULL)
405: return;
406:
407: if ((ptr = rcmd_srch ((int)parm->offset,guide_tab)) == NULLCP)
408: ptr = "UNKNOWN !!!";
409:
410: if (format == READOUT) {
411: ps_printf (ps,"%s on ",ptr);
412: AttrT_print (ps,parm->attrib,EDBOUT);
413: } else {
414: AttrT_print (ps,parm->attrib,format);
415: ps_printf (ps,"$%s",ptr);
416: }
417:
418:
419: }
420:
421:
422: static Criteria_print (ps,a,format)
423: PS ps;
424: struct Criteria * a;
425: int format;
426: {
427: char * sep;
428:
429: if (format == READOUT)
430: sep = " OR ";
431: else
432: sep = "|";
433:
434: if (a == NULL)
435: return;
436:
437: switch (a -> offset) {
438: case Criteria_type:
439: CriteriaItem_print (ps,a->un.type,format);
440: break;
441: case Criteria_and:
442: if (format == READOUT)
443: sep = " AND ";
444: else
445: sep = "@";
446: case Criteria_or:
447: {
448: struct and_or_set *and_or_set;
449: char * tmp = NULLCP;
450:
451: for (and_or_set = a -> un.and_or; and_or_set; and_or_set = and_or_set->and_or_next) {
452: if (tmp != NULLCP)
453: ps_print (ps,tmp);
454: ps_print (ps,"(");
455: Criteria_print(ps,and_or_set->and_or_comp,format);
456: ps_print (ps,")");
457: tmp = sep;
458: }
459: }
460: break;
461:
462: case Criteria_not:
463: if (format == READOUT)
464: ps_print (ps,"NOT ");
465: else
466: ps_print (ps,"!");
467: ps_print (ps,"(");
468: Criteria_print (ps,a->un.not,format);
469: ps_print (ps,")");
470: break;
471: }
472: }
473:
474: static guideprint (ps,a,format)
475: PS ps;
476: struct Guide * a;
477: int format;
478: {
479: if (a->objectClass) {
480: if (format == READOUT) {
481: ps_print (ps,"Class: ");
482: oidprint (ps,a->objectClass,format);
483: ps_print (ps,", search for: ");
484: } else {
485: oidprint (ps,a->objectClass,format);
486: ps_print (ps,"#");
487: }
488: }
489:
490: Criteria_print (ps,a->criteria,format);
491:
492: }
493:
494: static PE guideenc (m)
495: struct Guide * m;
496: {
497: PE ret_pe;
498:
499: (void) encode_SA_Guide (&ret_pe,0,0,NULLCP,m);
500:
501: return (ret_pe);
502: }
503:
504: static struct Guide * guidedec (pe)
505: PE pe;
506: {
507: struct Guide * m;
508:
509: if (decode_SA_Guide (pe,1,NULLIP,NULLVP,&m) == NOTOK)
510: return ((struct Guide *) NULL);
511:
512: if (decode_Criteria (m->criteria) == NOTOK)
513: return ((struct Guide *) NULL);
514:
515: return (m);
516: }
517:
518: static decode_Criteria (m)
519: struct Criteria * m;
520: {
521: int result;
522:
523: switch (m -> offset) {
524: case Criteria_type:
525: result = decode_CriteriaItem (m -> un.type);
526: break;
527:
528: case Criteria_and:
529: case Criteria_or:
530: {
531: struct and_or_set *and_or_set;
532:
533: result = OK;
534: for (and_or_set = m -> un.and_or; and_or_set;) {
535: struct and_or_set *f_and_or_set = and_or_set -> and_or_next;
536: if (decode_Criteria (and_or_set -> and_or_comp) == NOTOK)
537: result = NOTOK;
538: and_or_set = f_and_or_set;
539: }
540:
541: }
542: break;
543:
544: case Criteria_not:
545: result = decode_Criteria (m -> un.not);
546: break;
547: }
548:
549: return (result);
550: }
551:
552: static decode_CriteriaItem (m)
553: struct CriteriaItem *m;
554: {
555:
556: if (m == NULL)
557: return OK;
558:
559: return OK;
560: }
561:
562: static criteriaItem_cmp (a,b)
563: struct CriteriaItem *a,*b;
564: {
565:
566: if (a == NULL)
567: return (b==NULL ? 0 : -1);
568: if (b == NULL)
569: return (1);
570:
571: if (a->offset != b->offset)
572: return (a->offset>b->offset ? 1 : -1);
573:
574: return (AttrT_cmp (a->attrib,b->attrib));
575: }
576:
577: static criteria_cmp(a,b)
578: struct Criteria * a, *b;
579: {
580: int result;
581:
582: if (a==NULL)
583: return(b==NULL ? 0 : -1);
584: if (b==NULL)
585: return(1);
586:
587: if (a->offset != b->offset)
588: return (a->offset > b->offset ? 1 : -1);
589:
590: switch (a -> offset) {
591: case Criteria_type:
592: return (criteriaItem_cmp (a->un.type, b->un.type));
593:
594: case Criteria_and:
595: case Criteria_or:
596: {
597: struct and_or_set *a_set;
598: struct and_or_set *b_set;
599:
600: for (a_set = a->un.and_or; a_set ; a_set = a_set->and_or_next) {
601: for (b_set = b->un.and_or; b_set ; b_set = b_set->and_or_next) {
602: if ((result=criteria_cmp (a_set -> and_or_comp,b_set->and_or_comp)) == 0)
603: break;
604: }
605: if (result != 0)
606: return (1);
607: }
608: for (b_set = b->un.and_or; b_set ; b_set = b_set->and_or_next) {
609: for (a_set = a->un.and_or; a_set ; a_set = a_set->and_or_next) {
610: if ((result=criteria_cmp (a_set -> and_or_comp,b_set->and_or_comp)) == 0)
611: break;
612: }
613: if (result != 0)
614: return (-1);
615: }
616: return (0);
617:
618: }
619:
620: case Criteria_not:
621: result = criteria_cmp (a->un.not,b->un.not);
622: break;
623: }
624:
625: return (result);
626: }
627:
628: static guidecmp (a,b)
629: struct Guide *a, *b;
630: {
631: int i;
632: if (a == (struct Guide *)NULL)
633: if (b == (struct Guide *)NULL)
634: return (0);
635: else
636: return (1);
637:
638: if (b==(struct Guide *)NULL)
639: return (-1);
640:
641: if ((i=oid_cmp(a->objectClass,b->objectClass)) == 0)
642: return (criteria_cmp(a->criteria,b->criteria));
643:
644: return (i);
645: }
646:
647: guide_syntax ()
648: {
649: (void) add_attribute_syntax ("Guide",
650: (IFP) guideenc, (IFP) guidedec,
651: (IFP) guideparse,guideprint,
652: (IFP) guidecpy, guidecmp,
653: guidefree, NULLCP,
654: NULLIFP, TRUE);
655:
656: }
657:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.