|
|
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.