Return to daVarRegister.c CVS log | Up to [HallC] / Analyzer / CTP |
1 saw 1.1 /*----------------------------------------------------------------------------- 2 * Copyright (c) 1992 Southeastern Universities Research Association, 3 * Continuous Electron Beam Accelerator Facility 4 * 5 * This software was developed under a United States Government license 6 * described in the NOTICE file included as part of this distribution. 7 * 8 * Stephen A. Wood, 12000 Jefferson Ave., Newport News, VA 23606 9 * Email: saw@cebaf.gov Tel: (804) 249-7367 Fax: (804) 249-5800 10 *----------------------------------------------------------------------------- 11 * 12 * Description: 13 * C and Fortran routines for registering variables to be used by 14 * the test, histogram and parameter packages. 15 * 16 * Author: Stephen Wood, CEBAF HALL C 17 * 18 * Revision History: 19 * $Log: daVarRegister.c,v $ | ||
20 saw 1.3 * Revision 1.2 1999/11/04 20:34:04 saw 21 * Alpha compatibility. 22 * New RPC call needed for root event display. 23 * Start of code to write ROOT trees (ntuples) from new "tree" block 24 * | ||
25 saw 1.2 * Revision 1.13 1999/08/25 13:16:05 saw 26 * *** empty log message *** 27 * 28 * Revision 1.12 1999/03/01 19:51:32 saw 29 * Add Absoft Fortran stuff 30 * 31 * Revision 1.11 1997/05/29 18:56:25 saw 32 * Lock changes before adding Absoft(Linux) compatibility 33 * | ||
34 saw 1.1 * Revision 1.10 1996/07/31 20:37:53 saw 35 * Use hash table for name storage. 36 * 37 * Revision 1.9 1994/09/27 20:20:53 saw 38 * Remove linux dependencies, allow wild cards in daVarList 39 * 40 * Revision 1.8 1994/08/24 14:27:00 saw 41 * Have daVarLookupPWithClass return S_DAVAR_UNKNOWN if var not found 42 * 43 * Revision 1.7 1994/06/03 20:59:26 saw 44 * Replace stderr with STDERR 45 * 46 * Revision 1.6 1994/02/10 21:58:33 saw 47 * Change node variable name to nd to not conflict with node type. 48 * 49 * Revision 1.5 1994/02/10 18:34:05 saw 50 * Small fixes for SGI compatibility 51 * 52 * Revision 1.4 1993/11/24 21:37:39 saw 53 * Add fortran calls for registering double (REAL *8) variable type. 54 * 55 saw 1.1 * Revision 1.3 1993/11/22 20:09:42 saw 56 * Add REGPARMSTRING fortran call for new Fortran string type DAVARFSTRING 57 * 58 * Revision 1.2 1993/08/12 19:58:10 saw 59 * On HPUX don't use native tsearch. 60 * 61 * Revision 1.1 1993/05/10 20:05:09 saw 62 * Initial revision 63 * 64 * 65 * 18-dec-92 saw Original version 66 * 67 * 68 * Routines available to general users: 69 * -------- 70 * daVarRegister(int flag, daVarStruct *args) 71 * daVarLookup(char *name, daVarStruct *results) 72 * 73 * Routines available to "friendly" packages (e.g.) RPC service routines 74 * -------- 75 * daVarLookupP(char *name, daVarStruct **results) 76 saw 1.1 * daVarList(char ***listp) 77 * daVarFreeList(char **list) 78 * 79 * 80 */ 81 #include "cfortran.h" 82 #include "daVar.h" 83 84 #define USEHASH 85 #ifdef USEHASH 86 #include "daVarHash.h" 87 #else 88 #if !defined(ultrix) 89 #define NO_TSEARCH 90 #endif 91 92 #include <stdio.h> 93 #ifdef NOFNMATCH 94 #include "fnmatch.h" 95 #else 96 #include <fnmatch.h> 97 saw 1.1 #endif 98 99 /* Stuff for Tsearch routines*/ 100 typedef struct node_t 101 { 102 daVarStruct *key; 103 struct node_t *left, *right; 104 } node; 105 106 #ifdef NO_TSEARCH 107 typedef enum { preorder, postorder, endorder, leaf } VISIT; 108 node *mytsearch(void *key, node **rootp, int (* compar)()); 109 node *mytfind(void *key, node **rootp, int (* compar)()); 110 void mytwalk(); 111 #else 112 #include <search.h> 113 #define mytsearch tsearch 114 #define mytfind tfind 115 #define mytwalk twalk 116 #endif 117 #endif 118 saw 1.1 119 #ifdef USEHASH 120 symbolEntry *hash_table[TABLE_SIZE]; 121 int hashNotInited=1; 122 #else 123 node *daVarRoot=0; 124 #endif 125 int daVarCount=0; /* Used by daVarList */ 126 char **daVarListGlob; 127 char *daVarListPattern; 128 int (*daVarListCompFunction)(); 129 int daVarListPattern_length; 130 131 /* Local prototypes */ 132 int daVarComp(daVarStruct *item1, daVarStruct *item2); 133 134 /* Code */ | ||
135 saw 1.2 int daVarRegister(int flag, daVarStruct *args) | ||
136 saw 1.1 /* Should accept a title arg of zero and create a null string in that 137 case. 138 */ 139 { 140 daVarStruct search, *new, **searchresult; 141 int fullnamelen; 142 143 if(flag != 0) { 144 fprintf(STDERR, 145 "(daVarRegister) Only zero allowed for flag argument now.\n"); 146 return(S_FAILURE); 147 } 148 149 search.name = args->name; 150 /* printf("Searching for %s\n",args->name);*/ 151 #ifdef USEHASH 152 if(hashNotInited) {crlHashCreate(hash_table); hashNotInited = 0;} 153 if(searchresult = (daVarStruct **) crlHashFind((CrlSymbol) &search,hash_table)) { 154 #else 155 if(searchresult = (daVarStruct **) mytfind(&search,&daVarRoot,daVarComp)){ 156 #endif 157 saw 1.1 fprintf(STDERR, 158 "(daVar) Replacing definition of variable \"%s\" in table\n", 159 args->name); 160 free((*searchresult)->title); 161 if(args->title) { 162 if(((*searchresult)->title = (char *) malloc(strlen(args->title)+1)) 163 == NULL) 164 return(S_FAILURE); 165 strcpy((*searchresult)->title,args->title); 166 } else { 167 if(((*searchresult)->title = (char *) malloc(1)) 168 == NULL) 169 return(S_FAILURE); 170 (*searchresult)->title[0] = '\0'; 171 } 172 (*searchresult)->varptr = args->varptr; 173 (*searchresult)->size = (args->size<=0) ? 1 : args->size; 174 (*searchresult)->type = args->type; 175 (*searchresult)->flag = args->flag; 176 (*searchresult)->rhook = args->rhook; 177 (*searchresult)->whook = args->whook; 178 saw 1.1 (*searchresult)->opaque = args->opaque; 179 return(S_DAVAR_REPLACED); 180 } else { 181 if((new = (daVarStruct *) malloc(sizeof(daVarStruct))) == NULL) 182 return(S_FAILURE); 183 if((new->name = (char *) malloc(strlen(args->name)+1)) == NULL) 184 return(S_FAILURE); 185 strcpy(new->name,args->name); 186 187 188 if(args->title) { 189 if((new->title = (char *) malloc(strlen(args->title)+1)) == NULL) 190 return(S_FAILURE); 191 strcpy(new->title,args->title); 192 } else { 193 if((new->title = (char *) malloc(1)) == NULL) 194 return(S_FAILURE); 195 new->title[0] = '\0'; 196 } 197 new->type = args->type; 198 new->varptr = args->varptr; 199 saw 1.1 new->size = (args->size<=0) ? 1 : args->size; 200 new->flag = args->flag; 201 new->rhook = args->rhook; 202 new->whook = args->whook; 203 new->opaque = args->opaque; 204 205 #ifdef USEHASH 206 if(crlHashAdd((CrlSymbol) new, hash_table)) 207 #else 208 if(mytsearch((void *) new,&daVarRoot,daVarComp)) 209 #endif 210 return(S_SUCCESS); 211 else 212 return(S_FAILURE); 213 } 214 } 215 216 | ||
217 saw 1.2 int daVarLookup(char *name, daVarStruct *result) | ||
218 saw 1.1 { 219 daVarStruct search, **searchresult; 220 static char *namel=0; /* Pointers to static space for copies of */ 221 static int namelsize=0; 222 static char *titlel=0; /* the name and title pointers */ 223 static int titlelsize=0; 224 int len; 225 226 search.name = name; 227 #ifdef USEHASH 228 if(searchresult = (daVarStruct **) crlHashFind((CrlSymbol) &search,hash_table)) { 229 #else 230 if(searchresult = (daVarStruct **) mytfind(&search,&daVarRoot,daVarComp)){ 231 #endif 232 233 len=strlen((*searchresult)->name); 234 if(len >= namelsize) { 235 if(namel) free(namel); 236 namel = (char *) malloc(len+1); 237 namelsize = len+1; 238 } 239 saw 1.1 strcpy(namel,(*searchresult)->name); 240 result->name = namel; 241 242 len=strlen((*searchresult)->title); 243 if(len >= titlelsize) { 244 if(titlel) free(titlel); 245 titlel = (char *) malloc(len + 1); 246 titlelsize = len+1; 247 } 248 strcpy(titlel,(*searchresult)->title); 249 result->title = titlel; 250 251 result->type = (*searchresult)->type; 252 result->varptr = (*searchresult)->varptr; 253 result->size = (*searchresult)->size; 254 result->opaque = (*searchresult)->opaque; 255 result->rhook = (*searchresult)->rhook; 256 result->whook = (*searchresult)->whook; 257 return(S_SUCCESS); 258 } else 259 return(S_DAVAR_UNKNOWN); 260 saw 1.1 } | ||
261 saw 1.2 int daVarStrcmp(register char *s1, register char *s2) | ||
262 saw 1.1 { 263 while(toupper(*s1) == toupper(*s2++)) 264 if(*s1++ == '\0') 265 return(0); 266 return(toupper(*s1) - toupper(*--s2)); 267 } 268 int daVarFnmatch(register char *pattern, register char *s, register int n) 269 { 270 return(fnmatch(pattern,s,0)); 271 } 272 int daVarStrncmp(register char *s1, register char *s2, register int n) 273 { 274 while(toupper(*s1) == toupper(*s2++)) 275 if(*s1++ == '\0' || (--n) <= 0) 276 return(0); 277 return(toupper(*s1) - toupper(*--s2)); 278 } 279 280 int daVarComp(daVarStruct *item1, daVarStruct *item2) 281 /* Do case insensitive comparisons of keys */ 282 { 283 saw 1.1 return(daVarStrcmp(item1->name,item2->name)); 284 } 285 | ||
286 saw 1.2 int daVarLookupP(char *name, daVarStruct **varstructptr) | ||
287 saw 1.1 { 288 daVarStruct search, **searchresult; 289 290 search.name = name; 291 #ifdef USEHASH 292 if(searchresult = (daVarStruct **) crlHashFind((CrlSymbol) &search,hash_table)) { 293 #else 294 if(searchresult = (daVarStruct **) mytfind(&search,&daVarRoot,daVarComp)){ 295 #endif 296 *varstructptr = *searchresult; 297 return(S_SUCCESS); 298 } else 299 return(S_DAVAR_UNKNOWN); 300 } 301 302 daVarLookupPWithClass(char *name, char **prefixlist, daVarStruct **varp) 303 { 304 int namlen,namtrylen; 305 char *namtry; 306 307 namlen = strlen(name); 308 saw 1.1 if(daVarLookupP(name,varp)==S_SUCCESS) return(S_SUCCESS); 309 namtrylen = namlen + 10; 310 namtry = (char *) malloc(namtrylen+1); 311 while(*prefixlist){ 312 int thislen; 313 thislen = strlen(*prefixlist) + namlen + 1; 314 if(thislen > namtrylen) { 315 namtrylen = thislen; 316 namtry = (char *) realloc(namtry,namtrylen); 317 } 318 strcpy(namtry,*prefixlist); 319 strcat(namtry,"."); 320 strcat(namtry,name); 321 if(daVarLookupP(namtry,varp)==S_SUCCESS) { 322 free(namtry); 323 return(S_SUCCESS); 324 } 325 prefixlist++; 326 } 327 free(namtry); 328 return(S_DAVAR_UNKNOWN); /* Variable not registered */ 329 saw 1.1 } 330 | ||
331 saw 1.2 void daVarCount_node | ||
332 saw 1.1 #ifdef USEHASH 333 (void *entry) 334 { 335 #else 336 (node *nd,VISIT order, int level) 337 { 338 if(order==postorder || order == leaf) 339 #endif 340 daVarCount++; 341 } 342 | ||
343 saw 1.3 void daVarList_node | ||
344 saw 1.1 #ifdef USEHASH 345 (void *entry) 346 { 347 #else 348 (node *nd,VISIT order, int level) 349 { 350 if(order==postorder || order == leaf) 351 #endif 352 { 353 char *name; 354 355 name = ((daVarStruct *) entry)->name; 356 if(daVarListPattern_length == 0 || 357 (daVarListCompFunction)(daVarListPattern,name,daVarListPattern_length) == 0) 358 daVarListGlob[daVarCount++] = name; 359 } 360 } 361 362 | ||
363 saw 1.2 int daVarList(char *pattern, char ***listp, int *count) | ||
364 saw 1.1 /* User is not allowed to muck with the strings pointed to in the list 365 because they are the actual strings in the tables. */ 366 { 367 368 if(strchr(pattern,'*') || strchr(pattern,'?')) { 369 daVarListCompFunction = daVarFnmatch; 370 } else { 371 daVarListCompFunction = daVarStrncmp; 372 } 373 if(pattern) { 374 daVarListPattern = pattern; 375 daVarListPattern_length = strlen(daVarListPattern); 376 } else 377 daVarListPattern_length = 0; 378 daVarCount = 0; 379 #ifdef USEHASH 380 crlHashWalk(hash_table,daVarCount_node); 381 #else 382 mytwalk(daVarRoot,daVarCount_node);/* Should make list only big enough 383 for what matches */ 384 #endif 385 saw 1.1 386 if((*listp = daVarListGlob = 387 (char **) malloc((daVarCount)*sizeof(char *))) == NULL) 388 return(S_FAILURE); 389 daVarCount = 0; 390 #ifdef USEHASH 391 crlHashWalk(hash_table,daVarList_node); 392 #else 393 mytwalk(daVarRoot,daVarList_node); 394 #endif 395 *count = daVarCount; 396 return(S_SUCCESS); 397 } 398 #ifndef USEHASH 399 daVarPrint_node(node *nd,VISIT order, int level) 400 { 401 char *name,*title; 402 403 if(order==postorder || order == leaf) { 404 name = ((daVarStruct *) nd->key)->name; 405 title = ((daVarStruct *) nd->key)->title; 406 saw 1.1 printf("XX: %s %s %x %x\n",name,title,nd,nd->key); 407 } 408 } 409 | ||
410 saw 1.2 int daVarPrint() | ||
411 saw 1.1 { 412 mytwalk(daVarRoot,daVarPrint_node); 413 return(S_SUCCESS); 414 } 415 #endif | ||
416 saw 1.2 int daVarFreeList(char **list) | ||
417 saw 1.1 /* Free's up the list of variables in listp */ 418 { 419 int i; 420 421 free(list); 422 return(S_SUCCESS); 423 } 424 425 /* Fortran entry points */ 426 427 #define LENDEFARRAY int *size, 428 #define LENDEFSCALER 429 #define LENARGARRAY *size 430 #define LENARGSCALER 1 431 432 #define MAKEFSUB(SUBNAME,CLASS,TYPENAME,DATYPE,ARRAY) \ | ||
433 saw 1.2 int SUBNAME(char *name, TYPENAME *vptr, LENDEF##ARRAY char *title\ | ||
434 saw 1.1 ,unsigned l_name, unsigned l_title)\ 435 {\ | ||
436 saw 1.2 int A0;\ | ||
437 saw 1.1 daVarStruct args;\ 438 char *BN=0;\ 439 char *BT=0;\ 440 char *BF = 0;\ 441 \ 442 BF = malloc(strlen(CLASS)+l_name+1);\ 443 strcpy(BF,CLASS);\ 444 args.name = strcat(BF,((!*(int *)name)?0:memchr(name,'\0',l_name)?name:\ 445 (memcpy(BN=(char *) malloc(l_name+1),name,l_name)\ 446 ,BN[l_name]='\0',kill_trailing(BN,' '))));\ 447 args.title = ((!*(int *)title)?0:memchr(title,'\0',l_title)?title:\ 448 (memcpy(BT=(char *) malloc(l_title+1),title,l_title)\ 449 ,BT[l_title]='\0',kill_trailing(BT,' ')));\ 450 args.size = LENARG##ARRAY;\ 451 args.varptr = (void *) vptr;\ 452 args.flag = DAVAR_READWRITE;\ 453 args.type = DATYPE;\ 454 args.opaque = 0;\ | ||
455 saw 1.3 args.rhook = 0;\ 456 args.whook = 0;\ | ||
457 saw 1.1 A0 = daVarRegister((int) 0, &args);\ 458 if(BF) free(BF);\ 459 if(BN) free(BN);\ 460 if(BT) free(BT);\ 461 return(A0);\ 462 } | ||
463 saw 1.2 464 /* Can't figure out a more clever way */ 465 #ifdef AbsoftUNIXFortran | ||
466 saw 1.1 MAKEFSUB(regreal,"",float,DAVARFLOAT,SCALER) 467 MAKEFSUB(regdouble,"",double,DAVARDOUBLE,SCALER) 468 MAKEFSUB(regint,"",int,DAVARINT,SCALER) 469 MAKEFSUB(regrealarray,"",float,DAVARFLOAT,ARRAY) 470 MAKEFSUB(regdoublearray,"",double,DAVARDOUBLE,ARRAY) 471 MAKEFSUB(regintarray,"",int,DAVARINT,ARRAY) 472 473 MAKEFSUB(regparmreal,"parm.",float,DAVARFLOAT,SCALER) 474 MAKEFSUB(regparmdouble,"parm.",double,DAVARDOUBLE,SCALER) 475 MAKEFSUB(regeventreal,"event.",float,DAVARFLOAT,SCALER) 476 MAKEFSUB(regeventdouble,"event.",double,DAVARDOUBLE,SCALER) 477 MAKEFSUB(regparmint,"parm.",int,DAVARINT,SCALER) 478 MAKEFSUB(regeventint,"event.",int,DAVARINT,SCALER) 479 MAKEFSUB(regparmrealarray,"parm.",float,DAVARFLOAT,ARRAY) 480 MAKEFSUB(regparmdoublearray,"parm.",double,DAVARDOUBLE,ARRAY) 481 MAKEFSUB(regeventrealarray,"event.",float,DAVARFLOAT,ARRAY) 482 MAKEFSUB(regeventdoublearray,"event.",double,DAVARDOUBLE,ARRAY) 483 MAKEFSUB(regparmintarray,"parm.",int,DAVARINT,ARRAY) 484 MAKEFSUB(regeventintarray,"event.",int,DAVARINT,ARRAY) 485 486 MAKEFSUB(regtestint,"test.",int,DAVARINT,SCALER) 487 saw 1.1 MAKEFSUB(regtestintarray,"test.",int,DAVARINT,ARRAY) 488 #else 489 MAKEFSUB(regreal_,"",float,DAVARFLOAT,SCALER) 490 MAKEFSUB(regdouble_,"",double,DAVARDOUBLE,SCALER) 491 MAKEFSUB(regint_,"",int,DAVARINT,SCALER) 492 MAKEFSUB(regrealarray_,"",float,DAVARFLOAT,ARRAY) 493 MAKEFSUB(regdoublearray_,"",double,DAVARDOUBLE,ARRAY) 494 MAKEFSUB(regintarray_,"",int,DAVARINT,ARRAY) 495 496 MAKEFSUB(regparmreal_,"parm.",float,DAVARFLOAT,SCALER) 497 MAKEFSUB(regparmdouble_,"parm.",double,DAVARDOUBLE,SCALER) 498 MAKEFSUB(regeventreal_,"event.",float,DAVARFLOAT,SCALER) 499 MAKEFSUB(regeventdouble_,"event.",double,DAVARDOUBLE,SCALER) 500 MAKEFSUB(regparmint_,"parm.",int,DAVARINT,SCALER) 501 MAKEFSUB(regeventint_,"event.",int,DAVARINT,SCALER) 502 MAKEFSUB(regparmrealarray_,"parm.",float,DAVARFLOAT,ARRAY) 503 MAKEFSUB(regparmdoublearray_,"parm.",double,DAVARDOUBLE,ARRAY) 504 MAKEFSUB(regeventrealarray_,"event.",float,DAVARFLOAT,ARRAY) 505 MAKEFSUB(regeventdoublearray_,"event.",double,DAVARDOUBLE,ARRAY) 506 MAKEFSUB(regparmintarray_,"parm.",int,DAVARINT,ARRAY) 507 MAKEFSUB(regeventintarray_,"event.",int,DAVARINT,ARRAY) 508 saw 1.1 509 MAKEFSUB(regtestint_,"test.",int,DAVARINT,SCALER) 510 MAKEFSUB(regtestintarray_,"test.",int,DAVARINT,ARRAY) 511 #endif 512 513 /* Entry points for String registration. Do entry points for anything other 514 than parmameters make sense? */ | ||
515 saw 1.2 #ifdef AbsoftUNIXFortran 516 int regparmstring | ||
517 saw 1.1 #else | ||
518 saw 1.2 int regparmstring_ | ||
519 saw 1.1 #endif 520 (char *name, char *sptr, char *title 521 ,unsigned l_name, unsigned l_sptr, unsigned l_title) 522 { | ||
523 saw 1.2 int A0; | ||
524 saw 1.1 daVarStruct args; 525 char *BN=0; 526 527 char *BT=0; 528 char *BF = 0; 529 530 BF = malloc(5+l_name+1); 531 strcpy(BF,"parm."); 532 args.name = strcat(BF,((!*(int *)name)?0:memchr(name,'\0',l_name)?name: 533 (memcpy(BN=(char *) malloc(l_name+1),name,l_name) 534 ,BN[l_name]='\0',kill_trailing(BN,' ')))); 535 args.title = ((!*(int *)title)?0:memchr(title,'\0',l_title)?title: 536 (memcpy(BT=(char *) malloc(l_title+1),title,l_title) 537 ,BT[l_title]='\0',kill_trailing(BT,' '))); 538 args.size = l_sptr; 539 args.varptr = (void *) sptr; 540 args.flag = DAVAR_READWRITE; 541 args.type = DAVARFSTRING; 542 args.opaque = 0; | ||
543 saw 1.3 args.rhook = 0; 544 args.whook = 0; | ||
545 saw 1.1 A0 = daVarRegister((int) 0, &args); 546 if(BF) free(BF); 547 if(BN) free(BN); 548 return(A0); 549 } 550 551 #ifdef NO_TSEARCH 552 /* 553 * Tree search generalized from Knuth (6.2.2) Algorithm T just like 554 * the AT&T man page says. 555 * 556 * The node_t structure is for internal use only, lint doesn't grok it. 557 * 558 * Written by reading the System V Interface Definition, not the code. 559 * 560 * Totally public domain. 561 */ 562 /*LINTLIBRARY*/ 563 564 /* 565 #include <search.h> 566 saw 1.1 567 typedef struct node_t 568 { 569 char *key; 570 struct node_t *left, *right; 571 } 572 node; 573 */ 574 575 node *mytsearch(key, rootp, compar) 576 /* find or insert datum into search tree */ 577 void *key; /* key to be located */ 578 register node **rootp; /* address of tree root */ 579 int (*compar)(); /* ordering function */ 580 { 581 register node *q; 582 583 if (rootp == (struct node_t **)0) 584 return ((struct node_t *)0); 585 while (*rootp != (struct node_t *)0) /* Knuth's T1: */ 586 { 587 saw 1.1 int r; 588 589 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ 590 return (*rootp); /* we found it! */ 591 rootp = (r < 0) ? 592 &(*rootp)->left : /* T3: follow left branch */ 593 &(*rootp)->right; /* T4: follow right branch */ 594 } 595 q = (node *) malloc(sizeof(node)); /* T5: key not found */ 596 if (q != (struct node_t *)0) /* make new node */ 597 { 598 *rootp = q; /* link new node to old */ 599 q->key = key; /* initialize new node */ 600 q->left = q->right = (struct node_t *)0; 601 } 602 return (q); 603 } 604 605 node *mytdelete(key, rootp, compar) 606 /* delete node with given key */ 607 char *key; /* key to be deleted */ 608 saw 1.1 register node **rootp; /* address of the root of tree */ 609 int (*compar)(); /* comparison function */ 610 { 611 node *p; 612 register node *q; 613 register node *r; 614 int cmp; 615 616 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0) 617 return ((struct node_t *)0); 618 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) 619 { 620 p = *rootp; 621 rootp = (cmp < 0) ? 622 &(*rootp)->left : /* follow left branch */ 623 &(*rootp)->right; /* follow right branch */ 624 if (*rootp == (struct node_t *)0) 625 return ((struct node_t *)0); /* key not found */ 626 } 627 r = (*rootp)->right; /* D1: */ 628 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */ 629 saw 1.1 q = r; 630 else if (r != (struct node_t *)0) /* Right link is null? */ 631 { 632 if (r->left == (struct node_t *)0) /* D2: Find successor */ 633 { 634 r->left = q; 635 q = r; 636 } 637 else 638 { /* D3: Find (struct node_t *)0 link */ 639 for (q = r->left; q->left != (struct node_t *)0; q = r->left) 640 r = q; 641 r->left = q->right; 642 q->left = (*rootp)->left; 643 q->right = (*rootp)->right; 644 } 645 } 646 free((struct node_t *) *rootp); /* D4: Free node */ 647 *rootp = q; /* link parent to new node */ 648 return(p); 649 } 650 saw 1.1 651 static void trecurse(root, action, level) 652 /* Walk the nodes of a tree */ 653 register node *root; /* Root of the tree to be walked */ 654 register void (*action)(); /* Function to be called at each node */ 655 register int level; 656 { 657 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0) 658 (*action)(root, leaf, level); 659 else 660 { 661 (*action)(root, preorder, level); 662 if (root->left != (struct node_t *)0) 663 trecurse(root->left, action, level + 1); 664 (*action)(root, postorder, level); 665 if (root->right != (struct node_t *)0) 666 trecurse(root->right, action, level + 1); 667 (*action)(root, endorder, level); 668 } 669 } 670 671 saw 1.1 void mytwalk(root, action) /* Walk the nodes of a tree */ 672 node *root; /* Root of the tree to be walked */ 673 void (*action)(); /* Function to be called at each node */ 674 { 675 if (root != (node *)0 && action != (void(*)())0) 676 trecurse(root, action, 0); 677 } 678 679 /* mytsearch.c ends here */ 680 /* 681 * Tree search generalized from Knuth (6.2.2) Algorithm T just like 682 * the AT&T man page says. 683 * 684 * The node_t structure is for internal use only, lint doesn't grok it. 685 * 686 * Written by reading the System V Interface Definition, not the code. 687 * 688 * Totally public domain. 689 */ 690 /*LINTLIBRARY*/ 691 /* 692 saw 1.1 #include <search.h> 693 694 typedef struct node_t 695 { 696 char *key; 697 struct node_t *left, *right; 698 } node; 699 */ 700 701 node *mytfind(key, rootp, compar) 702 /* find a node, or return 0 */ 703 void *key; /* key to be found */ 704 register node **rootp; /* address of the tree root */ 705 int (*compar)(); /* ordering function */ 706 { 707 if (rootp == (struct node_t **)0) 708 return ((struct node_t *)0); 709 while (*rootp != (struct node_t *)0) /* T1: */ 710 { 711 int r; 712 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ 713 saw 1.1 return (*rootp); /* key found */ 714 rootp = (r < 0) ? 715 &(*rootp)->left : /* T3: follow left branch */ 716 &(*rootp)->right; /* T4: follow right branch */ 717 } 718 return (node *)0; 719 } 720 #endif |
Analyzer/Replay: Mark Jones, Documents: Stephen Wood |
Powered by ViewCVS 0.9.2-cvsgraph-1.4.0 |