#include "lc4_memory.h"
#include <stdio.h>
#include <stdlib.h>
#define GET_LAST_4(X) ((X) & 0xF)
#define GET_FIRST_4(X) ((X >> 12) & 0xF)
int add_to_list(row_of_memory **head, short unsigned int address,
short unsigned int contents) {
row_of_memory *node = search_address(*head, address);
// if a node with the specified address already exists in the LinkedList, this
// function MUST update the contents field and take no other action
if (node) {
node->contents = contents;
return 0;
}
// allocate space for a new node
node = (row_of_memory *)malloc(sizeof(row_of_memory));
// return -1 if malloc fails
if (!node) {
fprintf(stderr, "Memory allocation failed\n");
return -1;
}
// set the address and contents fields based on the function arguments
// and set the label and assembly fields to NULL
node->address = address;
node->contents = contents;
node->label = NULL;
node->assembly = NULL;
node->next = NULL;
// if the head pointer is NULL, this function MUST set the newly created node
// as the head of the LinkedList.
if (!*head) {
*head = node;
}
// Otherwise, this function MUST insert the
// newly created node into the LinkedList based on the address field in
// ascending order
else {
row_of_memory *current = *head;
row_of_memory *previous = NULL;
// traverse the list to find the correct position for the new node
while (current != NULL && current->address < address) {
previous = current;
current = current->next;
}
// insert at head (new node has smallest address)
if (!previous) {
node->next = *head;
*head = node;
}
// insert at middle or tail
else {
previous->next = node;
node->next = current;
}
}
return 0;
}
row_of_memory *search_address(row_of_memory *head, short unsigned int address) {
if (!head) {
return NULL;
}
row_of_memory *curr = head;
while (curr) {
if (curr->address == address) {
return curr;
}
curr = curr->next;
}
return NULL;
}
row_of_memory *search_opcode(row_of_memory *head, short unsigned int opcode) {
if (!head) {
return NULL;
}
row_of_memory *curr = head;
while (curr) {
/* traverse linked list until node is found with matching opcode in the most
significant 4 bits AND "assembly" field of node is NULL */
if (!curr->assembly && GET_FIRST_4(curr->contents) == GET_LAST_4(opcode)) {
return curr;
}
curr = curr->next;
}
return NULL;
}
void print_list(row_of_memory *head) {
if (!head) {
return;
}
// headers: more space is given to label based on the provided sols
printf("%-20s%-20s%-20s%-20s\n", "<label>", "<address>", "<contents>",
"<assembly>");
row_of_memory *curr = head;
while (curr) {
unsigned short opcode = GET_FIRST_4(curr->contents);
printf("%-20s%-20.04X%-20.04X%-20s\n", (curr->label) ? curr->label : "",
curr->address, curr->contents,
(curr->assembly && opcode == 0x0001) ? curr->assembly : "");
curr = curr->next;
}
return;
}
int delete_list(row_of_memory **head) {
/* delete entire list node by node */
/* set the list head pointer to NULL upon deletion */
if (!*head) {
return 0;
}
row_of_memory *curr = *head;
while (curr) {
// need to free extra space allocated for assembly and label
if (curr->assembly) {
free(curr->assembly);
}
if (curr->label) {
free(curr->label);
}
curr = curr->next;
free(*head);
*head = curr;
}
return 0;
}