Implementation of the undef function
It's not necessary to special-case the head of the list if you think about it in a different way.  In particular, each entry in your hashtable is a pointer to an Nlist structure, so if you take the address of the hashtable entry, you can treat it just like any other node.  Specifically, you can use this:

void undef(char *name)
{
    struct Nlist **tmp = &amp;hashtab[hash(name)];
    struct Nlist *old;

    /* find our matching node */
    for ( ; *tmp &amp;&amp; strcmp(name, (*tmp)-&gt;name); tmp=&amp;((*tmp)-&gt;next));

    /* if we have found it, delete and adjust pointer */
    if (*tmp != NULL) {
        old = *tmp;
        free(old-&gt;name);
        free(old-&gt;defn);
        *tmp = old-&gt;next;
        free(old);
    }
}


Also note that defn was not being deleted in your original code, resulting in a memory leak.