Skip to content

Commit

Permalink
Exerc 6_5.
Browse files Browse the repository at this point in the history
  • Loading branch information
rsm-lisper committed Jul 12, 2024
1 parent f93d072 commit 057e707
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 0 deletions.
3 changes: 3 additions & 0 deletions chapter_6.structures/6_5.undef/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BINARY=undef

include ../../Exercise_incl.mk
13 changes: 13 additions & 0 deletions chapter_6.structures/6_5.undef/getline.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# include <stdio.h>

int getline (char *line, int lim)
{
int c;
char *l0 = line;

while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
*line++ = c;
*line = '\0';

return c == EOF ? -1 : line - l0;
}
6 changes: 6 additions & 0 deletions chapter_6.structures/6_5.undef/getline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ifndef GETLINE_H
# define GETLINE_H

int getline (char *line, int lim);

# endif
107 changes: 107 additions & 0 deletions chapter_6.structures/6_5.undef/hashtab.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# include <stdio.h>
# include <stdlib.h>
# include <string.h>

struct nlist { /* table entry: */
struct nlist *next; /* next entry in chain */
char *name; /* defined name */
char *defn; /* replacement text */
};

#define HASHSIZE 101

static struct nlist *hashtab[HASHSIZE]; /* pointer table */

/* hash: form hash value for string s */
unsigned hash (char *s)
{
unsigned hashval;

for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}

/* lookup: look for s in hashtab */
struct nlist *lookup (char *s)
{
struct nlist *np;

for (np = hashtab[hash(s)]; np != NULL; np = np->next)
if (strcmp(s, np->name) == 0)
return np; /* found */
return NULL; /* not found */
}

/* make a duplicate of s */
char *strdup (char *s)
{
char *p;

p = (char *) malloc(strlen(s)+1); /* +1 for '\0' */
if (p != NULL)
strcpy(p, s);
return p;
}

/* install: put (name, defn) in hashtab */
struct nlist *install (char *name, char *defn)
{
struct nlist *np;
unsigned hashval;

if ((np = lookup(name)) == NULL) { /* not found */
np = (struct nlist *) malloc(sizeof(*np));
if (np == NULL || (np->name = strdup(name)) == NULL)
return NULL;
hashval = hash(name);
np->next = hashtab[hashval];
hashtab[hashval] = np;
} else /* already there */
free((void *) np->defn); /*free previous defn */
if ((np->defn = strdup(defn)) == NULL)
return NULL;
return np;
}

/* free_node: free the memory taken by nlist, including internal strings */
void free_node (struct nlist *np)
{
free(np->name);
free(np->defn);
free(np);
}

/* undef: remove name from hashtab */
int undef (char *name)
{
struct nlist *np, *prev;

if ((np = hashtab[hash(name)]) != NULL) {
if (strcmp(np->name, name) == 0) {
hashtab[hash(name)] = np->next;
free_node(np);
return 1;
} else {
for (prev = np, np = np->next; np != NULL; prev = np, np = np->next)
if (strcmp(name, np->name) == 0) {
prev->next = np->next;
free_node(np);
return 1;
}
}
}

return 0;
}

/* print_hashtab: print hash table content */
void print_hashtab (void)
{
int i;
struct nlist *np;

for (i = 0; i < HASHSIZE; i++)
for (np = hashtab[i]; np != NULL; np = np->next)
printf("[%d] '%s': '%s'\n", i, np->name, np->defn);
}
13 changes: 13 additions & 0 deletions chapter_6.structures/6_5.undef/hashtab.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ifndef HASHTAB_H
# define HASHTAB_H

/* lookup: look for s in hashtab */
struct nlist *lookup (char *s);
/* install: put (name, defn) in hashtab */
struct nlist *install (char *name, char *defn);
/* undef: remove name from hashtab */
int undef (char *name);
/* print_hashtab: print hash table content */
void print_hashtab (void);

# endif
42 changes: 42 additions & 0 deletions chapter_6.structures/6_5.undef/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# include <stdio.h>
# include <string.h>
# include "getline.h"
# include "hashtab.h"

# define BUFSIZE 1024

int main ()
{
char line[BUFSIZE], name[BUFSIZE], defn[BUFSIZE];

while (getline(line, BUFSIZE) != -1)
if (line[0] == '+') {
int li = 2, ni = 0, di = 0;
while (line[li] != ' ' && line[li] != '\0')
name[ni++] = line[li++];
if (line[li] == '\0') {
printf("ERROR! unexpected end of line while reading definition");
return 0;
}
name[ni] = '\0';
li++;
while (line[li] != '\0')
defn[di++] = line[li++];
defn[di] = '\0';
install(name, defn);
}
else if (line[0] == '-') {
int li = 2, ni = 0;
while (line[li] != '\0')
name[ni++] = line[li++];
name[ni] = '\0';
undef(name);
} else {
printf("unrecognised operation '%c', should be '+' or '-'.\n", line[0]);
return 0;
}

print_hashtab();

return 0;
}
4 changes: 4 additions & 0 deletions chapter_6.structures/6_5.undef/tests/0_defs.tin
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
+ some other
+ some different
+ some last one
+ any any single time
2 changes: 2 additions & 0 deletions chapter_6.structures/6_5.undef/tests/0_defs.tout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[5] 'some': 'last one'
[91] 'any': 'any single time'
9 changes: 9 additions & 0 deletions chapter_6.structures/6_5.undef/tests/1_undefs.tin
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
+ once once upon a time
+ this this one is safe
+ delme you should not see this!
+ delete this one should also be deleted
+ fun fun fun fun
- delme
+ not ton
- delete
+ end .
5 changes: 5 additions & 0 deletions chapter_6.structures/6_5.undef/tests/1_undefs.tout
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[32] 'this': 'this one is safe'
[52] 'fun': 'fun fun fun'
[63] 'once': 'once upon a time'
[76] 'end': '.'
[86] 'not': 'ton'

0 comments on commit 057e707

Please sign in to comment.