// Print fancy 2D view of memory // Note, This is limited to memory_sizes of under 16MB void vlad_reveal(void *alpha[26]) { vlad_stats(); int i, j; vlink_t offset; char graph[STAT_HEIGHT][STAT_WIDTH][20]; char free_sizes[26][32]; char alloc_sizes[26][32]; char label[3]; // letters for used memory, numbers for free memory int free_count, alloc_count, max_count; free_header_t * block; // initilise size lists for (i=0; i<26; i++) { free_sizes[i][0]= '\0'; alloc_sizes[i][0]= '\0'; } // Fill graph with free memory offset = 0; i = 1; free_count = 0; while (offset < memory_size){ block = (free_header_t *)(memory + offset); if (block->magic == MAGIC_FREE) { snprintf(free_sizes[free_count++], 32, "%d) %d bytes", i, block->size); snprintf(label, 3, "%d", i++); fill_block(graph, offset,label); } offset += block->size; } // Fill graph with allocated memory alloc_count = 0; for (i=0; i<26; i++) { if (alpha[i] != NULL) { offset = ((byte *) alpha[i] - (byte *) memory) - HEADER_SIZE; block = (free_header_t *)(memory + offset); snprintf(alloc_sizes[alloc_count++], 32, "%c) %d bytes", 'a' + i, block->size); snprintf(label, 3, "%c", 'a' + i); fill_block(graph, offset,label); } } // Print all the memory! for (i=0; i<STAT_HEIGHT; i++) { for (j=0; j<STAT_WIDTH; j++) { printf("%s", graph[i][j]); } printf("\n"); } //Print table of sizes max_count = (free_count > alloc_count)? free_count: alloc_count; printf(FG_FREE"%-32s"CL_RESET, "Free"); if (alloc_count > 0){ printf(FG_ALLOC"%s\n"CL_RESET, "Allocated"); } else { printf("\n"); } for (i=0; i<max_count;i++) { printf("%-32s%s\n", free_sizes[i], alloc_sizes[i]); } }
int main(int argc, char *argv[]) { char line[BUFSIZ]; // input line char var; // which "variable" int val; // value of N void *ptr[26]; // array of pointer "variable"s int quiet = 0; // flag to reduce output "noise" setbuf(stdout, NULL); // don't buffer stdout // sort out quiet-ness if (argc > 2 && argv[2][0] == 'q') quiet = 1; // initialise pointer variables int i; for (i = 'a'; i <= 'z'; i++) { ptr[i-'a'] = NULL; } // start the allocator vlad_init(MEMORY_SIZE); // main loop ... read command and carry it out if (isatty(0) && !quiet) printf("> "); while (fgets(line, BUFSIZ, stdin) != NULL) { // if reading from a file, echo the command if (!isatty(0)) printf("%s\n",line); // do some cheap-and-nasty parsing using sscanf if (sscanf(line, "+ %[a-z] %d", &var, &val) == 2) { // set a pointer variable using vlad_malloc() if (ptr[var-'a'] != NULL) fprintf(stderr, "Attempt to alloc over already allocated pointer\n"); else { Byte *b = vlad_malloc(val); if (b == NULL) fprintf(stderr, "Failed to allocate %d bytes for ptr[%c]\n", val, var); else { ptr[var-'a'] = b; if (!quiet) printf("ptr[%c] allocated %p\n", var, b); } } } else if (sscanf(line, "- %[a-z]", &var) == 1) { // free memory allocated by sal if (ptr[var-'a'] == NULL) fprintf(stderr, "Attempt to free null pointer\n"); else { Byte *b = ptr[var-'a']; if (!quiet) printf("Deallocating memory at %p\n", b); vlad_free(b); ptr[var-'a'] = NULL; } } else if (sscanf(line, "* %[a-z] %d", &var, &val) == 2) { // write something into an allocated piece of memory if (ptr[var-'a'] == NULL) fprintf(stderr, "Attempt to write via unallocated pointer\n"); else { Byte *x = ptr[var-'a']; *x = (Byte)val; if (!quiet) printf("Memory at %p assigned %d\n", x, *x); } } else if (line[0] == '?') { printf("Possible commands:\n"); printf("+ X N ... allocate N bytes and assign to X\n"); printf("- X ... free memory associated with X\n"); printf("* X N ... store N in memory referenced by X\n"); printf("! ... show sal statistics\n"); printf("? ... show this help message\n"); printf("q ... quit this program (^D also works)\n"); printf(" where X is a single letter in a..z\n"); printf(" and N is an integer value\n"); } else if (line[0] == '!') { vlad_stats(); } else if (line[0] == '#') { vlad_reveal(ptr); } else if (line[0] == 'q') { break; } else { printf("Invalid command\n"); } if (isatty(0) && !quiet) printf("> "); } vlad_end(); return EXIT_SUCCESS; }