Fix the functions that have had code started in them (C Programing) #include #in
ID: 3749491 • Letter: F
Question
Fix the functions that have had code started in them (C Programing)
#include
#include
#include
#include
#include
#include "Debug.h"
#include "symbol.h"
/** @file symbol.c
* @brief You will modify this file and implement the symbol.h interface
* @details Your implementation of the functions defined in symbol.h.
* You may add other functions if you find it helpful. Added functions
* should be declared static to indicate they are only used
* within this file. The reference implementation added approximately
* 110 lines of code to this file. This count includes lines containing
* only a single closing bracket (}).
*
* @author Your name goes here
*/
/** size of LC3 memory */
#define LC3_MEMORY_SIZE (1 << 16)
/** Provide prototype for strdup() */
char *strdup(const char *s);
/** defines data structure used to store nodes in hash table */
typedef struct node {
struct node* next; /**< linked list of symbols at same index */
int hash; /**< hash value - makes searching faster */
symbol_t symbol; /**< the data the user is interested in */
} node_t;
/** defines the data structure for the hash table */
struct sym_table {
int capacity; /**< length of hast_table array */
int size; /**< number of symbols (may exceed capacity) */
node_t** hash_table; /**< array of head of linked list for this index */
char** addr_table; /**< look up symbols by addr (optional) */
};
/** djb hash - found at http://www.cse.yorku.ca/~oz/hash.html
* tolower() call to make case insensitive.
*/
static int symbol_hash (const char* name) {
unsigned char* str = (unsigned char*) name;
unsigned long hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + tolower(c); /* hash * 33 + c */
c = hash & 0x7FFFFFFF; /* keep 31 bits - avoid negative values */
return c;
}
/** @todo implement this function */
sym_table_t* symbol_init (int capacity) {
struct sym_table *table;
table = malloc(1 * sizeof(struct sym_table));
table->size= capacity;
table->hash_table = malloc(capacity * sizeof(struct node *));
int i;
//printf("%d ", table->size);
for(i = 0; i < table->size; i++) {
table->hash_table[i] = NULL;
}
return table;
}
/** @todo implement this function */
void symbol_term (sym_table_t* symTab) {
}
/** @todo implement this function */
void symbol_reset(sym_table_t* symTab) {
}
/** @todo implement this function */
int symbol_add (sym_table_t* symTab, const char* name, int addr) {
int hash;
int index;
strdup(name);
struct node *node_new;
node_new = malloc(1 * sizeof(struct node));
node_new->next = symbol_search(symTab, name, &hash, &index);
if(node_new->next == NULL) {
return 0;
}
node_new->symbol.name = strdup(name);
node_new->symbol.addr = addr;
symTab->hash_table[index] = node_new;
printf("%s ", symTab->hash_table[index]->symbol.name);
return 1;
}
/** @todo implement this function */
struct node* symbol_search (sym_table_t* symTab, const char* name, int* hash, int* index) {
*hash = symbol_hash(name);
*index = *hash % symTab->size;
struct node *node_new;
node_new = malloc(1 * sizeof(struct node));
if(symbol_find_by_name(symTab,name) == NULL){
node_new->next = symTab->hash_table[*index];
return node_new;
}
return NULL;
}
/** @todo implement this function */
symbol_t* symbol_find_by_name (sym_table_t* symTab, const char* name) {
int i;
for(i = 0; i < symTab->size; i++) {
if(!(symTab->hash_table[i] == NULL))
{
if(strcasecmp(symTab->hash_table[i]->symbol.name,name)==0) {
// printf("%s ", "duplicate");
// printf("%s", symTab->hash_table[0]->symbol.name);
return symTab->hash_table[i]->symbol.name;
}
}
}
return NULL;
}
/** @todo implement this function */
char* symbol_find_by_addr (sym_table_t* symTab, int addr) {
return NULL;
}
/** @todo implement this function */
void symbol_iterate (sym_table_t* symTab, iterate_fnc_t fnc, void* data) {
int i;
for(i = 0; i < symTab->size; i++) {
if(!(symTab->hash_table[i] == NULL))
{
printf("%s", symTab->hash_table[i]->symbol.name);
}
}
}
/** @todo implement this function */
int symbol_size (sym_table_t* symTab) {
return 0;
}
/** @todo implement this function */
int compare_names (const void* vp1, const void* vp2) {
// symbol_t* sym1 = *((symbol_t**) vp1); // study qsort to understand this
return 0;
}
/** @todo implement this function */
int compare_addresses (const void* vp1, const void* vp2) {
return 0;
}
/** @todo implement this function */
symbol_t** symbol_order (sym_table_t* symTab, int order) {
// will call qsort with either compare_names or compare_addresses
return NULL;
}
====================================================================
====================================================================
====================================================================
====================================================================
#ifndef __SYMBOL_H__
#define __SYMBOL_H__
/** @file symbol.h
* @brief Defines the interface to symbol.c functions (do not modify)
* @details This file defines the interface to a C file symbol.c that
* you will complete. The underlying data structure(s) used will be
* defined by the actual assignment. The assignment will define whether symbols
* are case sensitive or case in-sensitive.
* <p>
* In this implementation, you will learn about dynamic memory management using
* malloc/free. You will also learn about function pointers (callback functions).
*/
/** order in list is order in hash table */
#define HASH 0
/** order in list is alphabetical by name */
#define NAME 1
/** order in list is by increasing address */
#define ADDR 2
/** This defines an opaque type. The actual contents of the structure are hidden
* in the implementation (symbol.c) and only a pointer to this structure is
* used externally to that file. A pointer to an opaque structure is sometimes
* referred to as a handle.
*/
typedef struct sym_table sym_table_t;
/** The symbol_find methods return a pointer to this data structure. It is up
* to the implementor to decide how to use this stucture in the implementation.
*/
typedef struct symbol {
char* name; /**< the name of the symbol */
int addr; /**< symbol's address in the LC3 memory */
} symbol_t;
/** Add a symbol to the symbol table.
* @param symTab - pointer to the symbol table
* @param name - the name of the symbol
* @param addr - the address of the symbol
* @return 1 if name is currently in the symbol table,
* 0 otherwise
*/
int symbol_add (sym_table_t* symTab, const char* name, int addr);
/** Find a name by its LC3 address
* @param symTab - pointer to the symbol table
* @param addr - an LC3 address
* @return the <b>label</b> at that address or NULL if no symbol is
* associated with the adddress.
*/
char* symbol_find_by_addr (sym_table_t* symTab, int addr);
/** Find a symbol by its name
* @param symTab - pointer to the symbol table
* @param name - the symbols name
* @return the symbols information or NULL if no symbol is associated with
* the name.
* Most of the work is done by <code>symbol_search()</code>. That routine
* returns a <code>node_t*</code>, but this routine returns a
* <code>symbol_t*</code>. Study
* <a href="http://stackoverflow.com/questions/5767973/getting-the-address-of-a-struct-member">this</a> posting to understand how you might solve this.
*/
symbol_t* symbol_find_by_name (sym_table_t* symTab, const char* name);
/** Create a new symbol table and return a pointer to it. This function is a
* constructor for a symbol table. It allocates and initializes both the
* <code>hash_table</code> and the <code>addr_table</code>. The latter is
* an array of <code>char*</code> that is indexed by an LC3
* address to find the label (if any) associated with that address.
* @param capacity - the size of the hash table.
* @return a pointer to the symbol table.
*/
sym_table_t* symbol_init (int capacity);
/** Remove all the symbols from the symbol table. After this call the opaque
* symbol table pointer is still valid and new symbols may be added to it.
* If needed, clear the <code>addr_table</code>.
* @param symTab - pointer to the symbol table
*/
void symbol_reset (sym_table_t* symTab);
/** This function is only used internally and should be declared static. It is
* a useful support function for the <code>add()/find()</code> functions.
* It is declared here for documentation purposes. The function returns
* <b>three</b> values: one in the return value, and the other two using
* the pointers to the hash and index values.
* @param symTab - pointer to the symbol table
* @param name - the name of the symbol
* @param hash - pointer to location where hash value will be stored
* @param index - pointer to location where index will be stored
* @return the nodes information or NULL if no symbol is associated with
* the name.
*/
struct node* symbol_search (sym_table_t* symTab, const char* name, int* hash, int* index);
/** Remove all symbols from the symbol table, and free all allocated memory.
* This function is a destructor for a symbol table.
* There must not be any memory leaks. After executing this function, the
* opaque pointer to the symbol table is no longer valid.
*/
void symbol_term(sym_table_t* symTab);
/** Defines the signature of a callback function (also known as a function
* pointer). This is how languages such as Java and C++ do <b>dynamic</b>
* binding (i.e. figure out which function to call). Recall that in Java the
* code <code>obj.equals(object)</code> will call one of possibly many
* different methods depending on the actual type of <code>obj</code>. This
* is because the method <b>.equals()</b> may be <b>overridden</b>.
* <p>
* In the LC3, dynamic binding is based on the <b>JSRR</b> opcode. With this
* opcode, the address of the routine to call is stored in a register and can
* be changed at runtime. Compare this to a <b>JSR nameOfRoutine</b> opcode which
* specifies what routine to call from the label that follows it. Thus, the
* address is fixed at <b>assembly</b> time.
* <p>
* This is used in the symbol_iterate() function. An interesting variation
* would be to have the callback function return an integer which determines
* whether the iteration should contibue or terminate.
* @param symTab - pointer to the symbol table
* @param data - any additional information to be passed on to fnc. The called
* function will cast this to whatever type was actually passed.
*/
typedef void (*iterate_fnc_t)(symbol_t* sym, void* data);
/** This function calls the function for every entry in the symbol table.
* The assigment will define the order in which the entries should be visited.
* @param symTab - pointer to the symbol table
* @param fnc - the function to be called on every element
* @param data - any additional information to be passed on to fnc. The called
* function will cast this to whatever type was actually passed.
*/
void symbol_iterate (sym_table_t* symTab, iterate_fnc_t fnc, void* data);
/** A callback function for <code>qsort</code> to order by name in a case
* insensative way.
* @param vp1 pointer to first element
* @param vp2 pointer to second element
* @ return a number representing the correct ordering (neg, 0, pos)
*/
int compare_names (const void* vp1, const void* vp2);
/** A callback function for <code>qsort</code> to order by address
* <b>NOTE</b>: If two elements have the same address, then return the result
* of comparing by name, so that name becomes the secondary sort key.
* @param vp1 pointer to first element
* @param vp2 pointer to second element
* @ return a number representing the correct ordering (neg, 0, pos)
*/
int compare_addresses (const void* vp1, const void* vp2);
/** Return the number of elements currently in the symbol table
* @param symTab - pointer to the symbol table
* @return number of elements
*/
int symbol_size (sym_table_t* symTab);
/** This function returns an ordered, dymanically allocated array of
* <code>symbol_t*</code>. You may wish to use <code>qsort()</code> to order
* it. The caller will <code>free()</code> the return value.
* @param symTab - pointer to the symbol table
* @param order - defines the sorting order for the list (HASH, NAME, ADDR)
* @return pointer to an array of <code>symbol_t*</code>
*/
symbol_t** symbol_order (sym_table_t* symTab, int order);
#endif /* __SYMBOL_H__ */
Explanation / Answer
testSymbol.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Debug.h"
#include "symbol.h"
/** Maximum length of command line processed */
#define MAX_LINE_LENGTH 128
/** Delimiter used separate tokens on line - used by strtok() */
const char *delim = " ";
/** Print a usage statement describing how program is used */
static void help() {
puts("Usage: testSymbol [-debug] ");
puts("then enter commands from keyboard, one per line: ");
puts("init capacity - create symbol table with given capacity");
puts(" MUST be first action taken");
puts("add name address - prints 1 on succeses, 0 on failure");
puts("count - prints count of names/addresses");
puts(" uses function pointers");
puts("debug level - turn debug on/off (0 is off)");
puts("exit/quit - terminates program");
puts("get name - prints NULL or name/address");
puts("label address - prints NULL or name associated with address");
puts("list - prints all names/addresses");
puts(" uses function pointers");
puts("order option - calls symbol_order and print value(s)");
puts(" - option is HASH|NAME|ADDR");
puts("search name - prints NULL or name/address and hash/index");
puts("size - call symbol_size()");
puts("reset - call symbol_reset() ");
}
/** Print a usage statement describing how program is used, and exits */
static void usage() {
help();
}
static char* nextToken () {
char* tok = strtok(NULL, delim);
if (! tok)
usage();
return tok;
}
static int nextInt() {
char* junk;
char* tok = nextToken();
return (int) strtol(tok, &junk, 0);
}
static void countSymbols (symbol_t* sym, void *data) {
int* ip = (int*) data;
*ip = *ip + 1;
}
static void printResult(symbol_t* sym, void* data) {
FILE* f = (FILE*) data;
if (! sym)
fprintf(f, "NULL ");
else
fprintf(f, "name:%-20s addr:%-6d ", sym->name, sym->addr);
}
static void printList (sym_table_t* symTab, int order) {
int size = symbol_size(symTab);
symbol_t** list = symbol_order(symTab, order);
if (list) {
for (int i = 0; i < size; i++)
printResult(list[i], stdout);
puts("");
free(list);
}
}
int main (int argc, const char* argv[]) {
char line[MAX_LINE_LENGTH];
int count, addr;
char *cmd, *name;
sym_table_t* symTab = NULL;
debugInit(&argc, argv);
if (argc != 1)
usage();
while (fgets(line, sizeof(line), stdin) != NULL) {
char *cr = strchr(line ,' '); /* get rid of trailing , if any */
if (cr)
*cr = '';
cmd = strtok(line, delim);
if ((! cmd) || (*cmd == '#')) // skip blank lines, comments
continue;
if (strcmp(cmd, "debug") == 0) {
debugLevel = nextInt();
}
else if ((strcmp(cmd, "exit") == 0) || (strcmp(cmd, "quit") == 0)) {
break;
}
else if (strcmp(cmd, "help") == 0) {
help();
}
else if (strcmp(cmd, "init") == 0) {
count = nextInt();
symTab = symbol_init(count);
debug("initialized with size %d", count);
}
else if (symTab == NULL) {
puts("Please initialize symbol table before use");
}
else if (strcmp(cmd, "add") == 0) {
name = nextToken();
addr = nextInt();
printf("%s ", (symbol_add(symTab, name, addr) ? "OK" : "Duplicate"));
}
else if (strcmp(cmd, "count") == 0) {
count = 0;
symbol_iterate(symTab, countSymbols, &count);
printf("symbol count: %d ", count);
}
else if (strcmp(cmd, "get") == 0) {
name = nextToken();
printResult(symbol_find_by_name(symTab, name), stdout);
}
else if (strcmp(cmd, "label") == 0) {
addr = nextInt();
printf("label at addr %d '%s' ", addr,
symbol_find_by_addr(symTab, addr));
}
else if (strcmp(cmd, "list") == 0) {
symbol_iterate(symTab, printResult, stdout);
puts("");
}
else if (strcmp(cmd, "order") == 0) {
name = nextToken();
if (strcmp(name, "HASH") == 0)
printList(symTab, HASH);
else if (strcmp(name, "NAME") == 0)
printList(symTab, NAME);
else if (strcmp(name, "ADDR") == 0)
printList(symTab, ADDR);
else
help();
}
else if (strcmp(cmd, "reset") == 0) {
symbol_reset(symTab);
}
else if (strcmp(cmd, "search") == 0) {
int hash, index;
name = nextToken();
struct node* node = symbol_search(symTab, name, &hash, &index);
printf("symbol '%s' hash: %d index: %d is %s in symbol table ", name,
hash, index, (node ? "" : "NOT"));
}
else if (strcmp(cmd, "size") == 0) {
printf("symbol table contains %d entries ", symbol_size(symTab));
}
else {
help();
}
}
symbol_term(symTab); /* can check for memory leaks now */
return 0;
}
symbol.h
#ifndef __SYMBOL_H__
#define __SYMBOL_H__
#define HASH 0
#define NAME 1
#define ADDR 2
typedef struct sym_table sym_table_t;
typedef struct symbol {
char* name; /**< the name of the symbol */
int addr; /**< symbol's address in the LC3 memory */
} symbol_t;
int symbol_add (sym_table_t* symTab, const char* name, int addr);
char* symbol_find_by_addr (sym_table_t* symTab, int addr);
symbol_t* symbol_find_by_name (sym_table_t* symTab, const char* name);
sym_table_t* symbol_init (int capacity);
void symbol_reset (sym_table_t* symTab);
struct node* symbol_search (sym_table_t* symTab, const char* name, int* hash, int* index);
void symbol_term(sym_table_t* symTab);
typedef void (*iterate_fnc_t)(symbol_t* sym, void* data);
void symbol_iterate (sym_table_t* symTab, iterate_fnc_t fnc, void* data);
int compare_names (const void* vp1, const void* vp2);
int compare_addresses (const void* vp1, const void* vp2);
int symbol_size (sym_table_t* symTab);
symbol_t** symbol_order (sym_table_t* symTab, int order);
#endif /* __SYMBOL_H__ */
symbol.c
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "Debug.h"
#include "symbol.h"
#define LC3_MEMORY_SIZE (1 << 16)
char *strdup(const char *s);
typedef struct node {
struct node* next; /**< linked list of symbols at same index */
int hash; /**< hash value - makes searching faster */
symbol_t symbol; /**< the data the user is interested in */
} node_t;
struct sym_table {
int capacity; /**< length of hast_table array */
int size; /**< number of symbols (may exceed capacity) */
node_t** hash_table; /**< array of head of linked list for this index */
char** addr_table; /**< look up symbols by addr (optional) */
};
static int symbol_hash (const char* name) {
unsigned char* str = (unsigned char*) name;
unsigned long hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + tolower(c); /* hash * 33 + c */
c = hash & 0x7FFFFFFF; /* keep 31 bits - avoid negative values */
return c;
}
sym_table_t* symbol_init (int capacity) {
//allocate sym_table_t
sym_table_t* t = (sym_table_t*)malloc(sizeof(sym_table_t));
//initialize capacitiy
t->capacity = capacity;
t->size = 0;
char **u = (char**)calloc(65535, sizeof(char*));
t->addr_table = u;
node_t** n = (node_t**)calloc(capacity, sizeof(node_t*));
t->hash_table = n;
return t;
}
void symbol_term (sym_table_t* symTab) {
symbol_reset(symTab);
free(symTab->hash_table);
symTab->hash_table = NULL;
free(symTab->addr_table);
symTab->addr_table = NULL;
free(symTab);
symTab = NULL;
}
void symbol_reset(sym_table_t* symTab) {
for(int i = 0; i < symTab->capacity; i++){
if(symTab->hash_table[i] == NULL)
continue;
else if(symTab->hash_table[i] != NULL && symTab->hash_table[i]->next != NULL){
node_t* n = symTab->hash_table[i];
node_t* next;
while(n != NULL){
next = n->next;
free(n->symbol.name);
n->symbol.name = NULL;
free(n);
n = next;
}
symTab->hash_table[i] = NULL;
}
else{
free(symTab->hash_table[i]->symbol.name);
symTab->hash_table[i]->symbol.name = NULL;
free(symTab->hash_table[i]);
symTab->hash_table[i] = NULL;
}
}
symTab->size = 0;
}
int symbol_add (sym_table_t* symTab, const char* name, int addr) {
int index = symbol_hash(name) % symTab->capacity;
int hash = symbol_hash(name);
if(symTab->hash_table[index] == NULL){
node_t* newNode = (node_t*)malloc(sizeof(node_t));
char* yop = strdup(name);
newNode->symbol.name = yop;
newNode->symbol.addr = addr;
newNode->next = NULL;
newNode->hash = symbol_hash(name);
symTab->hash_table[index] = newNode;
symTab->size += 1;
symTab->addr_table[addr] = yop;
return 1;
}
else{
if(symbol_search(symTab, name, &hash, &index) == NULL){
if(symTab->capacity > index){
node_t* newNode = (node_t*)malloc(sizeof(node_t));
char* yop = strdup(name);
newNode->symbol.name = yop;
newNode->symbol.addr = addr;
newNode->next = symTab->hash_table[index];
newNode->hash = symbol_hash(name);
symTab->hash_table[index] = newNode;
symTab->size += 1;
symTab->addr_table[addr] = yop;
return 1;
}
}
else
return 0;
}
return -1;
}
struct node* symbol_search (sym_table_t* symTab, const char* name, int* hash, int* index) {
*hash = symbol_hash(name);
*index = *hash % (symTab->capacity);
if(symTab->hash_table[*index] == NULL){
return NULL;
}
for(int i = 0; i <symTab->capacity; i++){
node_t* n = symTab->hash_table[i];
while(n != NULL){
int result = strcasecmp(name, n->symbol.name);
if(result == 0)
return n;
else
n = n->next;
}
}
return NULL;
}
symbol_t* symbol_find_by_name (sym_table_t* symTab, const char* name) {
int index = symbol_hash(name) % symTab->capacity;
int hash = symbol_hash(name);
node_t* n = symbol_search(symTab, name, &hash, &index);
hash = n->hash;
return &(symTab->hash_table[index]->symbol);
}
char* symbol_find_by_addr (sym_table_t* symTab, int addr) {
if(symTab->addr_table[addr] == NULL)
return NULL;
else{
return symTab->addr_table[addr];
}
return NULL;
}
void symbol_iterate (sym_table_t* symTab, iterate_fnc_t fnc, void* data) {
if(symTab->capacity == 1){
node_t* n = symTab->hash_table[0];
while(n != NULL){
(*fnc)(&(n->symbol),data);
if(n->next == NULL)
break;
else
n = n->next;
}
}
else{
for(int i = 0; i < symTab->capacity; i++){
node_t* n = symTab->hash_table[i];
while(n != NULL){
(*fnc)(&(n->symbol),data);
if(n->next == NULL)
break;
else
n = n->next;
}
}
}
}
int symbol_size (sym_table_t* symTab) {
return symTab->size;
}
int compare_names (const void* vp1, const void* vp2) {
symbol_t* sym1 = *((symbol_t**) vp1);
symbol_t* sym2 = *((symbol_t**) vp2);
char* a = (sym1->name);
char* b = (sym2->name);
int result = strcasecmp(a, b);
return result;
}
int compare_addresses (const void* vp1, const void* vp2) {
symbol_t* sym1 = *((symbol_t**) vp1);
symbol_t* sym2 = *((symbol_t**) vp2);
int a = (sym1->addr) - (sym2->addr);
if(a != 0)
return a;
else
return compare_names(&sym1, &sym2);
}
symbol_t** symbol_order (sym_table_t* symTab, int order) {
// will call qsort with either compare_names or compare_addresses
symbol_t** s = (symbol_t**)calloc(symTab->size, sizeof(symbol_t*));
int j = 0;
for(int i = 0; i < symTab->capacity; i++){
node_t* n = symTab->hash_table[i];
if(symTab->hash_table[i] == NULL)
continue;
else{
while(n != NULL){
s[j] = &(n->symbol);
j += 1;
if(n->next == NULL)
break;
else
n = n->next;
}
}
}
if(order == 0 && s[0] != NULL)
return s;
else if(order == 1 && s[0] != NULL){
qsort(s, symTab->size, sizeof(symbol_t*), compare_names);
return s;
}
else if(order == 2 && s[0] != NULL){
qsort(s, symTab->size, sizeof(symbol_t*), compare_addresses);
return s;
}
else
return NULL;
return NULL;
}
Debug.h
#ifndef __DEBUG_H__
#define __DEBUG_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
void debugInit(int* argc, const char* argv[]);
void debugToFile(const char* fileName);
void debugClose(void);
extern int debugLevel;
extern FILE* debugFile;
#ifdef DEBUG
#define DEBUG_ENABLED 1 // debug code available at runtime
#else
#define DEBUG_ENABLED 0 // all debug code optimized out
#endif
#define HERE debug("HERE")
#define debugV(name) #name,(name)
#define vDebug(fmt, name) debug("%s=(" fmt ")" , debugV(name))
#define debug(fmt, ...) lDebug(1, fmt, ##__VA_ARGS__)
#define lDebug(level, fmt, ...)
do {
if (DEBUG_ENABLED && (debugLevel >= level))
fprintf((debugFile ? debugFile : stderr), "DEBUG %s[%d] %s() " fmt " ",
__FILE__, __LINE__, __func__, ##__VA_ARGS__);
} while(0)
#ifdef __cplusplus
}
#endif
#endif
Debug.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Debug.h"
int debugLevel = 0;
FILE* debugFile = 0;
static const char* prefix = "-debug";
void debugInit (int* argc, const char* argv[]) {
debugFile = stderr;
if (*argc > 1) {
const char* arg1 = argv[1];
size_t len = strlen(prefix);
if (strncmp(arg1, prefix, len) == 0) {
debugLevel = 1;
if (strlen(arg1) > len)
debugLevel = atoi(arg1 + len);
(*argc)--; // decrement number of arguments
for (int i = 1; i < *argc; i++) // remove first argument
argv[i] = argv[i+1];
}
}
}
void debugToFile (const char* fileName) {
debugClose();
FILE* f = fopen(fileName, "w"); // "w+" ?
if (f)
debugFile = f;
}
void debugClose(void) {
if (debugFile && (debugFile != stderr)) {
fclose(debugFile);
debugFile = stderr;
}
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.