home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3222 < prev    next >
Encoding:
Internet Message Format  |  1991-04-21  |  26.2 KB

  1. From: tron1@tronsbox.xei.com (Kenneth Jamieson)
  2. Newsgroups: alt.sources
  3. Subject: X_Hash list (02/02)
  4. Message-ID: <1560@tronsbox.xei.com>
  5. Date: 20 Apr 91 04:02:38 GMT
  6.  
  7.  
  8. Submitted by: tron1@tronsbox
  9. Archive-name: X_HASH/part 2
  10.  
  11. ---- Cut Here and unpack ----
  12. #!/bin/sh
  13. # this is x_hash.02 (part 2 of X_HASH)
  14. # do not concatenate these parts, unpack them in order with /bin/sh
  15. # file src/x_list.c continued
  16. #
  17. touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
  18. if [ -s /tmp/s3_touch$$ ]
  19. then
  20.     TOUCH=can
  21. else
  22.     TOUCH=cannot
  23. fi
  24. rm -f /tmp/s3_touch$$
  25. CurArch=2
  26. if test ! -r s3_seq_.tmp
  27. then echo "Please unpack part 1 first!"
  28.      exit 1; fi
  29. ( read Scheck
  30.   if test "$Scheck" != $CurArch
  31.   then echo "Please unpack part $Scheck next!"
  32.        exit 1;
  33.   else exit 0; fi
  34. ) < s3_seq_.tmp || exit 1
  35. echo "x - Continuing file src/x_list.c"
  36. sed 's/^X//' << 'SHAR_EOF' >> src/x_list.c
  37. X}
  38. X  
  39. Xint get_count_xlist( struct x_list * xlist ){
  40. X  if( xlist == NULL ){                     /* If the list pointer is bad */
  41. X    return( 0 );
  42. X  }
  43. X  return( xlist->count );        /* Return the current count    */
  44. X}
  45. X
  46. Xint free_xlist( struct x_list * xlist ){
  47. X  if( xlist == NULL ){                     /* If the list pointer is bad */
  48. X    return( (int)FALSE );
  49. X  }
  50. X  while( get_count_xlist( xlist ) != 0 ){
  51. X    del_xlist( xlist );
  52. X  }
  53. X  free((char *) xlist );
  54. X  return( (int)TRUE );
  55. X}
  56. X
  57. Xint set_user_xlist( struct x_list * xlist, void * data ){
  58. X  if( xlist == NULL ){                     /* If the list pointer is bad */
  59. X    return( (int)FALSE );
  60. X  }
  61. X  xlist->data = data;
  62. X  return( (int)TRUE );
  63. X}
  64. X
  65. Xvoid * get_user_xlist( struct x_list * xlist ){
  66. X  if( xlist == NULL ){                     /* If the list pointer is bad */
  67. X    return( (int)FALSE );
  68. X  }
  69. X  return( xlist->data );
  70. X}
  71. X
  72. Xint tail_xlist( struct x_list * xlist ){
  73. X  if( xlist == NULL ){
  74. X    return( (int)FALSE );            /* if list pointer is bad */
  75. X  }                                                    
  76. X  if( xlist->last == NULL ){                           
  77. X    return( (int)FALSE );            /* if list is empty       */
  78. X  }                                                    
  79. X  xlist->current = xlist->last;        /* reset the current pointer*/
  80. X  xlist->node = xlist->count - 1;        /* Reset node number */
  81. X  return( (int)TRUE );
  82. X}
  83. X
  84. Xint get_nodenum_xlist( struct x_list * xlist ){
  85. X  if( xlist == NULL ){                     /* If the list pointer is bad */
  86. X    return( (int)FALSE );
  87. X  }  
  88. X  return( xlist->node );
  89. X}
  90. X
  91. Xint goto_xlist( struct x_list * xlist, int target ){
  92. X  int count;
  93. X  if( xlist == NULL ){                     /* If the list pointer is bad */
  94. X    return( (int)FALSE );
  95. X  }
  96. X  if( target < 0 ){
  97. X    return( (int)FALSE );
  98. X  }
  99. X  count = get_count_xlist( xlist );
  100. X  if( target > count ){
  101. X    return( (int)FALSE );
  102. X  }
  103. X  count = get_nodenum_xlist( xlist );    /* Re-use the count integer */
  104. X  if( target > count ){
  105. X    while( target > get_nodenum_xlist( xlist ) ){
  106. X      if( next_xlist( xlist ) == FALSE ){
  107. X    return( (int)FALSE );        /* Error ? */
  108. X      }
  109. X    }
  110. X    return( (int)TRUE );
  111. X  }
  112. X  if( target < count ){
  113. X    while( target < get_nodenum_xlist( xlist ) ){
  114. X      if( prev_xlist( xlist ) == FALSE ){
  115. X    return( (int)FALSE );        /* Error ? */
  116. X      }
  117. X    }
  118. X    return( (int)TRUE );
  119. X  }
  120. X  if( target == count ){
  121. X    return( (int)TRUE );        /* Error ? */
  122. X  }
  123. X  return( (int)FALSE );            /* No idea what happened!          */
  124. X                                        /* I mean, if it is not > < or = ! */
  125. X}
  126. X
  127. X#ifdef __cplusplus
  128. X
  129. XX_List::X_List(){
  130. X  list = init_xlist();
  131. X}
  132. X
  133. XX_List::X_List( void * name ){
  134. X  list = init_xlist();
  135. X  set_user( name );
  136. X}
  137. X
  138. Xint X_List::add( void * data ){
  139. X  return( add_xlist( list, data ) );
  140. X}
  141. X
  142. Xvoid * X_List::get(){
  143. X  return( get_xlist( list ) );
  144. X}
  145. X
  146. Xint X_List::head(){
  147. X  return( head_xlist( list ) );
  148. X}
  149. X
  150. Xint X_List::tail(){
  151. X  return( tail_xlist( list ) );
  152. X}
  153. X
  154. Xint X_List::put( void * data ){
  155. X  return( put_xlist( list, data ) );
  156. X}
  157. X
  158. Xint X_List::del(){
  159. X  return( del_xlist( list ) );
  160. X}
  161. X
  162. Xint X_List::next(){
  163. X  return( next_xlist( list ) );
  164. X}
  165. X
  166. Xint X_List::prev(){
  167. X  return( prev_xlist( list ) );
  168. X}
  169. X
  170. Xint X_List::count(){
  171. X  return( get_count_xlist( list ) );
  172. X}
  173. X
  174. Xint X_List::set_user( void * name ){
  175. X  return( set_user_xlist( list, name ) );
  176. X}
  177. X
  178. Xvoid * X_List::get_user(){
  179. X  return( get_user_xlist( list ) );
  180. X}
  181. X
  182. Xint X_List::nodenum(){
  183. X  return( (int)get_nodenum_xlist( list ) );
  184. X}
  185. X
  186. Xint X_List::goto_node( int target ){
  187. X  return( goto_xlist( list, target ) );
  188. X}
  189. X
  190. Xvoid * X_List::operator[]( int target ){
  191. X  if( this->goto_node( target ) == FALSE ){
  192. X    return( NULL );
  193. X  }
  194. X  return( this->get() );
  195. X}
  196. X
  197. XX_List::~X_List(){
  198. X  free_xlist( list );
  199. X}
  200. X
  201. X
  202. X
  203. X#endif
  204. X
  205. X
  206. SHAR_EOF
  207. echo "File src/x_list.c is complete"
  208. chmod 0440 src/x_list.c || echo "restore of src/x_list.c fails"
  209. if [ $TOUCH = can ]
  210. then
  211.     touch -am 0418223391 src/x_list.c
  212. fi
  213. # ============= src/x_list.h ==============
  214. echo "x - extracting src/x_list.h (Text)"
  215. sed 's/^X//' << 'SHAR_EOF' > src/x_list.h &&
  216. X/* 
  217. X
  218. X   Doubly linked list header file : 
  219. X
  220. X         x_list.h 1.1 4/18/91 
  221. X
  222. X*/
  223. X
  224. X/*
  225. X
  226. XThis text in this file is copyright (c) 1991 by Kenneth Jamieson.
  227. X
  228. XThe author may be reached at the US MAIL address listed below, or
  229. Xby sending unix mail to ...
  230. X
  231. X           tron1@tronsbox.xei.com            or
  232. X       ...!uunet!tronsbox.xei.com!tron1  or
  233. X       yelling "Hey Ken!" if you happen to be close enough.
  234. X
  235. X
  236. X       SEE THE FILE "sharew.h" for details before you
  237. X       use this code !!!
  238. X
  239. X*/
  240. X
  241. X
  242. X
  243. X#ifndef _x_list_h    /* To solve any double defined errors */
  244. X#define _x_list_h 
  245. X
  246. X#ifndef TRUE        /* Just a standard define of mine */
  247. X#define TRUE 1
  248. X#endif
  249. X#ifndef FALSE        /* Just a standard define of mine */
  250. X#define FALSE 0
  251. X#endif
  252. X
  253. X/* Below, we will define the structures we need for this code.... */
  254. X
  255. Xstruct x_list_entry {             /* Just a generic entry in out list  */
  256. X  void * data;             /* The data pointer to store         */
  257. X  struct x_list_entry * prev;    /* The pointer to the previous entry */
  258. X  struct x_list_entry * next;    /* The pointer to the next entry     */
  259. X};
  260. X
  261. Xstruct x_list {             /* The header that will start every list */
  262. X  void * data;             /* A user pointer so you can name it     */
  263. X  struct x_list_entry * first;     /* Pointer to the first entry in list    */
  264. X  struct x_list_entry * current; /* Pointer to the current entry in list  */
  265. X  struct x_list_entry * last;    /* Pointer to the last entry in the list */
  266. X  int node;             /* The number of the current node        */
  267. X  int count;             /* A count of the number of nodes in list*/
  268. X};
  269. X
  270. X
  271. Xstruct x_list_entry * init_xlist_entry();            
  272. X/* Create and init a new entry struct */
  273. X
  274. Xstruct x_list * init_xlist();                    
  275. X/* create and init a new list head    */
  276. X
  277. Xint add_xlist( struct x_list * xlist , void * new_data );    
  278. X/* Add a new data item to the list    */
  279. X
  280. Xvoid * get_xlist(struct x_list * xlist );            
  281. X/* Get the data pointer from current entry in the list */
  282. X
  283. Xint head_xlist( struct x_list * xlist );            
  284. X/* Go to the top of the list          */
  285. X
  286. Xint put_xlist( struct x_list * xlist, void * new_data );    
  287. X/* Replace data for current node      */
  288. X
  289. Xint del_xlist( struct x_list * xlist );                
  290. X/* Kill the current item and re-weave the list   */
  291. X
  292. Xint next_xlist( struct x_list * xlist );            
  293. X/* Goto next node              */
  294. X
  295. Xint prev_xlist( struct x_list * xlist );            
  296. X/* Go to prev node              */
  297. X
  298. Xint get_count_xlist( struct x_list * xlist );            
  299. X/* get the counter               */
  300. X
  301. Xint free_xlist( struct x_list * xlist );
  302. X/* Delete the entire list             */
  303. X
  304. Xint set_user_xlist( struct x_list * xlist, void * data );
  305. X/* Set the user pointer for a xlist   */
  306. X
  307. Xvoid * get_user_xlist( struct x_list * xlist );
  308. X/* Get the user pointer for a xlist   */
  309. X
  310. Xint tail_xlist( struct x_list * );
  311. X/* Sets the current node to the last node in list */
  312. X
  313. Xint goto_xlist( struct x_list * xlist, int target );
  314. X/* Sets the current node to the target'th node in list if possible */
  315. X
  316. Xint get_nodenum_xlist( struct x_list * xlist );
  317. X/* Gives you the node number of the node you are on */
  318. X
  319. X#ifdef __cplusplus
  320. X
  321. Xclass X_List {
  322. X  struct x_list * list;
  323. X public:
  324. X  X_List();
  325. X  X_List( void * name );
  326. X  int add( void * data );
  327. X  void * get();
  328. X  int head();
  329. X  int tail();
  330. X  int put( void * data);
  331. X  int del();
  332. X  int next();
  333. X  int prev();
  334. X  int count();
  335. X  int set_user( void * name );
  336. X  void * get_user();
  337. X  int nodenum();
  338. X  int goto_node( int target );
  339. X  void * operator[](int);
  340. X  ~X_List();
  341. X};
  342. X
  343. X
  344. X#endif
  345. X
  346. X#endif
  347. X
  348. X
  349. SHAR_EOF
  350. chmod 0440 src/x_list.h || echo "restore of src/x_list.h fails"
  351. if [ $TOUCH = can ]
  352. then
  353.     touch -am 0418223391 src/x_list.h
  354. fi
  355. # ============= src/Makefile ==============
  356. echo "x - extracting src/Makefile (Text)"
  357. sed 's/^X//' << 'SHAR_EOF' > src/Makefile &&
  358. X# UNIX Makefile for the x_list library
  359. X#
  360. X#     Unix Makefile for x_list functions. 
  361. X#
  362. X#    make.unx 1.1 4/18/91 
  363. X#
  364. X# Set the CC variable to any compiler that can take ANSI C
  365. XCC=CC
  366. X
  367. X# Set any other flags you want the compiler to honor
  368. XCFLAGS=-O -I.. -I. -I../../include -L. -L../../lib
  369. X
  370. X# The command that is used to make an archive 
  371. X# BSD and SUNOS
  372. X# ARCHIVE=ar cr 
  373. X# System V
  374. XARCHIVE=ar -cr 
  375. X
  376. Xall: testlist testhash
  377. X    @echo " "
  378. X    @echo "======================================================="
  379. X    @echo "= Done building x_hash list manager system...         ="
  380. X    @echo "= Run the program 'testit' to see if it works.        ="
  381. X    @echo "= Remember to type 'make install' if all went well.   ="
  382. X    @echo "= Then you can 'make clean' to get rid of temp files. ="
  383. X    @echo "= - - - - - - - - - - - - - - - - - - - - - - - - - - ="
  384. X    @echo "= Please don't forget that this is is shareware!      ="
  385. X    @echo "======================================================="
  386. X    @echo " "
  387. X
  388. Xinstall:
  389. X    cp libx_list.a ../../lib
  390. X    chmod 644 ../../lib/libx_list.a
  391. X    cp x_list.h ../../include
  392. X    chmod 644 ../../include/x_list.h
  393. X    cp libx_hash.a ../../lib
  394. X    chmod 644 ../../lib/libx_hash.a
  395. X    cp x_hash.h ../../include
  396. X    chmod 644 ../../include/x_hash.h
  397. X
  398. Xlibx_list.a: x_list.o 
  399. X    $(ARCHIVE) libx_list.a x_list.o
  400. X    -ranlib libx_list.a
  401. X
  402. Xx_list.o: x_list.c x_list.h 
  403. X    $(CC) $(CFLAGS) -c x_list.c
  404. X
  405. Xtestlist: testlist.c libx_list.a x_list.h 
  406. X    $(CC) $(CFLAGS) -o testlist testlist.c -lx_list 
  407. X
  408. Xlibx_hash.a: x_hash.o 
  409. X    $(ARCHIVE) libx_hash.a x_hash.o
  410. X    -ranlib libx_hash.a
  411. X
  412. Xx_hash.o: x_hash.c x_hash.h x_list.h
  413. X    $(CC) $(CFLAGS) -c x_hash.c
  414. X
  415. Xtesthash: testhash.c libx_hash.a libx_list.a x_hash.h 
  416. X    $(CC) $(CFLAGS)  -o testhash testhash.c -lx_hash -lx_list
  417. X
  418. Xclean: 
  419. X    -rm x_hash.o
  420. X    -rm libx_hash.a
  421. X    -rm x_list.o
  422. X    -rm libx_list.a
  423. X    -rm testlist.o
  424. X    -rm testlist
  425. X    -rm testhash.o
  426. X    -rm testhash
  427. X
  428. SHAR_EOF
  429. chmod 0440 src/Makefile || echo "restore of src/Makefile fails"
  430. if [ $TOUCH = can ]
  431. then
  432.     touch -am 0419235091 src/Makefile
  433. fi
  434. # ============= text/install ==============
  435. if test ! -d 'text' ; then
  436.     echo "x - creating directory text"
  437.     mkdir 'text'
  438. fi
  439. echo "x - extracting text/install (Text)"
  440. sed 's/^X//' << 'SHAR_EOF' > text/install &&
  441. X
  442. X    1) Go into the source directory.
  443. X
  444. X    2) type "make"
  445. X
  446. X    3) type "testlist"
  447. X
  448. X    4) type "testhash"
  449. X
  450. X    have fun!
  451. X
  452. SHAR_EOF
  453. chmod 0640 text/install || echo "restore of text/install fails"
  454. if [ $TOUCH = can ]
  455. then
  456.     touch -am 0419234991 text/install
  457. fi
  458. # ============= text/lists ==============
  459. echo "x - extracting text/lists (Text)"
  460. sed 's/^X//' << 'SHAR_EOF' > text/lists &&
  461. X                   
  462. X                  *********
  463. X                  * LISTS *
  464. X                  *********
  465. X
  466. X
  467. X         Let's get this legal stuff out of the way !
  468. X                   
  469. X
  470. XThis text in this file is copyright (c) 1991 by Kenneth Jamieson.
  471. X
  472. XThe author may be reached at the US MAIL address listed below, or
  473. Xby sending unix mail to ...
  474. X
  475. X           tron1@tronsbox.xei.com            or
  476. X       ...!uunet!tronsbox.xei.com!tron1  or
  477. X       yelling "Hey Ken!" if you happen to be close enough.
  478. X
  479. X
  480. X    Ok, now, about lists.... This will be a simple text to
  481. Xintroduce some of the basic list theory so that you can use the
  482. Xroutines in this library.
  483. X
  484. X    I am using a "doubly linked list", this is a list where
  485. Xevery piece of data knows where to find every other one... consider the 
  486. Xchart below. (I will number the "nodes" for clarity):
  487. X
  488. X    1-2-3-4-5
  489. X
  490. X    That is a 5 node list, where the node on the left is the parent
  491. Xor previous node, and the one on the right is the child or next node.
  492. X
  493. X    Now, lets store some data here, and introduce a concept or two.
  494. XI am going to stand the list on it's side this time.
  495. X
  496. X    *1    (red)
  497. X     |
  498. X     2    (green)
  499. X     |
  500. X     3    (blue)
  501. X     |
  502. X     4    (yellow)
  503. X     |
  504. X     5    (orange)
  505. X
  506. X    See the "*" ? I am going to use that to show the "current" node in
  507. Xthe list. Now, we have put colors "in" the nodes. We can move that
  508. X"*" up or down the list, to the next and previous nodes.
  509. X
  510. X    We can replace the data that is in the current node, and we can
  511. Xadd nodes to the end. Also, we can delete a node completely. 
  512. X
  513. X    Any list that you can move "previous: and "next" in is 
  514. Xdoubly-linked. A singly-linked list only lest you move "next". 
  515. X
  516. X
  517. X
  518. XWHY USE LISTS AS A PROGRAMMER ?
  519. X
  520. X
  521. X    With respect to "C" programming, why do we use lists at all ?
  522. X
  523. X    Let's say you are going to get a list of names from a user,
  524. Xand you don't know how many names you will get. You have 2 choices if you
  525. Xhave to keep those names in memory...
  526. X
  527. X    1) Allocate more space than you will "EVER" need.
  528. X
  529. X       Advantage - You don't have to worry about lists! It is just
  530. X               an array for you!
  531. X
  532. X       Disadvantage - You often allocate MUCH more space than you
  533. X            really use. Thus, you waste memory. Also, it is
  534. X             generally good to avoid putting limits into a program
  535. X            like "You can only enter 1000 names". A lack of
  536. X            limits makes your code efficient (space wise) and
  537. X            more flexible.
  538. X
  539. X    2) Use lists!
  540. X
  541. X       Advantage - You never waste space (a bit on the list 
  542. X               overhead .. but not that much usually). You can
  543. X               adapt to almost anything.
  544. X
  545. X       Disadvantage - Lists are a pain! De-bugging list code
  546. X              can drive you up a wall! 
  547. X
  548. X
  549. X    Since I obviously feel you will want to use lists, let's talk
  550. X    more about them....
  551. X
  552. X
  553. X
  554. X
  555. XHOW TO IMPLEMENT A DOUBLY-LINKED LIST FOR C and C++:
  556. X
  557. X    I am not going to go into great detail of all the low level code here,
  558. Xbecause you can just go look at the source in x_list.c to see most of that.
  559. XHere, we will take a look at the design considerations we should have for C
  560. Xand C++.
  561. X
  562. X    The natural thing to build a linked list of is pointers. This
  563. Xallows us a lot of flexibility.  Consider the example below....
  564. X
  565. Xstruct node{
  566. X    struct node * prev;
  567. X    struct node * next;
  568. X    void * data;
  569. X}
  570. X
  571. X    This structure will for the basis for our list. Because we want
  572. Xa doubly-linked list, we have two list pointers here, on that points to the
  573. Xaddress of the next node, and one to the previous node. The void * that
  574. Xis there is the data we are going to store in the list. It is nice to
  575. Xstore a pointer as the data of the list so that we do not
  576. Xlimit the things we can use the list for.
  577. X
  578. X    We can actually make a list out of these things. They are
  579. Xcomplete to form a simple list. Consider the program below:
  580. X
  581. Xmain(){
  582. X    struct node node1;
  583. X    struct node node2;
  584. X
  585. X    node1.prev = NULL;
  586. X    node1.next = &node2;
  587. X    node2.prev = &node1;
  588. X    node2.next = NULL;
  589. X}
  590. X
  591. X
  592. X    That programs forms a list. Node1 knows where to find node2 and
  593. Xthe opposite is true. There IS no previous node for node1 so that is
  594. XNULL. In the same manner, there is no next node from node2 so that is also
  595. Xset to NULL. 
  596. X
  597. X    That's it ! Thats the magic of lists. If I have a pointer to
  598. Xnode2, I can find node one at &node2->prev and so on.
  599. X
  600. X    Now, that is not EVERYTHING about it (it never is .. :-) ).
  601. XThe whole point of the list is that we want to make it bigger as we
  602. Xgo along, not declare it at the start of the program like we did above.
  603. X
  604. X    So let's look at a minor variation:
  605. X    (I will show only the code here, assume that the structure
  606. X    "node" is defined for this program in a header file or something)
  607. X    
  608. X
  609. X1   #include <malloc.h>        /* Get the memory stuff */
  610. X2   main(){
  611. X3    struct node * node1;
  612. X4
  613. X5    node1 = (struct node *)malloc( sizeof(struct node) );
  614. X6    node1->prev = NULL;
  615. X7
  616. X8    node1->next = (struct node *)malloc( sizeof( struct node ) );
  617. X9    node1->next->next = NULL;
  618. X10    node1->next->prev = node1;
  619. X11  }
  620. X
  621. X    WHAT HAPPENED!! you say ?
  622. X
  623. X    Trust me, it isn't that bad. Let's take it step by step.
  624. X
  625. X    First, obviously it would not compile with those line numbers.
  626. XOk.. second, you will see that we only declared one pointer. The
  627. Xpointer for the first node. That is the ONLY pointer we cannot infer
  628. Xfrom the list. YOU WILL ALWAYS HAVE AT LEAST ONE POINTER declared as
  629. Xa "base" for the list.
  630. X
  631. X    Step by step then....
  632. X
  633. XLINE 1 : We included the file for the malloc() call because we 
  634. X     use that call this time.
  635. X
  636. XLINE 2 : Start the program :-).
  637. X
  638. XLINE 3 : Declare a place to store the pointer for node1.
  639. X
  640. XLINE 5 : We allocate space for our first node, and store the 
  641. X     pointer for it in the variable node1.
  642. X
  643. XLINE 6 : There will never be a node BEFORE node1. So the
  644. X     address of the previous node in NULL. It is
  645. X     important that you PUT a NULL there yourself
  646. X     because you are not sure of it's value.
  647. X
  648. X     The DEFINITION of the "head" or "top" of
  649. X     a list is "the node with no previous node". There
  650. X     will only ever be one node like this in a list.
  651. X
  652. XLINE 8 : We are going to save a step here. We are going to
  653. X     allocate space for another node, and store it's 
  654. X     pointer right into the space for it in node1. In this
  655. X     manner, we do NOT need to declare another variable.
  656. X
  657. X     While this looks confusing, it really isn't. The only
  658. X     place that the address of node2 is relevant from
  659. X     at this time is node1.
  660. X
  661. XLINE 9 : We are at the end of the list (we only have 
  662. X     two nodes at this time) .. so there is no
  663. X     "next" node. Since we don't have a
  664. X     pointer for node2, we need to say "node1->next" every
  665. X     time we want to talk about node2, but there are ways to
  666. X     solve this problem in later examples.
  667. X
  668. XLINE 10: Now, to complete the list, we need to tell
  669. X     node2 about node1's address.
  670. X
  671. X     So, we set the pervious node pointer in node2
  672. X     to be node1's pointer.
  673. X
  674. X
  675. X    The weave is now complete and we have a linked
  676. Xlist. You can see though, that we need some better way to 
  677. Xmove from node to node. Because it would be a real pain
  678. Xabout 5 nodes in ... could you imagine : 
  679. X
  680. X    node1->next->next->next->next
  681. X    
  682. X    It would get silly real fast!
  683. X    
  684. X    So, what I have done in this library is just 
  685. Xkeep another structure for each list. It has a pointer to the
  686. Xfirst node in that list, a pointer to the last node, and a
  687. Xpointer to the current node.
  688. X
  689. X    The current node makes the list act a LOT like a
  690. Xloose leaf notebook. If you think of an empty list, you have
  691. Xa notebook with nothing in it at all. In this analogy, you 
  692. Xmust add a piece of paper before you can write anything into the
  693. Xlist. You do that as I showed you above, by adding a new node.
  694. X
  695. X    The current node is just a marker, an indication of
  696. Xwhere the notebook is open to right now. If we continue or
  697. Xexample above, we have the pointer to the first node in the
  698. Xlist stored as "node1" ... we will want to deal with node2 to
  699. Xfor a while, so we can just say ...
  700. X
  701. X    current_node = node1->next;
  702. X
  703. X    Get it ?? This way, we don't have to say "node1->next"
  704. Xall the time. When the time comes to deal with node1 again, we can
  705. Xjust say ...
  706. X
  707. X    current_node = node1;
  708. X    
  709. X    And there we are.
  710. X
  711. X    Now, in a list with many nodes, it is even more important
  712. Xbecause to get to node 5 it is tough to say ..
  713. X
  714. X    current-node = node1->next->next->next->next;
  715. X
  716. X    But it is EASY to say ....
  717. X
  718. X    current_node = node1;
  719. X    for( x = 0; x < 4; x++ ){
  720. X        current_node = current_node->next;
  721. X    }
  722. X
  723. X    THAT code can take us to the 5 node in the list as well, 
  724. Xbecause we can just keep advancing. If we are at node 5, and want 
  725. Xto get to node 4, we can just say ..
  726. X
  727. X    current_node = current_node->prev;
  728. X
  729. X    So, you see that if you have the concept of a current node,
  730. Xand the pointer to the first node in the list, you are capable
  731. Xof going forward and backwards in the list.
  732. X
  733. X    Since the last node of a list is the only node with a 
  734. Xnext pointer of NULL, we can find it very easy now.
  735. X
  736. X    if( current_node->next |= NULL ){
  737. X        current_node = current_node->next;
  738. X    }
  739. X
  740. X    That will leave current_node set to the last node in the
  741. Xlist without any trouble at all, no matter where you happen to
  742. Xbe.
  743. X
  744. X    The last thing I will show you about is how to delete a
  745. Xnode. Suppose we want to remove the current_node from the list
  746. Xcompletely. What do we have to do ???? Well, the parent of the
  747. Xcurrent node has to be pointed to the child of the current
  748. Xnode so that the chain is not broken..
  749. X
  750. X    current_node->prev->next = current_node->next;
  751. X
  752. X    And the child of the current node has to be told of
  753. Xit's new parent (since it isn't us any more!)..
  754. X
  755. X    current_node->next->prev = current_node->prev;
  756. X
  757. X    Now, the chain is intact, and the ONLY place there is a
  758. Xpointer to the current node is in the current_node variable! We
  759. Xwant to free that memory, so we should say ...
  760. X
  761. X    free(current_node);
  762. X    current_node = node1;
  763. X
  764. X    That de-allocates that memory, and leaves us with a 
  765. Xvalid current node pointer.
  766. X
  767. X    Now you should be able to look at my code and have
  768. Xsome idea what it is doing. Have fun!
  769. X
  770. SHAR_EOF
  771. chmod 0640 text/lists || echo "restore of text/lists fails"
  772. if [ $TOUCH = can ]
  773. then
  774.     touch -am 0419234791 text/lists
  775. fi
  776. # ============= text/readme ==============
  777. echo "x - extracting text/readme (Text)"
  778. sed 's/^X//' << 'SHAR_EOF' > text/readme &&
  779. X
  780. X            :*:*:*:*: IMPORTANT :*:*:*:*:
  781. X
  782. X          READ THE FILE "distrib" BEFORE TO BEGIN TO
  783. X              USE OR COMPILE THIS CODE!
  784. X
  785. X
  786. X    Hi ! X_List stands for "Xanadu List", it is a project that I have been
  787. Xplaying with on and off for over a year. While there is not much code,
  788. Xit has been a long road to understanding this stuff enough that I was
  789. Xhappy with the results.
  790. X
  791. X    I have always, as programmer, had a great fear of pointers. Well,
  792. Xmaybe fear is to strong a word by I was certainly not fond of the little
  793. Xdevils.  And NOTHING will bring you face to face with pointers faster than
  794. Xa good doubly linked list.
  795. X
  796. X    I sat there. Oh, I could use some canned list routines, but
  797. XI wanted to KNOW what was happening in there. I wanted to be able to
  798. Xlook at the source and say "AHA!". Well, I couldn't. The routines I could
  799. Xget the source to were way over my head, and not commented well.
  800. X
  801. X    So what I have done is look at what MY needs for list processing
  802. Xwere, under both C and C++, and write the routines to do them. Along the way,
  803. XI have tried to comment the code pretty well, and in the file "lists" you will
  804. Xfind a mini-tutorial about what a list is and why we use them. The code in
  805. Xhere is probably not as commented as you would like (or me!) but it is better
  806. Xthan most, and combined with "lists" you should be fine.
  807. X
  808. X    This code is shareware, and so you should read the "distrib" file
  809. Xbefore you use this code. It is pretty lenient I feel, and hopefully you
  810. Xwon't find it restrictive. In addition, hopefully I can make some money for
  811. Xa new hard drive ;-). Also, please upload this archive unaltered to any
  812. XBBS or network to would like. Shareware lives by being spread!
  813. X
  814. X    This code was developed with Turbo C++ 1.0 under the VP/ix emulator
  815. Xof Interactive Systems Unix SysV3.2.
  816. X
  817. X    Every attempt has been made to make this code run under the
  818. Xfollowing environments:
  819. X
  820. X    1: Unix. Any ANSI C or C++ 2.0 variant. SYSV, BSD and SUNOS.
  821. X        (can anyone confirm g++?)
  822. X
  823. X    2: Ms-Dos. Turbo C++ and Turbo C.
  824. X        (can anyone confirm MSC?)
  825. X
  826. X    3: Amiga.  Lattice C++ 1.0 and SAS/C 5.10
  827. X        Note: I used SAS/C 5.10 as the C back end to the
  828. X              Lattice C++ compiler.
  829. X        
  830. X
  831. X    I personally run it under all three, in both C and C++ programs so
  832. Xyou should be ok.
  833. X
  834. X    Have fun! Read "distrib" and "install" next, "lists" for a 
  835. Xoverview of linked lists, and "docs" for the documentation for the routines 
  836. Xhere and happy listing!
  837. X
  838. X
  839. XNOTE FOR UNIX USERS:
  840. X
  841. X    Forgive the fact that these text files have dos format CR-LF line
  842. Xterminators in them, there was no reason to have two versions and stripping
  843. Xthem is easy enough.
  844. X
  845. X    - Kenneth Jamieson
  846. X
  847. X
  848. X-----------------------------------------------------
  849. X* UNIX is a trademark of AT&T
  850. X* Amiga is a trademark of Commodore Business Machines
  851. X* MS-DOS is a trademark of Microsoft Inc 
  852. X
  853. X
  854. SHAR_EOF
  855. chmod 0640 text/readme || echo "restore of text/readme fails"
  856. if [ $TOUCH = can ]
  857. then
  858.     touch -am 0417205791 text/readme
  859. fi
  860. # ============= text/WHATIS ==============
  861. echo "x - extracting text/WHATIS (Text)"
  862. sed 's/^X//' << 'SHAR_EOF' > text/WHATIS &&
  863. X            *********************
  864. X            *WHAT IS X_HASH ????*
  865. X            *********************
  866. X
  867. X    X_HASH is a collection of two libraries, X_List and X_Hash. 
  868. X
  869. X    You will need a ANSI C compiler or a C++ compiler.
  870. X
  871. X
  872. X    1) X_List is a stand-alone library for C and C++ that will
  873. X       allow for the simple, efficient management of doubly linked
  874. X       lists of pointers in a logical form. This is one of the most
  875. X       often used programming constructs.
  876. X
  877. X    2) X_Hash allows for a list of pointers to be stored by a 
  878. X       key value. A function is provided to turn a text string into
  879. X       this key value. Thus, a pointer may be stored much like in a
  880. X       database.
  881. X
  882. X       X_Hash needs X_List available to operate.
  883. X
  884. X    3) DOCUMENTATION is on the way, for now, the sample "test" programs
  885. X       should get you started, mail me any questions!
  886. X
  887. X       (HINT) FULL DOCS available to registered users!
  888. X
  889. X========[ Xanadu Enterprises Inc. Amiga & Unix Software Development]=======
  890. X= "I know how you feel, you don't know if you want to hit me or kiss me - =
  891. X=  --- I get a lot of that."  Madonna as Breathless Mahoney (Dick Tracy)  =
  892. X=========== Ken Jamieson: uunet!tronsbox.xei.com!tron1  ===================
  893. X=     NONE of the opinions represented here are endorsed by anybody.      =
  894. X=== The Romantic Encounters BBS 201-759-8450(PEP) / 201-759-8568(2400) ==== 
  895. X
  896. X
  897. X
  898. X
  899. X
  900. X
  901. SHAR_EOF
  902. chmod 0640 text/WHATIS || echo "restore of text/WHATIS fails"
  903. if [ $TOUCH = can ]
  904. then
  905.     touch -am 0419234791 text/WHATIS
  906. fi
  907. rm -f s3_seq_.tmp
  908. echo "You have unpacked the last part"
  909. exit 0
  910. -- 
  911. ========[ Xanadu Enterprises Inc. Amiga & Unix Software Development]=======
  912. = "I know how you feel, you don't know if you want to hit me or kiss me - =
  913. =  --- I get a lot of that."  Madonna as Breathless Mahoney (Dick Tracy)  =
  914. =========== Ken Jamieson: uunet!tronsbox.xei.com!tron1  ===================
  915. =     NONE of the opinions represented here are endorsed by anybody.      =
  916. === The Romantic Encounters BBS 201-759-8450(PEP) / 201-759-8568(2400) ==== 
  917.