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]