예제 #1
0
파일: utility.c 프로젝트: LukeWalsh/ipa2_1
/* This function generates a huffman coding tree using a stack implementation
   to keep track of the nodes.
   The paremeter is a file stream containing a huffman header at the top.
   The function will return the head of the binary tree, or it will print an
   error message and return NULL if the header file is incorrect. 
*/
LEAF* GenerateTree(FILE* fptr) {
   fseek(fptr, 0, SEEK_SET);
   char c;
   STACK_ELEMENT* stackHead = NULL;
   
   do {
      c = fgetc(fptr);
      if (c == '1') {
         LEAF* myLeaf = ConstructLeafNode(fgetc(fptr));
         /* Push the character to the stack as a new leaf node */
         stackHead = PushNodeToStack(stackHead, myLeaf);
      }
      else if (c == '0') {
         if (stackHead == NULL) {
            /* There should be something on the stack, break for error */
            break;
         }
         /* if the stack contains only one element, we have constructed the entire Huffman coding tree.
            This is the case where we want to return the fully constructed tree */
         else if (stackHead->next == NULL) {
            int numberOfCharacters;
            fscanf(fptr, "%d\n", &numberOfCharacters);
            LEAF* tree = stackHead->node;
            DestroyStack(stackHead);
            return tree;
         }
         /* This is the case where we want to combine the top two nodes off of the stack */
         else {
            LEAF* leafHead = ConstructLeafNode(NO_CHARACTER);
            /* First off the stack becomes the rchild of the new node */
            leafHead->rchild = stackHead->node;
            stackHead = PopFromStack(stackHead);
            /* Second off the stack becomes the lchild of the new node */
            leafHead->lchild = stackHead->node;
            stackHead = PopFromStack(stackHead);
            /* Push the new node on to the top in place of the two we just removed */
            stackHead = PushNodeToStack(stackHead, leafHead);
         }
      }
   } while (c != EOF || c != '\n');

   /* There is something wrong if we have arrived here */
   PrintError(INVALID_HEADER);
   return NULL;
}
예제 #2
0
// This is called via ScanAddressesInRegion to process the permanent mutables.  It is
// also called from ScanObjectAddress to process root addresses.
// It processes all the addresses reachable from the object.
void RecursiveScan::ScanAddressesInObject(PolyObject *obj, POLYUNSIGNED lengthWord)
{
    if (OBJ_IS_BYTE_OBJECT(lengthWord))
    {
        Completed(obj);
        return;
    }

    while (true)
    {
        ASSERT (OBJ_IS_LENGTH(lengthWord));

        // Get the length and base address.  N.B.  If this is a code segment
        // these will be side-effected by GetConstSegmentForCode.
        POLYUNSIGNED length = OBJ_OBJECT_LENGTH(lengthWord);
        PolyWord *baseAddr = (PolyWord*)obj;

        if (OBJ_IS_CODE_OBJECT(lengthWord))
        {
            // It's better to process the whole code object in one go.
            ScanAddress::ScanAddressesInObject(obj, lengthWord);
            length = 0; // Finished
        }
        ASSERT(! OBJ_IS_BYTE_OBJECT(lengthWord)); // Check - remove this later

        // else it's a normal object,

        // If there are only two addresses in this cell that need to be
        // followed we follow them immediately and treat this cell as done.
        // If there are more than two we push the address of this cell on
        // the stack, follow the first address and then rescan it.  That way
        // list cells are processed once only but we don't overflow the
        // stack by pushing all the addresses in a very large vector.
        PolyWord *endWord = baseAddr + length;
        PolyObject *firstWord = 0;
        PolyObject *secondWord = 0;

        while (baseAddr != endWord)
        {
            PolyWord wordAt = *baseAddr;

            if (wordAt.IsDataPtr() && wordAt != PolyWord::FromUnsigned(0))
            {
                // Normal address.  We can have words of all zeros at least in the
                // situation where we have a partially constructed code segment where
                // the constants at the end of the code have not yet been filled in.
                if (TestForScan(baseAddr)) // Test value at baseAddr (may side-effect it)
                {
                    PolyObject *wObj = (*baseAddr).AsObjPtr();
                    if (wObj->IsByteObject())
                    {
                        // Can do this now - don't need to push it
                        MarkAsScanning(wObj);
                        Completed(wObj);
                    }
                    else if (firstWord == 0)
                    {
                        firstWord = wObj;
                        // We mark the word immediately.  We can have
                        // two words in an object that are the same
                        // and we don't want to process it again.
                        MarkAsScanning(firstWord);
                    }
                    else if (secondWord == 0)
                        secondWord = wObj;
                    else break;  // More than two words.
                }
            }
            else if (wordAt.IsCodePtr())
            {
                // If we're processing the constant area of a code segment this could
                // be a code address.
                PolyObject *oldObject = ObjCodePtrToPtr(wordAt.AsCodePtr());
                // Calculate the byte offset of this value within the code object.
                POLYUNSIGNED offset = wordAt.AsCodePtr() - (byte*)oldObject;
                wordAt = oldObject;
                bool test = TestForScan(&wordAt);
                // TestForScan may side-effect the word.
                PolyObject *newObject = wordAt.AsObjPtr();
                wordAt = PolyWord::FromCodePtr((byte*)newObject + offset);
                if (wordAt != *baseAddr)
                    *baseAddr = wordAt;
                if (test)
                {
                    if (firstWord == 0)
                    {
                        firstWord = newObject;
                        MarkAsScanning(firstWord);
                    }
                    else if (secondWord == 0)
                        secondWord = newObject;
                    else break;
                }
            }
            baseAddr++;
        }

        if (baseAddr == endWord)
        {
            // We have done everything except possibly firstWord and secondWord.
            Completed(obj);
            if (secondWord != 0)
            {
                MarkAsScanning(secondWord);
                // Put this on the stack.  If this is a list node we will be
                // pushing the tail.
                PushToStack(secondWord);
            }
        }
        else // Put this back on the stack while we process the first word
            PushToStack(obj);

        if (firstWord != 0)
            // Process it immediately.
            obj = firstWord;
        else if (StackIsEmpty())
            return;
        else
            obj = PopFromStack();

        lengthWord = obj->LengthWord();
    }
}
예제 #3
0
void UserInterface::PopFromStack(String elementName){
	PopFromStack(GetElementByName(elementName));
}