Buddy Allocator  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
simulator.c
Go to the documentation of this file.
1 #include <assert.h>
2 #include <errno.h>
3 #include <getopt.h>
4 #include <limits.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <stdbool.h>
8 #include <string.h>
9 
10 #include "buddy.h"
11 
15 typedef enum status_t {
16  SUCCESS = 0,
20 } status_t;
21 
25 typedef enum severity_t {
28 } severity_t;
29 
34 typedef struct var_t {
35  void* mem;
36  bool in_use;
37 } var_t;
38 
39 
40 static FILE *in = NULL; // Input file
41 static var_t var_map[256]; // Keep track of variable allocations
42 static int linenum = 0; // Line number in input file
43 
44 
52 static var_t* get_var(char var)
53 {
54  if ((var >= 'a' && var <= 'z') || (var >= 'A' && var <= 'Z'))
55  return &var_map[(int) var];
56  else
57  return NULL;
58 }
59 
67 static void print_fault(const char* cmd, const char* msg, severity_t sev)
68 {
69  const char* severity_msg;
70 
71  switch(sev) {
72  case ERROR:
73  severity_msg = "ERROR";
74  break;
75  case WARNING:
76  severity_msg = "WARNING";
77  break;
78  default:
79  severity_msg = "?????";
80  }
81 
82  fprintf(stderr, "%s: Line %d: %s\n", severity_msg, linenum, msg);
83  fprintf(stderr, " Faulting Command: %s\n", cmd);
84 }
85 
92 static status_t parse_error(const char* cmd)
93 {
94  print_fault(cmd, "Failed to parse command", ERROR);
95  return BADINPUT;
96 }
97 
104 static status_t parse_alloc(char* cmd)
105 {
106  assert(cmd != NULL);
107  assert(cmd[0] != '\0');
108 
109  char var_name;
110  int size;
111  char alter_size;
112  int matched;
113 
114  errno = 0;
115  matched = sscanf(cmd, "%c=alloc(%d%c)", &var_name, &size, &alter_size);
116 
117  // Error check sprintf
118  if (matched == 3 && errno == 0) {
119  // Check what the alter_size variable actually contains
120  switch (alter_size) {
121  case 'k':
122  case 'K':
123  size *= 1024;
124  case ')':
125  break;
126  default:
127  return parse_error(cmd);
128  }
129  }
130  else {
131  return parse_error(cmd);
132  }
133 
134  // Resolve variable
135  var_t* var = get_var(var_name);
136 
137  if (var == NULL)
138  return parse_error(cmd);
139 
140  // Allocate variable
141  var->mem = buddy_alloc(size);
142 
143  if (var->mem == NULL) {
144  print_fault(cmd, "buddy_alloc returned NULL", WARNING);
145  printf("Out of memory\n");
146  return OUTOFMEMORY;
147  }
148 
149  var->in_use = true;
150 
151  return SUCCESS;
152 }
153 
160 static status_t parse_free(char* cmd)
161 {
162  assert(cmd != NULL);
163 
164  char var_name;
165  int matched;
166  var_t* var;
167 
168  // Read the command string
169  errno = 0;
170  matched = sscanf(cmd, "free(%c)", &var_name);
171 
172  // Check if sscanf was valid
173  if (matched != 1 || errno != 0 || (var = get_var(var_name)) == NULL)
174  return parse_error(cmd);
175 
176  // Ensure that the variable is in use
177  if (!var->in_use) {
178  print_fault(cmd, "Double free", ERROR);
179  return DOUBLEFREE;
180  }
181 
182  // Free variable
183  buddy_free(var->mem);
184  var->mem = NULL;
185  var->in_use = false;
186 
187  return SUCCESS;
188 }
189 
190 
199 static status_t parse_command(char* cmd, int cmd_len)
200 {
201  assert(cmd != NULL);
202 
203  int ws_cursor = 0;
204 
205  if (cmd[0] == '\0' || cmd[0] == '\n' || cmd[0] == '\r')
206  return SUCCESS;
207 
208  // remove whitespace from command
209  for (int i = 0; i < cmd_len; ++i) {
210  switch (cmd[i]) {
211  case ' ':
212  case '\n':
213  case '\r':
214  case '\t':
215  break;
216 
217  default:
218  cmd[ws_cursor++] = cmd[i];
219  }
220  }
221 
222  status_t status;
223 
224  // We have 2 commands: alloc and free.
225  if (strstr(cmd, "alloc") != NULL)
226  status = parse_alloc(cmd);
227  else if (strstr(cmd, "free") != NULL)
228  status = parse_free(cmd);
229  else
230  return parse_error(cmd);
231 
232  if (status != SUCCESS)
233  return status;
234 
235  // Output free blocks
236  buddy_dump();
237 
238  return SUCCESS;
239 }
240 
247 {
248  char* line = NULL;
249  size_t len = 0;
250  ssize_t read;
251 
252  status_t status = SUCCESS;
253 
254  while (status == SUCCESS && (read = getline(&line, &len, in)) > 0) {
255  ++linenum;
256  status = parse_command(line, len);
257  }
258 
259  return status;
260 }
261 
262 
269 void print_usage(char* prog_name, FILE* out)
270 {
271  fprintf(out, "Usage:\n");
272  fprintf(out, " ./%s [-i filename]\n", prog_name);
273  fprintf(out, " -i [optional] - Specify an input file name to read from. If this option \n");
274  fprintf(out, " is not used then input is expected from standard input.\n");
275 }
276 
277 int main(int argc, char** argv)
278 {
279  int opt;
280 
281  status_t prog_status;
282 
283  in = stdin;
284 
285  // Parse command line options
286  while ((opt = getopt(argc, argv, "i:")) != -1) {
287  switch (opt) {
288  case 'i':
289  in = fopen(optarg, "r");
290  break;
291 
292  case '?':
293  switch (optopt) {
294  case 'i':
295  fprintf(stderr, "ERROR: Missing filename after '%c'", optopt);
296  return EXIT_FAILURE;
297  }
298 
299  print_usage(argv[0], stdout);
300  return EXIT_FAILURE;
301  }
302  }
303 
304  // Error check the input file
305  if (in == NULL) {
306  perror("ERROR: Failed to open input file.");
307  return EXIT_FAILURE;
308  }
309 
310  // Zero memory
311  memset(var_map, 0, sizeof(var_map));
312 
313  // Execute program
314  buddy_init();
315  prog_status = parse_file();
316 
317  if (in != stdin)
318  fclose(in);
319 
320  if (prog_status == SUCCESS)
321  return EXIT_SUCCESS;
322  else
323  return EXIT_FAILURE;
324 }
void * mem
A pointer to a memory block.
Definition: simulator.c:35
static status_t parse_file()
Definition: simulator.c:246
static status_t parse_alloc(char *cmd)
Definition: simulator.c:104
void buddy_dump()
Definition: buddy.c:135
status_t
Definition: simulator.c:15
static int linenum
Definition: simulator.c:42
static void print_fault(const char *cmd, const char *msg, severity_t sev)
Definition: simulator.c:67
severity_t
Definition: simulator.c:25
static FILE * in
Definition: simulator.c:40
static status_t parse_command(char *cmd, int cmd_len)
Definition: simulator.c:199
bool in_use
Is this variable currently in use? This is probably redundant if we assume variables not in use are N...
Definition: simulator.c:36
void print_usage(char *prog_name, FILE *out)
Definition: simulator.c:269
void * buddy_alloc(int size)
Definition: buddy.c:110
int main(int argc, char **argv)
Definition: simulator.c:277
static status_t parse_free(char *cmd)
Definition: simulator.c:160
static status_t parse_error(const char *cmd)
Definition: simulator.c:92
void buddy_free(void *addr)
Definition: buddy.c:125
struct var_t var_t
static var_t * get_var(char var)
Definition: simulator.c:52
void buddy_init()
Definition: buddy.c:79
static var_t var_map[256]
Definition: simulator.c:41