140412Sbostic /* 240412Sbostic * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 340412Sbostic * All rights reserved. 440411Sbostic * 540412Sbostic * This code is derived from software contributed to Berkeley by 640412Sbostic * Adam de Boor. 740411Sbostic * 8*42741Sbostic * %sccs.include.redist.c% 940411Sbostic */ 1040412Sbostic 1140411Sbostic #ifndef lint 12*42741Sbostic static char sccsid[] = "@(#)lstConcat.c 5.3 (Berkeley) 06/01/90"; 1340412Sbostic #endif /* not lint */ 1440411Sbostic 1540412Sbostic /*- 1640412Sbostic * listConcat.c -- 1740412Sbostic * Function to concatentate two lists. 1840412Sbostic */ 1940412Sbostic 2040411Sbostic #include "lstInt.h" 2140411Sbostic 2240411Sbostic /*- 2340411Sbostic *----------------------------------------------------------------------- 2440411Sbostic * Lst_Concat -- 2540411Sbostic * Concatenate two lists. New elements are created to hold the data 2640411Sbostic * elements, if specified, but the elements themselves are not copied. 2740411Sbostic * If the elements should be duplicated to avoid confusion with another 2840411Sbostic * list, the Lst_Duplicate function should be called first. 2940411Sbostic * If LST_CONCLINK is specified, the second list is destroyed since 3040411Sbostic * its pointers have been corrupted and the list is no longer useable. 3140411Sbostic * 3240411Sbostic * Results: 3340411Sbostic * SUCCESS if all went well. FAILURE otherwise. 3440411Sbostic * 3540411Sbostic * Side Effects: 3640411Sbostic * New elements are created and appended the the first list. 3740411Sbostic *----------------------------------------------------------------------- 3840411Sbostic */ 3940411Sbostic ReturnStatus 4040411Sbostic Lst_Concat (l1, l2, flags) 4140411Sbostic Lst l1; /* The list to which l2 is to be appended */ 4240411Sbostic Lst l2; /* The list to append to l1 */ 4340411Sbostic int flags; /* LST_CONCNEW if LstNode's should be duplicated 4440411Sbostic * LST_CONCLINK if should just be relinked */ 4540411Sbostic { 4640411Sbostic register ListNode ln; /* original LstNode */ 4740411Sbostic register ListNode nln; /* new LstNode */ 4840411Sbostic register ListNode last; /* the last element in the list. Keeps 4940411Sbostic * bookkeeping until the end */ 5040411Sbostic register List list1 = (List)l1; 5140411Sbostic register List list2 = (List)l2; 5240411Sbostic 5340411Sbostic if (!LstValid (l1) || !LstValid (l2)) { 5440411Sbostic return (FAILURE); 5540411Sbostic } 5640411Sbostic 5740411Sbostic if (flags == LST_CONCLINK) { 5840411Sbostic if (list2->firstPtr != NilListNode) { 5940411Sbostic /* 6040411Sbostic * We set the nextPtr of the 6140411Sbostic * last element of list two to be NIL to make the loop easier and 6240411Sbostic * so we don't need an extra case should the first list turn 6340411Sbostic * out to be non-circular -- the final element will already point 6440411Sbostic * to NIL space and the first element will be untouched if it 6540411Sbostic * existed before and will also point to NIL space if it didn't. 6640411Sbostic */ 6740411Sbostic list2->lastPtr->nextPtr = NilListNode; 6840411Sbostic /* 6940411Sbostic * So long as the second list isn't empty, we just link the 7040411Sbostic * first element of the second list to the last element of the 7140411Sbostic * first list. If the first list isn't empty, we then link the 7240411Sbostic * last element of the list to the first element of the second list 7340411Sbostic * The last element of the second list, if it exists, then becomes 7440411Sbostic * the last element of the first list. 7540411Sbostic */ 7640411Sbostic list2->firstPtr->prevPtr = list1->lastPtr; 7740411Sbostic if (list1->lastPtr != NilListNode) { 7840411Sbostic list1->lastPtr->nextPtr = list2->firstPtr; 7940411Sbostic } 8040411Sbostic list1->lastPtr = list2->lastPtr; 8140411Sbostic } 8240411Sbostic if (list1->isCirc && list1->firstPtr != NilListNode) { 8340411Sbostic /* 8440411Sbostic * If the first list is supposed to be circular and it is (now) 8540411Sbostic * non-empty, we must make sure it's circular by linking the 8640411Sbostic * first element to the last and vice versa 8740411Sbostic */ 8840411Sbostic list1->firstPtr->prevPtr = list1->lastPtr; 8940411Sbostic list1->lastPtr->nextPtr = list1->firstPtr; 9040411Sbostic } 9140411Sbostic free ((Address)l2); 9240411Sbostic } else if (list2->firstPtr != NilListNode) { 9340411Sbostic /* 9440411Sbostic * We set the nextPtr of the last element of list 2 to be nil to make 9540411Sbostic * the loop less difficult. The loop simply goes through the entire 9640411Sbostic * second list creating new LstNodes and filling in the nextPtr, and 9740411Sbostic * prevPtr to fit into l1 and its datum field from the 9840411Sbostic * datum field of the corresponding element in l2. The 'last' node 9940411Sbostic * follows the last of the new nodes along until the entire l2 has 10040411Sbostic * been appended. Only then does the bookkeeping catch up with the 10140411Sbostic * changes. During the first iteration of the loop, if 'last' is nil, 10240411Sbostic * the first list must have been empty so the newly-created node is 10340411Sbostic * made the first node of the list. 10440411Sbostic */ 10540411Sbostic list2->lastPtr->nextPtr = NilListNode; 10640411Sbostic for (last = list1->lastPtr, ln = list2->firstPtr; 10740411Sbostic ln != NilListNode; 10840411Sbostic ln = ln->nextPtr) 10940411Sbostic { 11040411Sbostic PAlloc (nln, ListNode); 11140411Sbostic nln->datum = ln->datum; 11240411Sbostic if (last != NilListNode) { 11340411Sbostic last->nextPtr = nln; 11440411Sbostic } else { 11540411Sbostic list1->firstPtr = nln; 11640411Sbostic } 11740411Sbostic nln->prevPtr = last; 11840411Sbostic nln->flags = nln->useCount = 0; 11940411Sbostic last = nln; 12040411Sbostic } 12140411Sbostic 12240411Sbostic /* 12340411Sbostic * Finish bookkeeping. The last new element becomes the last element 12440411Sbostic * of list one. 12540411Sbostic */ 12640411Sbostic list1->lastPtr = last; 12740411Sbostic 12840411Sbostic /* 12940411Sbostic * The circularity of both list one and list two must be corrected 13040411Sbostic * for -- list one because of the new nodes added to it; list two 13140411Sbostic * because of the alteration of list2->lastPtr's nextPtr to ease the 13240411Sbostic * above for loop. 13340411Sbostic */ 13440411Sbostic if (list1->isCirc) { 13540411Sbostic list1->lastPtr->nextPtr = list1->firstPtr; 13640411Sbostic list1->firstPtr->prevPtr = list1->lastPtr; 13740411Sbostic } else { 13840411Sbostic last->nextPtr = NilListNode; 13940411Sbostic } 14040411Sbostic 14140411Sbostic if (list2->isCirc) { 14240411Sbostic list2->lastPtr->nextPtr = list2->firstPtr; 14340411Sbostic } 14440411Sbostic } 14540411Sbostic 14640411Sbostic return (SUCCESS); 14740411Sbostic } 14840411Sbostic 149