1*40411Sbostic /*- 2*40411Sbostic * listConcat.c -- 3*40411Sbostic * Function to concatentate two lists. 4*40411Sbostic * 5*40411Sbostic * Copyright (c) 1988 by the Regents of the University of California 6*40411Sbostic * 7*40411Sbostic * Permission to use, copy, modify, and distribute this 8*40411Sbostic * software and its documentation for any purpose and without 9*40411Sbostic * fee is hereby granted, provided that the above copyright 10*40411Sbostic * notice appears in all copies. Neither the University of California nor 11*40411Sbostic * Adam de Boor makes any representations about the suitability of this 12*40411Sbostic * software for any purpose. It is provided "as is" without 13*40411Sbostic * express or implied warranty. 14*40411Sbostic * 15*40411Sbostic */ 16*40411Sbostic #ifndef lint 17*40411Sbostic static char *rcsid = 18*40411Sbostic "$Id: lstConcat.c,v 1.6 89/07/06 12:50:04 adam Exp $ SPRITE (Berkeley)"; 19*40411Sbostic #endif lint 20*40411Sbostic 21*40411Sbostic #include "lstInt.h" 22*40411Sbostic 23*40411Sbostic /*- 24*40411Sbostic *----------------------------------------------------------------------- 25*40411Sbostic * Lst_Concat -- 26*40411Sbostic * Concatenate two lists. New elements are created to hold the data 27*40411Sbostic * elements, if specified, but the elements themselves are not copied. 28*40411Sbostic * If the elements should be duplicated to avoid confusion with another 29*40411Sbostic * list, the Lst_Duplicate function should be called first. 30*40411Sbostic * If LST_CONCLINK is specified, the second list is destroyed since 31*40411Sbostic * its pointers have been corrupted and the list is no longer useable. 32*40411Sbostic * 33*40411Sbostic * Results: 34*40411Sbostic * SUCCESS if all went well. FAILURE otherwise. 35*40411Sbostic * 36*40411Sbostic * Side Effects: 37*40411Sbostic * New elements are created and appended the the first list. 38*40411Sbostic *----------------------------------------------------------------------- 39*40411Sbostic */ 40*40411Sbostic ReturnStatus 41*40411Sbostic Lst_Concat (l1, l2, flags) 42*40411Sbostic Lst l1; /* The list to which l2 is to be appended */ 43*40411Sbostic Lst l2; /* The list to append to l1 */ 44*40411Sbostic int flags; /* LST_CONCNEW if LstNode's should be duplicated 45*40411Sbostic * LST_CONCLINK if should just be relinked */ 46*40411Sbostic { 47*40411Sbostic register ListNode ln; /* original LstNode */ 48*40411Sbostic register ListNode nln; /* new LstNode */ 49*40411Sbostic register ListNode last; /* the last element in the list. Keeps 50*40411Sbostic * bookkeeping until the end */ 51*40411Sbostic register List list1 = (List)l1; 52*40411Sbostic register List list2 = (List)l2; 53*40411Sbostic 54*40411Sbostic if (!LstValid (l1) || !LstValid (l2)) { 55*40411Sbostic return (FAILURE); 56*40411Sbostic } 57*40411Sbostic 58*40411Sbostic if (flags == LST_CONCLINK) { 59*40411Sbostic if (list2->firstPtr != NilListNode) { 60*40411Sbostic /* 61*40411Sbostic * We set the nextPtr of the 62*40411Sbostic * last element of list two to be NIL to make the loop easier and 63*40411Sbostic * so we don't need an extra case should the first list turn 64*40411Sbostic * out to be non-circular -- the final element will already point 65*40411Sbostic * to NIL space and the first element will be untouched if it 66*40411Sbostic * existed before and will also point to NIL space if it didn't. 67*40411Sbostic */ 68*40411Sbostic list2->lastPtr->nextPtr = NilListNode; 69*40411Sbostic /* 70*40411Sbostic * So long as the second list isn't empty, we just link the 71*40411Sbostic * first element of the second list to the last element of the 72*40411Sbostic * first list. If the first list isn't empty, we then link the 73*40411Sbostic * last element of the list to the first element of the second list 74*40411Sbostic * The last element of the second list, if it exists, then becomes 75*40411Sbostic * the last element of the first list. 76*40411Sbostic */ 77*40411Sbostic list2->firstPtr->prevPtr = list1->lastPtr; 78*40411Sbostic if (list1->lastPtr != NilListNode) { 79*40411Sbostic list1->lastPtr->nextPtr = list2->firstPtr; 80*40411Sbostic } 81*40411Sbostic list1->lastPtr = list2->lastPtr; 82*40411Sbostic } 83*40411Sbostic if (list1->isCirc && list1->firstPtr != NilListNode) { 84*40411Sbostic /* 85*40411Sbostic * If the first list is supposed to be circular and it is (now) 86*40411Sbostic * non-empty, we must make sure it's circular by linking the 87*40411Sbostic * first element to the last and vice versa 88*40411Sbostic */ 89*40411Sbostic list1->firstPtr->prevPtr = list1->lastPtr; 90*40411Sbostic list1->lastPtr->nextPtr = list1->firstPtr; 91*40411Sbostic } 92*40411Sbostic free ((Address)l2); 93*40411Sbostic } else if (list2->firstPtr != NilListNode) { 94*40411Sbostic /* 95*40411Sbostic * We set the nextPtr of the last element of list 2 to be nil to make 96*40411Sbostic * the loop less difficult. The loop simply goes through the entire 97*40411Sbostic * second list creating new LstNodes and filling in the nextPtr, and 98*40411Sbostic * prevPtr to fit into l1 and its datum field from the 99*40411Sbostic * datum field of the corresponding element in l2. The 'last' node 100*40411Sbostic * follows the last of the new nodes along until the entire l2 has 101*40411Sbostic * been appended. Only then does the bookkeeping catch up with the 102*40411Sbostic * changes. During the first iteration of the loop, if 'last' is nil, 103*40411Sbostic * the first list must have been empty so the newly-created node is 104*40411Sbostic * made the first node of the list. 105*40411Sbostic */ 106*40411Sbostic list2->lastPtr->nextPtr = NilListNode; 107*40411Sbostic for (last = list1->lastPtr, ln = list2->firstPtr; 108*40411Sbostic ln != NilListNode; 109*40411Sbostic ln = ln->nextPtr) 110*40411Sbostic { 111*40411Sbostic PAlloc (nln, ListNode); 112*40411Sbostic nln->datum = ln->datum; 113*40411Sbostic if (last != NilListNode) { 114*40411Sbostic last->nextPtr = nln; 115*40411Sbostic } else { 116*40411Sbostic list1->firstPtr = nln; 117*40411Sbostic } 118*40411Sbostic nln->prevPtr = last; 119*40411Sbostic nln->flags = nln->useCount = 0; 120*40411Sbostic last = nln; 121*40411Sbostic } 122*40411Sbostic 123*40411Sbostic /* 124*40411Sbostic * Finish bookkeeping. The last new element becomes the last element 125*40411Sbostic * of list one. 126*40411Sbostic */ 127*40411Sbostic list1->lastPtr = last; 128*40411Sbostic 129*40411Sbostic /* 130*40411Sbostic * The circularity of both list one and list two must be corrected 131*40411Sbostic * for -- list one because of the new nodes added to it; list two 132*40411Sbostic * because of the alteration of list2->lastPtr's nextPtr to ease the 133*40411Sbostic * above for loop. 134*40411Sbostic */ 135*40411Sbostic if (list1->isCirc) { 136*40411Sbostic list1->lastPtr->nextPtr = list1->firstPtr; 137*40411Sbostic list1->firstPtr->prevPtr = list1->lastPtr; 138*40411Sbostic } else { 139*40411Sbostic last->nextPtr = NilListNode; 140*40411Sbostic } 141*40411Sbostic 142*40411Sbostic if (list2->isCirc) { 143*40411Sbostic list2->lastPtr->nextPtr = list2->firstPtr; 144*40411Sbostic } 145*40411Sbostic } 146*40411Sbostic 147*40411Sbostic return (SUCCESS); 148*40411Sbostic } 149*40411Sbostic 150