l_func.c
上传用户:aidanglao
上传日期:2007-01-07
资源大小:69k
文件大小:18k
源码类别:

Oracle数据库

开发平台:

Unix_Linux

  1. /**********************************************************************
  2. /* Copyright (C) 1990 - 1999 Steve A. Olson
  3. /*  11617 Quarterfield Dr
  4. /* Ellicott City, MD, 21042
  5. /* All rights reserved.
  6. /**********************************************************************
  7. /* */
  8. /*
  9. /* L_FUNC.C -- LIST Functions.
  10. /* The Class specific INSERT, DELETE, and FIND functions.
  11. /*
  12. /* Functions within this module are:
  13. /*
  14. /* void *lnullpfv(), *ldelq(), *ldelsrch(),
  15. /* *ldelbtree();
  16. /* LNODE *lnullpfn(), *lfindq(), *lfindsrch();
  17. /* LNODE *lfascend(), *lfdesc(), *lfbtree();
  18. /* LNODE *liuascend(), *liudesc();
  19. /* int linsstack(), linsdesc(), linsascend(),
  20. /* linsbtree(), linsq(), lnullpfi();
  21. /*
  22. /* */ 
  23. #include <stdio.h>
  24. #include "list.h"
  25. /* LDELQ -- Delete an Element from a QUEUE
  26. /* All DELETE functions receive the following paramaters:
  27. /* **first,
  28. /* **last,
  29. /* **current
  30.  */
  31. void *
  32. ldelq(LNODE **first, LNODE **last,LNODE ** current)
  33. {
  34. register LNODE *tmp;
  35. register void *info;
  36. if( (*first) ) {
  37. tmp = (*first)->next;
  38. info= (*first)->info;
  39. free( (*first) );
  40. (*first) = tmp;
  41. if( tmp ) tmp->prev = NULL_LNODE;
  42. else (*last)   = NULL_LNODE;
  43. return( info );
  44. }
  45. return( (void *)0 );
  46. }
  47. /* LDELSRCH -- Delete an Element from INORDER, UNSORTED, ASCENDing or
  48. /* DESCENDing LIST.
  49. /*
  50. /* All DELETE functions receive the following paramaters:
  51. /* **first,
  52. /* **last,
  53. /* **current
  54.  */
  55. void *
  56. ldelsrch(LNODE **first, LNODE **last, LNODE **current)
  57. {
  58. register void *info;
  59. if( (*current) == NULL_LNODE )
  60. return( (void *)0 );
  61. info= (*current)->info;
  62. /* update last and first pointers
  63.  */
  64. if( (*current) == (*first) ) (*first) = (*current)->next;
  65. if( (*current) == (*last) ) (*last)  = (*current)->prev;
  66. /* Unlink element from list
  67.  */
  68. if( (*current)->prev != NULL_LNODE )
  69. (*current)->prev->next = (*current)->next;
  70. if( (*current)->next != NULL_LNODE )
  71. (*current)->next->prev = (*current)->prev;
  72. (*current)->next = NULL_LNODE;
  73. (*current)->prev = NULL_LNODE;
  74. /* Free NODE
  75.  */
  76. free( (*current) );
  77. return (info);
  78. }
  79. /* LDELBTREE -- Delete an Element from a BTREE LIST
  80. /*
  81. /* All DELETE functions receive the following paramaters:
  82. /* **first,
  83. /* **last,
  84. /* **current
  85.  */
  86. void *
  87. ldelbtree(LNODE **first, LNODE **last, LNODE **current)
  88. {
  89. register void *info, *tmp;
  90. register LNODE *new;
  91. if( (*current) == NULL_LNODE )
  92. return( (void *)0 );
  93. info=(*current)->info;
  94. /* Delete if first node
  95.  */
  96. if( (*current) == (*first) ) {
  97. if( (*first)->prev ) {
  98. /* UPDATE first
  99.  */
  100. (*first)=(*first)->prev;
  101. for(new=(*first); new->next!=NULL_LNODE; new=new->next)
  102. ;
  103. new->next = (*current)->next;
  104. }
  105. else (*first) = (*first)->next;
  106. free( (*current) );
  107. return(info);
  108. }
  109. if( (*last) == NULL_LNODE ) {
  110. return( (void *)0 );
  111. }
  112. /* Not the First NODE
  113.  */
  114. if( (*last)->prev == (*current) ) {
  115. if( (*current)->prev ) {
  116. (*last)->prev = (*current)->prev;
  117. for(new=(*current)->prev;
  118. new && new->next!=NULL_LNODE;
  119. new=new->next)
  120.     ;
  121. if(new)
  122. new->next = (*current)->next;
  123. } else (*last)->prev = (*current)->next;
  124. free( (*current) );
  125. return( info );
  126. } else if( (*last)->next == (*current) ) {
  127. if( (*current)->prev ) {
  128. (*last)->next = (*current)->prev;
  129. for(new=(*current)->prev;
  130. new && new->next!=NULL_LNODE;
  131. new=new->next)
  132.     ;
  133. if(new)
  134. new->next = (*current)->next;
  135. } else (*last)->next = (*current)->next;
  136. free( (*current) );
  137. return( info );
  138. }
  139. /* else {
  140. /* printf("Bad Last not parent of currentn");
  141. /* return( (void *)0 );
  142. /* }
  143.  */
  144. }
  145. /* LFINDQ -- Find an Element on a QUEUE.
  146. /*
  147. /* A QUEUE --ALWAYS-- Finds FIRST Element.  Thats what a QUEUE is.
  148. /*
  149. /* All FIND functions receive the following paramaters:
  150. /* **first, 
  151. /* **last,
  152. /* size,
  153. /* cmp_f,
  154. /* cmp_info;
  155.  */
  156. LNODE *
  157. lfindq(LNODE **first, LNODE **last, int size, PFI cmp_f, void *cmp_i)
  158. {
  159. return( (*first) );
  160. }
  161. /* LFASCEND -- Find an Element on a Searchable ASCENDING LIST.
  162. /*
  163. /* The compare function, 'cmp_f', MUST return 0 on a MATCH.
  164. /* The compare function is called like so for each Element in the LIST
  165. /* until a MATCH is found or the cmp_f returns >0
  166. /* cmp_f(info, cmp_i)
  167. /*
  168. /* All Find functions receive the following paramaters:
  169. /* **first, 
  170. /* **last,
  171. /* size,
  172. /* cmp_f,
  173. /* cmp_info;
  174.  */
  175. LNODE *
  176. lfascend(LNODE **first, LNODE **last, int size, PFI cmp_f, void *cmp_i)
  177. {
  178. register LNODE *tmp;
  179. register short cmpval;
  180. for( tmp=(*first); tmp!=NULL_LNODE; tmp=tmp->next)
  181. if( (cmpval=((*cmp_f)(tmp->info, cmp_i))) == 0)
  182. return( tmp );
  183. else if (cmpval>0) /* No need to search rest */
  184. break;
  185. return( NULL_LNODE );
  186. }
  187. /* LFDESC -- Find an Element on a Searchable DESC LIST.
  188. /*
  189. /* The compare function, 'cmp_f', MUST return 0 on a MATCH.
  190. /* The compare function is called like so for each Element in the LIST
  191. /* until a MATCH is found or the cmp_f returns <0
  192. /* cmp_f(info, cmp_i)
  193. /*
  194. /* All Find functions receive the following paramaters:
  195. /* **first, 
  196. /* **last,
  197. /* size,
  198. /* cmp_f,
  199. /* cmp_info;
  200.  */
  201. LNODE *
  202. lfdesc(LNODE **first, LNODE **last, int size, PFI cmp_f, void *cmp_i)
  203. {
  204. register LNODE *tmp;
  205. register short cmpval;
  206. for( tmp=(*first); tmp!=NULL_LNODE; tmp=tmp->next)
  207. if( (cmpval=((*cmp_f)(tmp->info, cmp_i))) == 0)
  208. return( tmp );
  209. else if (cmpval<0) /* No need to search rest */
  210. break;
  211. return( NULL_LNODE );
  212. }
  213. /* LFINDSRCH -- Find an Element on a Searchable LIST: INORDER, UNSORTED,
  214. /* ASCEND, DESCEND.
  215. /*
  216. /* The compare function, 'cmp_f', MUST return 0 on a MATCH.
  217. /* The compare function is called like so for each Element in the LIST
  218. /* until a MATCH is found or it reaches the END of the LIST.
  219. /* cmp_f(info, cmp_i)
  220. /*
  221. /* All Find functions receive the following paramaters:
  222. /* **first, 
  223. /* **last,
  224. /* size,
  225. /* cmp_f,
  226. /* cmp_info;
  227.  */
  228. LNODE *
  229. lfindsrch(LNODE **first, LNODE **last, int size, PFI cmp_f, void *cmp_i)
  230. {
  231. register LNODE *tmp;
  232. for( tmp=(*first); tmp!=NULL_LNODE; tmp=tmp->next)
  233. if( ((*cmp_f)(tmp->info, cmp_i)) == 0)
  234. return( tmp );
  235. return( NULL_LNODE );
  236. }
  237. /* LFINDBTREE -- Find an Element on a BTREE LIST
  238. /*
  239. /* The compare function, 'cmp_f', MUST return 0 on a MATCH.
  240. /* The compare function is called like so for each Element in the LIST
  241. /* until a MATCH is found or it reaches the END of the LIST.
  242. /* cmp_f(info, cmp_i)
  243. /*
  244. /* All Find functions receive the following paramaters:
  245. /* **first, 
  246. /* **last,
  247. /* size,
  248. /* cmp_f,
  249. /* cmp_info;
  250.  */
  251. LNODE *
  252. lfbtree(LNODE **first, LNODE **last, int size, PFI cmp_f, void *cmp_i)
  253. {
  254. register int ret;
  255. if( (*first) == NULL_LNODE)
  256. return( NULL_LNODE );
  257. if( (ret=(*cmp_f)((*first)->info, cmp_i)) == 0)
  258. return( (*first) );
  259. (*last)=(*first);
  260. if(ret<0) {
  261. return(lfbtree(&(*first)->next,last, size, cmp_f, cmp_i));
  262. } else /* if(ret>0) */ {
  263. return(lfbtree(&(*first)->prev,last, size, cmp_f, cmp_i));
  264. }
  265. }
  266. /* LINSSTACK -- Insert an Element onto a STACK.
  267. /*
  268. /* A STACK --ALWAYS-- Inserts at FIRST Element.  Thats what a STACK is.
  269. /*
  270. /* All Insert functions receive the following paramaters:
  271. /* *first, 
  272. /* *last,
  273. /* cmp_f,
  274. /* info;
  275.  */
  276. int
  277. linsstack( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  278. {
  279. register LNODE *new;
  280. if( (new=(LNODE *)malloc( sizeof(LNODE))) == (NULL_LNODE) )
  281. return( 0 );
  282. new->weight = 0;
  283. new->next = (*first);
  284. new->prev = NULL_LNODE;
  285. new->info = info;
  286. if((*first)==NULL_LNODE)
  287. (*last)=new;
  288. else (*first)->prev = new; /* link new to front of list */
  289. (*first) = new;
  290. return(1);
  291. }
  292. /* LIUDESC -- Insert an Element NO DUPS into a DESCENDING List.
  293. /*
  294. /* The compare function, 'cmp_f', must return <0 when the INFO
  295. /* Inserted is 'Less Than' another INFO structure and = when Equal.
  296. /* The 'cmp_f' must know what a user-malloc'd INFO structure is and
  297. /* what makes one 'Less Than', 'Equal to', and 'Greater Than' another. 
  298. /*
  299. /* 'cmp_f' gets the new INFO struct as its second parameter.
  300. /*
  301. /* All Insert functions receive the following paramaters:
  302. /* *first, 
  303. /* *last,
  304. /* cmp_f,
  305. /* info;
  306.  */
  307. int
  308. liudesc( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  309. {
  310. register LNODE *new, *n;
  311. register short val;
  312. for( n= (*first); n!=NULL_LNODE; n=n->next) {
  313. if( (val=(*cmp_f)(n->info, info)) < 0 )
  314. break;
  315. else if( val==0 )
  316. return(2); /* SUCCESS its already there */
  317. }
  318. if( (new=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  319. return(0);
  320. new->weight = 0;
  321. new->info = info;
  322. new->next = n;
  323. if(n) {
  324. if(n->prev) n->prev->next = new;
  325. new->prev = n->prev;
  326. n->prev = new;
  327. } else {
  328. new->prev = (*last);
  329. if( (*last) ) (*last)->next = new;
  330. (*last) = new;
  331. }
  332. if( n == (*first))
  333. (*first) = new;
  334. return (1);
  335. }
  336. /* LINSDESC -- Insert an Element into a DESCENDING List.
  337. /*
  338. /* The compare function, 'cmp_f', must return <0 when the INFO
  339. /* Inserted is 'Less Than' another INFO structure.  The 'cmp_f' must
  340. /* know what a user-malloc'd INFO structure is and what makes one
  341. /* 'Less Than', 'Equal to', and 'Greater Than' another. 
  342. /*
  343. /* 'cmp_f' gets the new INFO struct as its second parameter.
  344. /*
  345. /* All Insert functions receive the following paramaters:
  346. /* *first, 
  347. /* *last,
  348. /* cmp_f,
  349. /* info;
  350.  */
  351. int
  352. linsdesc( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  353. {
  354. register LNODE *new, *n;
  355. if( (new=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  356. return(0);
  357. new->weight = 0;
  358. new->info = info;
  359. for( n= (*first); n!=NULL_LNODE; n=n->next)
  360. if( (*cmp_f)(n->info, info) < 0 )
  361. break;
  362. new->next = n;
  363. if(n) {
  364. if(n->prev) n->prev->next = new;
  365. new->prev = n->prev;
  366. n->prev = new;
  367. } else {
  368. new->prev = (*last);
  369. if( (*last) ) (*last)->next = new;
  370. (*last) = new;
  371. }
  372. if( n == (*first))
  373. (*first) = new;
  374. return (1);
  375. }
  376. /* LIUASCEND -- Insert an Element NO DUPS into an ASCENDING List.
  377. /*
  378. /* The compare function, 'cmp_f', must return >0 when the INFO
  379. /* Inserted is 'Greater Than' another INFO structure and = when equal.
  380. /* The 'cmp_f' must know what a user-malloc'd INFO structure is and
  381. /* what makes one 'Less Than', 'Equal to', and 'Greater Than' another. 
  382. /*
  383. /* 'cmp_f' gets the new INFO struct as its second parameter.
  384. /*
  385. /* All Insert functions receive the following paramaters:
  386. /* *first, 
  387. /* *last,
  388. /* cmp_f,
  389. /* info;
  390.  */
  391. int
  392. liuascend( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  393. {
  394. register LNODE *new, *n;
  395. register short val;
  396. for( n= (*first); n!=NULL_LNODE; n=n->next) {
  397. if( (val=(*cmp_f)(n->info, info)) > 0 )
  398. break;
  399. else if( val==0 )
  400. return(2);
  401. }
  402. if( (new=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  403. return(0);
  404. new->weight = 0;
  405. new->info = info;
  406. new->next = n;
  407. if(n) {
  408. if(n->prev) n->prev->next = new;
  409. new->prev = n->prev;
  410. n->prev = new;
  411. } else {
  412. new->prev = (*last);
  413. if( (*last) ) (*last)->next = new;
  414. (*last) = new;
  415. }
  416. if( n == (*first))
  417. (*first) = new;
  418. return (1);
  419. }
  420. /* LINSASCEND -- Insert an Element into an ASCENDING List.
  421. /*
  422. /* The compare function, 'cmp_f', must return >0 when the INFO
  423. /* Inserted is 'Greater Than' another INFO structure.  The 'cmp_f' must
  424. /* know what a user-malloc'd INFO structure is and what makes one
  425. /* 'Less Than', 'Equal to', and 'Greater Than' another. 
  426. /*
  427. /* 'cmp_f' gets the new INFO struct as its second parameter.
  428. /*
  429. /* All Insert functions receive the following paramaters:
  430. /* *first, 
  431. /* *last,
  432. /* cmp_f,
  433. /* info;
  434.  */
  435. int
  436. linsascend( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  437. {
  438. register LNODE *new, *n;
  439. if( (new=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  440. return(0);
  441. new->weight = 0;
  442. new->info = info;
  443. for( n= (*first); n!=NULL_LNODE; n=n->next) {
  444. if( (*cmp_f)(n->info, info) > 0 )
  445. break;
  446. }
  447. new->next = n;
  448. if(n) {
  449. if(n->prev) n->prev->next = new;
  450. new->prev = n->prev;
  451. n->prev = new;
  452. } else {
  453. new->prev = (*last);
  454. if( (*last) ) (*last)->next = new;
  455. (*last) = new;
  456. }
  457. if( n == (*first))
  458. (*first) = new;
  459. return (1);
  460. }
  461. /* LINSQUEUE -- Insert an Element into a QUEUE.
  462. /*
  463. /* A QUEUE --ALWAYS-- Inserts at LAST Element.  Thats what a QUEUE is.
  464. /*
  465. /* All Insert functions receive the following paramaters:
  466. /* *first, 
  467. /* *last,
  468. /* cmp_f,
  469. /* info;
  470.  */
  471. int
  472. linsq( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  473. {
  474. register LNODE *new;
  475. if( (new=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  476. return(0);
  477. new->weight = 0;
  478. new->prev  = (*last);
  479. if( new->prev )
  480. new->prev->next = new;
  481. new->next = NULL_LNODE;
  482. new->info = info;
  483. (*last) = new;
  484. if( (*first) == NULL_LNODE )
  485. (*first) = (*last);
  486. return(1);
  487. }
  488. /* LINSBTREE -- Insert an Element into a BTREE List.
  489. /*
  490. /* The compare function, 'cmp_f', must return <0 when the INFO
  491. /* Inserted is 'Less Than' another INFO structure.  The 'cmp_f' must
  492. /* know what a user-malloc'd INFO structure is and what makes one
  493. /* 'Less Than', 'Equal to', and 'Greater Than' another. 
  494. /*
  495. /* 'cmp_f' gets the new INFO struct as its second parameter.
  496. /*
  497. /* All Insert functions receive the following paramaters:
  498. /* *first, 
  499. /* *last,
  500. /* cmp_f,
  501. /* info;
  502.  */
  503. int
  504. linsbtree( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  505. {
  506. register int ret;
  507. if((*first) == NULL_LNODE) {
  508. if( ((*first)=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  509. return(0);
  510. (*first)->weight = 0;
  511. (*first)->info   = info;
  512. (*first)->prev   = NULL_LNODE;
  513. (*first)->next   = NULL_LNODE;
  514. return (1);
  515. }
  516. ret = (*cmp_f)((*first)->info, info);
  517. if(ret>0) {
  518. return(linsbtree( &((*first)->prev),last,cmp_f,info));
  519. }
  520. if(ret<0) {
  521. return(linsbtree( &((*first)->next),last,cmp_f,info));
  522. }
  523. /* DUPLICATE */
  524. return(-2);
  525. }
  526. void
  527. rot_prev( LNODE **lnode )
  528. {
  529. LNODE **tmp;
  530. tmp = &((*lnode)->next);
  531. (*lnode)->next = (*tmp)->prev;
  532. (*tmp)->prev   = *lnode;
  533. lnode          = tmp;
  534. }
  535. void
  536. rot_next( LNODE **lnode )
  537. {
  538. LNODE **tmp;
  539. tmp = &((*lnode)->prev);
  540. (*lnode)->prev = (*tmp)->next;
  541. (*tmp)->next   = *lnode;
  542. lnode          = tmp;
  543. }
  544. /* L SCAN LIST -- Scan a regular LINKED-LIST. Start at first,
  545. /* walk each next till end.
  546. /* Call scan_f at each NODE.
  547. /*
  548. /* Break off scan if any scan_f returns a 0.
  549.  */
  550. int
  551. lscanl(LNODE *first,int size,PFV scan_f)
  552. {
  553. register LNODE *tmp;
  554. for( tmp=first; tmp!=NULL_LNODE; tmp=tmp->next)
  555. if( ((*scan_f)(tmp->info)) == 0 )
  556. return(0);
  557. return(1);
  558. }
  559. /* SCAN BTREE -- Walk a BTREE LINKED-LIST.
  560. /* Call scan_f at each NODE.
  561. /*
  562. /* Break off scan if any scan_f returns a 0.
  563.  */
  564. int
  565. lscanbt(LNODE *first,int size,PFV scan_f)
  566. {
  567. if(first==NULL_LNODE)
  568. return(1); /* This is OK, will happen normally
  569. /* At each leaf.
  570.  */
  571. if(lscanbt(first->prev,size,scan_f) == 0)
  572. return(0);
  573. if( ((*scan_f)((first)->info)) == 0 )
  574. return(0);
  575. if(lscanbt(first->next,size,scan_f) == 0)
  576. return(0);
  577. return(1);
  578. }
  579. /*
  580. /* HASH FUNCTIONS 
  581.  */
  582. #define HASHTABLESIZE 211
  583. static int
  584. GetHashKey(char *pKey)
  585. {
  586.     unsigned long g, h = 0;
  587.     while(*pKey){
  588. h = (h << 4) + toupper(*pKey++);
  589. g = h & 0xF0000000L;
  590. if(g) { h ^=g >> 24; }
  591. h &= ~g;
  592.     }
  593.     return( h % HASHTABLESIZE);
  594. }
  595. int
  596. linshash( LNODE **first, LNODE **last, PFI cmp_f, void *info)
  597. {
  598.     char *pKey; 
  599.     int iHashIndex;
  600.     LNODE **ppLnode;
  601.     if( (*first)== NULL_LNODE) {
  602. (*first)= (LNODE*)calloc( HASHTABLESIZE, sizeof(LNODE*) );
  603. /* I know, I know this really points to an array
  604. /* of those, but this is the defined structure
  605. /* of the LIST, so....
  606.  */
  607.     }
  608.     ppLnode = (LNODE**)(*first);
  609.     /* Get HASH KEY
  610.      */
  611.     pKey = (char *)(*cmp_f)(info);
  612. /* User supplied function returns the character
  613. /* string that represnts the HASH KEY
  614.  */
  615.     if(pKey) {
  616. char *pKey2;
  617. register LNODE *new,
  618. *pTmp;
  619. iHashIndex = GetHashKey(pKey);
  620. if( (new=(LNODE *)malloc( sizeof(LNODE) )) == NULL_LNODE )
  621. return(0);
  622. new->weight = 0;
  623. new->info = info;
  624. /*
  625. /* fprintf(stderr,"Adding:%sn",pKey);
  626. /* fflush (stderr);
  627.  */
  628. /* Search the "prev" list for match
  629.  */ 
  630. for( new->next=NULL_LNODE, pTmp=ppLnode[iHashIndex]
  631.     ;pTmp
  632.     ;new->next=pTmp, pTmp=pTmp->prev)
  633. {
  634.     pKey2 = (char *)(*cmp_f)(pTmp->info);
  635.     /*
  636.     /* Install a Sibling using PUSH semantics
  637.      */
  638.     if(strcmp(pKey,pKey2)==0) {
  639. LNODE *pTmp2=pTmp;
  640. while(pTmp2->next) {
  641.     pTmp2=pTmp2->next;
  642. }
  643. pTmp2->next = new;
  644. new->next = 0;
  645. new->prev = 0;
  646.     /* fprintf(stderr,"S(%d,%s)n",iHashIndex,pKey);
  647.     /* fflush(stderr);
  648.      */
  649. return(1);
  650.     }
  651. }
  652. if(new->next) /* new->next is last ELEMENT on "prev" list */
  653.      new->next->prev = new;
  654. else ppLnode[iHashIndex]=new; /* I'm first */
  655. new->next = NULL_LNODE; /* I've got no Siblings/Dups */
  656. new->prev = NULL_LNODE; /* I'm LAST on the LIST */
  657. /*
  658. /* fprintf(stderr,"C(%d,%s)n",iHashIndex,pKey);
  659. /* fflush(stderr);
  660.  */
  661. return(1);
  662.     }
  663.     return(0);
  664. }
  665. void *
  666. ldelhash(LNODE **first, LNODE **last,LNODE ** current)
  667. {
  668.     register LNODE *pTmp = (*current);
  669.     register void *pInfo;
  670.     if(!(*current))
  671. return( (void*)0 );
  672.     /* If this node has a "sibling"
  673.      */
  674.     if( (*current)->next ) {
  675. if( (*current)->prev ) 
  676.     (*current)->prev = (*current)->next;
  677. (*current)= (*current)->next;
  678.     } else if( (*current)->prev ) {
  679. (*current)= (*current)->prev;
  680.     }
  681.     pInfo = pTmp->info;
  682.     free( (pTmp) );
  683.     return(pInfo);
  684. }
  685. LNODE *
  686. lfindhash(LNODE **first, LNODE **last, int size, PFI cmp_f, void *cmp_i)
  687. {
  688.     char *pKey, *pKey2; 
  689.     int iHashIndex;
  690.     LNODE **ppLnode, *pTmp;
  691.     if( (*first)== NULL_LNODE) {
  692. return( NULL_LNODE );
  693.     }
  694.     ppLnode = (LNODE**)(*first);
  695.     /* Get HASH KEY
  696.      */
  697.     pKey = (char *)(*cmp_f)(cmp_i);
  698. /* User supplied function returns the character
  699. /* string that represnts the HASH KEY
  700.  */
  701.     if(pKey) {
  702. iHashIndex = GetHashKey(pKey);
  703. for( pTmp=ppLnode[iHashIndex]; pTmp!=NULL_LNODE; pTmp=pTmp->prev) {
  704.     pKey2 = (char *)(*cmp_f)(pTmp->info);
  705.     /* Collision Checking
  706.     /* fprintf(stderr,"L(%d,%s,%s)n",iHashIndex,pKey,pKey2);
  707.     /* fflush(stderr);
  708.      */
  709.     if(strcasecmp(pKey,pKey2)==0) {
  710.     /* if(strcmp(pKey,pKey2)==0) 
  711.     /* fprintf(stderr,"H(%d,%s)n",iHashIndex,pKey2);
  712.     /* fflush(stderr);
  713.      */
  714. return(pTmp);
  715.     }
  716. }
  717. return( NULL_LNODE );
  718.     }
  719.     return( NULL_LNODE);
  720. }
  721. int
  722. lscanhash(LNODE *first,int size,PFV scan_f)
  723. {
  724.     int i;
  725.     LNODE **ppLnode, *pInd, *pColl, *pSib;
  726.     ppLnode = (LNODE**) first;
  727.     for(i=0; i<HASHTABLESIZE;++i){
  728. pInd = ppLnode[i];
  729. if(!pInd)
  730.     continue;
  731. for(pColl=pInd; pColl; pColl = pColl->prev){
  732.     if( pColl->info && ((*scan_f)((pColl)->info)) == 0 ) {
  733. return(0);
  734.     }
  735.     for(pSib=pColl->next;pSib;pSib=pSib->next){
  736. if(pColl->info && ((*scan_f)((pSib)->info)) == 0 ) {
  737.     return(0);
  738. }
  739.     }
  740. }
  741.     }
  742.     
  743.     return(0);
  744. }
  745. /* Place holder functions 
  746.  */
  747. int
  748. lnullpfi()
  749. {
  750. return(0);
  751. }
  752. void *
  753. lnullpfv()
  754. {
  755. return((void *)0);
  756. }
  757. LNODE *
  758. lnullpfn()
  759. {
  760. return(NULL_LNODE);
  761. }