コード例 #1
0
/*
 *  PrintBacktrace
 *      Prints a call backtrace into the logging buffer
 */
void ExceptionTracer::PrintBacktrace()
{
    StackTracer tracer(this->context);

    char module_name[MAX_PATH];
    char sym_buffer[sizeof(SYMBOL_INFO) + symbol_max];

    int backtrace_count = 0;        // Num of frames traced
    bool has_symbol_api = false;    // True if we have the symbol API available for use
    DWORD old_options;              // Saves old symbol API options

    SYMBOL_INFO& symbol = *(SYMBOL_INFO*)sym_buffer;
    symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol.MaxNameLen = symbol_max;

    // Tries to get the symbol api
    if (SymInitialize(GetCurrentProcess(), 0, TRUE))
    {
        has_symbol_api = true;
        old_options = SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_NO_PROMPTS | SYMOPT_FAIL_CRITICAL_ERRORS);
    }

    Print("Backtrace (may be wrong):");
    EnterScope();
    {
        // Walks on the stack until there's no frame to trace or we traced 'max_backtrace' frames
        while (auto trace = tracer.Walk())
        {
            if (++backtrace_count >= max_backtrace)
                break;

            bool has_sym = false;   // This EIP has a symbol associated with it?
            DWORD64 displacement;   // EIP displacement relative to symbol

            // If we have access to the symbol api, try to get symbol name from pc (eip)
            if (has_symbol_api)
                has_sym = trace->pc ? !!SymFromAddr(GetCurrentProcess(), (DWORD64)trace->pc, &displacement, &symbol) : false;

            // Print everything up, this.... Ew, this looks awful!
            Print(backtrace_count == 1 ? "=>" : "  ");                           // First line should have '=>' to specify where it crashed
            Print("0x%p ", trace->pc);                                          // Print EIP at frame
            if (has_sym) Print("%s+0x%x ", symbol.Name, (DWORD)displacement);   // Print frame func symbol
            Print("in %s (+0x%x) ",                                             // Print module
                trace->module ? FindModuleName(trace->module, module_name, sizeof(module_name)) : "unknown",
                (uintptr_t)(trace->pc) - (uintptr_t)(trace->module) // Module displacement
            );
            if (trace->frame) Print("(0x%p) ", trace->frame);                    // Print frame pointer

            NewLine();
        }
    }
    LeaveScope();

    // Cleanup the symbol api
    if (has_symbol_api)
    {
        SymSetOptions(old_options);
        SymCleanup(GetCurrentProcess());
    }
}
コード例 #2
0
/*
 *  PrintRegisters
 *      Prints the content of the assembly registers into the logging buffer
 */
void ExceptionTracer::PrintRegisters()
{
    int regs_in_line = 0;       // Amount of registers currently printed on this line

    // Prints a register, followed by spaces
    auto PrintRegister = [this, &regs_in_line](const char* reg_name, uint32_t reg_value, const char* spaces)
    {
        Print("%s: 0x%p%s", reg_name, reg_value, spaces);
        if (++regs_in_line >= 4) { this->NewLine(); regs_in_line = 0; }
    };

    // Prints a general purposes register
    auto PrintIntRegister = [PrintRegister](const char* reg_name, uint32_t reg_value)
    {
        PrintRegister(reg_name, reg_value, "  ");
    };

    // Prints a segment register
    auto PrintSegRegister = [PrintRegister](const char* reg_name, uint32_t reg_value)
    {
        PrintRegister(reg_name, reg_value, "   ");
    };

    Print("Register dump:");
    EnterScope();
    {
        // Print main general purposes registers
        if (context.ContextFlags & CONTEXT_INTEGER)
        {
#if !_M_X64
            PrintIntRegister("EAX", context.Eax);
            PrintIntRegister("EBX", context.Ebx);
            PrintIntRegister("ECX", context.Ecx);
            PrintIntRegister("EDX", context.Edx);
            PrintIntRegister("EDI", context.Edi);
            PrintIntRegister("ESI", context.Esi);
#else
            PrintIntRegister("RAX", context.Rax);
            PrintIntRegister("RCX", context.Rcx);
            PrintIntRegister("RDX", context.Rdx);
            PrintIntRegister("RBX", context.Rbx);
            PrintIntRegister("RSP", context.Rsp);
            PrintIntRegister("RBP", context.Rbp);
            PrintIntRegister("RSI", context.Rsi);
            PrintIntRegister("RDI", context.Rdi);
            PrintIntRegister("_R8", context.R8);
            PrintIntRegister("_R9", context.R9);
            PrintIntRegister("R10", context.R10);
            PrintIntRegister("R11", context.R11);
            PrintIntRegister("R12", context.R12);
            PrintIntRegister("R13", context.R13);
            PrintIntRegister("R14", context.R14);
            PrintIntRegister("R15", context.R15);
#endif
        }

        // Print control registers
        if (context.ContextFlags & CONTEXT_CONTROL)
        {
#if !_M_X64
            PrintIntRegister("EBP", context.Ebp);
            PrintIntRegister("EIP", context.Eip);
            PrintIntRegister("ESP", context.Esp);
            PrintIntRegister("EFL", context.EFlags);
            PrintSegRegister("CS", context.SegCs);
            PrintSegRegister("SS", context.SegSs);
#else
            PrintIntRegister("RIP", context.Rip);
            PrintIntRegister("RFL", context.EFlags);
            PrintSegRegister("CS", context.SegCs);
            PrintSegRegister("SS", context.SegSs);
#endif
        }

        // Print segment registers
        if (context.ContextFlags & CONTEXT_SEGMENTS)
        {
            PrintSegRegister("GS", context.SegGs);
            PrintSegRegister("FS", context.SegFs);
            PrintSegRegister("ES", context.SegEs);
            PrintSegRegister("DS", context.SegDs);
        }
    }
    LeaveScope();
}
コード例 #3
0
/*
 *  PrintStackdump
 *      Prints the content of the stack into the logging buffer
 */
void ExceptionTracer::PrintStackdump()
{
    // We need the ESP of the exception context to execute a stack dump, make sure we have access to it
    if ((context.ContextFlags & CONTEXT_CONTROL) == 0)
        return;

    static const auto align = sizeof_word;      // Stack aligment
    static const auto max_words_in_line_magic = stackdump_words_per_line + 10;

    MEMORY_BASIC_INFORMATION mbi;
#if !_M_X64
    uintptr_t base, bottom, top = (uintptr_t)context.Esp;
#else
    uintptr_t base, bottom, top = (uintptr_t)context.Rsp;
#endif
    auto words_in_line = max_words_in_line_magic;

    // Finds the bottom of the stack from it's base pointer
    // Note: mbi will get overriden on this function
    auto GetStackBottom = [&mbi](uintptr_t base)
    {
        VirtualQuery((void*)base, &mbi, sizeof(mbi));                               // Find uncommited region of the stack
        VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));   // Find guard page
        VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));   // Find commited region of the stack
        auto last = (uintptr_t)mbi.BaseAddress;
        return (base + (last - base) + mbi.RegionSize);                             // base + distanceToLastRegion + lastRegionSize
    };

    // Prints an CPU word at the specified stack address
    auto PrintWord = [this, &words_in_line](uintptr_t addr)
    {
        if (words_in_line++ >= stackdump_words_per_line)
        {
            // Print new line only if it's not the first time we enter here (i.e. words_in_line has magical value)
            if (words_in_line != max_words_in_line_magic + 1) NewLine();
            words_in_line = 1;
            Print("0x%p: ", addr);
        }
        Print(" %p", *(uint32_t*)addr);
    };

    Print("Stack dump:");
    EnterScope();
    {
        // Makes sure the pointer at top (ESP) is valid and readable memory
        if (VirtualQuery((void*)(top), &mbi, sizeof(mbi))
            && (mbi.State & MEM_COMMIT)
            && (mbi.Protect & (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_READWRITE | PAGE_READONLY)) != 0)
        {
            base = (uintptr_t)mbi.AllocationBase;          // Base of the stack (uncommited)
            bottom = GetStackBottom(base);                  // Bottom of the stack (commited)

            // Align the stack top (esp) in a 4 bytes boundary
            auto remainder = top % align;
            uintptr_t current = remainder ? top + (align - remainder) : top;

            // on x86 stack grows downward! (i.e. from bottom to base)
            for (int n = 0; n < stackdump_max_words && current < bottom; ++n, current += align)
                PrintWord(current);

            NewLine();
            Print("base: 0x%p   top: 0x%p   bottom: 0x%p", base, top, bottom);
            NewLine();
        }
    }
    LeaveScope();
}
コード例 #4
0
void AssemblyGen(Quad** q, FILE* file, SymbolTable* s) {
/**************************************************************************
 * Name: AssemblyGen
 * Purpose: iterates through each quad, generates the corresponding
 *			assembly code, and outputs the assembly code to a file.
 * Parameters: q, the array of quads
 *			   file, the file to which the assembly code will be wrriten to
 *			   s, the symbol table for our program
 **************************************************************************/
	
	quads = q;
	symtab = s;
	
	/* Here, we keep an array called quadStartLocations that keeps track 
	 * of each quad number and its corresponding assembly code line
	 * number. This makes it easier to quickly to do detect what line we
	 * may need to jump to. 
	 */
	int i = 0;			// Quad number
	int AssemNum = 0;	// Assembly code line number
	int quadStartLocations[10000];
	
	int scopeStart[50] = {0};
	int curScope = 0;
	/* For each quad, we represent it with the form
	 * (op, a1, a2, a3)
	 */
	OpKind op = quads[i]->op;
	Address a1 = quads[i]->addr1;
	Address a2 = quads[i]->addr2;
	Address a3 = quads[i]->addr3;
	
	/* Symbol Table nodes for a1, a2, and a3 respectively */
	SymNode *s1;
	SymNode *s2;
	SymNode *s3;
	
	/* Loop through each quad, generating assembly code as necessary */
	while (quads[i] != NULL) {
		a1 = quads[i]->addr1;
		a2 = quads[i]->addr2;
		a3 = quads[i]->addr3;
		
		quadStartLocations[i] = AssemNum; /* Keeping track of which assembly code line
										   * numbers correspond to which quad numbers.
										   */
		
		
		/* TYPE DETECTION
		 *
		 * All variables are stored in quads as a string beginning with a '$',
		 * so we have see if each value is of type String. If it is then we know
		 * that it is a variable.
		 * Otherwise, it is either an Int constant or Double constant.
		 *
		 * This is checked for all 3 quad variables below.
		 */
		
		char type_to_store = 'i';		/* Type of variable to be stored to (default: int) */
		char type_of_storage = 'i';		/* Type of variable to be stored (default: int) */
		
		/* TYPE DETECTION OF THE FIRST QUAD VARIABLE */
		if (a1.kind == String){
			s1 = LookupInSymbolTable(symtab, a1.contents.name);
			printf(" %s", a1.contents.name);
			if (s1->attrs->type == DouT)
				type_of_storage = 'd';
		}
		else if (a1.kind == IntConst) {
			printf(" %d", a1.contents.val);
		}
		else if (a1.kind == DouConst) {
			printf(" %f", a1.contents.dval);
			type_of_storage = 'd';
		}
		else printf(" - ");
		
		/* TYPE DETECTION OF THE SECOND QUAD VARIABLE */
		if (a2.kind == String){
			s2 = LookupInSymbolTable(symtab, a2.contents.name);
			printf(" %s", a2.contents.name);
		}
		else if (a2.kind == IntConst) {
			printf(" %d", a2.contents.val);
		}
		else if (a2.kind == DouConst) {
			printf(" %f", a2.contents.dval);
		}
		else printf(" - ");
		
		/* TYPE DETECTION OF THE THIRD QUAD VARIABLE */
		if (a3.kind == String){
			s3 = LookupInSymbolTable(symtab, a3.contents.name);
			printf(" %s\n", a3.contents.name);
		}
		else if (a3.kind == IntConst) {
			printf(" %d\n", a3.contents.val);
		}
		else if (a3.kind == DouConst) {
			printf(" %f\n", a3.contents.dval);
		}
		else printf(" - \n");
		
		AssemKind AK;
		char* AssemCommand = " ";
		
		
		
		/****************************************************/
		/****************** TM48 COMMANDS *******************/
		/****************************************************/
		
		if (quads[i]->op == add) {				/* Addition (+) */
			AK = math;		 AssemCommand = "ADD";
		}
		else if (quads[i]->op == sub) {			/* Subtraction (-) */
			AK = math;		 AssemCommand = "SUB";
		}
		else if (quads[i]->op == mul) {			/* Multiplication (*) */
			AK = math;		 AssemCommand = "MUL";
		}
		else if (quads[i]->op == divi) {		/* Division (/) */
			AK = math;		 AssemCommand = "DIV";
		}
		else if (quads[i]->op == gt) {			/* Greater Than (>) */
			AK = inequality; AssemCommand = "GT";
		}
		else if (quads[i]->op == gteq) {		/* Greater Than or Equal (>=) */
			AK = inequality; AssemCommand = "GE";
		}
		else if (quads[i]->op == lt) {			/* Less Than (<) */
			AK = inequality; AssemCommand = "LT";
		}
		else if (quads[i]->op == lteq) {		/* Less Than or Equal (<=) */
			AK = inequality; AssemCommand = "LE";
		}
		else if (quads[i]->op == eq) {			/* Equals (=) */
			AK = inequality; AssemCommand = "EQ";
		}
		else if (quads[i]->op == neq) {			/* Not Equal To (!=) */
			AK = inequality; AssemCommand = "NE";
		}
		else if (quads[i]->op == asn) {			/* Store value */
			AK = assignment; AssemCommand = "ST";
		}
		else if (quads[i]->op == rd) {			/* Read from STD IN */
			AK = read;		 AssemCommand = "IN";
		}
		else if (quads[i]->op == wri) {			/* Write to STD OUT */
			AK = write;		 AssemCommand = "OUT";
		}
		else if (quads[i]->op == if_f) {		/* If False, Jump */
			AK = iffalse;	 AssemCommand = " ";
		}
		else if (quads[i]->op == gotoq) {		/* Go to Quad */
			AK = jumptoquad; AssemCommand = "LDA";
		}
		else if (quads[i]->op == loadpar) {		/* Load a Function's Parameter */
			AK = loadparam;  AssemCommand = "LD";
		}
		else if (quads[i]->op == con) {			/* Continue Statement */
			AK = cont;		 AssemCommand = "CONT";
		}
		else if (quads[i]->op == exs) {			/* Exit Scope */
			AK = exitScope;  AssemCommand = " ";
		}
		else if (quads[i]->op == ens) {			/* Enter Scope */
			AK = enterScope; AssemCommand = " ";
		}
		else if (quads[i]->op == ret) {			/* Return */
			AK = retu; AssemCommand = "LDA";
		}
		else {
			AK = other; AssemCommand = "ERROR";
		}
	
		/****************************************************/
		/***************** CODE GENERATION ******************/
		/****************************************************/
		
		/** Initialize registers **/
		if (i == 0) {
			fprintf(file, "%d: LD 6, 0(0)\n", AssemNum++);
			fprintf(file, "%d: LDF 6, 0(0)\n", AssemNum++);
			fprintf(file, "%d: ST 0, 0(0)\n", AssemNum++);
			fprintf(file, "%d: STF 0, 0(0)\n", AssemNum++);
		}
		switch (AK) {
				
			/*** MATH OPERATORS ***/
			case (math): 
				if (a2.kind == String) {	
					printf("%d\n", s2->attrs->type);
					if (s2->attrs->type == IntT) {		
						fprintf(file, "%d: LD 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
						if (a3.kind == String) {
							if (s3->attrs->type == IntT) {
								/* Operation between Int var and Int var */
								fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset); 
								fprintf(file, "%d: %s 0, 0, 1\n", AssemNum++, AssemCommand);
							}
							else if (s3->attrs->type == DouT) {
								/* Operation between Int var and Double var */
								type_to_store = 'd';
								fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
								if (s3->attrs->memoffset % 8 == 0)
									fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset); 
								else 
									fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
								fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
							}
							else {
								fprintf(file, "ERROR - Math\n");
							}
						}
						else if (a3.kind == IntConst) {
							/* Operation between Int var and Int constant */
							fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
							fprintf(file, "%d: %s 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else if (a3.kind == DouConst) {
							/* Operation between Int var and Double constant */
							type_to_store = 'd';
							fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
							fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval); 
							fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else {
							fprintf(file, "ERROR - Math\n");
						}
					}
					else if (s2->attrs->type == DouT) {
						type_to_store = 'd';
						if (s2->attrs->memoffset % 8 == 0) 
							fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
						else 
							fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset + 4);
						//fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
						if (a3.kind == String) {
							if (s3->attrs->type == IntT) {
								/* Operation between Double var and Int var */
								fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								fprintf(file, "%d: CVTIF 1, 1, 1\n", AssemNum++);
								fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
							}
							else if (s3->attrs->type == DouT) {
								/* Operation between Double var and Double var */
								if (s3->attrs->memoffset % 8 == 0)
									fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								else
									fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
								fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
							}
							else {
								fprintf(file, "ERROR - Math\n");
							}
						}
						else if (a3.kind == IntConst) {
							/* Operation between Double var and Int constant */
							fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
							fprintf(file, "%d: CVTIF 1, 1, 1\n", AssemNum++);
							fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else if (a3.kind == DouConst) {
							/* Operation between Double var and Double constant */
							fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
							fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else {
							fprintf(file, "ERROR - Math\n");
						}
					}
					else {
						fprintf(file, "ERROR - Math\n");
					}
				}
				else if (a2.kind == IntConst) {
					fprintf(file, "%d: LDC 0, %d(0)\n", AssemNum++, a2.contents.val);
					if (a3.kind == String) {
						if (s3->attrs->type == IntT) {
							/* Operation between Int constant and Int var */
							fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							fprintf(file, "%d: %s 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else if (s3->attrs->type == DouT) {
							/* Operation between Int constant and Double var */
							type_to_store = 'd';
							fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
							if (s3->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							else 
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);

							fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else {
							fprintf(file, "ERROR - Math\n");
						}
					}
					else if (a3.kind == IntConst) {
						/* Operation between Int constant and Int constant */
						fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
						fprintf(file, "%d: %s 0, 0, 1\n", AssemNum++, AssemCommand);
					}
					else if (a3.kind == DouConst) {
						/* Operation between Int constant and Double constant */
						type_to_store = 'd';
						fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
						fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
						fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
					}
					else {
						fprintf(file, "ERROR - Math\n");
					}
				}
				else if (a2.kind == DouConst) {
					type_to_store = 'd';
					fprintf(file, "%d: LDFC 0, %f(0)\n", AssemNum++, a2.contents.dval);
					if (a3.kind == String) {
						if (s3->attrs->type == IntT) {
							/* Operation between Double constant and Int var */
							fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							fprintf(file, "%d: CVTIF 1, 1, 1\n", AssemNum++);
							fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else if (s3->attrs->type == DouT) {
							/* Operation between Double constant and Double var */
							if (s3->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							else
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
							fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
						}
						else {
							fprintf(file, "ERROR - Math\n");
						}
					}
					else if (a3.kind == IntConst) {
						/* Operation between Double constant and Int constant */
						fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
						fprintf(file, "%d: CVTIF 1, 1, 1\n", AssemNum++);
						fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
					}
					else if (a3.kind == DouConst) {
						/* Operation between Double constant and Double constant */
						fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
						fprintf(file, "%d: %sF 0, 0, 1\n", AssemNum++, AssemCommand);
					}
					else {
						fprintf(file, "ERROR - Math\n");
					}
				}
				else {
					fprintf(file, "ERROR - Math\n");
				}
				
				
				/** Storing values based on data types **/
				
				/* Store double in double */
				if (type_to_store == 'd' && type_of_storage == 'd') {		
					//fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					if (s1->attrs->memoffset % 8 == 0) 
						fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					else  
						fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);
				}
				/* Store double in int */
				else if (type_to_store == 'd' && type_of_storage == 'i') {	
					fprintf(file, "%d: CVTFI 0, 0, 0\n", AssemNum++);
					fprintf(file, "%d: ST 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
				}
				/* Store int in double */
				else if (type_to_store == 'i' && type_of_storage == 'd') {	
					fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
					if (s1->attrs->memoffset % 8 == 0)
						fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					else 
						fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);
					//fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
				}
				/* Store int in int */
				else if (type_to_store == 'i' && type_of_storage == 'i') {	
					fprintf(file, "%d: ST 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
				}
				else {
					fprintf(file, "ERROR - Math\n");
				} 
				break;
				

			/*** INEQUALITIES ***/
			case inequality:
				if (a2.kind == String) {
					if (s2->attrs->type == IntT) {
						fprintf(file, "%d: LD 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
						if (a3.kind == String) {
							if (s3->attrs->type == IntT) {
								/* Ineqality between Int var and Int var */
								fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								fprintf(file, "%d: SUB 0, 1, 0\n", AssemNum++);
								fprintf(file, "%d: J%s 0, 2(7)\n", AssemNum++, AssemCommand);
								fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
								fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
								fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
							}
							else if (s3->attrs->type == DouT) {
								/* Ineqality between Int var and Double var */
								fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
								//fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								if (s3->attrs->memoffset % 8 == 0)
									fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								else
									fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
								fprintf(file, "%d: SUBF 0, 1, 0\n", AssemNum++);
								fprintf(file, "%d: JF%s 0, 2(7)\n", AssemNum++, AssemCommand);
								fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
								fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
								fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
							}
							else {
								fprintf(file, "ERROR - Inequality\n");
							}
						}
						else if (a3.kind == IntConst) {
							/* Ineqality between Int var and Int constant */
							fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
							fprintf(file, "%d: SUB 0, 1, 0\n", AssemNum++);
							fprintf(file, "%d: J%s 0, 2(7)\n", AssemNum++, AssemCommand);
							fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
							fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
							fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
						}
						else if (a3.kind == DouConst) {
							/* Ineqality between Int var and Double constant */
							fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
							fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
							fprintf(file, "%d: SUBF 0, 1, 0\n", AssemNum++);
							fprintf(file, "%d: JF%s 0, 2(7)\n", AssemNum++, AssemCommand);
							fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
							fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
							fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
						}
						else {
							fprintf(file, "ERROR - Inequality\n");
						}
					}
					else if (s2->attrs->type == DouT) {
						if (s2->attrs->memoffset % 8 == 0)
							fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
						else
							fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset + 4);
						//fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
						if (a3.kind == String) {
							if (s3->attrs->type == IntT) {
								/* Ineqality between Double var and Int var */
								fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								fprintf(file, "%d: CVTIF 1, 1, 1\n", AssemNum++);
							}
							else if (s3->attrs->type == DouT) {
								/* Ineqality between Double var and Double var */
								//fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								if (s3->attrs->memoffset % 8 == 0)
									fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
								else 
									fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
							}
							else {
								fprintf(file, "ERROR - Inequality\n");
							}
						}
						else if (a3.kind == IntConst) {
							/* Ineqality between Double var and Int constant */
							fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
							fprintf(file, "%d: CVTIF 1, 1, 1\n", AssemNum++);
						}
						else if (a3.kind == DouConst) {
							/* Ineqality between Double var and Double constant */
							fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
						}
						else {
							fprintf(file, "ERROR - Inequality\n");
						}
						fprintf(file, "%d: SUBF 0, 1, 0\n", AssemNum++);
						fprintf(file, "%d: JF%s 0, 2(7)\n", AssemNum++, AssemCommand);
						fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
						fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
						fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
					}
					else {
						fprintf(file, "ERROR - Inequality\n");
					}
				}
				else if (a2.kind == IntConst) {
					fprintf(file, "%d: LDC 0, %d(0)\n", AssemNum++, a2.contents.val);
					if (a3.kind == String) {
						if (s3->attrs->type == IntT) {
							/* Ineqality between Int constant and Int var */
							fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							fprintf(file, "%d: SUB 0, 1, 0\n", AssemNum++);
							fprintf(file, "%d: J%s 0, 2(7)\n", AssemNum++, AssemCommand);
							fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
							fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
							fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
						}
						else if (s3->attrs->type == DouT) {
							/* Ineqality between Int constant and Double var */
							fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
							if (s3->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							else
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
							fprintf(file, "%d: SUBF 0, 1, 0\n", AssemNum++);
							fprintf(file, "%d: JF%s 0, 2(7)\n", AssemNum++, AssemCommand);
							fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
							fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
							fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
						}
						else {
							fprintf(file, "ERROR - Inequality\n");
						}
					}
					else if (a3.kind == IntConst) {
						/* Ineqality between Int constant and Int constant */
						fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
						fprintf(file, "%d: SUB 0, 1, 0\n", AssemNum++);
						fprintf(file, "%d: J%s 0, 2(7)\n", AssemNum++, AssemCommand);
						fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
						fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
						fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
					}
					else if (a3.kind == DouConst) {
						/* Ineqality between Int constant and Double constant */
						fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
						fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
						fprintf(file, "%d: SUBF 0, 1, 0\n", AssemNum++);
						fprintf(file, "%d: JF%s 0, 2(7)\n", AssemNum++, AssemCommand);
						fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
						fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
						fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
					}
					else {
						fprintf(file, "ERROR - Inequality\n");
					}
				}
				else if (a2.kind == DouConst) {
					fprintf(file, "%d: LDFC 0, %f(0)\n", AssemNum++, a2.contents.dval);
					if (a3.kind == String) {
						if (s3->attrs->type == IntT) {
							/* Ineqality between Double constant and Int var */
							fprintf(file, "%d: LD 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							fprintf(file, "%d: CVTIF 1, 0, 1\n", AssemNum++);
						}
						else if (s3->attrs->type == DouT) {
							/* Ineqality between Double constant and Double var */
							if (s3->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset);
							else
								fprintf(file, "%d: LDF 1, %d(5)\n", AssemNum++, -s3->attrs->memoffset + 4);
						}
						else {
							fprintf(file, "ERROR - Inequality\n");
						}
					}
					else if (a3.kind == IntConst) {
						/* Ineqality between Double constant and Int constant */
						fprintf(file, "%d: LDC 1, %d(0)\n", AssemNum++, a3.contents.val);
						fprintf(file, "%d: CVTIF 1, 0, 1\n", AssemNum++);
					}
					else if (a3.kind == DouConst) {
						/* Ineqality between Double constant and Double constant */
						fprintf(file, "%d: LDFC 1, %f(0)\n", AssemNum++, a3.contents.dval);
					}
					else {
						fprintf(file, "ERROR - Inequality\n");
					}
					fprintf(file, "%d: SUBF 0, 1, 0\n", AssemNum++);
					fprintf(file, "%d: JF%s 0, 2(7)\n", AssemNum++, AssemCommand);
					fprintf(file, "%d: LDC 0, 0(0)\n", AssemNum++);
					fprintf(file, "%d: LDA 7, 1(7)\n", AssemNum++);
					fprintf(file, "%d: LDC 0, 1(0)\n", AssemNum++);
				}
				else {
					fprintf(file, "ERROR\n");
				}
				break;
				
			/*** ASSIGNMENT ***/
			case assignment:
				if (type_of_storage == 'd') {
					if (a2.kind == String) {
						if (s2->attrs->type == IntT) {
							/* Store an Int variable in a Double variable */
							fprintf(file, "%d: LD 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
							fprintf(file, "%d: CVTIF 0, 0, 0\n", AssemNum++);
							if (s1->attrs->memoffset % 8 == 0) 
								fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
							else  
								fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);

						}
						else if (s2->attrs->type == DouT) {
							/* Store a Double variable in a Double variable */
							if (s2->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
							else 
								fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset + 4);
							if (s1->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
							else 
								fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);
							//fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						}
						else {
							fprintf(file, "ERROR - Assignment 1\n");
						}
					}
					else if (a2.kind == DouConst) {
						/* Store a Double constant in a Double variable */
						fprintf(file, "%d: LDFC 0, %f(0)\n", AssemNum++, a2.contents.dval);
						if (s1->attrs->memoffset % 8 == 0) 
							fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						else
							fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);
						//fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					}
					else if (a2.kind == IntConst) {
						/* Store an Int constant in a Double variable */
						fprintf(file, "%d: LDC 0, %d(0)\n", AssemNum++, a2.contents.val);
						fprintf(file, "%d: CVTIF 0 0, 0\n", AssemNum++);
						if (s1->attrs->memoffset % 8 == 0)
							fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						else 
							fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);
						//fprintf(file, "%d: STF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					}
					else {
						fprintf(file, "ERROR - Assignment 2\n");
					}
				}
				else { /* If storage type is an integer */
					if (a2.kind == String) {
						if (s2->attrs->type == IntT) {
							/* Store an Int variable in an Int variable */
							fprintf(file, "%d: LD 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
							fprintf(file, "%d: ST 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						}
						else if (s2->attrs->type == DouT) {
							/* Store a Double variable in an Int variable */
							if (s2->attrs->memoffset % 8 == 0)
								fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
							else 
								fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s2->attrs->memoffset + 4);
							//fprintf(file, "%d: f, %d(5)\n", AssemNum++, -s2->attrs->memoffset);
							fprintf(file, "%d: CVTFI 0, 0, 0\n", AssemNum++);
							fprintf(file, "%d: ST 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						}
						else {
							/*f*/printf(/*file,*/ "ERROR - Assignment 3\n");
						}
					}
					else if (a2.kind == DouConst) {
						/* Store a Double constant in an Int variable */
						fprintf(file, "%d: LDFC 0, %f(0)\n", AssemNum++, a2.contents.dval);
						fprintf(file, "%d: CVTFI 0 0, 0\n", AssemNum++);
						fprintf(file, "%d: ST 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					}
					else if (a2.kind == IntConst) {
						/* Store an Int constant in an Int variable */
						fprintf(file, "%d: LDC 0, %d(0)\n", AssemNum++, a2.contents.val);
						fprintf(file, "%d: ST 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
					}
					else {
						fprintf(file, "ERROR - Assignment 4\n");
					}
				}
				break;
			
			/*** READ FROM STANDARD INPUT ***/
			case read:
				if (s1->attrs->type == IntT) {
					fprintf(file, "%d: IN 0, 0, 0\n", AssemNum++);
				}
				else if (s1->attrs->type == DouT) {
					fprintf(file, "%d: INF 0, 0, 0\n", AssemNum++);
				}
				else {
					fprintf(file, "ERROR - Read\n");
				}
				break;
			
			/*** WRITE TO STANDARD OUTPUT ***/
			case write:
				if (a1.kind == String) {
					if (s1->attrs->type == IntT) {
						fprintf(file, "%d: LD 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						fprintf(file, "%d: OUT 0, 0, 0\n", AssemNum++);
					}
					else if (s1->attrs->type == DouT) {
						if (s1->attrs->memoffset % 8 == 0)
							fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset);
						else 
							fprintf(file, "%d: LDF 0, %d(5)\n", AssemNum++, -s1->attrs->memoffset + 4);

						fprintf(file, "%d: OUTF 0, 0, 0\n", AssemNum++);
					}
					else {
						/*f*/printf(/*file,*/ "ERROR - Write\n");
					}
				}
				else if (a1.kind == IntConst) {
					fprintf(file, "%d: LDC 0, %d(0)\n", AssemNum++, a1.contents.val);
					fprintf(file, "%d: OUT 0, 0, 0\n", AssemNum++);
				}
				else if (a1.kind == DouConst) {
					fprintf(file, "%d: LDFC 0, %f(0)\n", AssemNum++, a1.contents.dval);
					fprintf(file, "%d: OUTF 0, 0, 0\n", AssemNum++);
				}
				else {
					fprintf(file, "ERROR - Write\n");
				}
				break;
			
				
			/* 
			 * "If False" and "Goto" quads are not analyzed in normal order.
			 * This is explained below when they are actually implemented.
			 */
			
			/*** JUMP IF FALSE ***/
			case iffalse:
				AssemNum++;
				AssemNum++;
				AssemNum++;
				break;
				
			/*** JUMP TO A QUAD ***/
			case jumptoquad:
				AssemNum++;
				break;
				
			/*** CONTINUE ***/
			case cont:
				fprintf(file, "%d: LDA 7, %d(7)\n", AssemNum++, curScope);
				break;
						
								
			case enterScope:
				//printf(" Level %d \n", GetNodeLevel(s1));
				printf("ENTERING SCOPE\n");
				scopeStart[++curScope] = i;
				EnterScope(symtab);
				//continue;
				break;
			case exitScope:
				scopeStart[--curScope] = 0;
				
				LeaveScope(symtab);
				//printf(" Level %d \n", GetNodeLevel(s1));
				//continue;
				break;
				
			case retu:
				printf("RETURNING AASFEGAEGEGAE\n");
				fprintf(file, "%d: LDA 7, %d(7)\n", AssemNum++, curScope);
				break;
				
			default:
				//printf("Quad not recognized.\n");
				break;
				
		}
		i++;
	}
	
	/*
	 * Due to the fact that there are times that we may want to jump to an
	 * unknown location that we have not processed yet, we wait to analyze 
	 * "goto" and "if false" quads until after all other asseembly lines
	 * have been analyzed. 
	 *
	 * By doing this we can just print a few lines out of order to avoid any
	 * rewriting of the output file.
	 * /
	
	/*** Printing assembly lines for goto statements. ***/
	i = 0;
	while (quads[i] != NULL) {
		a1 = quads[i]->addr1;
		a2 = quads[i]->addr2;
		a3 = quads[i]->addr3;
		
		if (quads[i]->op == gotoq) {
			fprintf(file, "%d: LDA 7, %d(7)\n", quadStartLocations[i], (quadStartLocations[a1.contents.val]) - quadStartLocations[i] - 1);
		}
		i++;
	}
	
	/*** Printing assembly lines for "if false" statements ***/
	i = 0;
	while (quads[i] != NULL) {
		a1 = quads[i]->addr1;
		a2 = quads[i]->addr2;
		a3 = quads[i]->addr3;
		
		if (quads[i]->op == if_f) {
			if (a1.kind == String) {
				s1 = LookupInSymbolTable(symtab, a1.contents.name);
				if (s1->attrs->type == IntT) {
					fprintf(file, "%d: LD 0, %d(5)\n", quadStartLocations[i], -s1->attrs->memoffset);
					fprintf(file, "%d: JNE 0, 1(7)\n", quadStartLocations[i]+1);
					fprintf(file, "%d: LDA 7, %d(7)\n", quadStartLocations[i]+2, (quadStartLocations[a2.contents.val]) - (quadStartLocations[i]+2) - 1);
				}
				else if (s1->attrs->type == DouT) {
					if (s1->attrs->memoffset % 8 == 0)
						fprintf(file, "%d: LDF 0, %d(5)\n", quadStartLocations[i], -s1->attrs->memoffset);
					else 
						fprintf(file, "%d: LDF 0, %d(5)\n", quadStartLocations[i], -s1->attrs->memoffset + 4);
					fprintf(file, "%d: JFNE 0, 1(7)\n", quadStartLocations[i]+1);
					fprintf(file, "%d: LDA 7, %d(7)\n", quadStartLocations[i]+2, (quadStartLocations[a2.contents.val]) - (quadStartLocations[i]+2) - 1);
				}
				else {
					printf("ERROR - IfFalse\n");
				}
			}
			i++;
		}
		printf("%d\n", i++);
	}	
	
	/* Code for debugging purposes.
	 * This prints quad lines and their corresponding assembly lines.
	 */
	
	int j = 0;
	for (j = 0; j < 100; j++) {
		printf("%d %d\n", j, quadStartLocations[j]);
	}
	
	
	fprintf(file, "%d: HALT 0, 0, 0\n", AssemNum++);
}