home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume38 / linkedlist / part01 next >
Text File  |  1993-08-12  |  64KB  |  2,531 lines

  1. Newsgroups: comp.sources.misc
  2. From: anita@bouw.tno.nl (Anita Eijs)
  3. Subject: v38i117:  linkedlist - Generic Linked List Package, Part01/02
  4. Message-ID: <csm-v38i117=linkedlist.091645@sparky.Sterling.COM>
  5. X-Md4-Signature: efd03753dbd25f67c85d0dd22c51fcc8
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Thu, 12 Aug 1993 14:17:28 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: anita@bouw.tno.nl (Anita Eijs)
  12. Posting-number: Volume 38, Issue 117
  13. Archive-name: linkedlist/part01
  14. Environment: UNIX, MS-DOS, VAX/VMS, Macintosh, Amiga
  15. Supersedes: linkedlist: Volume 37, Issue 36-37
  16.  
  17. LinkedList Version: 0.10, August 1992
  18.  
  19. The Generic Linked List Package is a package to define, create, update,
  20. query and delete one or more (nodes of) linked lists, to sort linked
  21. lists, and so on. The user doesn't have to take care of allocating a
  22. number of bytes for a node, inserting on the right place, deleting and
  23. freeing a node and so on.
  24.  
  25. Different kind of linked lists can be defined. In a singly linked list
  26. each node points to the next node, in a doubly linked list each node
  27. points also to the previous node. A chain is a list in which the last
  28. node has a NULL pointer and in a circular linked list the last node
  29. points back to the first node.
  30.  
  31. The package consists of a set of C-functions :
  32.     lDef        define linked list
  33.     lInfo        get information about linked list
  34.     lSize        get number of nodes of linked list
  35.     lSort        sort linked list
  36.     lDel        delete linked list
  37.     lDelAll        delete all linked lists
  38.     lDump        dump a linked list to a file
  39.     lUndump        undump a linked list from a file
  40.     lInsNode    insert node
  41.     lInfoNode    get information about node
  42.     lGetNode    get node
  43.     lFndNode    find node
  44.     lFndFlagNode    get node by flag
  45.     lUpdNode    update current node
  46.     lDelNode    delete node
  47.     lInfoIndxNode    get information about node by index
  48.     lGetIndxNode    get node by index
  49.     lUpdIndxNode    update node by index
  50.     lDelIndxNode    delete node by index
  51.  
  52. The Generic Linked List Package is ported to UNIX, MS-DOS, VAX/VMS and
  53. Macintosh.
  54.  
  55. Please look at the README file and the manual pages for more detailed
  56. information !
  57.  
  58.         Anita
  59.  
  60.     +--------------------------------------------------------+
  61.     | TNO - BOUW, PO-box 49, 2600 AA  Delft, The Netherlands |
  62.     | FAX : +31 15 122182         E-MAIL : anita@bouw.tno.nl |
  63.     +--------------------------------------------------------+
  64.  
  65. ------- cut here ---------------------------------------------------------------
  66. #! /bin/sh
  67. # This is a shell archive.  Remove anything before this line, then feed it
  68. # into a shell via "sh file" or similar.  To overwrite existing files,
  69. # type "sh file -c".
  70. # Contents:  README Doc Doc/lGetNode.3 example.c list.c sorted.c
  71. # Wrapped by kent@sparky on Thu Aug 12 09:13:07 1993
  72. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  73. echo If this archive is complete, you will see the following message:
  74. echo '          "shar: End of archive 1 (of 2)."'
  75. if test -f 'README' -a "${1}" != "-c" ; then 
  76.   echo shar: Will not clobber existing file \"'README'\"
  77. else
  78.   echo shar: Extracting \"'README'\" \(2301 characters\)
  79.   sed "s/^X//" >'README' <<'END_OF_FILE'
  80. X                Generic Linked List
  81. X                ===================
  82. X
  83. X
  84. XThe distribution of the Generic Linked List package (Version 0.10, August 1993)
  85. Xincludes the following files:
  86. X
  87. X    Doc/Intro.3        - [nt]roff manual pages
  88. X    Doc/lDef.3
  89. X    Doc/lDel.3
  90. X    Doc/lDelAll.3
  91. X    Doc/lDelIndxNode.3
  92. X    Doc/lDelNode.3
  93. X    Doc/lDump.3
  94. X    Doc/lFndFlagNode.3
  95. X    Doc/lFndNode.3
  96. X    Doc/lGetNode.3
  97. X    Doc/lGetIndxNode.3
  98. X    Doc/lInfo.3
  99. X    Doc/lInfoIndxNode.3
  100. X    Doc/lInfoNode.3
  101. X    Doc/lInsNode.3
  102. X    Doc/lSize.3
  103. X    Doc/lSort.3
  104. X    Doc/lUndump.3
  105. X    Doc/lUpdIndxNode.3
  106. X    Doc/lUpdNode.3
  107. X    Makefile        - Berkeley or System V Makefile
  108. X    Makefile.BCC        - Borland C++ v3.1 Makefile
  109. X    ReadMe.BCC        - some additional info about Borland port
  110. X    Makefile.Amiga        - Amiga SAS C 6.0 Makefile
  111. X    ReadMe.Amiga        - some additional info about Amiga port
  112. X    README            - this file !
  113. X    CHANGES            - list of changes
  114. X    Tools_makerule        - make rules for Makefile
  115. X    example.c        - example of use of Generic Linked List routines
  116. X    sorted.c        - example of several sorting solutions
  117. X    sorttest.c        - test of sorting theories in lSort
  118. X    list.c            - Generic Linked List sources
  119. X    list.h            - Generic Linked List defines and prototypes
  120. X
  121. X
  122. XThe installation of the Generic Linked List library is pretty simple :
  123. X
  124. X1)    Check the environment settings (TOOLS_HOME, DIR, LIB and RULE) in
  125. X    the Makefile. (Skip symbol define ERROR_FILE from CFLAGS.)
  126. X
  127. X2)    Check the environment settings (RANLIB) in the Tools_makerule.
  128. X
  129. X3)    Be sure that the LIB-directory is created.
  130. X
  131. X4)    Enter 'make newlib' at the UNIX prompt.
  132. X
  133. X5)    Enter 'make test' or 'make example' to create the executable of
  134. X    the program 'example' at the UNIX prompt.
  135. X
  136. X
  137. XThe Generic Linked List package is also ported to MSDOS, VAX-VMS, Macintosh
  138. Xand Amiga. On those machines the library was not created, but the source-
  139. Xfiles list.c and list.h were treated the same as all the other source-files
  140. X(*.[ch]) of the program.
  141. X
  142. X
  143. XThe Generic Linked List is in the public domain. It is available at our FTP
  144. Xarchive (ftp.tno.nl or hermes.bouw.tno.nl), just retrieve the files :
  145. X    /pub/TNO/BOUW/Bouwinf/linkedlist_0.10.README
  146. X    /pub/TNO/BOUW/Bouwinf/linkedlist_0.10.shar
  147. X
  148. X
  149. XIf you have any comments, suggestions, or find any bugs, or make any changes
  150. Xyou'd like to share, please let me know.
  151. X
  152. X
  153. XAnita Eijs    (anita@bouw.tno.nl)
  154. XTNO - BOUW - BouwInformatica
  155. XP.O. Box 49
  156. X2600 AA Delft
  157. XThe Netherlands
  158. XFAX : +31 15 122182
  159. END_OF_FILE
  160.   if test 2301 -ne `wc -c <'README'`; then
  161.     echo shar: \"'README'\" unpacked with wrong size!
  162.   fi
  163.   # end of 'README'
  164. fi
  165. if test ! -d 'Doc' ; then
  166.     echo shar: Creating directory \"'Doc'\"
  167.     mkdir 'Doc'
  168. fi
  169. if test -f 'Doc/lGetNode.3' -a "${1}" != "-c" ; then 
  170.   echo shar: Will not clobber existing file \"'Doc/lGetNode.3'\"
  171. else
  172.   echo shar: Extracting \"'Doc/lGetNode.3'\" \(1402 characters\)
  173.   sed "s/^X//" >'Doc/lGetNode.3' <<'END_OF_FILE'
  174. X'.so tmac.clman
  175. X.TH "lGetNode"
  176. X.IX lGetNode
  177. X.SH NAME
  178. XlGetNode - Get node.
  179. X.SH SYNOPSIS
  180. Xint
  181. X.BR "lGetNode" "(id, which, data, size)"
  182. X.br
  183. X.RT
  184. X.RP
  185. XIn    int    id    identifier of linked list
  186. X.RP
  187. XIn    int    which    which node must be retrieved
  188. X.RP
  189. XOut    Byte    *data    data of node
  190. X.RP
  191. XIn    int    size    size of data
  192. X.DT
  193. X.SH DESCRIPTION
  194. X\fBlGetNode\fP gets the data of a node of a linked list. Which node must
  195. Xbe retrieved can be specified by \fIwhich\fP. The first node, the current
  196. Xnode, the node before or after the current node and the node at the end
  197. Xof the list can be retrieved.
  198. X.br
  199. XBackward retrieving is only possible for doubly linked list. A previous
  200. Xnode can't be retrieved for singly linked lists.
  201. X.br
  202. XWhen the retrieved node is the first or the last node, the return code
  203. Xwill have the value lFIRST or lLAST. For the other nodes the routine
  204. Xreturns lSUCCESS.
  205. XWhen the linked list contains only one node, the return code will have
  206. Xthe value lFIRST, when retrieving backward, and the value lLAST, when
  207. Xretrieving forward.
  208. X.SH PARAMETER DEFINITIONS
  209. X.if t .ta 0.2i 1.5i
  210. X\fIwhich\fP :
  211. X.nf
  212. X    lFIRST    first node
  213. X    lPREVIOUS    previous node
  214. X    lCURRENT    current node
  215. X    lNEXT    next node
  216. X    lLAST    last node
  217. X.fi
  218. X.SH RETURN CODES
  219. X.nf
  220. XReturn on success :
  221. X    lSUCCESS, lFIRST, lLAST
  222. XReturn on error :
  223. X.fi
  224. X.in +0.2i
  225. XlUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lSIZE_NE, lNOT_DOUBLY
  226. X.in -0.2i
  227. X.SH AUTHOR
  228. XAnita Eijs (TNO - Bouw - BouwInformatica)
  229. END_OF_FILE
  230.   if test 1402 -ne `wc -c <'Doc/lGetNode.3'`; then
  231.     echo shar: \"'Doc/lGetNode.3'\" unpacked with wrong size!
  232.   fi
  233.   # end of 'Doc/lGetNode.3'
  234. fi
  235. if test -f 'example.c' -a "${1}" != "-c" ; then 
  236.   echo shar: Will not clobber existing file \"'example.c'\"
  237. else
  238.   echo shar: Extracting \"'example.c'\" \(3536 characters\)
  239.   sed "s/^X//" >'example.c' <<'END_OF_FILE'
  240. X#ifdef    AMIGA
  241. X#include        <string.h>
  242. X#endif
  243. X
  244. X#include        <stdio.h>
  245. X#include        "list.h"
  246. X
  247. Xtypedef struct rapport {
  248. X    char        title[30];
  249. X    char        author[15];
  250. X    int        date;
  251. X} Rapport;
  252. Xint    rapSz = sizeof(Rapport);
  253. X
  254. X#ifdef ANSI
  255. Xstatic void    insRap(int id, int where, int flag, char *title, char *author,
  256. X                int date);
  257. Xstatic void    prRapAll(int id);
  258. Xstatic void    prRap(int code, Rapport *rpprt);
  259. Xstatic int    search(int *date, Rapport *rpprt);
  260. Xstatic int    compare(Rapport *data1, Rapport *data2);
  261. X#else
  262. Xstatic void    insRap(), prRapAll(), prRap();
  263. Xstatic int    search(), compare();
  264. X#endif
  265. X
  266. Xint
  267. Xmain()
  268. X{
  269. X    int            id, code, search_date;
  270. X    Rapport        rap;
  271. X
  272. X    id = lDef(lSINGLY, lCHAIN);
  273. X
  274. X    insRap(id, lFIRST, 1, "Book 1", "People", 890129);
  275. X    insRap(id, lFIRST, 2, "Book 2", "More People", 890130);
  276. X    insRap(id, lLAST, 1, "Book 3", "Lots of People", 890131);
  277. X
  278. X    fprintf(stdout, "lGetNode\n");
  279. X    prRapAll(id);
  280. X
  281. X/*
  282. X** The following routine calls will generate the file '=listError='.
  283. X*/
  284. X    fprintf(stdout, "lGetIndxNode\n");
  285. X    code = lGetIndxNode(id, 4, &rap, rapSz);
  286. X    prRap(code, &rap);
  287. X    code = lGetIndxNode(id, 2, &rap, rapSz);
  288. X    prRap(code, &rap);
  289. X    code = lGetIndxNode(id, -1, &rap, rapSz);
  290. X    prRap(code, &rap);
  291. X    code = lGetIndxNode(id, 3, &rap, rapSz);
  292. X    prRap(code, &rap);
  293. X
  294. X    fprintf(stdout, "lFndNode\n");
  295. X    search_date = 890129;
  296. X    code = lFndNode(id, lFIRST, search, &search_date, &rap, rapSz);
  297. X    prRap(code, &rap);
  298. X    code = lFndNode(id, lNEXT, search, &search_date, &rap, rapSz);
  299. X    prRap(code, &rap);
  300. X    code = lFndNode(id, lNEXT, search, &search_date, &rap, rapSz);
  301. X    prRap(code, &rap);
  302. X
  303. X/*
  304. X** The following routine call will generate the binary file 'dump'.
  305. X*/
  306. X    code = lDump(id, "dump");
  307. X    fprintf(stdout, "lDump : %d\n", code);
  308. X
  309. X    lDel(id);
  310. X
  311. X    id = lUndump("dump");
  312. X    fprintf(stdout, "lUndump : %d\n", id);
  313. X
  314. X    insRap(id, lFIRST, 4, "Book 4", "The Author", 891127);
  315. X
  316. X    prRapAll(id);
  317. X
  318. X    fprintf(stdout, "lFndFlagNode\n");
  319. X    code = lFndFlagNode(id, lFIRST, 1, &rap, rapSz);
  320. X    prRap(code, &rap);
  321. X    code = lFndFlagNode(id, lNEXT, 1, &rap, rapSz);
  322. X    prRap(code, &rap);
  323. X    code = lFndFlagNode(id, lFIRST, 2, &rap, rapSz);
  324. X    prRap(code, &rap);
  325. X    code = lFndFlagNode(id, lFIRST, 7, &rap, rapSz);
  326. X    prRap(code, &rap);
  327. X    
  328. X    fprintf(stdout, "Untouched list\n");
  329. X    prRapAll(id);
  330. X
  331. X    fprintf(stdout, "lSort\n");
  332. X    lSort(id, lDESCENDING, lBUBBLE, compare);
  333. X    prRapAll(id);
  334. X
  335. X    fprintf(stdout, "lSort\n");
  336. X    lSort(id, lASCENDING, lHEAP, compare);
  337. X    prRapAll(id);
  338. X
  339. X    lDelAll();
  340. X}
  341. X
  342. Xstatic void
  343. XinsRap(id, where, flag, title, author, date)
  344. Xint        id, where, flag, date;
  345. Xchar        *title, *author;
  346. X{
  347. X    int        code;
  348. X    Rapport    rap;
  349. X
  350. X    strcpy(rap.title, title);
  351. X    strcpy(rap.author, author);
  352. X    rap.date = date;
  353. X    code = lInsNode(id, where, &rap, rapSz, flag);
  354. X}
  355. X
  356. Xstatic void
  357. XprRapAll(id)
  358. Xint    id;
  359. X{
  360. X    int        code;
  361. X    Rapport    rap;
  362. X
  363. X    code = lGetNode(id, lFIRST, &rap, rapSz);
  364. X    prRap(code, &rap);
  365. X    while (code == lFIRST || code == lSUCCESS || code == lLAST) {
  366. X        code = lGetNode(id, lNEXT, &rap, rapSz);
  367. X        prRap(code, &rap);
  368. X    }
  369. X}
  370. X
  371. Xstatic void
  372. XprRap(code, rpprt)
  373. Xint            code;
  374. XRapport        *rpprt;
  375. X{
  376. X    if (code >= 0)
  377. X        fprintf(stdout, "Rapport : '%s' '%s' '%d'\n", rpprt->title,
  378. X            rpprt->author, rpprt->date);
  379. X    else
  380. X        fprintf(stdout, "Return code = %d\n", code);
  381. X}
  382. X
  383. Xstatic int
  384. Xsearch(date, rpprt)
  385. Xint            *date;
  386. XRapport        *rpprt;
  387. X{
  388. X    if (rpprt->date > *date)
  389. X        return(lFOUND);
  390. X    else
  391. X        return(lNOT_FOUND);
  392. X}
  393. X
  394. Xstatic int 
  395. Xcompare(data1, data2)
  396. XRapport *data1, *data2;
  397. X{
  398. X    int    k = strcmp(data1->author, data2->author);
  399. X
  400. X    if (k == 0)
  401. X        return(lSAME);    /* key1 == key2 */
  402. X    else if (k > 0)
  403. X        return(l2LT1);    /* key1 > key2 */
  404. X    else if (k < 0)
  405. X        return(l1LT2);    /* key1 < key2 */
  406. X}
  407. END_OF_FILE
  408.   if test 3536 -ne `wc -c <'example.c'`; then
  409.     echo shar: \"'example.c'\" unpacked with wrong size!
  410.   fi
  411.   # end of 'example.c'
  412. fi
  413. if test -f 'list.c' -a "${1}" != "-c" ; then 
  414.   echo shar: Will not clobber existing file \"'list.c'\"
  415. else
  416.   echo shar: Extracting \"'list.c'\" \(40617 characters\)
  417.   sed "s/^X//" >'list.c' <<'END_OF_FILE'
  418. X/*
  419. X**    Anita Eijs    TNO-BOUW, BouwInformatica    May 1989
  420. X**
  421. X**    Generic Linked List Package
  422. X**
  423. X**    Updates:
  424. X**    900402    New routine:
  425. X**            lIndxNode    Get node by index.
  426. X**
  427. X**    900925    New routine:
  428. X**            lError    print error message in lERROR_FILE
  429. X**
  430. X**    901129    New routines:
  431. X**            lDump    Dump a linked list to a file.
  432. X**            lUndump    Undump a linked list from a file.
  433. X**
  434. X**    910301    'Mac'ed by Vinnie:
  435. X**            ListPtr = ListyPtr
  436. X**            Byte = byte
  437. X**            includes
  438. X**            typecasts
  439. X**
  440. X**    910316    New routine:
  441. X**            lFlagNode    Get node by flag.
  442. X**
  443. X**    ***** Version 0.7, March 1992 *****
  444. X**
  445. X**    930401    Several updates by Anita and Shane.
  446. X**        Some functions renamed:
  447. X**            lIndxNode --> lGetIndxNode
  448. X**            lFlagNode --> lFndFlagNode
  449. X**        New routines:
  450. X**            lSort        Sort a linked list.
  451. X**            lInfoIndxNode    Get information about node by index.
  452. X**            lDelIndxNode    Delete node by index.
  453. X**            lUpdIndxNode    Update node by index.
  454. X**        Parameter where added to lFndFlagNode to find several nodes
  455. X**        matching the requested flag.
  456. X**        Defines are made more specific; FIRST is renamed in lFIRST, etc.
  457. X**
  458. X**    ***** Version 0.8, May 1993 *****
  459. X**
  460. X**    ***** Version 0.9, June 1993 *****
  461. X**
  462. X**    930801    New routine:
  463. X**            lSize    Get number of nodes in linked list.
  464. X**
  465. X**    ***** Version 0.10, August 1993 *****
  466. X**
  467. X*/
  468. X
  469. X#ifdef __MSDOS__
  470. X#define    MSDOS
  471. X#define    ANSI
  472. X#endif
  473. X
  474. X#ifdef UNIX
  475. X#include    <malloc.h>
  476. X#endif
  477. X
  478. X#ifdef MSDOS
  479. X#include    <malloc.h>
  480. X#include    <io.h>        /* open, creat, write, read, close */
  481. X    /* added for Borland or other MSDOS C compilers */
  482. X#include    <stdlib.h>
  483. X#include    <fcntl.h>
  484. X#include    <sys\types.h>
  485. X#include    <sys\stat.h>
  486. X#include    <string.h>
  487. X#endif
  488. X
  489. X#ifdef VAXC
  490. X#include    <stdlib.h>
  491. X#endif
  492. X
  493. X#ifdef MAC
  494. X#include    <unix.h>    /* open, creat, write, read, close */
  495. X#include    <stddef.h>    /* sizeof */
  496. X#include    <stdlib.h>
  497. X#endif
  498. X
  499. X#ifdef AMIGA
  500. X#include    <stdlib.h>
  501. X#include    <fcntl.h>    /* open, creat, write, read, close */
  502. X#endif
  503. X
  504. X#include    <stdio.h>
  505. X#include    "list.h"
  506. X
  507. X/* -------------------------------------------------------------------------- */
  508. X
  509. X#ifndef NULL
  510. X#define    NULL    0
  511. X#endif
  512. X
  513. X#undef    FREE
  514. X#define FREE(VAR) if (VAR != NULL) free((char *)VAR);
  515. X#undef    MALLOC
  516. X#define MALLOC(VAR, TYPE) \
  517. X    if ((VAR = (TYPE *)malloc(sizeof(TYPE))) == NULL) { \
  518. X        fprintf(stderr, "No more memory for malloc().\n"); \
  519. X        return(lOUT_OF_MEMORY); \
  520. X    }
  521. X#undef    CALLOC
  522. X#define CALLOC(VAR, TYPE, NR) \
  523. X    if ((VAR = (TYPE *)calloc(NR, sizeof(TYPE))) == NULL) {\
  524. X        fprintf(stderr, "No more memory for calloc().\n"); \
  525. X        return(lOUT_OF_MEMORY); \
  526. X    }
  527. X
  528. X#undef    BYTE_COPY
  529. X#define BYTE_COPY(FROM, TO, SIZE) \
  530. X    { \
  531. X        register Byte    *frm = FROM, \
  532. X                *to = TO; \
  533. X        int        i = SIZE; \
  534. X        while (i--) *to++ = *frm++; \
  535. X    }
  536. X
  537. X    /* necessary for binary file access */
  538. X#ifdef MSDOS
  539. X#define    BIN_WRITE    O_WRONLY|O_BINARY
  540. X#define    BIN_READ    O_RDONLY|O_BINARY
  541. X#define    PMODE        S_IREAD
  542. X#else
  543. X#define    BIN_WRITE    1
  544. X#define    BIN_READ    0
  545. X#define    PMODE        0666
  546. X#endif
  547. X
  548. X/* -------------------------------------------------------------------------- */
  549. X
  550. X#ifndef ANSI
  551. Xtypedef    int        (*Func)();
  552. Xtypedef    unsigned char    Byte;
  553. X#endif
  554. X
  555. Xtypedef struct lnode {
  556. X    Byte        *data;    /* data of user */
  557. X    int        size;    /* size (number of bytes) of data */
  558. X    int        flag;    /* user information flag */
  559. X    struct lnode    *prv;    /* previous node */
  560. X    struct lnode    *nxt;    /* next node */
  561. X} ListNode, *NodePtr;
  562. X
  563. Xtypedef struct listhdr {
  564. X    int        id;        /* identifier of linked list */
  565. X    int        sd;        /* singly or doubly linked */
  566. X    int        cc;        /* chain or circular list */
  567. X    int        n;        /* number of nodes */
  568. X    NodePtr        first;        /* address of first node */
  569. X    NodePtr        current;    /* address of current node */
  570. X    NodePtr        last;        /* address of last node */
  571. X    struct listhdr    *nxt;        /* next linked list */
  572. X} ListHdr, *ListPtr;
  573. X
  574. Xtypedef struct header {    /* general info of linked list for dump file */
  575. X    int    sd;
  576. X    int    cc;
  577. X    int    n;
  578. X} Header;
  579. X
  580. Xtypedef struct info {    /* general info of node for dump file */
  581. X    int    size;
  582. X    int    flag;
  583. X} Info;
  584. X
  585. X/* -------------------------------------------------------------------------- */
  586. X
  587. X#ifdef ANSI
  588. Xstatic ListPtr    getAddress(int id);
  589. Xstatic void    delNodes(NodePtr node, int n);
  590. Xstatic void    delListInfo(ListPtr list);
  591. Xstatic void    lError(char *str, int code, int int1, int int2, char *str1);
  592. Xstatic int    setWhchNode(int id, int which, char *fname);
  593. Xstatic int    setIndxNode(int id, int index, char *fname);
  594. Xstatic void    partition(NodePtr *array, int order, Func func, int lb, int ub,
  595. X            int *pj);
  596. Xstatic int    stack_empty(int id);
  597. Xstatic int    intInSet(int intgr, int *set, int set_n);
  598. X#else
  599. Xstatic ListPtr    getAddress();
  600. Xstatic void    delNodes();
  601. Xstatic void    delListInfo();
  602. Xstatic void    lError();
  603. Xstatic int    setWhchNode();
  604. Xstatic int    setIndxNode();
  605. Xstatic void    partition();
  606. Xstatic int    stack_empty();
  607. Xstatic int    intInSet();
  608. X#endif
  609. X
  610. X/* -------------------------------------------------------------------------- */
  611. X
  612. Xstatic ListHdr    firstlist = { 1, 0, 0, 0, NULL, NULL, NULL, NULL };
  613. Xstatic ListPtr    ld = &firstlist;
  614. Xstatic int    idMax = 2;
  615. X
  616. X/* -------------------------------------------------------------------------- */
  617. X
  618. X/*******************************************************************************
  619. X** Define a new linked list and create info about it.
  620. X**
  621. X** Parameters:
  622. X**    In    int    sd    singly or doubly linked
  623. X**                (lSINGLY, lDOUBLY)
  624. X**    In    int    cc    chain or circular linked
  625. X**                (lCHAIN, lCIRCULAR)
  626. X**
  627. X** Return on success:
  628. X**    identifier of linked list
  629. X** Return on error:
  630. X**    lWRONG_SD, lWRONG_CC
  631. X*/
  632. Xint
  633. XlDef(sd, cc)
  634. Xint    sd, cc;
  635. X{
  636. X    ListPtr        list, new;
  637. X    static int    set1[] = { lSINGLY, lDOUBLY },
  638. X            set2[] = { lCHAIN, lCIRCULAR };
  639. X
  640. X        /* check parameters */
  641. X    if (intInSet(sd, set1, 2) != 0) {
  642. X        lError("lDef", lWRONG_SD, sd, 0, NULL);
  643. X        return(lWRONG_SD);
  644. X    }
  645. X    if (intInSet(cc, set2, 2) != 0) {
  646. X        lError("lDef", lWRONG_CC, cc, 0, NULL);
  647. X        return(lWRONG_CC);
  648. X    }
  649. X
  650. X    list = ld;
  651. X    while (list->nxt != NULL && list->sd != 0)
  652. X        list = list->nxt;
  653. X    if (list->sd != 0) {    /* new list */
  654. X        MALLOC(new, ListHdr);
  655. X        new->id = idMax++;
  656. X        new->sd = sd;
  657. X        new->cc = cc;
  658. X        new->n = 0;
  659. X        new->first = new->current = new->last = NULL;
  660. X        new->nxt = NULL;
  661. X        list->nxt = new;
  662. X        return(new->id);
  663. X    } else {        /* new list on existing place */
  664. X        list->sd = sd;
  665. X        list->cc = cc;
  666. X        return(list->id);
  667. X    }
  668. X}
  669. X
  670. X/*******************************************************************************
  671. X** Get info of linked list.
  672. X**
  673. X** Parameters:
  674. X**    In    int    id    identifier of linked list
  675. X**    Out    int    *sd    singly or doubly linked
  676. X**                (lSINGLY, lDOUBLY)
  677. X**    Out    int    *cc    chain or cicular linked
  678. X**                (lCHAIN, lCIRCULAR)
  679. X**    Out    int    *n    number of nodes
  680. X**
  681. X** Return on success:
  682. X**    lSUCCESS
  683. X** Return on error:
  684. X**    lUNKNOWN_ID
  685. X*/
  686. Xint
  687. XlInfo(id, sd, cc, n)
  688. Xint    id, *sd, *cc, *n;
  689. X{
  690. X    ListPtr    list;
  691. X
  692. X        /* check parameters */
  693. X    if ((list = getAddress(id)) == NULL) {
  694. X        lError("lInfo", lUNKNOWN_ID, id, 0, NULL);
  695. X        return(lUNKNOWN_ID);
  696. X    }
  697. X
  698. X        /* copy information */
  699. X    *sd = list->sd;
  700. X    *cc = list->cc;
  701. X    *n = list->n;
  702. X
  703. X    return(lSUCCESS);
  704. X}
  705. X
  706. X/*******************************************************************************
  707. X** Get number of nodes in linked list.
  708. X**
  709. X** Parameters:
  710. X**    In    int    id    identifier of linked list
  711. X**
  712. X** Return on success:
  713. X**    number of nodes
  714. X** Return on error:
  715. X**    lUNKNOWN_ID
  716. X*/
  717. Xint
  718. XlSize(id)
  719. Xint    id;
  720. X{
  721. X    ListPtr    list;
  722. X
  723. X        /* check parameters */
  724. X    if ((list = getAddress(id)) == NULL) {
  725. X        lError("lInfo", lUNKNOWN_ID, id, 0, NULL);
  726. X        return(lUNKNOWN_ID);
  727. X    }
  728. X
  729. X    return(list->n);
  730. X}
  731. X
  732. X/*******************************************************************************
  733. X** Sort a linked list.
  734. X**
  735. X** Parameters:
  736. X**    In    int    id    identifier of linked list
  737. X**    In    int    order    sorting order
  738. X**                (lDESCENDING, lASCENDING)
  739. X**    In    int    theory    sorting theory
  740. X**                (lBUBBLE, lHEAP, lINSERT, lQUICK, lSELECTION)
  741. X**    In    Func    func    number of nodes
  742. X**
  743. X** Return on success:
  744. X**    lSUCCESS
  745. X** Return on error:
  746. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_ORDER, lWRONG_THEORY
  747. X*/
  748. Xint
  749. XlSort(id, order, theory, func)
  750. Xint    id, order, theory;
  751. XFunc    func;
  752. X{
  753. X    int        node_n, i, s, f, k, where, j, cmp;
  754. X    ListPtr        list;
  755. X    NodePtr        temp, temp2, *array;
  756. X    static int    set1[] = { lASCENDING, lDESCENDING },
  757. X            set2[] = { lBUBBLE, lHEAP, lINSERT, lQUICK,
  758. X                lSELECTION };
  759. X
  760. X        /* check parameters */
  761. X    if ((list = getAddress(id)) == NULL) {
  762. X        lError("lSort", lUNKNOWN_ID, id, 0, NULL);
  763. X        return(lUNKNOWN_ID);
  764. X    }
  765. X    if (list->n == 0) {
  766. X        lError("lSort", lEMPTY_LIST, id, 0, NULL);
  767. X        return(lEMPTY_LIST);
  768. X    }
  769. X    if (intInSet(order, set1, 2) != 0) {
  770. X        lError("lSort", lWRONG_ORDER, id, 0, NULL);
  771. X        return(lWRONG_ORDER);
  772. X    }
  773. X    if (intInSet(theory, set2, 5) != 0) {
  774. X        lError("lSort", lWRONG_THEORY, id, 0, NULL);
  775. X        return(lWRONG_THEORY);
  776. X    }
  777. X
  778. X        /* one node is already sorted */
  779. X    if (list->n == 1)
  780. X        return(lSUCCESS);
  781. X
  782. X    node_n = list->n;
  783. X        /* allocate 1 extra so I can have a null in it */
  784. X    CALLOC(array, NodePtr, node_n+1);
  785. X
  786. X    list->current = list->first;
  787. X    for (i=0; i < node_n && list->current != NULL; i++) {
  788. X        array[i] = list->current;
  789. X        list->current = (list->current)->nxt;
  790. X    }
  791. X    array[node_n] = NULL;
  792. X
  793. X    switch (theory) {
  794. X    case lBUBBLE: {
  795. X        int    switched = 1;
  796. X
  797. X        for (i=0; i < node_n-1 && switched == 1; i++) {
  798. X            switched = 0;
  799. X            for (j=0; j < node_n-i-1; j++) {
  800. X                cmp = (*func)(array[j]->data, array[j+1]->data);
  801. X                if ((order == lASCENDING && cmp == l2LT1)
  802. X                 || (order == lDESCENDING && cmp == l1LT2)) {
  803. X                    temp = array[j];
  804. X                    array[j] = array[j+1];
  805. X                    array[j+1] = temp;
  806. X
  807. X                    switched = 1;
  808. X                }
  809. X            }
  810. X        }
  811. X        break;
  812. X    } /* end of lBUBBLE */
  813. X    case lHEAP:
  814. X        for (i=1; i<node_n; i++) {
  815. X            temp = array[i];
  816. X
  817. X            s = i;
  818. X            f = (s-1)/2;
  819. X            cmp = (*func)(array[f]->data, temp->data);
  820. X            while (s > 0 && ((order == lASCENDING && cmp == l1LT2)
  821. X             || (order == lDESCENDING && cmp == l2LT1))) {
  822. X                array[s] = array[f];
  823. X                s = f;
  824. X                f = (s-1)/2;
  825. X                cmp = (*func)(array[f]->data, temp->data);
  826. X            }
  827. X
  828. X            array[s] = temp;
  829. X        }
  830. X        for (i=node_n-1; i>0; i--) {
  831. X            temp = array[i];
  832. X            array[i] = array[0];
  833. X            f = 0;
  834. X
  835. X            if (i == 1)
  836. X                s = -1;
  837. X            else
  838. X                s = 1;
  839. X            if (i > 2) {
  840. X                cmp = (*func)(array[2]->data, array[1]->data);
  841. X                if ((order == lASCENDING && cmp == l2LT1)
  842. X                 || (order == lDESCENDING && cmp == l1LT2))
  843. X                    s = 2;
  844. X            }
  845. X
  846. X            if (s >= 0)
  847. X                cmp = (*func)(temp->data, array[s]->data);
  848. X            while (s >= 0 && ((order == lASCENDING && cmp == l1LT2)
  849. X             || (order == lDESCENDING && cmp == l2LT1))) {
  850. X                array[f] = array[s];
  851. X                f = s;
  852. X
  853. X                s = 2*f+1;
  854. X                if (s+1 <= i-1) {
  855. X                    cmp = (*func)(array[s]->data,
  856. X                        array[s+1]->data);
  857. X                    if ((order == lASCENDING
  858. X                        && cmp == l1LT2) ||
  859. X                     (order == lDESCENDING
  860. X                        && cmp == l2LT1))
  861. X                        s = s+1;
  862. X                }
  863. X                if (s > i-1)
  864. X                    s = -1;
  865. X                if (s >= 0)
  866. X                    cmp = (*func)(temp->data,
  867. X                        array[s]->data);
  868. X            }
  869. X            array[f] = temp;
  870. X        }
  871. X        break;
  872. X    case lINSERT:
  873. X        for (i=1; i<node_n; i++) {
  874. X            temp = array[i];
  875. X            cmp = (*func)(temp->data, array[i-1]->data);
  876. X            for (j=i-1; j>=0
  877. X             && ((order == lASCENDING && cmp == l1LT2)
  878. X             || (order == lDESCENDING && cmp == l2LT1)); j--) {
  879. X                temp2 = array[j];
  880. X                array[j] = array[j+1];
  881. X                array[j+1] = temp2;
  882. X                if (j > 0)
  883. X                    cmp = (*func)(temp->data,
  884. X                        array[j-1]->data);
  885. X            }
  886. X        }
  887. X        break;
  888. X    case lQUICK: {
  889. X        struct bndtype {
  890. X            int lb;
  891. X            int ub;
  892. X        }        newbnds;
  893. X        int        newbndsSz = sizeof(struct bndtype),
  894. X                stack = lDef(lDOUBLY, lCHAIN);
  895. X
  896. X        newbnds.lb = 0;
  897. X        newbnds.ub = node_n-1;
  898. X            /* basicly a push */
  899. X        lInsNode(stack, lLAST, &newbnds, newbndsSz, 0);
  900. X
  901. X            /* repeat as long as there are any unsorted subarrays
  902. X            ** on the stack */
  903. X        while (!stack_empty(stack)) {
  904. X                /* a pop */
  905. X            lGetNode(stack, lCURRENT, &newbnds, newbndsSz);
  906. X            lDelNode(stack, lCURRENT);
  907. X            while (newbnds.ub > newbnds.lb) {
  908. X                    /* process next sub array */
  909. X                partition(array, order, (*func), newbnds.lb,
  910. X                    newbnds.ub, &j);
  911. X                    /* stack the larger subarray */
  912. X                if (j-newbnds.lb > newbnds.ub-j) {
  913. X                        /* stack lower subarray */
  914. X                    i = newbnds.ub;
  915. X                    newbnds.ub = j-1;
  916. X                        /* basicly a push */
  917. X                    lInsNode(stack, lLAST, &newbnds,
  918. X                        newbndsSz, 0);
  919. X                        /* process upper subarray */
  920. X                    newbnds.lb = j+1;
  921. X                    newbnds.ub = i;
  922. X                } else {
  923. X                        /* stack upper subarray */
  924. X                    i = newbnds.lb;
  925. X                    newbnds.lb = j+1;
  926. X                        /* basicly a push */
  927. X                    lInsNode(stack, lLAST, &newbnds,
  928. X                        newbndsSz, 0);
  929. X                        /* process lower subarray */
  930. X                    newbnds.lb = i;
  931. X                    newbnds.ub = j-1;
  932. X                }
  933. X            }
  934. X        }
  935. X        lDel(stack);
  936. X        break;
  937. X    } /* end of lQUICK */
  938. X    case lSELECTION: {
  939. X        int    indx;
  940. X
  941. X        for (i=node_n-1; i>0; i--) {
  942. X            temp = array[0];
  943. X            indx = 0;
  944. X
  945. X            for (j=1; j<=i; j++) {
  946. X                cmp = (*func)(array[j]->data, temp->data);
  947. X                if ((order == lASCENDING && cmp == l2LT1)
  948. X                 || (order == lDESCENDING && cmp == l1LT2)) {
  949. X                    temp = array[j];
  950. X                    indx = j;
  951. X                }
  952. X            }
  953. X            array[indx] = array[i];
  954. X            array[i] = temp;
  955. X        }
  956. X        break;
  957. X    } /* end of lSELECTION */
  958. X    } /* end of switch */
  959. X
  960. X        /* init list to start and reset it */
  961. X    list->first = array[0];
  962. X    list->last = array[node_n-1];
  963. X
  964. X    list->current = list->first;
  965. X    for (k=0; k<node_n; k++) {
  966. X        if (k == 0)
  967. X            where = lFIRST;
  968. X        else if (k == node_n)
  969. X            where = lLAST;
  970. X        else
  971. X            where = lNEXT;
  972. X
  973. X        switch (where) {
  974. X        case lFIRST:
  975. X            if (list->cc == lCIRCULAR)
  976. X                (list->first)->prv = (list->last);
  977. X
  978. X            if (list->sd == lDOUBLY)
  979. X                array[k]->prv = NULL;
  980. X
  981. X            array[k]->nxt = array[k+1];
  982. X            break;
  983. X
  984. X        case lNEXT:
  985. X            if (list->sd == lDOUBLY)
  986. X                (list->first)->prv = array[k-1];
  987. X
  988. X            array[k]->nxt = array[k+1];
  989. X            break;
  990. X
  991. X        case lLAST:
  992. X            if (list->sd == lDOUBLY)
  993. X                array[k]->prv = array[k-1];
  994. X
  995. X            if (list->cc == lCIRCULAR)
  996. X                array[k]->nxt = list->first;
  997. X            else
  998. X                array[k]->nxt = NULL;
  999. X            break;
  1000. X        }
  1001. X    }
  1002. X    FREE(array);
  1003. X
  1004. X    return(lSUCCESS);
  1005. X}
  1006. X
  1007. X/*******************************************************************************
  1008. X** Dump a linked list to a file.
  1009. X**
  1010. X** Parameters:
  1011. X**    In    int    id    identifier of linked list
  1012. X**    In    char    *file    name of linked list dump file
  1013. X**
  1014. X** Return on success:
  1015. X**    lSUCCESS
  1016. X** Return on error:
  1017. X**    lUNKNOWN_ID, lOPEN_ERROR
  1018. X**
  1019. X** File structure:
  1020. X**    <header> { <info> <data> }
  1021. X**    header.n    number of <info>-<data>-combinations (nodes)
  1022. X**    info.size    size of <data>
  1023. X*/
  1024. Xint
  1025. XlDump(id, file)
  1026. Xint    id;
  1027. Xchar    *file;
  1028. X{
  1029. X#ifndef MSDOS
  1030. X    int    open(), creat(), write(), close();
  1031. X#endif
  1032. X
  1033. X    int    fdDump, i;
  1034. X    ListPtr    list;
  1035. X    NodePtr    node;
  1036. X    Info    info;
  1037. X    Header    header;
  1038. X
  1039. X        /* check parameters */
  1040. X    if ((list = getAddress(id)) == NULL) {
  1041. X        lError("lDump", lUNKNOWN_ID, id, 0, NULL);
  1042. X        return(lUNKNOWN_ID);
  1043. X    }
  1044. X
  1045. X    fdDump = open(file, BIN_WRITE);
  1046. X    if (fdDump == -1) {
  1047. X        fdDump = creat(file, PMODE);
  1048. X        if (fdDump == -1) {
  1049. X            lError("lDump", lOPEN_ERROR, 0, 0, file);
  1050. X            return(lOPEN_ERROR);
  1051. X        }
  1052. X    }
  1053. X
  1054. X    header.sd = list->sd;
  1055. X    header.cc = list->cc;
  1056. X    header.n = list->n;
  1057. X    write(fdDump, (char *) &header, sizeof(Header));
  1058. X
  1059. X    node = list->first;
  1060. X    for (i=0; i<header.n; i++) {
  1061. X        info.size = node->size;
  1062. X        info.flag = node->flag;
  1063. X        write(fdDump, (char *) &info, sizeof(Info));
  1064. X        write(fdDump, (char *) node->data, node->size);
  1065. X        node = node->nxt;
  1066. X    }
  1067. X
  1068. X    close(fdDump);
  1069. X
  1070. X    return(lSUCCESS);
  1071. X}
  1072. X
  1073. X/*******************************************************************************
  1074. X** Undump a linked list from a file.
  1075. X**
  1076. X** Parameters:
  1077. X**    In    char    *file    name of linked list dump file
  1078. X**
  1079. X** Return on success:
  1080. X**    lSUCCESS
  1081. X** Return on error:
  1082. X**    lOPEN_ERROR
  1083. X*/
  1084. Xint
  1085. XlUndump(file)
  1086. Xchar    *file;
  1087. X{
  1088. X#ifndef MSDOS
  1089. X#ifndef AMIGA
  1090. X    int    open(), read(), close();
  1091. X#endif
  1092. X#endif
  1093. X
  1094. X    int    fdDump, i, id;
  1095. X    Info    info;
  1096. X    Header    header;
  1097. X    Byte    *data;
  1098. X
  1099. X        /* check parameters */
  1100. X    fdDump = open(file, BIN_READ);
  1101. X    if (fdDump == -1) {
  1102. X        lError("lDump", lOPEN_ERROR, 0, 0, file);
  1103. X        return(lOPEN_ERROR);
  1104. X    }
  1105. X
  1106. X    read(fdDump, (char *) &header, sizeof(Header));
  1107. X    id = lDef(header.sd, header.cc);
  1108. X
  1109. X    for (i=0; i<header.n; i++) {
  1110. X        read(fdDump, (char *) &info, sizeof(Info));
  1111. X        CALLOC(data, Byte, info.size);
  1112. X        read(fdDump, (char *) data, info.size);
  1113. X        lInsNode(id, lLAST, data, info.size, info.flag);
  1114. X        FREE(data);
  1115. X    }
  1116. X
  1117. X    close(fdDump);
  1118. X
  1119. X    return(id);
  1120. X}
  1121. X
  1122. X/*******************************************************************************
  1123. X** Delete a linked list and clear info about it.
  1124. X**
  1125. X** Parameters:
  1126. X**    In    int    id    identifier of linked list
  1127. X**
  1128. X** Return on success:
  1129. X**    lSUCCESS
  1130. X** Return on error:
  1131. X**    lUNKNOWN_ID
  1132. X*/
  1133. Xint
  1134. XlDel(id)
  1135. Xint    id;
  1136. X{
  1137. X    ListPtr    list;
  1138. X
  1139. X        /* check parameters */
  1140. X    if ((list = getAddress(id)) == NULL) {
  1141. X        lError("lDel", lUNKNOWN_ID, id, 0, NULL);
  1142. X        return(lUNKNOWN_ID);
  1143. X    }
  1144. X
  1145. X        /* delete all nodes */
  1146. X    delNodes(list->first, list->n);
  1147. X        /* reset info as deleted linked list */
  1148. X    list->sd = list->cc = list->n = 0;
  1149. X    list->first = list->current = list->last = NULL;
  1150. X
  1151. X    return(lSUCCESS);
  1152. X}
  1153. X
  1154. X/*******************************************************************************
  1155. X** Delete all linked list and all info about those lists.
  1156. X**
  1157. X** No parameters.
  1158. X**
  1159. X** Return on success:
  1160. X**    lSUCCESS
  1161. X** Return on error:
  1162. X**    lNO_LIST
  1163. X*/
  1164. Xint
  1165. XlDelAll()
  1166. X{
  1167. X    ListPtr    list, nxt;
  1168. X
  1169. X    if (ld == NULL) {
  1170. X        lError("lDelAll", lNO_LIST, 0, 0, NULL);
  1171. X        return(lNO_LIST);
  1172. X    }
  1173. X
  1174. X    list = ld;
  1175. X    while (list != NULL) {
  1176. X        nxt = list->nxt;
  1177. X        if (list->sd != 0 && list->cc != 0)
  1178. X            lDel(list->id);    /* delete when not already deleted */
  1179. X        list = nxt;
  1180. X    }
  1181. X    delListInfo(ld->nxt);
  1182. X        /* save info of initial list */
  1183. X    firstlist.id = 1;
  1184. X    firstlist.sd = firstlist.cc = firstlist.n = 0;
  1185. X    firstlist.first = firstlist.current = firstlist.last = NULL;
  1186. X    firstlist.nxt = NULL;
  1187. X    ld = &firstlist;
  1188. X    idMax = 2;
  1189. X
  1190. X    return(lSUCCESS);
  1191. X}
  1192. X
  1193. X/*******************************************************************************
  1194. X** Insert a node in linked list.
  1195. X**
  1196. X** Parameters:
  1197. X**    In    int    id    identifier of linked list
  1198. X**    In    int    where    place where node must be inserted
  1199. X**                (lFIRST, lBEFORE, lAFTER, lLAST)
  1200. X**    In    Byte    *data    data of node
  1201. X**    In    int    size    size of data
  1202. X**    In    int    flag    user information flag
  1203. X**
  1204. X** Return on success:
  1205. X**    lSUCCESS
  1206. X** Return on error:
  1207. X**    lUNKNOWN_ID, lWRONG_WHERE
  1208. X*/
  1209. Xint
  1210. XlInsNode(id, where, data, size, flag)
  1211. Xint    id, where, size, flag;
  1212. XByte    *data;
  1213. X{
  1214. X    ListPtr        list;
  1215. X    NodePtr        node, new;
  1216. X    static int    set[] = { lFIRST, lBEFORE, lAFTER, lLAST };
  1217. X
  1218. X        /* check parameters */
  1219. X    if ((list = getAddress(id)) == NULL) {
  1220. X        lError("lInsNode", lUNKNOWN_ID, id, 0, NULL);
  1221. X        return(lUNKNOWN_ID);
  1222. X    }
  1223. X    if (intInSet(where, set, 4) != 0) {
  1224. X        lError("lInsNode", lWRONG_WHERE, where, 0, NULL);
  1225. X        return(lWRONG_WHERE);
  1226. X    }
  1227. X
  1228. X        /* create new node */
  1229. X    MALLOC(new, ListNode);
  1230. X    CALLOC(new->data, Byte, size);
  1231. X    BYTE_COPY(data, new->data, size);
  1232. X    new->size = size;
  1233. X    new->flag = flag;
  1234. X
  1235. X        /* specific insert cases */
  1236. X    if (list->first == NULL)
  1237. X        where = lONE_NODE;    /* first node in list */
  1238. X    else if (list->current == list->first && where == lBEFORE)
  1239. X        where = lFIRST;        /* before first is like insert first */
  1240. X    else if (list->current == list->last && where == lAFTER)
  1241. X        where = lLAST;        /* after last is like insert last */
  1242. X
  1243. X    switch (where) {
  1244. X    case lONE_NODE:
  1245. X        if (list->cc == lCHAIN)
  1246. X            new->prv = new->nxt = NULL;
  1247. X        else {
  1248. X            if (list->sd == lDOUBLY)
  1249. X                new->prv = new;
  1250. X            else
  1251. X                new->prv = NULL;
  1252. X            new->nxt = new;
  1253. X        }
  1254. X        list->first = list->last = new;
  1255. X        break;
  1256. X    case lFIRST:
  1257. X        new->prv = (list->first)->prv;
  1258. X        new->nxt = list->first;
  1259. X        if (list->cc == lCIRCULAR)
  1260. X            (list->last)->nxt = new;
  1261. X        else
  1262. X            (list->last)->nxt = NULL;
  1263. X        if (list->sd == lDOUBLY)
  1264. X            (list->first)->prv = new;
  1265. X        list->first = new;
  1266. X        break;
  1267. X    case lBEFORE:
  1268. X        new->prv = (list->current)->prv;    /* == NULL if lSINGLY */
  1269. X        new->nxt = list->current;
  1270. X
  1271. X        if (list->sd == lDOUBLY) {
  1272. X            ((list->current)->prv)->nxt = new;
  1273. X            (list->current)->prv = new;
  1274. X        } else {
  1275. X            node = list->first;
  1276. X                /* search for last before current */
  1277. X            while (node->nxt != list->current && node != list->last)
  1278. X                node = node->nxt;
  1279. X            node->nxt = new;
  1280. X        }
  1281. X        if (list->current == list->first)
  1282. X            list->first = new;
  1283. X        break;
  1284. X    case lAFTER:
  1285. X        if (list->sd == lDOUBLY)
  1286. X            new->prv = list->current;
  1287. X        else
  1288. X            new->prv = NULL;
  1289. X        new->nxt = (list->current)->nxt;
  1290. X        if (list->sd == lDOUBLY)
  1291. X            ((list->current)->nxt)->prv = new;
  1292. X        (list->current)->nxt = new;
  1293. X        if (list->current == list->last)
  1294. X            list->last = new;
  1295. X        break;
  1296. X    case lLAST:
  1297. X        node = list->last;
  1298. X        if (list->sd == lDOUBLY)
  1299. X            new->prv = node;
  1300. X        else
  1301. X            new->prv = NULL;
  1302. X        if (list->cc == lCIRCULAR)
  1303. X            new->nxt = list->first;
  1304. X        else
  1305. X            new->nxt = NULL;
  1306. X        if (list->sd == lDOUBLY && list->cc == lCIRCULAR)
  1307. X            (list->first)->prv = new;
  1308. X        node->nxt = new;
  1309. X        list->last = new;
  1310. X        break;
  1311. X    }
  1312. X
  1313. X    list->n++;
  1314. X    list->current = new;
  1315. X
  1316. X    return(lSUCCESS);
  1317. X}
  1318. X
  1319. X/*******************************************************************************
  1320. X** Get info of node of linked list.
  1321. X**
  1322. X** Parameters:
  1323. X**    In    int    id    identifier of linked list
  1324. X**    In    int    which    which node must be inspected
  1325. X**                (lFIRST, lPREVIOUS, lCURRENT, lNEXT, lLAST)
  1326. X**    Out    int    *size    size of data of node
  1327. X**    Out    int    *flag    user information flag
  1328. X**
  1329. X** Return on success:
  1330. X**    lSUCCESS
  1331. X** Return on error:
  1332. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lNOT_DOUBLY
  1333. X*/
  1334. Xint
  1335. XlInfoNode(id, which, size, flag)
  1336. Xint    id, which, *size, *flag;
  1337. X{
  1338. X    ListPtr    list;
  1339. X    int    rtrn;
  1340. X
  1341. X    rtrn = setWhchNode(id, which, "lInfoNode");
  1342. X    if (rtrn != lSUCCESS)    /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, */
  1343. X        return(rtrn);    /* lEOL, lNOT_DOUBLY */
  1344. X
  1345. X    list = getAddress(id);    /* already checked in setWhchNode */
  1346. X
  1347. X        /* copy information */
  1348. X    *size = (list->current)->size;
  1349. X    *flag = (list->current)->flag;
  1350. X
  1351. X    return(lSUCCESS);
  1352. X}
  1353. X
  1354. X/*******************************************************************************
  1355. X** Get data of node.
  1356. X**
  1357. X** Parameters:
  1358. X**    In    int    id    identifier of linked list
  1359. X**    In    int    which    which node must be retrieved
  1360. X**                (lFIRST, lPREVIOUS, lCURRENT, lNEXT, lLAST)
  1361. X**    Out    Byte    *data    data of node
  1362. X**    In    int    size    size of data
  1363. X**
  1364. X** Return on success:
  1365. X**    lSUCCESS, lFIRST, lLAST
  1366. X** Return on error:
  1367. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lNOT_DOUBLY, lSIZE_NE
  1368. X*/
  1369. Xint
  1370. XlGetNode(id, which, data, size)
  1371. Xint    id, which, size;
  1372. XByte    *data;
  1373. X{
  1374. X    ListPtr    list;
  1375. X    int    rtrn;
  1376. X
  1377. X    rtrn = setWhchNode(id, which, "lInfoNode");
  1378. X    if (rtrn != lSUCCESS)    /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, */
  1379. X        return(rtrn);    /* lEOL, lNOT_DOUBLY */
  1380. X
  1381. X    list = getAddress(id);    /* already checked in setWhchNode */
  1382. X
  1383. X        /* expected data and node must have same size */
  1384. X    if ((list->current)->size != size) {
  1385. X        lError("lGetNode", lSIZE_NE, size, (list->current)->size, NULL);
  1386. X        return(lSIZE_NE);
  1387. X    }
  1388. X
  1389. X    BYTE_COPY((list->current)->data, data, size);
  1390. X
  1391. X    if (list->n == 1) {
  1392. X        if (which == lPREVIOUS || which == lLAST)
  1393. X            return(lFIRST);
  1394. X        else if (which == lNEXT || which == lFIRST)
  1395. X            return(lLAST);
  1396. X        else
  1397. X            return(lLAST);    /* which == lCURRENT */
  1398. X    } else if (list->current == list->first)
  1399. X        return(lFIRST);
  1400. X    else if (list->current == list->last)
  1401. X        return(lLAST);
  1402. X
  1403. X    return(lSUCCESS);
  1404. X}
  1405. X
  1406. X/*******************************************************************************
  1407. X** Find node.
  1408. X**
  1409. X** Parameters:
  1410. X**    In    int    id    identifier of linked list
  1411. X**    In    int    which    from which node must be searched and in which
  1412. X**                direction
  1413. X**    In    Func    func    function for checking the data on conditions
  1414. X**    In    Byte    *ptr    data for comparison in function
  1415. X**    Out    Byte    *data    data of node
  1416. X**    In    int    size    size of data
  1417. X**
  1418. X** Return on success:
  1419. X**    lFOUND, lFIRST, lLAST, lNOT_FOUND
  1420. X** Return on error:
  1421. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lUNKNOWN_FUNC, lNOT_DOUBLY
  1422. X*/
  1423. Xint
  1424. XlFndNode(id, which, func, ptr, data, size)
  1425. Xint    id, which, size;
  1426. XFunc    func;
  1427. XByte    *ptr, *data;
  1428. X{
  1429. X    NodePtr        node;
  1430. X    ListPtr        list;
  1431. X    int        cmp = lNOT_FOUND;
  1432. X    static int    set[] = { lFIRST, lNEXT, lPREVIOUS, lLAST };
  1433. X
  1434. X        /* check parameters */
  1435. X    if ((list = getAddress(id)) == NULL) {
  1436. X        lError("lFndNode", lUNKNOWN_ID, id, 0, NULL);
  1437. X        return(lUNKNOWN_ID);
  1438. X    }
  1439. X    if (list->n == 0) {
  1440. X        lError("lFndNode", lEMPTY_LIST, id, 0, NULL);
  1441. X        return(lEMPTY_LIST);
  1442. X    }
  1443. X    if (intInSet(which, set, 4) != 0) {
  1444. X        lError("lFndNode", lWRONG_WHICH, which, 0, NULL);
  1445. X        return(lWRONG_WHICH);
  1446. X    }
  1447. X    if (func == NULL) {
  1448. X        lError("lFndNode", lUNKNOWN_FUNC, (int) func, 0, NULL);
  1449. X        return(lUNKNOWN_FUNC);
  1450. X    }
  1451. X
  1452. X        /* set node where searching must start */
  1453. X    switch (which) {
  1454. X    case lFIRST:    node = list->first;    break;
  1455. X    case lNEXT:
  1456. X    case lPREVIOUS:    node = list->current;    break;
  1457. X    case lLAST:    node = list->last;    break;
  1458. X    }
  1459. X
  1460. X        /* expected data and node must have same size */
  1461. X    if ((which == lFIRST || which == lLAST) && node->size == size) {
  1462. X        BYTE_COPY(node->data, data, size);
  1463. X        cmp = (*func)(ptr, data);
  1464. X    }
  1465. X
  1466. X    switch (which) {
  1467. X    case lFIRST:    /* search forward */
  1468. X    case lNEXT:
  1469. X        while (cmp != lFOUND && node->nxt != NULL
  1470. X         && node != list->last) {
  1471. X            node = node->nxt;
  1472. X                /* expected data and node must have same size */
  1473. X            if (node->size == size) {
  1474. X                BYTE_COPY(node->data, data, size);
  1475. X                cmp = (*func)(ptr, data);
  1476. X            }
  1477. X        }
  1478. X        if (cmp == lFOUND) {
  1479. X            list->current = node;
  1480. X            if (list->current == list->last)
  1481. X                return(lLAST);
  1482. X        }
  1483. X        break;
  1484. X    case lPREVIOUS:    /* search backward */
  1485. X    case lLAST:
  1486. X        if (list->sd != lDOUBLY && cmp == lNOT_FOUND) {
  1487. X            lError("lFndNode", lNOT_DOUBLY, id, 0, NULL);
  1488. X            return(lNOT_DOUBLY);
  1489. X        }
  1490. X        while (cmp != lFOUND && node->prv != NULL
  1491. X         && node->prv != list->first) {
  1492. X            node = node->prv;
  1493. X                /* expected data and node must have same size */
  1494. X            if (node->size == size) {
  1495. X                BYTE_COPY(node->data, data, size);
  1496. X                cmp = (*func)(ptr, data);
  1497. X            }
  1498. X        }
  1499. X        if (cmp == lFOUND) {
  1500. X            list->current = node;
  1501. X            if (list->current == list->first)
  1502. X                return(lFIRST);
  1503. X        }
  1504. X        break;
  1505. X    }
  1506. X
  1507. X    return(cmp);    /* lFOUND, lNOT_FOUND */
  1508. X}
  1509. X
  1510. X/*******************************************************************************
  1511. X** Get node by flag.
  1512. X**
  1513. X** Parameters:
  1514. X**    In    int    id    identifier of linked list
  1515. X**    In    int    which    from which node must be searched and in which
  1516. X**                direction
  1517. X**    In    int    flag    flag of node which must be retrieved
  1518. X**    Out    Byte    *data    data of node
  1519. X**    In    int    size    size of data
  1520. X**
  1521. X** Return on success:
  1522. X**    lFOUND, lFIRST, lLAST, lNOT_FOUND
  1523. X** Return on error:
  1524. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lSIZE_NE
  1525. X*/
  1526. Xint
  1527. XlFndFlagNode(id, which, flag, data, size)
  1528. Xint    id, which, flag, size;
  1529. XByte    *data;
  1530. X{
  1531. X    NodePtr        node;
  1532. X    ListPtr        list;
  1533. X    static int    set[] = { lFIRST, lNEXT, lPREVIOUS, lLAST };
  1534. X
  1535. X        /* check parameters */
  1536. X    if ((list = getAddress(id)) == NULL) {
  1537. X        lError("lFndFlagNode", lUNKNOWN_ID, id, 0, NULL);
  1538. X        return(lUNKNOWN_ID);
  1539. X    }
  1540. X    if (list->n == 0) {
  1541. X        lError("lFndFlagNode", lEMPTY_LIST, id, 0, NULL);
  1542. X        return(lEMPTY_LIST);
  1543. X    }
  1544. X    if (intInSet(which, set, 4) != 0) {
  1545. X        lError("lFndFlagNode", lWRONG_WHICH, which, 0, NULL);
  1546. X        return(lWRONG_WHICH);
  1547. X    }
  1548. X
  1549. X        /* set node where searching must start */
  1550. X    switch (which) {
  1551. X    case lFIRST:
  1552. X        node = list->first;
  1553. X        break;
  1554. X    case lNEXT:
  1555. X        if ((list->current)->nxt == NULL)
  1556. X            return(lNOT_FOUND);    /* end of list reached */
  1557. X        node = (list->current)->nxt;
  1558. X        break;
  1559. X    case lPREVIOUS:
  1560. X        if ((list->current)->prv == NULL)
  1561. X            return(lNOT_FOUND);    /* begin of list reached */
  1562. X        node = (list->current)->prv;
  1563. X        break;
  1564. X    case lLAST:
  1565. X        node = list->last;
  1566. X        break;
  1567. X    }
  1568. X
  1569. X        /* search till begin/end of list */
  1570. X    switch (which) {
  1571. X    case lFIRST:    /* search forward */
  1572. X    case lNEXT:
  1573. X        while (node->flag != flag && node != list->last)
  1574. X            node = node->nxt;
  1575. X        break;
  1576. X    case lPREVIOUS:    /* search backward */
  1577. X    case lLAST:
  1578. X        if (list->sd != lDOUBLY) {
  1579. X            lError("lFndFlagNode", lNOT_DOUBLY, id, 0, NULL);
  1580. X            return(lNOT_DOUBLY);
  1581. X        }
  1582. X        while (node->flag != flag && node != list->first)
  1583. X            node = node->prv;
  1584. X        break;
  1585. X    }
  1586. X
  1587. X    list->current = node;
  1588. X
  1589. X        /* extra flag-check for last node of list */
  1590. X    if ((list->current)->flag != flag) {
  1591. X        lError("lFndFlagNode", lNOT_FOUND, id, 0, NULL);
  1592. X        return(lNOT_FOUND);
  1593. X    }
  1594. X
  1595. X        /* expected data and node must have same size */
  1596. X    if ((list->current)->size != size) {
  1597. X        lError("lFndFlagNode", lSIZE_NE, size, (list->current)->size,
  1598. X            NULL);
  1599. X        return(lSIZE_NE);
  1600. X    }
  1601. X
  1602. X    BYTE_COPY((list->current)->data, data, size);
  1603. X
  1604. X    if (list->n == 1) {
  1605. X        if (which == lPREVIOUS || which == lLAST)
  1606. X            return(lFIRST);
  1607. X        else if (which == lNEXT || which == lFIRST)
  1608. X            return(lLAST);
  1609. X        else
  1610. X            return(lLAST);    /* which == lCURRENT */
  1611. X    } else if (list->current == list->first)
  1612. X        return(lFIRST);
  1613. X    else if (list->current == list->last)
  1614. X        return(lLAST);
  1615. X
  1616. X    return(lFOUND);
  1617. X}
  1618. X
  1619. X/*******************************************************************************
  1620. X** Update current node.
  1621. X**
  1622. X** Parameters:
  1623. X**    In    int    id    identifier of linked list
  1624. X**    In    Byte    *data    updated data of node
  1625. X**    In    int    size    size of data
  1626. X**    In    int    flag    updated user information flag
  1627. X**
  1628. X** Return on success:
  1629. X**    lSUCCESS
  1630. X** Return on error:
  1631. X**    lUNKNOWN_ID, lEMPTY_LIST
  1632. X*/
  1633. Xint
  1634. XlUpdNode(id, data, size, flag)
  1635. Xint    id, size, flag;
  1636. XByte    *data;
  1637. X{
  1638. X    ListPtr    list;
  1639. X
  1640. X        /* check parameters */
  1641. X    if ((list = getAddress(id)) == NULL) {
  1642. X        lError("lUpdNode", lUNKNOWN_ID, id, 0, NULL);
  1643. X        return(lUNKNOWN_ID);
  1644. X    }
  1645. X    if (list->n == 0) {
  1646. X        lError("lUpdNode", lEMPTY_LIST, id, 0, NULL);
  1647. X        return(lEMPTY_LIST);
  1648. X    }
  1649. X
  1650. X        /* if same size, replace node by updated node */
  1651. X        /* if not same size, insert updated node on current place */
  1652. X    if ((list->current)->size != size) {
  1653. X        FREE((list->current)->data);
  1654. X        CALLOC((list->current)->data, Byte, size);
  1655. X        (list->current)->size = size;
  1656. X    }
  1657. X    (list->current)->flag = flag;
  1658. X    BYTE_COPY(data, (list->current)->data, size);
  1659. X
  1660. X    return(lSUCCESS);
  1661. X}
  1662. X
  1663. X/*******************************************************************************
  1664. X** Delete node.
  1665. X**
  1666. X** Parameters:
  1667. X**    In    int    id    identifier of linked list
  1668. X**    In    int    which    which node must be deleted
  1669. X**                (lFIRST, lCURRENT, lLAST)
  1670. X**
  1671. X** Return on success:
  1672. X**    lSUCCESS
  1673. X** Return on error:
  1674. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH
  1675. X*/
  1676. Xint
  1677. XlDelNode(id, which)
  1678. Xint    id, which;
  1679. X{
  1680. X    NodePtr        node, prv, nxt;
  1681. X    ListPtr        list;
  1682. X    static int    set[] = { lFIRST, lCURRENT, lLAST };
  1683. X
  1684. X        /* check parameters */
  1685. X    if ((list = getAddress(id)) == NULL) {
  1686. X        lError("lDelNode", lUNKNOWN_ID, id, 0, NULL);
  1687. X        return(lUNKNOWN_ID);
  1688. X    }
  1689. X    if (list->n == 0) {
  1690. X        lError("lDelNode", lEMPTY_LIST, id, 0, NULL);
  1691. X        return(lEMPTY_LIST);
  1692. X    }
  1693. X    if (intInSet(which, set, 3) != 0) {
  1694. X        lError("lDelNode", lWRONG_WHICH, which, 0, NULL);
  1695. X        return(lWRONG_WHICH);
  1696. X    }
  1697. X
  1698. X        /* specific delete cases */
  1699. X    if (list->n == 1)
  1700. X        which = lONE_NODE;    /* one node in linked list */
  1701. X    else if (which == lCURRENT && list->first == list->current)
  1702. X        which = lFIRST;        /* current is also first node */
  1703. X    else if (which == lCURRENT && list->last == list->current)
  1704. X        which = lLAST;        /* current is also last node */
  1705. X
  1706. X    switch (which) {
  1707. X    case lONE_NODE:
  1708. X        node = list->first;
  1709. X        list->first = list->current = list->last = NULL;
  1710. X        break;
  1711. X    case lFIRST:
  1712. X        node = list->first;
  1713. X        nxt = node->nxt;
  1714. X        if (list->cc == lCIRCULAR) {
  1715. X            prv = list->last;
  1716. X            prv->nxt = nxt;
  1717. X        } else
  1718. X            prv = node->prv;    /* == NULL if lSINGLY */
  1719. X        if (list->sd == lDOUBLY)
  1720. X            nxt->prv = prv;
  1721. X        list->first = list->current = nxt;
  1722. X        break;
  1723. X    case lCURRENT:
  1724. X        node = list->current;
  1725. X        nxt = node->nxt;
  1726. X        if (list->sd == lDOUBLY) {
  1727. X            prv = node->prv;
  1728. X            nxt->prv = prv;
  1729. X        } else {
  1730. X            prv = node = list->first;
  1731. X            while (node != list->current) {
  1732. X                prv = node;
  1733. X                node = node->nxt;
  1734. X            }
  1735. X            if (prv == node)
  1736. X                prv = list->last;
  1737. X        }
  1738. X        prv->nxt = nxt;
  1739. X        list->current = nxt;
  1740. X        break;
  1741. X    case lLAST:
  1742. X        node = list->last;
  1743. X        if (list->sd == lDOUBLY)
  1744. X            prv = node->prv;
  1745. X        else {
  1746. X            if (list->current != list->last)
  1747. X                prv = node = list->current;
  1748. X            else
  1749. X                prv = node = list->first;
  1750. X            while (node != list->last) {
  1751. X                prv = node;
  1752. X                node = node->nxt;
  1753. X            }
  1754. X        }
  1755. X        nxt = node->nxt;
  1756. X        if (list->sd == lDOUBLY && list->cc == lCIRCULAR)
  1757. X            nxt->prv = prv;
  1758. X        prv->nxt = nxt;
  1759. X        list->last = list->current = prv;
  1760. X        break;
  1761. X    }
  1762. X
  1763. X    FREE(node->data);
  1764. X    FREE(node);
  1765. X    list->n--;
  1766. X
  1767. X    return(lSUCCESS);
  1768. X}
  1769. X
  1770. X/*******************************************************************************
  1771. X** Get information about node by index.
  1772. X**
  1773. X** Parameters:
  1774. X**    In    int    id    identifier of linked list
  1775. X**    In    int    index    index of node which must be inspected
  1776. X**    Out    int    *size    size of data of node
  1777. X**    Out    int    *flag    user information flag
  1778. X**
  1779. X** Return on success:
  1780. X**    lSUCCESS
  1781. X** Return on error:
  1782. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
  1783. X*/
  1784. Xint
  1785. XlInfoIndxNode(id, index, size, flag)
  1786. Xint    id, index, *size, *flag;
  1787. X{
  1788. X    ListPtr    list;
  1789. X    int    rtrn;
  1790. X
  1791. X    rtrn = setIndxNode(id, index, "lInfoIndxNode");
  1792. X    if (rtrn != lSUCCESS)
  1793. X        return(rtrn);    /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
  1794. X
  1795. X    list = getAddress(id);    /* already checked in setIndxNode */
  1796. X
  1797. X        /* copy information */
  1798. X    *size = (list->current)->size;
  1799. X    *flag = (list->current)->flag;
  1800. X
  1801. X    return(lSUCCESS);
  1802. X}
  1803. X
  1804. X/*******************************************************************************
  1805. X** Get node by index.
  1806. X**
  1807. X** Parameters:
  1808. X**    In    int    id    identifier of linked list
  1809. X**    In    int    index    index of node which must be retrieved
  1810. X**    Out    Byte    *data    data of node
  1811. X**    In    int    size    size of data
  1812. X**
  1813. X** Return on success:
  1814. X**    lSUCCESS, lFIRST, lLAST
  1815. X** Return on error:
  1816. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX, lSIZE_NE
  1817. X*/
  1818. Xint
  1819. XlGetIndxNode(id, index, data, size)
  1820. Xint    id, index, size;
  1821. XByte    *data;
  1822. X{
  1823. X    ListPtr    list;
  1824. X    int    rtrn;
  1825. X
  1826. X    rtrn = setIndxNode(id, index, "lGetIndxNode");
  1827. X    if (rtrn != lSUCCESS)
  1828. X        return(rtrn);    /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
  1829. X
  1830. X    list = getAddress(id);    /* already checked in setIndxNode */
  1831. X
  1832. X        /* expected data and node must have same size */
  1833. X    if ((list->current)->size != size) {
  1834. X        lError("lGetIndxNode", lSIZE_NE, size, (list->current)->size,
  1835. X            NULL);
  1836. X        return(lSIZE_NE);
  1837. X    }
  1838. X
  1839. X    BYTE_COPY((list->current)->data, data, size);
  1840. X
  1841. X    if (list->n == 1)
  1842. X        return(lLAST);
  1843. X    else if (list->current == list->first)
  1844. X        return(lFIRST);
  1845. X    else if (list->current == list->last)
  1846. X        return(lLAST);
  1847. X
  1848. X    return(lSUCCESS);
  1849. X}
  1850. X
  1851. X/*******************************************************************************
  1852. X** Update node by index.
  1853. X**
  1854. X** Parameters:
  1855. X**    In    int    id    identifier of linked list
  1856. X**    In    int    index    index of node which must be updated
  1857. X**    In    Byte    *data    updated data of node
  1858. X**    In    int    size    size of data
  1859. X**    In    int    flag    updated user information flag
  1860. X**
  1861. X** Return on success:
  1862. X**    lSUCCESS
  1863. X** Return on error:
  1864. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
  1865. X*/
  1866. Xint
  1867. XlUpdIndxNode(id, index, data, size, flag)
  1868. Xint    id, index, size, flag;
  1869. XByte    *data;
  1870. X{
  1871. X    ListPtr    list;
  1872. X    int    rtrn;
  1873. X
  1874. X    rtrn = setIndxNode(id, index, "lUpdIndxNode");
  1875. X    if (rtrn != lSUCCESS)
  1876. X        return(rtrn);    /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
  1877. X
  1878. X    list = getAddress(id);    /* already checked in setIndxNode */
  1879. X
  1880. X        /* if same size, replace node by updated node */
  1881. X        /* if not same size, insert updated node on current place */
  1882. X    if ((list->current)->size != size) {
  1883. X        FREE((list->current)->data);
  1884. X        CALLOC((list->current)->data, Byte, size);
  1885. X        (list->current)->size = size;
  1886. X    }
  1887. X    (list->current)->flag = flag;
  1888. X    BYTE_COPY(data, (list->current)->data, size);
  1889. X
  1890. X    return(lSUCCESS);
  1891. X}
  1892. X
  1893. X/*******************************************************************************
  1894. X** Delete node by index.
  1895. X**
  1896. X** Parameters:
  1897. X**    In    int    id    identifier of linked list
  1898. X**    In    int    index    index of node which must be deleted
  1899. X**
  1900. X** Return on success:
  1901. X**    lSUCCESS
  1902. X** Return on error:
  1903. X**    lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
  1904. X*/
  1905. Xint
  1906. XlDelIndxNode(id, index)
  1907. Xint    id, index;
  1908. X{
  1909. X    int    rtrn;
  1910. X
  1911. X    rtrn = setIndxNode(id, index, "lDelIndxNode");
  1912. X    if (rtrn != lSUCCESS)
  1913. X        return(rtrn);    /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
  1914. X
  1915. X    return(lDelNode(id, lCURRENT));    /* lSUCCESS */
  1916. X}
  1917. X
  1918. X/* ---------- static local functions ---------------------------------------- */
  1919. X
  1920. X/* get address of list data */
  1921. Xstatic ListPtr
  1922. XgetAddress(id)
  1923. Xint    id;
  1924. X{
  1925. X    ListPtr    list;
  1926. X
  1927. X    list = ld;
  1928. X    while (list != NULL && list->id != id)
  1929. X        list = list->nxt;
  1930. X
  1931. X    if (list == NULL)
  1932. X        return(NULL);    /* id not found */
  1933. X
  1934. X    if (list->sd == 0 && list->cc == 0)    /* deleted linked list */
  1935. X        return(NULL);    /* deleted linked list */
  1936. X
  1937. X    return(list);
  1938. X}
  1939. X
  1940. X/* delete nodes of a linked list */
  1941. Xstatic void
  1942. XdelNodes(node, n)
  1943. XNodePtr    node;
  1944. Xint    n;
  1945. X{
  1946. X    NodePtr    nxt;
  1947. X    int    i;
  1948. X
  1949. X    for (i=0; i<n; i++) {
  1950. X        nxt = node->nxt;
  1951. X        FREE(node->data);
  1952. X        FREE(node);
  1953. X        node = nxt;
  1954. X    }
  1955. X}
  1956. X
  1957. X/* delete info about linked list */
  1958. Xstatic void
  1959. XdelListInfo(list)
  1960. XListPtr    list;
  1961. X{
  1962. X    ListPtr    nxt;
  1963. X
  1964. X    while (list != NULL) {
  1965. X        nxt = list->nxt;
  1966. X        FREE(list);
  1967. X        list = nxt;
  1968. X    }
  1969. X}
  1970. X
  1971. X/* print error message in 'lERROR_FILE' when '-DERROR_FILE' is added as
  1972. X** cc option in the makefile */
  1973. Xstatic void
  1974. XlError(str, code, int1, int2, str1)
  1975. Xchar    *str, *str1;
  1976. Xint    code, int1, int2;
  1977. X{
  1978. X#ifdef ERROR_FILE
  1979. X    char    mess[60];
  1980. X    FILE    *fpError, *fopen();
  1981. X
  1982. X    switch (code) {
  1983. X    case lWRONG_SD:
  1984. X        sprintf(mess, "Parameter 'sd' has wrong value : %d", int1);
  1985. X        break;
  1986. X    case lWRONG_CC:
  1987. X        sprintf(mess, "Parameter 'cc' has wrong value : %d", int1);
  1988. X        break;
  1989. X    case lWRONG_WHERE:
  1990. X        sprintf(mess, "Parameter 'where' has wrong value : %d", int1);
  1991. X        break;
  1992. X    case lWRONG_WHICH:
  1993. X        sprintf(mess, "Parameter 'which' has wrong value : %d", int1);
  1994. X        break;
  1995. X    case lUNKNOWN_ID:
  1996. X        sprintf(mess, "List id '%d' is unknown", int1);
  1997. X        break;
  1998. X    case lUNKNOWN_FUNC:
  1999. X        sprintf(mess, "Function '%d' is unknown", int1);
  2000. X        break;
  2001. X    case lNO_LIST:
  2002. X        sprintf(mess, "There are no lists defined");
  2003. X        break;
  2004. X    case lEMPTY_LIST:
  2005. X#ifdef DEBUG
  2006. X        sprintf(mess, "List '%d' is empty", int1);
  2007. X        break;
  2008. X#else
  2009. X        return;
  2010. X#endif
  2011. X    case lEOL:
  2012. X#ifdef DEBUG
  2013. X        sprintf(mess, "End of list '%d' reached", int1);
  2014. X        break;
  2015. X#else
  2016. X        return;
  2017. X#endif
  2018. X    case lNOT_FOUND:
  2019. X#ifdef DEBUG
  2020. X        sprintf(mess, "Node not found in list '%d'", int1);
  2021. X        break;
  2022. X#else
  2023. X        return;
  2024. X#endif
  2025. X    case lNOT_DOUBLY:
  2026. X        sprintf(mess, "List '%d' is not doubly linked", int1);
  2027. X        break;
  2028. X    case lSIZE_NE:
  2029. X        sprintf(mess,
  2030. X            "Size of expected data '%d' and node '%d' not equal",
  2031. X            int1, int2);
  2032. X        break;
  2033. X    case lWRONG_INDEX:
  2034. X        sprintf(mess, "Index '%d' out of range [1:%d]", int1, int2);
  2035. X        break;
  2036. X    case lOPEN_ERROR:
  2037. X        sprintf(mess, "Can't open dump-file '%s'\n", str1);
  2038. X        break;
  2039. X    case lWRONG_ORDER:
  2040. X        sprintf(mess, "Parameter 'order' has wrong value : %d", int1);
  2041. X        break;
  2042. X    case lWRONG_THEORY:
  2043. X        sprintf(mess, "Parameter 'theory' has wrong value : %d", int1);
  2044. X        break;
  2045. X    }
  2046. X
  2047. X    fpError = fopen(lERROR_FILE, "a");
  2048. X    if (fpError == NULL) {
  2049. X        fprintf(stderr, "Can't open error-file '%s'\n", lERROR_FILE);
  2050. X        fprintf(stderr, "Error, '%s': %s\n", str, mess);
  2051. X    } else {
  2052. X        fprintf(fpError, "Error in '%s': %s\n", str, mess);
  2053. X        fclose(fpError);
  2054. X    }
  2055. X#endif
  2056. X}
  2057. X
  2058. Xstatic int
  2059. XsetWhchNode(id, which, fname)
  2060. Xint    id, which;
  2061. Xchar    *fname;
  2062. X{
  2063. X    ListPtr        list;
  2064. X    static int    set[] = { lFIRST, lNEXT, lCURRENT, lPREVIOUS, lLAST };
  2065. X
  2066. X        /* check parameters */
  2067. X    if ((list = getAddress(id)) == NULL) {
  2068. X        lError(fname, lUNKNOWN_ID, id, 0, NULL);
  2069. X        return(lUNKNOWN_ID);
  2070. X    }
  2071. X    if (list->n == 0) {
  2072. X        lError(fname, lEMPTY_LIST, id, 0, NULL);
  2073. X        return(lEMPTY_LIST);
  2074. X    }
  2075. X    if (intInSet(which, set, 5) != 0) {
  2076. X        lError(fname, lWRONG_WHICH, which, 0, NULL);
  2077. X        return(lWRONG_WHICH);
  2078. X    }
  2079. X
  2080. X        /* search for requested node */
  2081. X    switch (which) {
  2082. X    case lFIRST:
  2083. X        list->current = list->first;
  2084. X        break;
  2085. X    case lNEXT:
  2086. X        if ((list->current)->nxt == NULL) {
  2087. X            lError(fname, lEOL, id, 0, NULL);
  2088. X            return(lEOL);
  2089. X        }
  2090. X        list->current = (list->current)->nxt;
  2091. X        break;
  2092. X    case lCURRENT:
  2093. X        break;
  2094. X    case lPREVIOUS:
  2095. X        if (list->sd != lDOUBLY) {
  2096. X            lError(fname, lNOT_DOUBLY, id, 0, NULL);
  2097. X            return(lNOT_DOUBLY);
  2098. X        }
  2099. X        if ((list->current)->prv == NULL) {
  2100. X            lError(fname, lEOL, id, 0, NULL);
  2101. X            return(lEOL);
  2102. X        }
  2103. X        list->current = (list->current)->prv;
  2104. X        break;
  2105. X    case lLAST:
  2106. X        list->current = list->last;
  2107. X        break;
  2108. X    }
  2109. X
  2110. X    return(lSUCCESS);
  2111. X}
  2112. X
  2113. Xstatic int
  2114. XsetIndxNode(id, index, fname)
  2115. Xint    id, index;
  2116. Xchar    *fname;
  2117. X{
  2118. X    ListPtr    list;
  2119. X    int    i;
  2120. X
  2121. X        /* check parameters */
  2122. X    if ((list = getAddress(id)) == NULL) {
  2123. X        lError(fname, lUNKNOWN_ID, id, 0, NULL);
  2124. X        return(lUNKNOWN_ID);
  2125. X    }
  2126. X    if (list->n == 0) {
  2127. X        lError(fname, lEMPTY_LIST, id, 0, NULL);
  2128. X        return(lEMPTY_LIST);
  2129. X    }
  2130. X    if (index < 1 || list->n < index) {
  2131. X        lError(fname, lWRONG_INDEX, index, list->n, NULL);
  2132. X        return(lWRONG_INDEX);
  2133. X    }
  2134. X
  2135. X    if (index == 1)
  2136. X        list->current = list->first;
  2137. X    else if (index == list->n)
  2138. X        list->current = list->last;
  2139. X    else {
  2140. X        list->current = list->first;
  2141. X        for (i=1; i<index; i++)
  2142. X            list->current = (list->current)->nxt;
  2143. X    }
  2144. X
  2145. X    return(lSUCCESS);
  2146. X}
  2147. X
  2148. X/* local function for QUICK sort */
  2149. Xstatic void
  2150. Xpartition(array, order, func, lb, ub, pj)
  2151. XNodePtr    *array;
  2152. Xint    order, lb, ub, *pj;
  2153. XFunc    func;
  2154. X{
  2155. X    int    down, up, cmp;
  2156. X    NodePtr    temp, a;
  2157. X
  2158. X    a = array[lb];
  2159. X    up = ub;
  2160. X    down = lb;
  2161. X
  2162. X    while (down < up) {
  2163. X        cmp = (*func)(array[down]->data, a->data);
  2164. X        while (down < ub
  2165. X         && ((order == lASCENDING && (cmp == l1LT2 || cmp == lSAME))
  2166. X         || (order == lDESCENDING && (cmp == l2LT1 || cmp == lSAME)))) {
  2167. X            down++;
  2168. X            cmp = (*func)(array[down]->data, a->data);
  2169. X        }
  2170. X        cmp = (*func)(array[up]->data, a->data);
  2171. X        while ((order == lASCENDING && cmp == l2LT1)
  2172. X         || (order == lDESCENDING && cmp == l1LT2)) {
  2173. X            up--;
  2174. X            cmp = (*func)(array[up]->data, a->data);
  2175. X        }
  2176. X
  2177. X        if (down < up) {    /* interchange */
  2178. X            temp = array[down];
  2179. X            array[down] = array[up];
  2180. X            array[up] = temp;
  2181. X        }
  2182. X    }
  2183. X    array[lb] = array[up];
  2184. X    array[up] = a;
  2185. X    *pj = up;
  2186. X}
  2187. X
  2188. X/* local function for QUICK sort */
  2189. Xstatic int
  2190. Xstack_empty(id)
  2191. Xint    id;
  2192. X{
  2193. X    int    sd, cc, n;
  2194. X
  2195. X        /* check to see if linked list exists */
  2196. X    if (lInfo(id, &sd, &cc, &n) == lUNKNOWN_ID)
  2197. X        return(1);    /* linked list is non-existant */
  2198. X    if (n == 0)
  2199. X        return(1);
  2200. X    return(0);
  2201. X}
  2202. X
  2203. X/* ---------- static local functions (~anita/Tools/Clib) -------------------- */
  2204. X
  2205. X/* check if integer belongs to set of integers */
  2206. Xstatic int
  2207. XintInSet(intgr, set, set_n)
  2208. Xint    intgr, *set, set_n;
  2209. X{
  2210. X    int    i = 0;
  2211. X
  2212. X    while (set[i] != intgr && i < set_n)
  2213. X        i++;
  2214. X
  2215. X        /* 0 = yes, 1 = no */
  2216. X    return((i == set_n) ? 1 : 0);
  2217. X}
  2218. END_OF_FILE
  2219.   if test 40617 -ne `wc -c <'list.c'`; then
  2220.     echo shar: \"'list.c'\" unpacked with wrong size!
  2221.   fi
  2222.   # end of 'list.c'
  2223. fi
  2224. if test -f 'sorted.c' -a "${1}" != "-c" ; then 
  2225.   echo shar: Will not clobber existing file \"'sorted.c'\"
  2226. else
  2227.   echo shar: Extracting \"'sorted.c'\" \(8260 characters\)
  2228.   sed "s/^X//" >'sorted.c' <<'END_OF_FILE'
  2229. X#include    <stdio.h>
  2230. X#include    <string.h>
  2231. X#include    "list.h"
  2232. X
  2233. Xtypedef struct person {
  2234. X    char    lastname[15];
  2235. X    char    firstname[15];
  2236. X} Person, *PersonPtr;
  2237. Xint    personSz = sizeof(Person);
  2238. X
  2239. X#ifdef ANSI
  2240. Xstatic void    addPerson(int id, char *first, char *last);
  2241. Xstatic void    addPersonSorted(int id, char *first, char *last);
  2242. Xstatic int    compare(PersonPtr p1, PersonPtr p2, int order);
  2243. Xstatic int    fndNxtPerson(char *last, PersonPtr data);
  2244. Xstatic int    sortPerson(int id);
  2245. X#else
  2246. Xstatic void    addPerson(), addPersonSorted();
  2247. Xstatic int    compare(), fndNxtPerson(), sortPerson();
  2248. X#endif
  2249. X
  2250. Xint
  2251. Xmain()
  2252. X{
  2253. X    Person    person;
  2254. X    int    id, code;
  2255. X
  2256. X/* ------- first solution --------------------------------------------------- */
  2257. Xfprintf(stdout, "..... Insert sorted by last name .....\n");
  2258. X    id = lDef(lSINGLY, lCHAIN);
  2259. X    addPersonSorted(id, "Ernie", "Makris");
  2260. X    addPersonSorted(id, "Anita", "Eijs");
  2261. X    addPersonSorted(id, "John", "Johnson");
  2262. X    addPersonSorted(id, "Bart", "Simpson");
  2263. X    addPersonSorted(id, "James", "Bond");
  2264. X    addPersonSorted(id, "Al", "Bundy");
  2265. X
  2266. X    code = lGetNode(id, lFIRST, &person, personSz);
  2267. X    while (code != lEOL && code != lEMPTY_LIST) {
  2268. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2269. X        code = lGetNode(id, lNEXT, &person, personSz);
  2270. X    }
  2271. X    code = lDel(id);
  2272. X
  2273. X/* ------- second solution -------------------------------------------------- */
  2274. Xfprintf(stdout, "..... Insert unsorted .....\n");
  2275. X    id = lDef(lSINGLY, lCHAIN);
  2276. X    addPerson(id, "Ernie", "Makris");
  2277. X    addPerson(id, "Anita", "Eijs");
  2278. X    addPerson(id, "John", "Johnson");
  2279. X    addPerson(id, "Bart", "Simpson");
  2280. X    addPerson(id, "James", "Bond");
  2281. X    addPerson(id, "Al", "Bundy");
  2282. X
  2283. X    code = lGetNode(id, lFIRST, &person, personSz);
  2284. X    while (code != lEOL && code != lEMPTY_LIST) {
  2285. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2286. X        code = lGetNode(id, lNEXT, &person, personSz);
  2287. X    }
  2288. X
  2289. Xfprintf(stdout, "..... Sort by last name .....\n");
  2290. X    id = sortPerson(id);
  2291. X
  2292. X    code = lGetNode(id, lFIRST, &person, personSz);
  2293. X    while (code != lEOL && code != lEMPTY_LIST) {
  2294. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2295. X        code = lGetNode(id, lNEXT, &person, personSz);
  2296. X    }
  2297. X
  2298. X    code = lDel(id);
  2299. X
  2300. X/* ------- third solution --------------------------------------------------- */
  2301. Xfprintf(stdout, "..... Insert unsorted .....\n");
  2302. X    id = lDef(lSINGLY, lCHAIN);
  2303. X    addPerson(id, "Ernie", "Makris");
  2304. X    addPerson(id, "Anita", "Eijs");
  2305. X    addPerson(id, "John", "Johnson");
  2306. X    addPerson(id, "Bart", "Simpson");
  2307. X    addPerson(id, "James", "Bond");
  2308. X    addPerson(id, "Al", "Bundy");
  2309. X
  2310. X    code = lGetNode(id, lFIRST, &person, personSz);
  2311. X    while (code != lEOL && code != lEMPTY_LIST) {
  2312. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2313. X        code = lGetNode(id, lNEXT, &person, personSz);
  2314. X    }
  2315. X
  2316. Xfprintf(stdout, "..... Sort by last name ..... Bubble ASCENDING .....\n");
  2317. X    code = lSort(id, lASCENDING, lBUBBLE, compare);
  2318. X
  2319. X    code = lGetNode(id, lFIRST, &person, personSz);
  2320. X    while (code != lEOL && code != lEMPTY_LIST) {
  2321. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2322. X        code = lGetNode(id, lNEXT, &person, personSz);
  2323. X    }
  2324. X
  2325. Xfprintf(stdout, "..... Sort by last name ..... Bubble DESCENDING .....\n");
  2326. X    code = lSort(id, lDESCENDING, lBUBBLE, compare);
  2327. X
  2328. X    code = lGetNode(id, lFIRST, &person, personSz);
  2329. X    while (code != lEOL && code != lEMPTY_LIST) {
  2330. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2331. X        code = lGetNode(id, lNEXT, &person, personSz);
  2332. X    }
  2333. X
  2334. Xfprintf(stdout, "..... Sort by last name ..... Heap ASCENDING .....\n");
  2335. X    code = lSort(id, lASCENDING, lHEAP, compare);
  2336. X
  2337. X    code = lGetNode(id, lFIRST, &person, personSz);
  2338. X    while (code != lEOL && code != lEMPTY_LIST) {
  2339. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2340. X        code = lGetNode(id, lNEXT, &person, personSz);
  2341. X    }
  2342. X
  2343. Xfprintf(stdout, "..... Sort by last name ..... Heap DESCENDING .....\n");
  2344. X    code = lSort(id, lDESCENDING, lHEAP, compare);
  2345. X
  2346. X    code = lGetNode(id, lFIRST, &person, personSz);
  2347. X    while (code != lEOL && code != lEMPTY_LIST) {
  2348. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2349. X        code = lGetNode(id, lNEXT, &person, personSz);
  2350. X    }
  2351. X
  2352. Xfprintf(stdout, "..... Sort by last name ..... Insert ASCENDING .....\n");
  2353. X    code = lSort(id, lASCENDING, lINSERT, compare);
  2354. X
  2355. X    code = lGetNode(id, lFIRST, &person, personSz);
  2356. X    while (code != lEOL && code != lEMPTY_LIST) {
  2357. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2358. X        code = lGetNode(id, lNEXT, &person, personSz);
  2359. X    }
  2360. X
  2361. Xfprintf(stdout, "..... Sort by last name ..... Insert DESCENDING .....\n");
  2362. X    code = lSort(id, lDESCENDING, lINSERT, compare);
  2363. X
  2364. X    code = lGetNode(id, lFIRST, &person, personSz);
  2365. X    while (code != lEOL && code != lEMPTY_LIST) {
  2366. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2367. X        code = lGetNode(id, lNEXT, &person, personSz);
  2368. X    }
  2369. X
  2370. Xfprintf(stdout, "..... Sort by last name ..... Quick ASCENDING .....\n");
  2371. X    code = lSort(id, lASCENDING, lQUICK, compare);
  2372. X
  2373. X    code = lGetNode(id, lFIRST, &person, personSz);
  2374. X    while (code != lEOL && code != lEMPTY_LIST) {
  2375. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2376. X        code = lGetNode(id, lNEXT, &person, personSz);
  2377. X    }
  2378. X
  2379. Xfprintf(stdout, "..... Sort by last name ..... Quick DESCENDING .....\n");
  2380. X    code = lSort(id, lDESCENDING, lQUICK, compare);
  2381. X
  2382. X    code = lGetNode(id, lFIRST, &person, personSz);
  2383. X    while (code != lEOL && code != lEMPTY_LIST) {
  2384. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2385. X        code = lGetNode(id, lNEXT, &person, personSz);
  2386. X    }
  2387. X
  2388. Xfprintf(stdout, "..... Sort by last name ..... Selection ASCENDING .....\n");
  2389. X    code = lSort(id, lASCENDING, lSELECTION, compare);
  2390. X
  2391. X    code = lGetNode(id, lFIRST, &person, personSz);
  2392. X    while (code != lEOL && code != lEMPTY_LIST) {
  2393. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2394. X        code = lGetNode(id, lNEXT, &person, personSz);
  2395. X    }
  2396. X
  2397. Xfprintf(stdout, "..... Sort by last name ..... Selection DESCENDING .....\n");
  2398. X    code = lSort(id, lDESCENDING, lSELECTION, compare);
  2399. X
  2400. X    code = lGetNode(id, lFIRST, &person, personSz);
  2401. X    while (code != lEOL && code != lEMPTY_LIST) {
  2402. X        fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
  2403. X        code = lGetNode(id, lNEXT, &person, personSz);
  2404. X    }
  2405. X
  2406. X    code = lDel(id);
  2407. X}
  2408. X
  2409. Xstatic void
  2410. XaddPersonSorted(id, first, last)
  2411. Xint    id;
  2412. Xchar    *first, *last;
  2413. X{
  2414. X    Person    person, new;
  2415. X    char    tmp[15];
  2416. X    int    code;
  2417. X
  2418. X        /* find next last name */
  2419. X    strcpy(&tmp[0], last);
  2420. X    code = lFndNode(id, lFIRST, fndNxtPerson, &tmp[0], &person, personSz);
  2421. X
  2422. X    strcpy(new.lastname, last);
  2423. X    strcpy(new.firstname, first);
  2424. X
  2425. X        /* insert data in alphabetical order */
  2426. X    if (code == lEMPTY_LIST || code == lFIRST)
  2427. X        code = lInsNode(id, lFIRST, &new, personSz, 0);
  2428. X    else if (code == lNOT_FOUND)
  2429. X        code = lInsNode(id, lLAST, &new, personSz, 0);
  2430. X    else
  2431. X        code = lInsNode(id, lBEFORE, &new, personSz, 0);
  2432. X}
  2433. X
  2434. X/* find next by specified last name before which specified name must be */
  2435. X/* inserted (alphabetical order) */
  2436. Xstatic int
  2437. Xcompare(p1, p2, order)
  2438. XPersonPtr    p1, p2;
  2439. Xint        order;
  2440. X{
  2441. X    int    k = strcmp(p1->lastname, p2->lastname);
  2442. X
  2443. X    if (k == 0)
  2444. X        return(lSAME);
  2445. X    else if (k > 0)
  2446. X        return(l2LT1);
  2447. X    else if (k < 0)
  2448. X        return(l1LT2);
  2449. X}
  2450. X
  2451. X/* find next by specified last name before which specified name must be */
  2452. X/* inserted (alphabetical order) */
  2453. Xstatic int
  2454. XfndNxtPerson(last, data)
  2455. Xchar        *last;
  2456. XPersonPtr    data;
  2457. X{
  2458. X    if (strcmp(last, data->lastname) < 0)
  2459. X        return(lFOUND);
  2460. X    else
  2461. X        return(lNOT_FOUND);
  2462. X}
  2463. X
  2464. Xstatic void
  2465. XaddPerson(id, first, last)
  2466. Xint    id;
  2467. Xchar    *first, *last;
  2468. X{
  2469. X    Person    new;
  2470. X    int    code;
  2471. X
  2472. X    strcpy(new.lastname, last);
  2473. X    strcpy(new.firstname, first);
  2474. X    code = lInsNode(id, lLAST, &new, personSz, 0);
  2475. X}
  2476. X
  2477. Xstatic int
  2478. XsortPerson(id)
  2479. Xint    id;
  2480. X{
  2481. X    Person    person, next;
  2482. X    char    tmp[15];
  2483. X    int    code, id2;
  2484. X
  2485. X    id2 = lDef(lSINGLY, lCHAIN);
  2486. X
  2487. X    code = lGetNode(id, lFIRST, &person, personSz);
  2488. X    while (code != lEOL && code != lEMPTY_LIST) {
  2489. X
  2490. X            /* find next last name */
  2491. X        strcpy(&tmp[0], person.lastname);
  2492. X        code = lFndNode(id2, lFIRST, fndNxtPerson, &tmp[0], &next,
  2493. X            personSz);
  2494. X
  2495. X            /* insert data in alphabetical order */
  2496. X        if (code == lEMPTY_LIST || code == lFIRST)
  2497. X            code = lInsNode(id2, lFIRST, &person, personSz, 0);
  2498. X        else if (code == lNOT_FOUND)
  2499. X            code = lInsNode(id2, lLAST, &person, personSz, 0);
  2500. X        else
  2501. X            code = lInsNode(id2, lBEFORE, &person, personSz, 0);
  2502. X
  2503. X        code = lGetNode(id, lNEXT, &person, personSz);
  2504. X    }
  2505. X    code = lDel(id);
  2506. X    return(id2);
  2507. X}
  2508. END_OF_FILE
  2509.   if test 8260 -ne `wc -c <'sorted.c'`; then
  2510.     echo shar: \"'sorted.c'\" unpacked with wrong size!
  2511.   fi
  2512.   # end of 'sorted.c'
  2513. fi
  2514. echo shar: End of archive 1 \(of 2\).
  2515. cp /dev/null ark1isdone
  2516. MISSING=""
  2517. for I in 1 2 ; do
  2518.     if test ! -f ark${I}isdone ; then
  2519.     MISSING="${MISSING} ${I}"
  2520.     fi
  2521. done
  2522. if test "${MISSING}" = "" ; then
  2523.     echo You have unpacked both archives.
  2524.     rm -f ark[1-9]isdone
  2525. else
  2526.     echo You still must unpack the following archives:
  2527.     echo "        " ${MISSING}
  2528. fi
  2529. exit 0
  2530. exit 0 # Just in case...
  2531.