current output

Current PID: 0. Memory instantiation complete. OFF bits: 1. PFN bits: 2. VPN bits: 2
Current PID: 0. Mapped virtual page number 0 to physical frame number 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Mapped virtual page number 0 to physical frame number 1
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Mapped virtual page number 0 to physical frame number 2
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Mapped virtual page number 0 to physical frame number 3
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Inspected physical location 0. Value: 42
Current PID: 0. Inspected physical location 1. Value: 42
Current PID: 0. Inspected physical location 2. Value: 0
Current PID: 0. Inspected physical location 3. Value: 0
Current PID: 0. Inspected physical location 4. Value: 0
Current PID: 0. Inspected physical location 5. Value: 0
Current PID: 0. Inspected physical location 6. Value: 0
Current PID: 0. Inspected physical location 7. Value: 0


expected output:

Current PID: 0. Memory instantiation complete. OFF bits: 1. PFN bits: 2. VPN bits: 2
Current PID: 0. Mapped virtual page number 0 to physical frame number 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 0
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Mapped virtual page number 0 to physical frame number 1
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 1
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 1
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Mapped virtual page number 0 to physical frame number 2
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 2
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 2
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Mapped virtual page number 0 to physical frame number 3
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 3
Current PID: 0. Stored immediate 42 into location 0
Current PID: 0. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 3
Current PID: 0. Stored immediate 42 into location 1
Current PID: 0. Inspected physical location 0. Value: 42
Current PID: 0. Inspected physical location 1. Value: 42
Current PID: 0. Inspected physical location 2. Value: 42
Current PID: 0. Inspected physical location 3. Value: 42
Current PID: 0. Inspected physical location 4. Value: 42
Current PID: 0. Inspected physical location 5. Value: 42
Current PID: 0. Inspected physical location 6. Value: 42
Current PID: 0. Inspected physical location 7. Value: 42


as you can see the PFN needs to update here and the physical location value should be 42 for each, here is the input

% Test 5.1: mapping all the things
define 1 2 2
map 0 0
store 0 #42
store 1 #42
map 0 1
store 0 #42
store 1 #42
map 0 2
store 0 #42
store 1 #42
map 0 3
store 0 #42
store 1 #42
linspect 0
linspect 1
linspect 2
linspect 3
linspect 4
linspect 5
linspect 6
linspect 7



please look at my code and fix the problem

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TRUE 1
#define FALSE 0
#define MAX_PROCESSES 4
#define MAX_REGISTERS 2
#define MAX_PAGES 64
#define PAGE_SIZE 32
#define TLB_SIZE 8

// Output file
FILE* output_file;

// TLB replacement strategy (FIFO or LRU)
char* strategy;

// Global timestamp for TLB entries
int global_timestamp = 0;

// State variables
int define_called = FALSE;
int current_pid = 0;
int registers[MAX_PROCESSES][MAX_REGISTERS];
int page_table[MAX_PROCESSES][MAX_PAGES];
int* memory = NULL; // Dynamically allocated based on define
int off_bits = 0;
int pfn_bits = 0;
int vpn_bits = 0;

// TLB structure
typedef struct {
    int pid;
    int vpn;
    int pfn;
    int valid;
    int timestamp;
} TLBEntry;

TLBEntry tlb[TLB_SIZE];
int global_tlb_index = 0; // For FIFO replacement

// Function to tokenize input
char** tokenize_input(char* input) {
    char** tokens = NULL;
    char* token = strtok(input, " ");
    int num_tokens = 0;

    while (token != NULL) {
        num_tokens++;
        tokens = realloc(tokens, num_tokens * sizeof(char*));
        if (tokens == NULL) {
            fprintf(stderr, "Error: Memory allocation failed during tokenization.\n");
            exit(1);
        }
        tokens[num_tokens - 1] = malloc(strlen(token) + 1);
        if (tokens[num_tokens - 1] == NULL) {
            fprintf(stderr, "Error: Memory allocation failed during tokenization.\n");
            exit(1);
        }
        strcpy(tokens[num_tokens - 1], token);
        token = strtok(NULL, " ");
    }

    num_tokens++;
    tokens = realloc(tokens, num_tokens * sizeof(char*));
    if (tokens == NULL) {
        fprintf(stderr, "Error: Memory allocation failed during tokenization.\n");
        exit(1);
    }
    tokens[num_tokens - 1] = NULL;

    return tokens;
}

// TLB lookup
int tlb_lookup(int pid, int vpn, int* pfn, int* tlb_entry) {
    for (int i = 0; i < TLB_SIZE; i++) {
        if (tlb[i].valid && tlb[i].pid == pid && tlb[i].vpn == vpn) {
            *pfn = tlb[i].pfn;
            *tlb_entry = i;
            fprintf(output_file, "Current PID: %d. Translating. Lookup for VPN %d hit in TLB entry %d. PFN is %d\n",
                    pid, vpn, i, *pfn);
            
            // If using LRU, update the timestamp to mark this entry as recently used
            if (strcmp(strategy, "LRU") == 0) {
                tlb[i].timestamp = global_timestamp;
            }

            return TRUE;
        }
    }

    // On TLB miss
    fprintf(output_file, "Current PID: %d. Translating. Lookup for VPN %d caused a TLB miss\n", pid, vpn);
    return FALSE;
}

// Per-process TLB update with FIFO replacement
void tlb_update(int pid, int vpn, int pfn) {
    int entry_index = -1;

    // First, check for any invalid (unused) TLB entries
    for (int i = 0; i < TLB_SIZE; i++) {
        if (!tlb[i].valid) {
            entry_index = i;
            break;
        }
    }

    if (entry_index == -1) { // All TLB entries are valid, need to replace one
        if (strcmp(strategy, "FIFO") == 0) {
            // FIFO Replacement: Replace the next entry in cyclic order
            entry_index = global_tlb_index % TLB_SIZE;
            global_tlb_index++;
        }
        else if (strcmp(strategy, "LRU") == 0) {
            // LRU Replacement: Find the entry with the smallest timestamp (least recently used)
            int min_timestamp = tlb[0].timestamp;
            entry_index = 0;
            for (int i = 1; i < TLB_SIZE; i++) {
                if (tlb[i].timestamp < min_timestamp) {
                    min_timestamp = tlb[i].timestamp;
                    entry_index = i;
                }
            }
        }
        else {
            // Default to FIFO if strategy is unrecognized
            fprintf(stderr, "Warning: Unknown TLB replacement strategy '%s'. Defaulting to FIFO.\n", strategy);
            entry_index = global_tlb_index % TLB_SIZE;
            global_tlb_index++;
        }
    }

    // Update or populate the determined TLB entry
    tlb[entry_index].pid = pid;
    tlb[entry_index].vpn = vpn;
    tlb[entry_index].pfn = pfn;
    tlb[entry_index].valid = TRUE;
    tlb[entry_index].timestamp = global_timestamp; // Set timestamp to current

    fprintf(output_file, "Current PID: %d. Mapped virtual page number %d to physical frame number %d\n", pid, vpn, pfn);
}

// Function to handle loading an immediate into a register
void handle_load(char** tokens) {
    if (strcmp(tokens[1], "r1") == 0 || strcmp(tokens[1], "r2") == 0) {
        int reg_index = (strcmp(tokens[1], "r1") == 0) ? 0 : 1;
        int value = atoi(tokens[2] + 1); // Skip the '#' character
        registers[current_pid][reg_index] = value;
        fprintf(output_file, "Current PID: %d. Loaded immediate %d into register %s\n", current_pid, value, tokens[1]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[1]);
    }
}

// Function to handle add operation
void handle_add() {
    int result = registers[current_pid][0] + registers[current_pid][1];
    fprintf(output_file, "Current PID: %d. Added contents of registers r1 (%d) and r2 (%d). Result: %d\n",
            current_pid, registers[current_pid][0], registers[current_pid][1], result);
    registers[current_pid][0] = result;
}

// Function to map a virtual page to a physical frame
void handle_map(char** tokens) {
    int vpn = atoi(tokens[1]);
    int pfn = atoi(tokens[2]);

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range\n", current_pid, vpn);
        return;
    }

    if (pfn < 0 || pfn >= (1 << pfn_bits)) {
        fprintf(output_file, "Current PID: %d. Error: PFN %d out of range\n", current_pid, pfn);
        return;
    }

    // Update the page table
    page_table[current_pid][vpn] = pfn;

    // Update the TLB entry with the new mapping
    tlb_update(current_pid, vpn, pfn);
}

// Function to unmap a virtual page
void handle_unmap(char** tokens) {
    int vpn = atoi(tokens[1]);

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range\n", current_pid, vpn);
        return;
    }

    // Invalidate any TLB entry for this PID and VPN
    for (int i = 0; i < TLB_SIZE; i++) {
        if (tlb[i].valid && tlb[i].pid == current_pid && tlb[i].vpn == vpn) {
            tlb[i].valid = FALSE;
            // Do not print per-entry unmap messages to match expected output
        }
    }

    // Invalidate in the page table
    page_table[current_pid][vpn] = -1;
    fprintf(output_file, "Current PID: %d. Unmapped virtual page number %d\n", current_pid, vpn);
}

// Function to handle store operation
void handle_store(char** tokens) {
    int addr = atoi(tokens[1]);
    int reg_value;
    if (tokens[2][0] == '#') {
        reg_value = atoi(tokens[2] + 1);
    } else if (strcmp(tokens[2], "r1") == 0 || strcmp(tokens[2], "r2") == 0) {
        int reg_index = (strcmp(tokens[2], "r1") == 0) ? 0 : 1;
        reg_value = registers[current_pid][reg_index];
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[2]);
        return;
    }

    int vpn = addr >> off_bits; // Calculate VPN by shifting address right by off_bits
    int offset = addr & ((1 << off_bits) - 1); // Offset mask based on off_bits

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range for address %d\n", current_pid, vpn, addr);
        return;
    }

    int pfn;
    int tlb_entry;
    if (!tlb_lookup(current_pid, vpn, &pfn, &tlb_entry)) {
        // If TLB miss, fall back to page table
        pfn = page_table[current_pid][vpn];
        if (pfn != -1) {
            tlb_update(current_pid, vpn, pfn); // Update TLB if mapping is in page table
            fprintf(output_file, "Current PID: %d. Translating. Successfully mapped VPN %d to PFN %d\n", current_pid, vpn, pfn);
        } else {
            fprintf(output_file, "Current PID: %d. Error: attempted to store to unmapped address %d\n", current_pid, addr);
            return;
        }
    }

    int phys_addr = (pfn << off_bits) | offset;
    if (phys_addr < 0 || phys_addr >= (1 << (pfn_bits + off_bits))) {
        fprintf(output_file, "Current PID: %d. Error: physical address %d out of range\n", current_pid, phys_addr);
        return;
    }
    memory[phys_addr] = reg_value;

    if (tokens[2][0] == '#') {
        fprintf(output_file, "Current PID: %d. Stored immediate %d into location %d\n", current_pid, reg_value, addr);
    } else {
        fprintf(output_file, "Current PID: %d. Stored value of register %s (%d) into location %d\n", current_pid, tokens[2], reg_value, addr);
    }
}

// handle_load_mem function
void handle_load_mem(char** tokens) {
    int addr = atoi(tokens[2]);
    int vpn = addr >> off_bits; // Calculate VPN by shifting address right by off_bits
    int offset = addr & ((1 << off_bits) - 1); // Offset mask based on off_bits

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range for address %d\n", current_pid, vpn, addr);
        return;
    }

    int pfn;
    int tlb_entry;
    if (!tlb_lookup(current_pid, vpn, &pfn, &tlb_entry)) {
        // If TLB miss, fall back to page table
        pfn = page_table[current_pid][vpn];
        if (pfn != -1) {
            tlb_update(current_pid, vpn, pfn); // Update TLB if mapping is in page table
            fprintf(output_file, "Current PID: %d. Translating. Successfully mapped VPN %d to PFN %d\n", current_pid, vpn, pfn);
        } else {
            fprintf(output_file, "Current PID: %d. Translating. Translation for VPN %d not found in page table\n", current_pid, vpn);
            return;
        }
    }

    int phys_addr = (pfn << off_bits) | offset;
    if (phys_addr < 0 || phys_addr >= (1 << (pfn_bits + off_bits))) {
        fprintf(output_file, "Current PID: %d. Error: physical address %d out of range\n", current_pid, phys_addr);
        return;
    }

    if (strcmp(tokens[1], "r1") == 0 || strcmp(tokens[1], "r2") == 0) {
        int reg_index = (strcmp(tokens[1], "r1") == 0) ? 0 : 1;
        registers[current_pid][reg_index] = memory[phys_addr];
        fprintf(output_file, "Current PID: %d. Loaded value of location %d (%d) into register %s\n", current_pid, addr, memory[phys_addr], tokens[1]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[1]);
    }
}

// Function to inspect page table entry
void handle_pinspect(char** tokens) {
    int vpn = atoi(tokens[1]);
    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range for inspection\n", current_pid, vpn);
        return;
    }
    int pfn = page_table[current_pid][vpn];
    
    // Translate internal PFN of -1 to 0 for reporting
    int display_pfn = (pfn == -1) ? 0 : pfn;
    int valid = (pfn != -1) ? 1 : 0;
    
    fprintf(output_file, "Current PID: %d. Inspected page table entry %d. Physical frame number: %d. Valid: %d\n",
            current_pid, vpn, display_pfn, valid);
}

// Function to inspect TLB entry
void handle_tinspect(char** tokens) {
    int tlbn = atoi(tokens[1]);
    if (tlbn >= 0 && tlbn < TLB_SIZE) {
        TLBEntry entry = tlb[tlbn];
        fprintf(output_file, "Current PID: %d. Inspected TLB entry %d. VPN: %d. PFN: %d. Valid: %d. PID: %d. Timestamp: %d\n",
                current_pid, tlbn, entry.vpn, entry.pfn, entry.valid, entry.pid, entry.timestamp);
    } else {
        fprintf(output_file, "Current PID: %d. Error: TLB number %d out of range\n", current_pid, tlbn);
    }
}

// Function to inspect physical memory location
void handle_linspect(char** tokens) {
    int pl = atoi(tokens[1]);
    if (pl >= 0 && pl < (1 << (pfn_bits + off_bits))) { // Dynamic memory size
        fprintf(output_file, "Current PID: %d. Inspected physical location %d. Value: %d\n",
                current_pid, pl, memory[pl]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: physical location %d out of range\n", current_pid, pl);
    }
}

// Function to inspect register
void handle_rinspect(char** tokens) {
    if (strcmp(tokens[1], "r1") == 0 || strcmp(tokens[1], "r2") == 0) {
        int reg_index = (strcmp(tokens[1], "r1") == 0) ? 0 : 1;
        fprintf(output_file, "Current PID: %d. Inspected register %s. Content: %d\n",
                current_pid, tokens[1], registers[current_pid][reg_index]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[1]);
    }
}

int main(int argc, char* argv[]) {
    const char usage[] = "Usage: memsym.out <strategy> <input trace> <output trace>\n";
    char* input_trace;
    char* output_trace;
    char buffer[2048]; // Increased buffer size for longer lines

    // Parse command line arguments
    if (argc != 4) {
        printf("%s", usage);
        return 1;
    }
    strategy = argv[1];
    input_trace = argv[2];
    output_trace = argv[3];

    // Validate strategy
    if (strcmp(strategy, "FIFO") != 0 && strcmp(strategy, "LRU") != 0) {
        fprintf(stderr, "Error: Invalid TLB replacement strategy '%s'. Use 'FIFO' or 'LRU'.\n", strategy);
        return 1;
    }

    // Initialize memory and page tables to -1 (unmapped)
    for (int i = 0; i < MAX_PROCESSES; i++) {
        for (int j = 0; j < MAX_PAGES; j++) {
            page_table[i][j] = -1;
        }
    }

    // Initialize TLB entries to invalid
    for(int i = 0; i < TLB_SIZE; i++) {
        tlb[i].valid = FALSE;
        tlb[i].pid = -1;
        tlb[i].vpn = -1;
        tlb[i].pfn = -1;
        tlb[i].timestamp = 0;
    }

    // Open input and output files
    FILE* input_file = fopen(input_trace, "r");
    if (!input_file) {
        fprintf(stderr, "Error: Cannot open input file %s\n", input_trace);
        return 1;
    }
    output_file = fopen(output_trace, "w");  
    if (!output_file) {
        fprintf(stderr, "Error: Cannot open output file %s\n", output_trace);
        fclose(input_file);
        return 1;
    }

    while (fgets(buffer, sizeof(buffer), input_file)) {
        // Remove the newline character if present
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        }

        char** tokens = tokenize_input(buffer);

        // Ignore comments
        if (tokens[0] && tokens[0][0] == '%') {
            for (int i = 0; tokens[i] != NULL; i++)
                free(tokens[i]);
            free(tokens);
            continue;
        }

        // Increment the global timestamp for each instruction
        global_timestamp++;

        // Implement the memory simulator
        if (tokens[0] != NULL) {
            if (strcmp(tokens[0], "define") == 0) {
                if (define_called) {
                    fprintf(output_file, "Current PID: 0. Error: multiple calls to define in the same trace\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                } else {
                    if (tokens[1] == NULL || tokens[2] == NULL || tokens[3] == NULL) { // Ensure there are enough tokens
                        fprintf(output_file, "Current PID: 0. Error: insufficient arguments for define\n");
                        // Clean up tokens before exiting
                        for (int i = 0; tokens[i] != NULL; i++)
                            free(tokens[i]);
                        free(tokens);
                        break;
                    }
                    define_called = TRUE;
                    off_bits = atoi(tokens[1]);
                    pfn_bits = atoi(tokens[2]);
                    vpn_bits = atoi(tokens[3]);

                    // Calculate memory size based on OFF and PFN bits
                    // Total physical addresses = (2^PFN_bits) * (2^OFF_bits)
                    // Each address holds an integer
                    unsigned long memory_size = ((unsigned long)(1) << (pfn_bits + off_bits));

                    // Allocate memory
                    memory = (int*)malloc(memory_size * sizeof(int));
                    if (memory == NULL) {
                        fprintf(stderr, "Error: Memory allocation failed.\n");
                        fclose(input_file);
                        fclose(output_file);
                        return 1;
                    }
                    memset(memory, 0, memory_size * sizeof(int));

                    fprintf(output_file, "Current PID: 0. Memory instantiation complete. OFF bits: %d. PFN bits: %d. VPN bits: %d\n", off_bits, pfn_bits, vpn_bits);
                }
            } 
            else if (strcmp(tokens[0], "ctxswitch") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for ctxswitch\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                int new_pid = atoi(tokens[1]);
                if (new_pid < 0 || new_pid >= MAX_PROCESSES) {
                    fprintf(output_file, "Current PID: %d. Invalid context switch to process %d\n", current_pid, new_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                } else {
                    current_pid = new_pid;
                    fprintf(output_file, "Current PID: %d. Switched execution context to process: %d\n", current_pid, new_pid);
                }
            } 
            else if (strcmp(tokens[0], "load") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[2] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for load\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[2][0] == '#') {
                    handle_load(tokens);
                } else {
                    handle_load_mem(tokens);
                }
            } 
            else if (strcmp(tokens[0], "add") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_add();
            } 
            else if (strcmp(tokens[0], "map") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_map(tokens);
            } 
            else if (strcmp(tokens[0], "unmap") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_unmap(tokens);
            } 
            else if (strcmp(tokens[0], "store") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL || tokens[2] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for store\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_store(tokens);
            } 
            else if (strcmp(tokens[0], "pinspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for pinspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_pinspect(tokens);
            } 
            else if (strcmp(tokens[0], "tinspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for tinspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_tinspect(tokens);
            } 
            else if (strcmp(tokens[0], "linspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for linspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_linspect(tokens);
            } 
            else if (strcmp(tokens[0], "rinspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for rininspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_rinspect(tokens);
            } 
            else {
                fprintf(output_file, "Current PID: %d. Error: Unknown instruction %s\n", current_pid, tokens[0]);
                // Clean up tokens before exiting
                for (int i = 0; tokens[i] != NULL; i++)
                    free(tokens[i]);
                free(tokens);
                break;
            }
        }

        // Deallocate tokens
        for (int i = 0; tokens[i] != NULL; i++)
            free(tokens[i]);
        free(tokens);
    }

    // Close input and output files
    fclose(input_file);
    fclose(output_file);

    // Free dynamically allocated memory
    if (memory != NULL) {
        free(memory);
    }

    return 0;
}


only post relevant code updates such as there functions