[Solved] How preprocessor (i.e.#define) works? [closed]


In one of my assignment i have implemented simple pre-processor using c.I have used the simple hash table to store the name and its definition.
for example,

#define a 4

so here a is name and 4 is its definition.
So both a and 4 will be stored in the hash table.
now whenever in program name ‘a’ is encountered then it will be simply replaced by 4.
i am posting my code in c for pre-processor.Which is very simple.But it would be very helpful for you to understand how pre-processor works.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define HASHSIZE 101
#define BUFSIZE 100
#define MAXWORD 100

struct tnode {
    int loc[10]; // to store the locations at which words occur
    int i; // to store the index of array loc
    char *word;
    int count;
    struct tnode *left;
    struct tnode *right;
};

static struct nlist *hashtab[HASHSIZE];

int getword(char *word, int lim);
struct tnode *addtree(struct tnode *, char *);
void treeprint(struct tnode *);
struct tnode *talloc(void);

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

char buf[BUFSIZE];
int bufp = 0;

unsigned hash(char *s);
struct nlist *lookup(char *s);
char *strdup1(char *);
struct nlist *install(char *name, char *defn);
int undef(char *s); // this function will remove entry

struct tnode *z[10]; // to store address of each node(word)
int total = 0;       // index for array z
char s1[1000];       // to store entire input
static int q = 0;    // index to s1

int main() {
    struct nlist *pt;
    char word[100];
    char name1[10];
    char defn1[10];
    int i = 0;
    int k = 0;
    /*
    #define pi 5 is entered then...*/
    while (getword(word, MAXWORD) != EOF) {
        if (isalnum(word[0]) && (i == 0)) {
            if ((pt = lookup(&word[0])) !=
                NULL) // if name1(pi) is already present then replace it with its definition name(5)
            {
                strcpy(word, (pt->defn)); // if pi is alerady there then replace name by its definition
                // strcpy((pt->defn),word);
                for (k = 0; word[k] != '\0'; k++, q++) {
                    s1[q] = word[k];
                }

            } else // otherwise print the word
            {
                for (k = 0; word[k] != '\0'; k++, q++) {
                    s1[q] = word[k];
                }
            }
        }

        if (isalnum(word[0])) {
            if (i == 2) // copy word to defn1(i.e. defn1=5)
            {
                strcpy(defn1, word);
                install(name1, defn1);
                i = 0;
            }
        }
        if (isalnum(word[0])) {
            if (i == 1) // copy the word to name1(i.e. name1=pi)
            {
                strcpy(name1, word);
                i++;
            }
        }
        if (word[0] == '#') {
            if ((strcmp(word, "#define")) == 0) // if #define found then increase i to get next word(i.e. pi)
            {
                i++;
            } else {
                for (k = 0; word[k] != '\0'; k++, q++) {
                    s1[q] = word[k];
                }
            }
        }
    }

    // printf("%d",i);
    // printf("%s %s",name,defn);
    // printf("%s",pt->defn);
    printf("%s", s1);
}
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 */
}
/* 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 = strdup1(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 = strdup1(defn)) == NULL)
        return NULL;
    return np;
}
char *strdup1(char *s) {
    char *p;
    /* make a duplicate of s */
    p = (char *)malloc(strlen(s) + 1); /* +1 for '\0' */
    if (p != NULL)
        strcpy(p, s);
    return p;
}
int undef(char *s) {
    struct nlist *np1;
    if ((np1 = lookup(s)) != NULL) {
        hashtab[hash(s)] = NULL; // delete the entry in array hashtab associated to s
        free(np1); // free memory allocated to s
        return 1; // if sucessful then return 1 else 0
    }
    return 0;
}
int getword(char *word, int lim) {
    int c, getch(void);
    void ungetch(int);
    char *w = word;
    while (isspace(c = getch())) {
        s1[q] = ' ';
        q++;
    } // takes the space in string s1
    if (c != EOF)
        *w++ = c;
    if (!isalnum(c) && (c != '#')) /*takes all character except #,digit and number in s*/
    {
        if (c != EOF) {
            s1[q] = c;
            q++;
        }
        *w = '\0';
        return c;
    }
    for (; --lim > 0; w++)
        if (!isalnum(*w = getch())) {
            ungetch(*w);
            break;
        }
    *w = '\0';
    return word[0];
}
int getch(void) /* get a (possibly pushed-back) character */
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
/* push character back on input */
{
    if (bufp >= BUFSIZE)
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}

/* addtree: add a node with w, at or below p */
struct tnode *addtree(struct tnode *p, char *w) {
    int cond;
    if (p == NULL) {
        /* a new word has arrived */
        p = talloc();
        /* make a new node */
        p->word = strdup(w);
        p->count = 1;
        p->left = p->right = NULL;
    } else if ((cond = strcmp(w, p->word)) == 0)
        p->count++;
    /* repeated word */
    else if (cond < 0)
        /* less than into left subtree */
        p->left = addtree(p->left, w);
    else
        /* greater than into right subtree */
        p->right = addtree(p->right, w);
    return p;
}

/* talloc: make a tnode */
struct tnode *talloc(void) {
    return (struct tnode *)malloc(sizeof(struct tnode));
}

void treeprint(struct tnode *p) {
    int i = 0;
    for (i = 0; i < total; i++)
        printf("%s", z[i]->word);
}

The code is self explanatory.Mind you it is very simple pre-processor.

1

solved How preprocessor (i.e.#define) works? [closed]