home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume38
/
linkedlist
/
part01
next >
Wrap
Text File
|
1993-08-12
|
64KB
|
2,531 lines
Newsgroups: comp.sources.misc
From: anita@bouw.tno.nl (Anita Eijs)
Subject: v38i117: linkedlist - Generic Linked List Package, Part01/02
Message-ID: <csm-v38i117=linkedlist.091645@sparky.Sterling.COM>
X-Md4-Signature: efd03753dbd25f67c85d0dd22c51fcc8
Sender: kent@sparky.sterling.com (Kent Landfield)
Organization: Sterling Software
Date: Thu, 12 Aug 1993 14:17:28 GMT
Approved: kent@sparky.sterling.com
Submitted-by: anita@bouw.tno.nl (Anita Eijs)
Posting-number: Volume 38, Issue 117
Archive-name: linkedlist/part01
Environment: UNIX, MS-DOS, VAX/VMS, Macintosh, Amiga
Supersedes: linkedlist: Volume 37, Issue 36-37
LinkedList Version: 0.10, August 1992
The Generic Linked List Package is a package to define, create, update,
query and delete one or more (nodes of) linked lists, to sort linked
lists, and so on. The user doesn't have to take care of allocating a
number of bytes for a node, inserting on the right place, deleting and
freeing a node and so on.
Different kind of linked lists can be defined. In a singly linked list
each node points to the next node, in a doubly linked list each node
points also to the previous node. A chain is a list in which the last
node has a NULL pointer and in a circular linked list the last node
points back to the first node.
The package consists of a set of C-functions :
lDef define linked list
lInfo get information about linked list
lSize get number of nodes of linked list
lSort sort linked list
lDel delete linked list
lDelAll delete all linked lists
lDump dump a linked list to a file
lUndump undump a linked list from a file
lInsNode insert node
lInfoNode get information about node
lGetNode get node
lFndNode find node
lFndFlagNode get node by flag
lUpdNode update current node
lDelNode delete node
lInfoIndxNode get information about node by index
lGetIndxNode get node by index
lUpdIndxNode update node by index
lDelIndxNode delete node by index
The Generic Linked List Package is ported to UNIX, MS-DOS, VAX/VMS and
Macintosh.
Please look at the README file and the manual pages for more detailed
information !
Anita
+--------------------------------------------------------+
| TNO - BOUW, PO-box 49, 2600 AA Delft, The Netherlands |
| FAX : +31 15 122182 E-MAIL : anita@bouw.tno.nl |
+--------------------------------------------------------+
------- cut here ---------------------------------------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: README Doc Doc/lGetNode.3 example.c list.c sorted.c
# Wrapped by kent@sparky on Thu Aug 12 09:13:07 1993
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 1 (of 2)."'
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2301 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X Generic Linked List
X ===================
X
X
XThe distribution of the Generic Linked List package (Version 0.10, August 1993)
Xincludes the following files:
X
X Doc/Intro.3 - [nt]roff manual pages
X Doc/lDef.3
X Doc/lDel.3
X Doc/lDelAll.3
X Doc/lDelIndxNode.3
X Doc/lDelNode.3
X Doc/lDump.3
X Doc/lFndFlagNode.3
X Doc/lFndNode.3
X Doc/lGetNode.3
X Doc/lGetIndxNode.3
X Doc/lInfo.3
X Doc/lInfoIndxNode.3
X Doc/lInfoNode.3
X Doc/lInsNode.3
X Doc/lSize.3
X Doc/lSort.3
X Doc/lUndump.3
X Doc/lUpdIndxNode.3
X Doc/lUpdNode.3
X Makefile - Berkeley or System V Makefile
X Makefile.BCC - Borland C++ v3.1 Makefile
X ReadMe.BCC - some additional info about Borland port
X Makefile.Amiga - Amiga SAS C 6.0 Makefile
X ReadMe.Amiga - some additional info about Amiga port
X README - this file !
X CHANGES - list of changes
X Tools_makerule - make rules for Makefile
X example.c - example of use of Generic Linked List routines
X sorted.c - example of several sorting solutions
X sorttest.c - test of sorting theories in lSort
X list.c - Generic Linked List sources
X list.h - Generic Linked List defines and prototypes
X
X
XThe installation of the Generic Linked List library is pretty simple :
X
X1) Check the environment settings (TOOLS_HOME, DIR, LIB and RULE) in
X the Makefile. (Skip symbol define ERROR_FILE from CFLAGS.)
X
X2) Check the environment settings (RANLIB) in the Tools_makerule.
X
X3) Be sure that the LIB-directory is created.
X
X4) Enter 'make newlib' at the UNIX prompt.
X
X5) Enter 'make test' or 'make example' to create the executable of
X the program 'example' at the UNIX prompt.
X
X
XThe Generic Linked List package is also ported to MSDOS, VAX-VMS, Macintosh
Xand Amiga. On those machines the library was not created, but the source-
Xfiles list.c and list.h were treated the same as all the other source-files
X(*.[ch]) of the program.
X
X
XThe Generic Linked List is in the public domain. It is available at our FTP
Xarchive (ftp.tno.nl or hermes.bouw.tno.nl), just retrieve the files :
X /pub/TNO/BOUW/Bouwinf/linkedlist_0.10.README
X /pub/TNO/BOUW/Bouwinf/linkedlist_0.10.shar
X
X
XIf you have any comments, suggestions, or find any bugs, or make any changes
Xyou'd like to share, please let me know.
X
X
XAnita Eijs (anita@bouw.tno.nl)
XTNO - BOUW - BouwInformatica
XP.O. Box 49
X2600 AA Delft
XThe Netherlands
XFAX : +31 15 122182
END_OF_FILE
if test 2301 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test ! -d 'Doc' ; then
echo shar: Creating directory \"'Doc'\"
mkdir 'Doc'
fi
if test -f 'Doc/lGetNode.3' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Doc/lGetNode.3'\"
else
echo shar: Extracting \"'Doc/lGetNode.3'\" \(1402 characters\)
sed "s/^X//" >'Doc/lGetNode.3' <<'END_OF_FILE'
X'.so tmac.clman
X.TH "lGetNode"
X.IX lGetNode
X.SH NAME
XlGetNode - Get node.
X.SH SYNOPSIS
Xint
X.BR "lGetNode" "(id, which, data, size)"
X.br
X.RT
X.RP
XIn int id identifier of linked list
X.RP
XIn int which which node must be retrieved
X.RP
XOut Byte *data data of node
X.RP
XIn int size size of data
X.DT
X.SH DESCRIPTION
X\fBlGetNode\fP gets the data of a node of a linked list. Which node must
Xbe retrieved can be specified by \fIwhich\fP. The first node, the current
Xnode, the node before or after the current node and the node at the end
Xof the list can be retrieved.
X.br
XBackward retrieving is only possible for doubly linked list. A previous
Xnode can't be retrieved for singly linked lists.
X.br
XWhen the retrieved node is the first or the last node, the return code
Xwill have the value lFIRST or lLAST. For the other nodes the routine
Xreturns lSUCCESS.
XWhen the linked list contains only one node, the return code will have
Xthe value lFIRST, when retrieving backward, and the value lLAST, when
Xretrieving forward.
X.SH PARAMETER DEFINITIONS
X.if t .ta 0.2i 1.5i
X\fIwhich\fP :
X.nf
X lFIRST first node
X lPREVIOUS previous node
X lCURRENT current node
X lNEXT next node
X lLAST last node
X.fi
X.SH RETURN CODES
X.nf
XReturn on success :
X lSUCCESS, lFIRST, lLAST
XReturn on error :
X.fi
X.in +0.2i
XlUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lSIZE_NE, lNOT_DOUBLY
X.in -0.2i
X.SH AUTHOR
XAnita Eijs (TNO - Bouw - BouwInformatica)
END_OF_FILE
if test 1402 -ne `wc -c <'Doc/lGetNode.3'`; then
echo shar: \"'Doc/lGetNode.3'\" unpacked with wrong size!
fi
# end of 'Doc/lGetNode.3'
fi
if test -f 'example.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'example.c'\"
else
echo shar: Extracting \"'example.c'\" \(3536 characters\)
sed "s/^X//" >'example.c' <<'END_OF_FILE'
X#ifdef AMIGA
X#include <string.h>
X#endif
X
X#include <stdio.h>
X#include "list.h"
X
Xtypedef struct rapport {
X char title[30];
X char author[15];
X int date;
X} Rapport;
Xint rapSz = sizeof(Rapport);
X
X#ifdef ANSI
Xstatic void insRap(int id, int where, int flag, char *title, char *author,
X int date);
Xstatic void prRapAll(int id);
Xstatic void prRap(int code, Rapport *rpprt);
Xstatic int search(int *date, Rapport *rpprt);
Xstatic int compare(Rapport *data1, Rapport *data2);
X#else
Xstatic void insRap(), prRapAll(), prRap();
Xstatic int search(), compare();
X#endif
X
Xint
Xmain()
X{
X int id, code, search_date;
X Rapport rap;
X
X id = lDef(lSINGLY, lCHAIN);
X
X insRap(id, lFIRST, 1, "Book 1", "People", 890129);
X insRap(id, lFIRST, 2, "Book 2", "More People", 890130);
X insRap(id, lLAST, 1, "Book 3", "Lots of People", 890131);
X
X fprintf(stdout, "lGetNode\n");
X prRapAll(id);
X
X/*
X** The following routine calls will generate the file '=listError='.
X*/
X fprintf(stdout, "lGetIndxNode\n");
X code = lGetIndxNode(id, 4, &rap, rapSz);
X prRap(code, &rap);
X code = lGetIndxNode(id, 2, &rap, rapSz);
X prRap(code, &rap);
X code = lGetIndxNode(id, -1, &rap, rapSz);
X prRap(code, &rap);
X code = lGetIndxNode(id, 3, &rap, rapSz);
X prRap(code, &rap);
X
X fprintf(stdout, "lFndNode\n");
X search_date = 890129;
X code = lFndNode(id, lFIRST, search, &search_date, &rap, rapSz);
X prRap(code, &rap);
X code = lFndNode(id, lNEXT, search, &search_date, &rap, rapSz);
X prRap(code, &rap);
X code = lFndNode(id, lNEXT, search, &search_date, &rap, rapSz);
X prRap(code, &rap);
X
X/*
X** The following routine call will generate the binary file 'dump'.
X*/
X code = lDump(id, "dump");
X fprintf(stdout, "lDump : %d\n", code);
X
X lDel(id);
X
X id = lUndump("dump");
X fprintf(stdout, "lUndump : %d\n", id);
X
X insRap(id, lFIRST, 4, "Book 4", "The Author", 891127);
X
X prRapAll(id);
X
X fprintf(stdout, "lFndFlagNode\n");
X code = lFndFlagNode(id, lFIRST, 1, &rap, rapSz);
X prRap(code, &rap);
X code = lFndFlagNode(id, lNEXT, 1, &rap, rapSz);
X prRap(code, &rap);
X code = lFndFlagNode(id, lFIRST, 2, &rap, rapSz);
X prRap(code, &rap);
X code = lFndFlagNode(id, lFIRST, 7, &rap, rapSz);
X prRap(code, &rap);
X
X fprintf(stdout, "Untouched list\n");
X prRapAll(id);
X
X fprintf(stdout, "lSort\n");
X lSort(id, lDESCENDING, lBUBBLE, compare);
X prRapAll(id);
X
X fprintf(stdout, "lSort\n");
X lSort(id, lASCENDING, lHEAP, compare);
X prRapAll(id);
X
X lDelAll();
X}
X
Xstatic void
XinsRap(id, where, flag, title, author, date)
Xint id, where, flag, date;
Xchar *title, *author;
X{
X int code;
X Rapport rap;
X
X strcpy(rap.title, title);
X strcpy(rap.author, author);
X rap.date = date;
X code = lInsNode(id, where, &rap, rapSz, flag);
X}
X
Xstatic void
XprRapAll(id)
Xint id;
X{
X int code;
X Rapport rap;
X
X code = lGetNode(id, lFIRST, &rap, rapSz);
X prRap(code, &rap);
X while (code == lFIRST || code == lSUCCESS || code == lLAST) {
X code = lGetNode(id, lNEXT, &rap, rapSz);
X prRap(code, &rap);
X }
X}
X
Xstatic void
XprRap(code, rpprt)
Xint code;
XRapport *rpprt;
X{
X if (code >= 0)
X fprintf(stdout, "Rapport : '%s' '%s' '%d'\n", rpprt->title,
X rpprt->author, rpprt->date);
X else
X fprintf(stdout, "Return code = %d\n", code);
X}
X
Xstatic int
Xsearch(date, rpprt)
Xint *date;
XRapport *rpprt;
X{
X if (rpprt->date > *date)
X return(lFOUND);
X else
X return(lNOT_FOUND);
X}
X
Xstatic int
Xcompare(data1, data2)
XRapport *data1, *data2;
X{
X int k = strcmp(data1->author, data2->author);
X
X if (k == 0)
X return(lSAME); /* key1 == key2 */
X else if (k > 0)
X return(l2LT1); /* key1 > key2 */
X else if (k < 0)
X return(l1LT2); /* key1 < key2 */
X}
END_OF_FILE
if test 3536 -ne `wc -c <'example.c'`; then
echo shar: \"'example.c'\" unpacked with wrong size!
fi
# end of 'example.c'
fi
if test -f 'list.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'list.c'\"
else
echo shar: Extracting \"'list.c'\" \(40617 characters\)
sed "s/^X//" >'list.c' <<'END_OF_FILE'
X/*
X** Anita Eijs TNO-BOUW, BouwInformatica May 1989
X**
X** Generic Linked List Package
X**
X** Updates:
X** 900402 New routine:
X** lIndxNode Get node by index.
X**
X** 900925 New routine:
X** lError print error message in lERROR_FILE
X**
X** 901129 New routines:
X** lDump Dump a linked list to a file.
X** lUndump Undump a linked list from a file.
X**
X** 910301 'Mac'ed by Vinnie:
X** ListPtr = ListyPtr
X** Byte = byte
X** includes
X** typecasts
X**
X** 910316 New routine:
X** lFlagNode Get node by flag.
X**
X** ***** Version 0.7, March 1992 *****
X**
X** 930401 Several updates by Anita and Shane.
X** Some functions renamed:
X** lIndxNode --> lGetIndxNode
X** lFlagNode --> lFndFlagNode
X** New routines:
X** lSort Sort a linked list.
X** lInfoIndxNode Get information about node by index.
X** lDelIndxNode Delete node by index.
X** lUpdIndxNode Update node by index.
X** Parameter where added to lFndFlagNode to find several nodes
X** matching the requested flag.
X** Defines are made more specific; FIRST is renamed in lFIRST, etc.
X**
X** ***** Version 0.8, May 1993 *****
X**
X** ***** Version 0.9, June 1993 *****
X**
X** 930801 New routine:
X** lSize Get number of nodes in linked list.
X**
X** ***** Version 0.10, August 1993 *****
X**
X*/
X
X#ifdef __MSDOS__
X#define MSDOS
X#define ANSI
X#endif
X
X#ifdef UNIX
X#include <malloc.h>
X#endif
X
X#ifdef MSDOS
X#include <malloc.h>
X#include <io.h> /* open, creat, write, read, close */
X /* added for Borland or other MSDOS C compilers */
X#include <stdlib.h>
X#include <fcntl.h>
X#include <sys\types.h>
X#include <sys\stat.h>
X#include <string.h>
X#endif
X
X#ifdef VAXC
X#include <stdlib.h>
X#endif
X
X#ifdef MAC
X#include <unix.h> /* open, creat, write, read, close */
X#include <stddef.h> /* sizeof */
X#include <stdlib.h>
X#endif
X
X#ifdef AMIGA
X#include <stdlib.h>
X#include <fcntl.h> /* open, creat, write, read, close */
X#endif
X
X#include <stdio.h>
X#include "list.h"
X
X/* -------------------------------------------------------------------------- */
X
X#ifndef NULL
X#define NULL 0
X#endif
X
X#undef FREE
X#define FREE(VAR) if (VAR != NULL) free((char *)VAR);
X#undef MALLOC
X#define MALLOC(VAR, TYPE) \
X if ((VAR = (TYPE *)malloc(sizeof(TYPE))) == NULL) { \
X fprintf(stderr, "No more memory for malloc().\n"); \
X return(lOUT_OF_MEMORY); \
X }
X#undef CALLOC
X#define CALLOC(VAR, TYPE, NR) \
X if ((VAR = (TYPE *)calloc(NR, sizeof(TYPE))) == NULL) {\
X fprintf(stderr, "No more memory for calloc().\n"); \
X return(lOUT_OF_MEMORY); \
X }
X
X#undef BYTE_COPY
X#define BYTE_COPY(FROM, TO, SIZE) \
X { \
X register Byte *frm = FROM, \
X *to = TO; \
X int i = SIZE; \
X while (i--) *to++ = *frm++; \
X }
X
X /* necessary for binary file access */
X#ifdef MSDOS
X#define BIN_WRITE O_WRONLY|O_BINARY
X#define BIN_READ O_RDONLY|O_BINARY
X#define PMODE S_IREAD
X#else
X#define BIN_WRITE 1
X#define BIN_READ 0
X#define PMODE 0666
X#endif
X
X/* -------------------------------------------------------------------------- */
X
X#ifndef ANSI
Xtypedef int (*Func)();
Xtypedef unsigned char Byte;
X#endif
X
Xtypedef struct lnode {
X Byte *data; /* data of user */
X int size; /* size (number of bytes) of data */
X int flag; /* user information flag */
X struct lnode *prv; /* previous node */
X struct lnode *nxt; /* next node */
X} ListNode, *NodePtr;
X
Xtypedef struct listhdr {
X int id; /* identifier of linked list */
X int sd; /* singly or doubly linked */
X int cc; /* chain or circular list */
X int n; /* number of nodes */
X NodePtr first; /* address of first node */
X NodePtr current; /* address of current node */
X NodePtr last; /* address of last node */
X struct listhdr *nxt; /* next linked list */
X} ListHdr, *ListPtr;
X
Xtypedef struct header { /* general info of linked list for dump file */
X int sd;
X int cc;
X int n;
X} Header;
X
Xtypedef struct info { /* general info of node for dump file */
X int size;
X int flag;
X} Info;
X
X/* -------------------------------------------------------------------------- */
X
X#ifdef ANSI
Xstatic ListPtr getAddress(int id);
Xstatic void delNodes(NodePtr node, int n);
Xstatic void delListInfo(ListPtr list);
Xstatic void lError(char *str, int code, int int1, int int2, char *str1);
Xstatic int setWhchNode(int id, int which, char *fname);
Xstatic int setIndxNode(int id, int index, char *fname);
Xstatic void partition(NodePtr *array, int order, Func func, int lb, int ub,
X int *pj);
Xstatic int stack_empty(int id);
Xstatic int intInSet(int intgr, int *set, int set_n);
X#else
Xstatic ListPtr getAddress();
Xstatic void delNodes();
Xstatic void delListInfo();
Xstatic void lError();
Xstatic int setWhchNode();
Xstatic int setIndxNode();
Xstatic void partition();
Xstatic int stack_empty();
Xstatic int intInSet();
X#endif
X
X/* -------------------------------------------------------------------------- */
X
Xstatic ListHdr firstlist = { 1, 0, 0, 0, NULL, NULL, NULL, NULL };
Xstatic ListPtr ld = &firstlist;
Xstatic int idMax = 2;
X
X/* -------------------------------------------------------------------------- */
X
X/*******************************************************************************
X** Define a new linked list and create info about it.
X**
X** Parameters:
X** In int sd singly or doubly linked
X** (lSINGLY, lDOUBLY)
X** In int cc chain or circular linked
X** (lCHAIN, lCIRCULAR)
X**
X** Return on success:
X** identifier of linked list
X** Return on error:
X** lWRONG_SD, lWRONG_CC
X*/
Xint
XlDef(sd, cc)
Xint sd, cc;
X{
X ListPtr list, new;
X static int set1[] = { lSINGLY, lDOUBLY },
X set2[] = { lCHAIN, lCIRCULAR };
X
X /* check parameters */
X if (intInSet(sd, set1, 2) != 0) {
X lError("lDef", lWRONG_SD, sd, 0, NULL);
X return(lWRONG_SD);
X }
X if (intInSet(cc, set2, 2) != 0) {
X lError("lDef", lWRONG_CC, cc, 0, NULL);
X return(lWRONG_CC);
X }
X
X list = ld;
X while (list->nxt != NULL && list->sd != 0)
X list = list->nxt;
X if (list->sd != 0) { /* new list */
X MALLOC(new, ListHdr);
X new->id = idMax++;
X new->sd = sd;
X new->cc = cc;
X new->n = 0;
X new->first = new->current = new->last = NULL;
X new->nxt = NULL;
X list->nxt = new;
X return(new->id);
X } else { /* new list on existing place */
X list->sd = sd;
X list->cc = cc;
X return(list->id);
X }
X}
X
X/*******************************************************************************
X** Get info of linked list.
X**
X** Parameters:
X** In int id identifier of linked list
X** Out int *sd singly or doubly linked
X** (lSINGLY, lDOUBLY)
X** Out int *cc chain or cicular linked
X** (lCHAIN, lCIRCULAR)
X** Out int *n number of nodes
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID
X*/
Xint
XlInfo(id, sd, cc, n)
Xint id, *sd, *cc, *n;
X{
X ListPtr list;
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lInfo", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X
X /* copy information */
X *sd = list->sd;
X *cc = list->cc;
X *n = list->n;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Get number of nodes in linked list.
X**
X** Parameters:
X** In int id identifier of linked list
X**
X** Return on success:
X** number of nodes
X** Return on error:
X** lUNKNOWN_ID
X*/
Xint
XlSize(id)
Xint id;
X{
X ListPtr list;
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lInfo", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X
X return(list->n);
X}
X
X/*******************************************************************************
X** Sort a linked list.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int order sorting order
X** (lDESCENDING, lASCENDING)
X** In int theory sorting theory
X** (lBUBBLE, lHEAP, lINSERT, lQUICK, lSELECTION)
X** In Func func number of nodes
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_ORDER, lWRONG_THEORY
X*/
Xint
XlSort(id, order, theory, func)
Xint id, order, theory;
XFunc func;
X{
X int node_n, i, s, f, k, where, j, cmp;
X ListPtr list;
X NodePtr temp, temp2, *array;
X static int set1[] = { lASCENDING, lDESCENDING },
X set2[] = { lBUBBLE, lHEAP, lINSERT, lQUICK,
X lSELECTION };
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lSort", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError("lSort", lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X if (intInSet(order, set1, 2) != 0) {
X lError("lSort", lWRONG_ORDER, id, 0, NULL);
X return(lWRONG_ORDER);
X }
X if (intInSet(theory, set2, 5) != 0) {
X lError("lSort", lWRONG_THEORY, id, 0, NULL);
X return(lWRONG_THEORY);
X }
X
X /* one node is already sorted */
X if (list->n == 1)
X return(lSUCCESS);
X
X node_n = list->n;
X /* allocate 1 extra so I can have a null in it */
X CALLOC(array, NodePtr, node_n+1);
X
X list->current = list->first;
X for (i=0; i < node_n && list->current != NULL; i++) {
X array[i] = list->current;
X list->current = (list->current)->nxt;
X }
X array[node_n] = NULL;
X
X switch (theory) {
X case lBUBBLE: {
X int switched = 1;
X
X for (i=0; i < node_n-1 && switched == 1; i++) {
X switched = 0;
X for (j=0; j < node_n-i-1; j++) {
X cmp = (*func)(array[j]->data, array[j+1]->data);
X if ((order == lASCENDING && cmp == l2LT1)
X || (order == lDESCENDING && cmp == l1LT2)) {
X temp = array[j];
X array[j] = array[j+1];
X array[j+1] = temp;
X
X switched = 1;
X }
X }
X }
X break;
X } /* end of lBUBBLE */
X case lHEAP:
X for (i=1; i<node_n; i++) {
X temp = array[i];
X
X s = i;
X f = (s-1)/2;
X cmp = (*func)(array[f]->data, temp->data);
X while (s > 0 && ((order == lASCENDING && cmp == l1LT2)
X || (order == lDESCENDING && cmp == l2LT1))) {
X array[s] = array[f];
X s = f;
X f = (s-1)/2;
X cmp = (*func)(array[f]->data, temp->data);
X }
X
X array[s] = temp;
X }
X for (i=node_n-1; i>0; i--) {
X temp = array[i];
X array[i] = array[0];
X f = 0;
X
X if (i == 1)
X s = -1;
X else
X s = 1;
X if (i > 2) {
X cmp = (*func)(array[2]->data, array[1]->data);
X if ((order == lASCENDING && cmp == l2LT1)
X || (order == lDESCENDING && cmp == l1LT2))
X s = 2;
X }
X
X if (s >= 0)
X cmp = (*func)(temp->data, array[s]->data);
X while (s >= 0 && ((order == lASCENDING && cmp == l1LT2)
X || (order == lDESCENDING && cmp == l2LT1))) {
X array[f] = array[s];
X f = s;
X
X s = 2*f+1;
X if (s+1 <= i-1) {
X cmp = (*func)(array[s]->data,
X array[s+1]->data);
X if ((order == lASCENDING
X && cmp == l1LT2) ||
X (order == lDESCENDING
X && cmp == l2LT1))
X s = s+1;
X }
X if (s > i-1)
X s = -1;
X if (s >= 0)
X cmp = (*func)(temp->data,
X array[s]->data);
X }
X array[f] = temp;
X }
X break;
X case lINSERT:
X for (i=1; i<node_n; i++) {
X temp = array[i];
X cmp = (*func)(temp->data, array[i-1]->data);
X for (j=i-1; j>=0
X && ((order == lASCENDING && cmp == l1LT2)
X || (order == lDESCENDING && cmp == l2LT1)); j--) {
X temp2 = array[j];
X array[j] = array[j+1];
X array[j+1] = temp2;
X if (j > 0)
X cmp = (*func)(temp->data,
X array[j-1]->data);
X }
X }
X break;
X case lQUICK: {
X struct bndtype {
X int lb;
X int ub;
X } newbnds;
X int newbndsSz = sizeof(struct bndtype),
X stack = lDef(lDOUBLY, lCHAIN);
X
X newbnds.lb = 0;
X newbnds.ub = node_n-1;
X /* basicly a push */
X lInsNode(stack, lLAST, &newbnds, newbndsSz, 0);
X
X /* repeat as long as there are any unsorted subarrays
X ** on the stack */
X while (!stack_empty(stack)) {
X /* a pop */
X lGetNode(stack, lCURRENT, &newbnds, newbndsSz);
X lDelNode(stack, lCURRENT);
X while (newbnds.ub > newbnds.lb) {
X /* process next sub array */
X partition(array, order, (*func), newbnds.lb,
X newbnds.ub, &j);
X /* stack the larger subarray */
X if (j-newbnds.lb > newbnds.ub-j) {
X /* stack lower subarray */
X i = newbnds.ub;
X newbnds.ub = j-1;
X /* basicly a push */
X lInsNode(stack, lLAST, &newbnds,
X newbndsSz, 0);
X /* process upper subarray */
X newbnds.lb = j+1;
X newbnds.ub = i;
X } else {
X /* stack upper subarray */
X i = newbnds.lb;
X newbnds.lb = j+1;
X /* basicly a push */
X lInsNode(stack, lLAST, &newbnds,
X newbndsSz, 0);
X /* process lower subarray */
X newbnds.lb = i;
X newbnds.ub = j-1;
X }
X }
X }
X lDel(stack);
X break;
X } /* end of lQUICK */
X case lSELECTION: {
X int indx;
X
X for (i=node_n-1; i>0; i--) {
X temp = array[0];
X indx = 0;
X
X for (j=1; j<=i; j++) {
X cmp = (*func)(array[j]->data, temp->data);
X if ((order == lASCENDING && cmp == l2LT1)
X || (order == lDESCENDING && cmp == l1LT2)) {
X temp = array[j];
X indx = j;
X }
X }
X array[indx] = array[i];
X array[i] = temp;
X }
X break;
X } /* end of lSELECTION */
X } /* end of switch */
X
X /* init list to start and reset it */
X list->first = array[0];
X list->last = array[node_n-1];
X
X list->current = list->first;
X for (k=0; k<node_n; k++) {
X if (k == 0)
X where = lFIRST;
X else if (k == node_n)
X where = lLAST;
X else
X where = lNEXT;
X
X switch (where) {
X case lFIRST:
X if (list->cc == lCIRCULAR)
X (list->first)->prv = (list->last);
X
X if (list->sd == lDOUBLY)
X array[k]->prv = NULL;
X
X array[k]->nxt = array[k+1];
X break;
X
X case lNEXT:
X if (list->sd == lDOUBLY)
X (list->first)->prv = array[k-1];
X
X array[k]->nxt = array[k+1];
X break;
X
X case lLAST:
X if (list->sd == lDOUBLY)
X array[k]->prv = array[k-1];
X
X if (list->cc == lCIRCULAR)
X array[k]->nxt = list->first;
X else
X array[k]->nxt = NULL;
X break;
X }
X }
X FREE(array);
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Dump a linked list to a file.
X**
X** Parameters:
X** In int id identifier of linked list
X** In char *file name of linked list dump file
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lOPEN_ERROR
X**
X** File structure:
X** <header> { <info> <data> }
X** header.n number of <info>-<data>-combinations (nodes)
X** info.size size of <data>
X*/
Xint
XlDump(id, file)
Xint id;
Xchar *file;
X{
X#ifndef MSDOS
X int open(), creat(), write(), close();
X#endif
X
X int fdDump, i;
X ListPtr list;
X NodePtr node;
X Info info;
X Header header;
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lDump", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X
X fdDump = open(file, BIN_WRITE);
X if (fdDump == -1) {
X fdDump = creat(file, PMODE);
X if (fdDump == -1) {
X lError("lDump", lOPEN_ERROR, 0, 0, file);
X return(lOPEN_ERROR);
X }
X }
X
X header.sd = list->sd;
X header.cc = list->cc;
X header.n = list->n;
X write(fdDump, (char *) &header, sizeof(Header));
X
X node = list->first;
X for (i=0; i<header.n; i++) {
X info.size = node->size;
X info.flag = node->flag;
X write(fdDump, (char *) &info, sizeof(Info));
X write(fdDump, (char *) node->data, node->size);
X node = node->nxt;
X }
X
X close(fdDump);
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Undump a linked list from a file.
X**
X** Parameters:
X** In char *file name of linked list dump file
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lOPEN_ERROR
X*/
Xint
XlUndump(file)
Xchar *file;
X{
X#ifndef MSDOS
X#ifndef AMIGA
X int open(), read(), close();
X#endif
X#endif
X
X int fdDump, i, id;
X Info info;
X Header header;
X Byte *data;
X
X /* check parameters */
X fdDump = open(file, BIN_READ);
X if (fdDump == -1) {
X lError("lDump", lOPEN_ERROR, 0, 0, file);
X return(lOPEN_ERROR);
X }
X
X read(fdDump, (char *) &header, sizeof(Header));
X id = lDef(header.sd, header.cc);
X
X for (i=0; i<header.n; i++) {
X read(fdDump, (char *) &info, sizeof(Info));
X CALLOC(data, Byte, info.size);
X read(fdDump, (char *) data, info.size);
X lInsNode(id, lLAST, data, info.size, info.flag);
X FREE(data);
X }
X
X close(fdDump);
X
X return(id);
X}
X
X/*******************************************************************************
X** Delete a linked list and clear info about it.
X**
X** Parameters:
X** In int id identifier of linked list
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID
X*/
Xint
XlDel(id)
Xint id;
X{
X ListPtr list;
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lDel", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X
X /* delete all nodes */
X delNodes(list->first, list->n);
X /* reset info as deleted linked list */
X list->sd = list->cc = list->n = 0;
X list->first = list->current = list->last = NULL;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Delete all linked list and all info about those lists.
X**
X** No parameters.
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lNO_LIST
X*/
Xint
XlDelAll()
X{
X ListPtr list, nxt;
X
X if (ld == NULL) {
X lError("lDelAll", lNO_LIST, 0, 0, NULL);
X return(lNO_LIST);
X }
X
X list = ld;
X while (list != NULL) {
X nxt = list->nxt;
X if (list->sd != 0 && list->cc != 0)
X lDel(list->id); /* delete when not already deleted */
X list = nxt;
X }
X delListInfo(ld->nxt);
X /* save info of initial list */
X firstlist.id = 1;
X firstlist.sd = firstlist.cc = firstlist.n = 0;
X firstlist.first = firstlist.current = firstlist.last = NULL;
X firstlist.nxt = NULL;
X ld = &firstlist;
X idMax = 2;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Insert a node in linked list.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int where place where node must be inserted
X** (lFIRST, lBEFORE, lAFTER, lLAST)
X** In Byte *data data of node
X** In int size size of data
X** In int flag user information flag
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lWRONG_WHERE
X*/
Xint
XlInsNode(id, where, data, size, flag)
Xint id, where, size, flag;
XByte *data;
X{
X ListPtr list;
X NodePtr node, new;
X static int set[] = { lFIRST, lBEFORE, lAFTER, lLAST };
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lInsNode", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (intInSet(where, set, 4) != 0) {
X lError("lInsNode", lWRONG_WHERE, where, 0, NULL);
X return(lWRONG_WHERE);
X }
X
X /* create new node */
X MALLOC(new, ListNode);
X CALLOC(new->data, Byte, size);
X BYTE_COPY(data, new->data, size);
X new->size = size;
X new->flag = flag;
X
X /* specific insert cases */
X if (list->first == NULL)
X where = lONE_NODE; /* first node in list */
X else if (list->current == list->first && where == lBEFORE)
X where = lFIRST; /* before first is like insert first */
X else if (list->current == list->last && where == lAFTER)
X where = lLAST; /* after last is like insert last */
X
X switch (where) {
X case lONE_NODE:
X if (list->cc == lCHAIN)
X new->prv = new->nxt = NULL;
X else {
X if (list->sd == lDOUBLY)
X new->prv = new;
X else
X new->prv = NULL;
X new->nxt = new;
X }
X list->first = list->last = new;
X break;
X case lFIRST:
X new->prv = (list->first)->prv;
X new->nxt = list->first;
X if (list->cc == lCIRCULAR)
X (list->last)->nxt = new;
X else
X (list->last)->nxt = NULL;
X if (list->sd == lDOUBLY)
X (list->first)->prv = new;
X list->first = new;
X break;
X case lBEFORE:
X new->prv = (list->current)->prv; /* == NULL if lSINGLY */
X new->nxt = list->current;
X
X if (list->sd == lDOUBLY) {
X ((list->current)->prv)->nxt = new;
X (list->current)->prv = new;
X } else {
X node = list->first;
X /* search for last before current */
X while (node->nxt != list->current && node != list->last)
X node = node->nxt;
X node->nxt = new;
X }
X if (list->current == list->first)
X list->first = new;
X break;
X case lAFTER:
X if (list->sd == lDOUBLY)
X new->prv = list->current;
X else
X new->prv = NULL;
X new->nxt = (list->current)->nxt;
X if (list->sd == lDOUBLY)
X ((list->current)->nxt)->prv = new;
X (list->current)->nxt = new;
X if (list->current == list->last)
X list->last = new;
X break;
X case lLAST:
X node = list->last;
X if (list->sd == lDOUBLY)
X new->prv = node;
X else
X new->prv = NULL;
X if (list->cc == lCIRCULAR)
X new->nxt = list->first;
X else
X new->nxt = NULL;
X if (list->sd == lDOUBLY && list->cc == lCIRCULAR)
X (list->first)->prv = new;
X node->nxt = new;
X list->last = new;
X break;
X }
X
X list->n++;
X list->current = new;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Get info of node of linked list.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int which which node must be inspected
X** (lFIRST, lPREVIOUS, lCURRENT, lNEXT, lLAST)
X** Out int *size size of data of node
X** Out int *flag user information flag
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lNOT_DOUBLY
X*/
Xint
XlInfoNode(id, which, size, flag)
Xint id, which, *size, *flag;
X{
X ListPtr list;
X int rtrn;
X
X rtrn = setWhchNode(id, which, "lInfoNode");
X if (rtrn != lSUCCESS) /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, */
X return(rtrn); /* lEOL, lNOT_DOUBLY */
X
X list = getAddress(id); /* already checked in setWhchNode */
X
X /* copy information */
X *size = (list->current)->size;
X *flag = (list->current)->flag;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Get data of node.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int which which node must be retrieved
X** (lFIRST, lPREVIOUS, lCURRENT, lNEXT, lLAST)
X** Out Byte *data data of node
X** In int size size of data
X**
X** Return on success:
X** lSUCCESS, lFIRST, lLAST
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lEOL, lNOT_DOUBLY, lSIZE_NE
X*/
Xint
XlGetNode(id, which, data, size)
Xint id, which, size;
XByte *data;
X{
X ListPtr list;
X int rtrn;
X
X rtrn = setWhchNode(id, which, "lInfoNode");
X if (rtrn != lSUCCESS) /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, */
X return(rtrn); /* lEOL, lNOT_DOUBLY */
X
X list = getAddress(id); /* already checked in setWhchNode */
X
X /* expected data and node must have same size */
X if ((list->current)->size != size) {
X lError("lGetNode", lSIZE_NE, size, (list->current)->size, NULL);
X return(lSIZE_NE);
X }
X
X BYTE_COPY((list->current)->data, data, size);
X
X if (list->n == 1) {
X if (which == lPREVIOUS || which == lLAST)
X return(lFIRST);
X else if (which == lNEXT || which == lFIRST)
X return(lLAST);
X else
X return(lLAST); /* which == lCURRENT */
X } else if (list->current == list->first)
X return(lFIRST);
X else if (list->current == list->last)
X return(lLAST);
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Find node.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int which from which node must be searched and in which
X** direction
X** In Func func function for checking the data on conditions
X** In Byte *ptr data for comparison in function
X** Out Byte *data data of node
X** In int size size of data
X**
X** Return on success:
X** lFOUND, lFIRST, lLAST, lNOT_FOUND
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lUNKNOWN_FUNC, lNOT_DOUBLY
X*/
Xint
XlFndNode(id, which, func, ptr, data, size)
Xint id, which, size;
XFunc func;
XByte *ptr, *data;
X{
X NodePtr node;
X ListPtr list;
X int cmp = lNOT_FOUND;
X static int set[] = { lFIRST, lNEXT, lPREVIOUS, lLAST };
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lFndNode", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError("lFndNode", lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X if (intInSet(which, set, 4) != 0) {
X lError("lFndNode", lWRONG_WHICH, which, 0, NULL);
X return(lWRONG_WHICH);
X }
X if (func == NULL) {
X lError("lFndNode", lUNKNOWN_FUNC, (int) func, 0, NULL);
X return(lUNKNOWN_FUNC);
X }
X
X /* set node where searching must start */
X switch (which) {
X case lFIRST: node = list->first; break;
X case lNEXT:
X case lPREVIOUS: node = list->current; break;
X case lLAST: node = list->last; break;
X }
X
X /* expected data and node must have same size */
X if ((which == lFIRST || which == lLAST) && node->size == size) {
X BYTE_COPY(node->data, data, size);
X cmp = (*func)(ptr, data);
X }
X
X switch (which) {
X case lFIRST: /* search forward */
X case lNEXT:
X while (cmp != lFOUND && node->nxt != NULL
X && node != list->last) {
X node = node->nxt;
X /* expected data and node must have same size */
X if (node->size == size) {
X BYTE_COPY(node->data, data, size);
X cmp = (*func)(ptr, data);
X }
X }
X if (cmp == lFOUND) {
X list->current = node;
X if (list->current == list->last)
X return(lLAST);
X }
X break;
X case lPREVIOUS: /* search backward */
X case lLAST:
X if (list->sd != lDOUBLY && cmp == lNOT_FOUND) {
X lError("lFndNode", lNOT_DOUBLY, id, 0, NULL);
X return(lNOT_DOUBLY);
X }
X while (cmp != lFOUND && node->prv != NULL
X && node->prv != list->first) {
X node = node->prv;
X /* expected data and node must have same size */
X if (node->size == size) {
X BYTE_COPY(node->data, data, size);
X cmp = (*func)(ptr, data);
X }
X }
X if (cmp == lFOUND) {
X list->current = node;
X if (list->current == list->first)
X return(lFIRST);
X }
X break;
X }
X
X return(cmp); /* lFOUND, lNOT_FOUND */
X}
X
X/*******************************************************************************
X** Get node by flag.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int which from which node must be searched and in which
X** direction
X** In int flag flag of node which must be retrieved
X** Out Byte *data data of node
X** In int size size of data
X**
X** Return on success:
X** lFOUND, lFIRST, lLAST, lNOT_FOUND
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH, lSIZE_NE
X*/
Xint
XlFndFlagNode(id, which, flag, data, size)
Xint id, which, flag, size;
XByte *data;
X{
X NodePtr node;
X ListPtr list;
X static int set[] = { lFIRST, lNEXT, lPREVIOUS, lLAST };
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lFndFlagNode", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError("lFndFlagNode", lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X if (intInSet(which, set, 4) != 0) {
X lError("lFndFlagNode", lWRONG_WHICH, which, 0, NULL);
X return(lWRONG_WHICH);
X }
X
X /* set node where searching must start */
X switch (which) {
X case lFIRST:
X node = list->first;
X break;
X case lNEXT:
X if ((list->current)->nxt == NULL)
X return(lNOT_FOUND); /* end of list reached */
X node = (list->current)->nxt;
X break;
X case lPREVIOUS:
X if ((list->current)->prv == NULL)
X return(lNOT_FOUND); /* begin of list reached */
X node = (list->current)->prv;
X break;
X case lLAST:
X node = list->last;
X break;
X }
X
X /* search till begin/end of list */
X switch (which) {
X case lFIRST: /* search forward */
X case lNEXT:
X while (node->flag != flag && node != list->last)
X node = node->nxt;
X break;
X case lPREVIOUS: /* search backward */
X case lLAST:
X if (list->sd != lDOUBLY) {
X lError("lFndFlagNode", lNOT_DOUBLY, id, 0, NULL);
X return(lNOT_DOUBLY);
X }
X while (node->flag != flag && node != list->first)
X node = node->prv;
X break;
X }
X
X list->current = node;
X
X /* extra flag-check for last node of list */
X if ((list->current)->flag != flag) {
X lError("lFndFlagNode", lNOT_FOUND, id, 0, NULL);
X return(lNOT_FOUND);
X }
X
X /* expected data and node must have same size */
X if ((list->current)->size != size) {
X lError("lFndFlagNode", lSIZE_NE, size, (list->current)->size,
X NULL);
X return(lSIZE_NE);
X }
X
X BYTE_COPY((list->current)->data, data, size);
X
X if (list->n == 1) {
X if (which == lPREVIOUS || which == lLAST)
X return(lFIRST);
X else if (which == lNEXT || which == lFIRST)
X return(lLAST);
X else
X return(lLAST); /* which == lCURRENT */
X } else if (list->current == list->first)
X return(lFIRST);
X else if (list->current == list->last)
X return(lLAST);
X
X return(lFOUND);
X}
X
X/*******************************************************************************
X** Update current node.
X**
X** Parameters:
X** In int id identifier of linked list
X** In Byte *data updated data of node
X** In int size size of data
X** In int flag updated user information flag
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST
X*/
Xint
XlUpdNode(id, data, size, flag)
Xint id, size, flag;
XByte *data;
X{
X ListPtr list;
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lUpdNode", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError("lUpdNode", lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X
X /* if same size, replace node by updated node */
X /* if not same size, insert updated node on current place */
X if ((list->current)->size != size) {
X FREE((list->current)->data);
X CALLOC((list->current)->data, Byte, size);
X (list->current)->size = size;
X }
X (list->current)->flag = flag;
X BYTE_COPY(data, (list->current)->data, size);
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Delete node.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int which which node must be deleted
X** (lFIRST, lCURRENT, lLAST)
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_WHICH
X*/
Xint
XlDelNode(id, which)
Xint id, which;
X{
X NodePtr node, prv, nxt;
X ListPtr list;
X static int set[] = { lFIRST, lCURRENT, lLAST };
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError("lDelNode", lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError("lDelNode", lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X if (intInSet(which, set, 3) != 0) {
X lError("lDelNode", lWRONG_WHICH, which, 0, NULL);
X return(lWRONG_WHICH);
X }
X
X /* specific delete cases */
X if (list->n == 1)
X which = lONE_NODE; /* one node in linked list */
X else if (which == lCURRENT && list->first == list->current)
X which = lFIRST; /* current is also first node */
X else if (which == lCURRENT && list->last == list->current)
X which = lLAST; /* current is also last node */
X
X switch (which) {
X case lONE_NODE:
X node = list->first;
X list->first = list->current = list->last = NULL;
X break;
X case lFIRST:
X node = list->first;
X nxt = node->nxt;
X if (list->cc == lCIRCULAR) {
X prv = list->last;
X prv->nxt = nxt;
X } else
X prv = node->prv; /* == NULL if lSINGLY */
X if (list->sd == lDOUBLY)
X nxt->prv = prv;
X list->first = list->current = nxt;
X break;
X case lCURRENT:
X node = list->current;
X nxt = node->nxt;
X if (list->sd == lDOUBLY) {
X prv = node->prv;
X nxt->prv = prv;
X } else {
X prv = node = list->first;
X while (node != list->current) {
X prv = node;
X node = node->nxt;
X }
X if (prv == node)
X prv = list->last;
X }
X prv->nxt = nxt;
X list->current = nxt;
X break;
X case lLAST:
X node = list->last;
X if (list->sd == lDOUBLY)
X prv = node->prv;
X else {
X if (list->current != list->last)
X prv = node = list->current;
X else
X prv = node = list->first;
X while (node != list->last) {
X prv = node;
X node = node->nxt;
X }
X }
X nxt = node->nxt;
X if (list->sd == lDOUBLY && list->cc == lCIRCULAR)
X nxt->prv = prv;
X prv->nxt = nxt;
X list->last = list->current = prv;
X break;
X }
X
X FREE(node->data);
X FREE(node);
X list->n--;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Get information about node by index.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int index index of node which must be inspected
X** Out int *size size of data of node
X** Out int *flag user information flag
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
X*/
Xint
XlInfoIndxNode(id, index, size, flag)
Xint id, index, *size, *flag;
X{
X ListPtr list;
X int rtrn;
X
X rtrn = setIndxNode(id, index, "lInfoIndxNode");
X if (rtrn != lSUCCESS)
X return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
X
X list = getAddress(id); /* already checked in setIndxNode */
X
X /* copy information */
X *size = (list->current)->size;
X *flag = (list->current)->flag;
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Get node by index.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int index index of node which must be retrieved
X** Out Byte *data data of node
X** In int size size of data
X**
X** Return on success:
X** lSUCCESS, lFIRST, lLAST
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX, lSIZE_NE
X*/
Xint
XlGetIndxNode(id, index, data, size)
Xint id, index, size;
XByte *data;
X{
X ListPtr list;
X int rtrn;
X
X rtrn = setIndxNode(id, index, "lGetIndxNode");
X if (rtrn != lSUCCESS)
X return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
X
X list = getAddress(id); /* already checked in setIndxNode */
X
X /* expected data and node must have same size */
X if ((list->current)->size != size) {
X lError("lGetIndxNode", lSIZE_NE, size, (list->current)->size,
X NULL);
X return(lSIZE_NE);
X }
X
X BYTE_COPY((list->current)->data, data, size);
X
X if (list->n == 1)
X return(lLAST);
X else if (list->current == list->first)
X return(lFIRST);
X else if (list->current == list->last)
X return(lLAST);
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Update node by index.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int index index of node which must be updated
X** In Byte *data updated data of node
X** In int size size of data
X** In int flag updated user information flag
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
X*/
Xint
XlUpdIndxNode(id, index, data, size, flag)
Xint id, index, size, flag;
XByte *data;
X{
X ListPtr list;
X int rtrn;
X
X rtrn = setIndxNode(id, index, "lUpdIndxNode");
X if (rtrn != lSUCCESS)
X return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
X
X list = getAddress(id); /* already checked in setIndxNode */
X
X /* if same size, replace node by updated node */
X /* if not same size, insert updated node on current place */
X if ((list->current)->size != size) {
X FREE((list->current)->data);
X CALLOC((list->current)->data, Byte, size);
X (list->current)->size = size;
X }
X (list->current)->flag = flag;
X BYTE_COPY(data, (list->current)->data, size);
X
X return(lSUCCESS);
X}
X
X/*******************************************************************************
X** Delete node by index.
X**
X** Parameters:
X** In int id identifier of linked list
X** In int index index of node which must be deleted
X**
X** Return on success:
X** lSUCCESS
X** Return on error:
X** lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX
X*/
Xint
XlDelIndxNode(id, index)
Xint id, index;
X{
X int rtrn;
X
X rtrn = setIndxNode(id, index, "lDelIndxNode");
X if (rtrn != lSUCCESS)
X return(rtrn); /* lUNKNOWN_ID, lEMPTY_LIST, lWRONG_INDEX */
X
X return(lDelNode(id, lCURRENT)); /* lSUCCESS */
X}
X
X/* ---------- static local functions ---------------------------------------- */
X
X/* get address of list data */
Xstatic ListPtr
XgetAddress(id)
Xint id;
X{
X ListPtr list;
X
X list = ld;
X while (list != NULL && list->id != id)
X list = list->nxt;
X
X if (list == NULL)
X return(NULL); /* id not found */
X
X if (list->sd == 0 && list->cc == 0) /* deleted linked list */
X return(NULL); /* deleted linked list */
X
X return(list);
X}
X
X/* delete nodes of a linked list */
Xstatic void
XdelNodes(node, n)
XNodePtr node;
Xint n;
X{
X NodePtr nxt;
X int i;
X
X for (i=0; i<n; i++) {
X nxt = node->nxt;
X FREE(node->data);
X FREE(node);
X node = nxt;
X }
X}
X
X/* delete info about linked list */
Xstatic void
XdelListInfo(list)
XListPtr list;
X{
X ListPtr nxt;
X
X while (list != NULL) {
X nxt = list->nxt;
X FREE(list);
X list = nxt;
X }
X}
X
X/* print error message in 'lERROR_FILE' when '-DERROR_FILE' is added as
X** cc option in the makefile */
Xstatic void
XlError(str, code, int1, int2, str1)
Xchar *str, *str1;
Xint code, int1, int2;
X{
X#ifdef ERROR_FILE
X char mess[60];
X FILE *fpError, *fopen();
X
X switch (code) {
X case lWRONG_SD:
X sprintf(mess, "Parameter 'sd' has wrong value : %d", int1);
X break;
X case lWRONG_CC:
X sprintf(mess, "Parameter 'cc' has wrong value : %d", int1);
X break;
X case lWRONG_WHERE:
X sprintf(mess, "Parameter 'where' has wrong value : %d", int1);
X break;
X case lWRONG_WHICH:
X sprintf(mess, "Parameter 'which' has wrong value : %d", int1);
X break;
X case lUNKNOWN_ID:
X sprintf(mess, "List id '%d' is unknown", int1);
X break;
X case lUNKNOWN_FUNC:
X sprintf(mess, "Function '%d' is unknown", int1);
X break;
X case lNO_LIST:
X sprintf(mess, "There are no lists defined");
X break;
X case lEMPTY_LIST:
X#ifdef DEBUG
X sprintf(mess, "List '%d' is empty", int1);
X break;
X#else
X return;
X#endif
X case lEOL:
X#ifdef DEBUG
X sprintf(mess, "End of list '%d' reached", int1);
X break;
X#else
X return;
X#endif
X case lNOT_FOUND:
X#ifdef DEBUG
X sprintf(mess, "Node not found in list '%d'", int1);
X break;
X#else
X return;
X#endif
X case lNOT_DOUBLY:
X sprintf(mess, "List '%d' is not doubly linked", int1);
X break;
X case lSIZE_NE:
X sprintf(mess,
X "Size of expected data '%d' and node '%d' not equal",
X int1, int2);
X break;
X case lWRONG_INDEX:
X sprintf(mess, "Index '%d' out of range [1:%d]", int1, int2);
X break;
X case lOPEN_ERROR:
X sprintf(mess, "Can't open dump-file '%s'\n", str1);
X break;
X case lWRONG_ORDER:
X sprintf(mess, "Parameter 'order' has wrong value : %d", int1);
X break;
X case lWRONG_THEORY:
X sprintf(mess, "Parameter 'theory' has wrong value : %d", int1);
X break;
X }
X
X fpError = fopen(lERROR_FILE, "a");
X if (fpError == NULL) {
X fprintf(stderr, "Can't open error-file '%s'\n", lERROR_FILE);
X fprintf(stderr, "Error, '%s': %s\n", str, mess);
X } else {
X fprintf(fpError, "Error in '%s': %s\n", str, mess);
X fclose(fpError);
X }
X#endif
X}
X
Xstatic int
XsetWhchNode(id, which, fname)
Xint id, which;
Xchar *fname;
X{
X ListPtr list;
X static int set[] = { lFIRST, lNEXT, lCURRENT, lPREVIOUS, lLAST };
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError(fname, lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError(fname, lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X if (intInSet(which, set, 5) != 0) {
X lError(fname, lWRONG_WHICH, which, 0, NULL);
X return(lWRONG_WHICH);
X }
X
X /* search for requested node */
X switch (which) {
X case lFIRST:
X list->current = list->first;
X break;
X case lNEXT:
X if ((list->current)->nxt == NULL) {
X lError(fname, lEOL, id, 0, NULL);
X return(lEOL);
X }
X list->current = (list->current)->nxt;
X break;
X case lCURRENT:
X break;
X case lPREVIOUS:
X if (list->sd != lDOUBLY) {
X lError(fname, lNOT_DOUBLY, id, 0, NULL);
X return(lNOT_DOUBLY);
X }
X if ((list->current)->prv == NULL) {
X lError(fname, lEOL, id, 0, NULL);
X return(lEOL);
X }
X list->current = (list->current)->prv;
X break;
X case lLAST:
X list->current = list->last;
X break;
X }
X
X return(lSUCCESS);
X}
X
Xstatic int
XsetIndxNode(id, index, fname)
Xint id, index;
Xchar *fname;
X{
X ListPtr list;
X int i;
X
X /* check parameters */
X if ((list = getAddress(id)) == NULL) {
X lError(fname, lUNKNOWN_ID, id, 0, NULL);
X return(lUNKNOWN_ID);
X }
X if (list->n == 0) {
X lError(fname, lEMPTY_LIST, id, 0, NULL);
X return(lEMPTY_LIST);
X }
X if (index < 1 || list->n < index) {
X lError(fname, lWRONG_INDEX, index, list->n, NULL);
X return(lWRONG_INDEX);
X }
X
X if (index == 1)
X list->current = list->first;
X else if (index == list->n)
X list->current = list->last;
X else {
X list->current = list->first;
X for (i=1; i<index; i++)
X list->current = (list->current)->nxt;
X }
X
X return(lSUCCESS);
X}
X
X/* local function for QUICK sort */
Xstatic void
Xpartition(array, order, func, lb, ub, pj)
XNodePtr *array;
Xint order, lb, ub, *pj;
XFunc func;
X{
X int down, up, cmp;
X NodePtr temp, a;
X
X a = array[lb];
X up = ub;
X down = lb;
X
X while (down < up) {
X cmp = (*func)(array[down]->data, a->data);
X while (down < ub
X && ((order == lASCENDING && (cmp == l1LT2 || cmp == lSAME))
X || (order == lDESCENDING && (cmp == l2LT1 || cmp == lSAME)))) {
X down++;
X cmp = (*func)(array[down]->data, a->data);
X }
X cmp = (*func)(array[up]->data, a->data);
X while ((order == lASCENDING && cmp == l2LT1)
X || (order == lDESCENDING && cmp == l1LT2)) {
X up--;
X cmp = (*func)(array[up]->data, a->data);
X }
X
X if (down < up) { /* interchange */
X temp = array[down];
X array[down] = array[up];
X array[up] = temp;
X }
X }
X array[lb] = array[up];
X array[up] = a;
X *pj = up;
X}
X
X/* local function for QUICK sort */
Xstatic int
Xstack_empty(id)
Xint id;
X{
X int sd, cc, n;
X
X /* check to see if linked list exists */
X if (lInfo(id, &sd, &cc, &n) == lUNKNOWN_ID)
X return(1); /* linked list is non-existant */
X if (n == 0)
X return(1);
X return(0);
X}
X
X/* ---------- static local functions (~anita/Tools/Clib) -------------------- */
X
X/* check if integer belongs to set of integers */
Xstatic int
XintInSet(intgr, set, set_n)
Xint intgr, *set, set_n;
X{
X int i = 0;
X
X while (set[i] != intgr && i < set_n)
X i++;
X
X /* 0 = yes, 1 = no */
X return((i == set_n) ? 1 : 0);
X}
END_OF_FILE
if test 40617 -ne `wc -c <'list.c'`; then
echo shar: \"'list.c'\" unpacked with wrong size!
fi
# end of 'list.c'
fi
if test -f 'sorted.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sorted.c'\"
else
echo shar: Extracting \"'sorted.c'\" \(8260 characters\)
sed "s/^X//" >'sorted.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <string.h>
X#include "list.h"
X
Xtypedef struct person {
X char lastname[15];
X char firstname[15];
X} Person, *PersonPtr;
Xint personSz = sizeof(Person);
X
X#ifdef ANSI
Xstatic void addPerson(int id, char *first, char *last);
Xstatic void addPersonSorted(int id, char *first, char *last);
Xstatic int compare(PersonPtr p1, PersonPtr p2, int order);
Xstatic int fndNxtPerson(char *last, PersonPtr data);
Xstatic int sortPerson(int id);
X#else
Xstatic void addPerson(), addPersonSorted();
Xstatic int compare(), fndNxtPerson(), sortPerson();
X#endif
X
Xint
Xmain()
X{
X Person person;
X int id, code;
X
X/* ------- first solution --------------------------------------------------- */
Xfprintf(stdout, "..... Insert sorted by last name .....\n");
X id = lDef(lSINGLY, lCHAIN);
X addPersonSorted(id, "Ernie", "Makris");
X addPersonSorted(id, "Anita", "Eijs");
X addPersonSorted(id, "John", "Johnson");
X addPersonSorted(id, "Bart", "Simpson");
X addPersonSorted(id, "James", "Bond");
X addPersonSorted(id, "Al", "Bundy");
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X code = lDel(id);
X
X/* ------- second solution -------------------------------------------------- */
Xfprintf(stdout, "..... Insert unsorted .....\n");
X id = lDef(lSINGLY, lCHAIN);
X addPerson(id, "Ernie", "Makris");
X addPerson(id, "Anita", "Eijs");
X addPerson(id, "John", "Johnson");
X addPerson(id, "Bart", "Simpson");
X addPerson(id, "James", "Bond");
X addPerson(id, "Al", "Bundy");
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name .....\n");
X id = sortPerson(id);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
X code = lDel(id);
X
X/* ------- third solution --------------------------------------------------- */
Xfprintf(stdout, "..... Insert unsorted .....\n");
X id = lDef(lSINGLY, lCHAIN);
X addPerson(id, "Ernie", "Makris");
X addPerson(id, "Anita", "Eijs");
X addPerson(id, "John", "Johnson");
X addPerson(id, "Bart", "Simpson");
X addPerson(id, "James", "Bond");
X addPerson(id, "Al", "Bundy");
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Bubble ASCENDING .....\n");
X code = lSort(id, lASCENDING, lBUBBLE, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Bubble DESCENDING .....\n");
X code = lSort(id, lDESCENDING, lBUBBLE, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Heap ASCENDING .....\n");
X code = lSort(id, lASCENDING, lHEAP, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Heap DESCENDING .....\n");
X code = lSort(id, lDESCENDING, lHEAP, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Insert ASCENDING .....\n");
X code = lSort(id, lASCENDING, lINSERT, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Insert DESCENDING .....\n");
X code = lSort(id, lDESCENDING, lINSERT, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Quick ASCENDING .....\n");
X code = lSort(id, lASCENDING, lQUICK, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Quick DESCENDING .....\n");
X code = lSort(id, lDESCENDING, lQUICK, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Selection ASCENDING .....\n");
X code = lSort(id, lASCENDING, lSELECTION, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
Xfprintf(stdout, "..... Sort by last name ..... Selection DESCENDING .....\n");
X code = lSort(id, lDESCENDING, lSELECTION, compare);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X fprintf(stdout, "%s, %s\n", person.lastname, person.firstname);
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X
X code = lDel(id);
X}
X
Xstatic void
XaddPersonSorted(id, first, last)
Xint id;
Xchar *first, *last;
X{
X Person person, new;
X char tmp[15];
X int code;
X
X /* find next last name */
X strcpy(&tmp[0], last);
X code = lFndNode(id, lFIRST, fndNxtPerson, &tmp[0], &person, personSz);
X
X strcpy(new.lastname, last);
X strcpy(new.firstname, first);
X
X /* insert data in alphabetical order */
X if (code == lEMPTY_LIST || code == lFIRST)
X code = lInsNode(id, lFIRST, &new, personSz, 0);
X else if (code == lNOT_FOUND)
X code = lInsNode(id, lLAST, &new, personSz, 0);
X else
X code = lInsNode(id, lBEFORE, &new, personSz, 0);
X}
X
X/* find next by specified last name before which specified name must be */
X/* inserted (alphabetical order) */
Xstatic int
Xcompare(p1, p2, order)
XPersonPtr p1, p2;
Xint order;
X{
X int k = strcmp(p1->lastname, p2->lastname);
X
X if (k == 0)
X return(lSAME);
X else if (k > 0)
X return(l2LT1);
X else if (k < 0)
X return(l1LT2);
X}
X
X/* find next by specified last name before which specified name must be */
X/* inserted (alphabetical order) */
Xstatic int
XfndNxtPerson(last, data)
Xchar *last;
XPersonPtr data;
X{
X if (strcmp(last, data->lastname) < 0)
X return(lFOUND);
X else
X return(lNOT_FOUND);
X}
X
Xstatic void
XaddPerson(id, first, last)
Xint id;
Xchar *first, *last;
X{
X Person new;
X int code;
X
X strcpy(new.lastname, last);
X strcpy(new.firstname, first);
X code = lInsNode(id, lLAST, &new, personSz, 0);
X}
X
Xstatic int
XsortPerson(id)
Xint id;
X{
X Person person, next;
X char tmp[15];
X int code, id2;
X
X id2 = lDef(lSINGLY, lCHAIN);
X
X code = lGetNode(id, lFIRST, &person, personSz);
X while (code != lEOL && code != lEMPTY_LIST) {
X
X /* find next last name */
X strcpy(&tmp[0], person.lastname);
X code = lFndNode(id2, lFIRST, fndNxtPerson, &tmp[0], &next,
X personSz);
X
X /* insert data in alphabetical order */
X if (code == lEMPTY_LIST || code == lFIRST)
X code = lInsNode(id2, lFIRST, &person, personSz, 0);
X else if (code == lNOT_FOUND)
X code = lInsNode(id2, lLAST, &person, personSz, 0);
X else
X code = lInsNode(id2, lBEFORE, &person, personSz, 0);
X
X code = lGetNode(id, lNEXT, &person, personSz);
X }
X code = lDel(id);
X return(id2);
X}
END_OF_FILE
if test 8260 -ne `wc -c <'sorted.c'`; then
echo shar: \"'sorted.c'\" unpacked with wrong size!
fi
# end of 'sorted.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked both archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...