|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Adam de Boor. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that: (1) source distributions retain this entire copyright ! 10: * notice and comment, and (2) distributions including binaries display ! 11: * the following acknowledgement: ``This product includes software ! 12: * developed by the University of California, Berkeley and its contributors'' ! 13: * in the documentation or other materials provided with the distribution ! 14: * and in all advertising materials mentioning features or use of this ! 15: * software. Neither the name of the University nor the names of its ! 16: * contributors may be used to endorse or promote products derived ! 17: * from this software without specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: static char sccsid[] = "@(#)lstConcat.c 5.3 (Berkeley) 6/1/90"; ! 25: #endif /* not lint */ ! 26: ! 27: /*- ! 28: * listConcat.c -- ! 29: * Function to concatentate two lists. ! 30: */ ! 31: ! 32: #include "lstInt.h" ! 33: ! 34: /*- ! 35: *----------------------------------------------------------------------- ! 36: * Lst_Concat -- ! 37: * Concatenate two lists. New elements are created to hold the data ! 38: * elements, if specified, but the elements themselves are not copied. ! 39: * If the elements should be duplicated to avoid confusion with another ! 40: * list, the Lst_Duplicate function should be called first. ! 41: * If LST_CONCLINK is specified, the second list is destroyed since ! 42: * its pointers have been corrupted and the list is no longer useable. ! 43: * ! 44: * Results: ! 45: * SUCCESS if all went well. FAILURE otherwise. ! 46: * ! 47: * Side Effects: ! 48: * New elements are created and appended the the first list. ! 49: *----------------------------------------------------------------------- ! 50: */ ! 51: ReturnStatus ! 52: Lst_Concat (l1, l2, flags) ! 53: Lst l1; /* The list to which l2 is to be appended */ ! 54: Lst l2; /* The list to append to l1 */ ! 55: int flags; /* LST_CONCNEW if LstNode's should be duplicated ! 56: * LST_CONCLINK if should just be relinked */ ! 57: { ! 58: register ListNode ln; /* original LstNode */ ! 59: register ListNode nln; /* new LstNode */ ! 60: register ListNode last; /* the last element in the list. Keeps ! 61: * bookkeeping until the end */ ! 62: register List list1 = (List)l1; ! 63: register List list2 = (List)l2; ! 64: ! 65: if (!LstValid (l1) || !LstValid (l2)) { ! 66: return (FAILURE); ! 67: } ! 68: ! 69: if (flags == LST_CONCLINK) { ! 70: if (list2->firstPtr != NilListNode) { ! 71: /* ! 72: * We set the nextPtr of the ! 73: * last element of list two to be NIL to make the loop easier and ! 74: * so we don't need an extra case should the first list turn ! 75: * out to be non-circular -- the final element will already point ! 76: * to NIL space and the first element will be untouched if it ! 77: * existed before and will also point to NIL space if it didn't. ! 78: */ ! 79: list2->lastPtr->nextPtr = NilListNode; ! 80: /* ! 81: * So long as the second list isn't empty, we just link the ! 82: * first element of the second list to the last element of the ! 83: * first list. If the first list isn't empty, we then link the ! 84: * last element of the list to the first element of the second list ! 85: * The last element of the second list, if it exists, then becomes ! 86: * the last element of the first list. ! 87: */ ! 88: list2->firstPtr->prevPtr = list1->lastPtr; ! 89: if (list1->lastPtr != NilListNode) { ! 90: list1->lastPtr->nextPtr = list2->firstPtr; ! 91: } ! 92: list1->lastPtr = list2->lastPtr; ! 93: } ! 94: if (list1->isCirc && list1->firstPtr != NilListNode) { ! 95: /* ! 96: * If the first list is supposed to be circular and it is (now) ! 97: * non-empty, we must make sure it's circular by linking the ! 98: * first element to the last and vice versa ! 99: */ ! 100: list1->firstPtr->prevPtr = list1->lastPtr; ! 101: list1->lastPtr->nextPtr = list1->firstPtr; ! 102: } ! 103: free ((Address)l2); ! 104: } else if (list2->firstPtr != NilListNode) { ! 105: /* ! 106: * We set the nextPtr of the last element of list 2 to be nil to make ! 107: * the loop less difficult. The loop simply goes through the entire ! 108: * second list creating new LstNodes and filling in the nextPtr, and ! 109: * prevPtr to fit into l1 and its datum field from the ! 110: * datum field of the corresponding element in l2. The 'last' node ! 111: * follows the last of the new nodes along until the entire l2 has ! 112: * been appended. Only then does the bookkeeping catch up with the ! 113: * changes. During the first iteration of the loop, if 'last' is nil, ! 114: * the first list must have been empty so the newly-created node is ! 115: * made the first node of the list. ! 116: */ ! 117: list2->lastPtr->nextPtr = NilListNode; ! 118: for (last = list1->lastPtr, ln = list2->firstPtr; ! 119: ln != NilListNode; ! 120: ln = ln->nextPtr) ! 121: { ! 122: PAlloc (nln, ListNode); ! 123: nln->datum = ln->datum; ! 124: if (last != NilListNode) { ! 125: last->nextPtr = nln; ! 126: } else { ! 127: list1->firstPtr = nln; ! 128: } ! 129: nln->prevPtr = last; ! 130: nln->flags = nln->useCount = 0; ! 131: last = nln; ! 132: } ! 133: ! 134: /* ! 135: * Finish bookkeeping. The last new element becomes the last element ! 136: * of list one. ! 137: */ ! 138: list1->lastPtr = last; ! 139: ! 140: /* ! 141: * The circularity of both list one and list two must be corrected ! 142: * for -- list one because of the new nodes added to it; list two ! 143: * because of the alteration of list2->lastPtr's nextPtr to ease the ! 144: * above for loop. ! 145: */ ! 146: if (list1->isCirc) { ! 147: list1->lastPtr->nextPtr = list1->firstPtr; ! 148: list1->firstPtr->prevPtr = list1->lastPtr; ! 149: } else { ! 150: last->nextPtr = NilListNode; ! 151: } ! 152: ! 153: if (list2->isCirc) { ! 154: list2->lastPtr->nextPtr = list2->firstPtr; ! 155: } ! 156: } ! 157: ! 158: return (SUCCESS); ! 159: } ! 160:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.