Search This Blog

Macro Preprocessor for C Using C - Simulation of Macro Processor in C Language

You might have used macros in different languages. In C language, we use #define preprocessor directive for macros. Macro preprocessor expands macro calls (macro invocation) using the macro definition. In this post, we will see a c program to simulate macro preprocessing. This program implements a macro preprocessor for c using c. The program obtains macro definition and parameters from #define directives and replaces every macro call with macro definition with formal parameters substituted with actual ones.

The input to the program is a c program named input.c which should located in the same directory of this program. The output of this program will be displayed in screen and also an output file is generated with name output.c which is located in the same directory. The following is the macro preprocessor program. Below that, i have added a sample input program and corresponding output (with expanded macros).

Macro Preprocessor Program

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct argItem
{
 char name[15];
 int argCount;
 char args[10][15];
 char def[100];
}MacroTab[10];

char ch,*sourceCode;
char *output,*line;
int MacroCount=0,MacroUsed=0;

int indexof(char *subString,int fromIndex,char *MainString)
{

 int Mainlength,subLength,i,j,retIndex=-1;
 Mainlength=strlen(MainString);
 subLength=strlen(subString);
 if(Mainlength<1||subLength<1||Mainlength-fromIndex<subLength)
  return(-1);
 for(i=fromIndex;Mainlength-i>=subLength;i++)
  {
  if(*(MainString+i)==*(subString))
   {
   retIndex=i;
   for(j=0;j<subLength;j++)
    {
    if(*(MainString+i+j)!=*(subString+j))
     {
     retIndex=-1;
     break;
     }
    }
   if(retIndex!=-1)
    return retIndex;
   }
  }
 return (-1);
}

char * subString(char *MainString,int fromIndex,int toIndex)
{
int Mainlength,j;
char *subStr;
Mainlength=strlen(MainString);
if(fromIndex<0||fromIndex>=Mainlength||toIndex<fromIndex||toIndex>=Mainlength)
 {
 return(NULL);
 }
subStr=(char *)malloc(1000*sizeof(char));
for(j=0;j<=toIndex-fromIndex;j++)
 *(subStr+j)=*(MainString+fromIndex+j);

*(subStr+j)='\0';
return(subStr);
}

char * replace(char *MainString,char *victim,char *newComer)
{
int Mainlength,victimLength,newComerLength,MainI,OutI,j,found;
char *output;
Mainlength=strlen(MainString);
victimLength=strlen(victim);
newComerLength=strlen(newComer);
if(Mainlength<victimLength||victimLength<1||newComerLength<1)
 {
 return(NULL);
 }
output=(char *)malloc(1000*sizeof(char));
OutI=0;
for(MainI=0;MainI<Mainlength;MainI++)
 {
 if(*(MainString+MainI)!=*(victim))
  {
  *(output+OutI)=*(MainString+MainI);
  OutI++;
  }
 else
  {
  found=1;
  if(Mainlength-MainI<victimLength)
   found=0;
  else
   {
   for(j=1;j<victimLength;j++)
    {
    if(*(MainString+MainI+j)!=*(victim+j))
     {
     found=0;
     break;
     }
    }
   }
  if(found==0)
   {
   *(output+OutI)=*(MainString+MainI);
   OutI++;
   }
  else
   {
   for(j=0;j<newComerLength;j++)
    {
    *(output+OutI)=*(newComer+j);
    OutI++;
    }
   MainI+=victimLength-1;
   }
  }
 }
*(output+OutI)='\0';
return(output);
}


char* NextLine()
{
 int i=0,end=0,j,k;
 char *ret;
 if(strlen(sourceCode)<1)
  return(NULL);
 i=indexof("\n",0,sourceCode);
 if(i==-1)
  {
  i=strlen(sourceCode);
  end=1;
  }
 ret=subString(sourceCode,0,i);
 sourceCode=sourceCode+i+1-end;
 return(ret);
}

void scan()
{
int i,j,k,l;
char temp[30];
i=indexof("#define",0,sourceCode);
if(i>0)
 {
 printf("\nMacros found in source code");
 MacroUsed=1;
 i=0;
 while(indexof("#define",i,sourceCode)>0)
  {
  i=indexof("#define",i,sourceCode)+1;
  j=indexof(" ",i,sourceCode)+1;
  k=indexof("(",j,sourceCode)-1;
  strcpy(MacroTab[MacroCount].name,subString(sourceCode,j,k));
  strcpy(temp,subString(sourceCode,k+2,indexof(")",k+2,sourceCode)-1));
  i=indexof(")",k+2,sourceCode);
  k=0;
  for(j=0;temp[j]!='\0';j++)
   {
   if(temp[j]==',')
    {
    strcpy(MacroTab[MacroCount].args[MacroTab[MacroCount].argCount],subString(temp,k,j-1));
    k=j+1;
    MacroTab[MacroCount].argCount++;
    }
   }
  strcpy(MacroTab[MacroCount].args[MacroTab[MacroCount].argCount],subString(temp,k,j-1));
  MacroTab[MacroCount].argCount++;
  strcpy(MacroTab[MacroCount].def,subString(sourceCode,i+2,indexof("\n",i+2,sourceCode)-1));
  MacroCount++;
  }
 }
else
 {
 MacroUsed=0;
 }

}

void main()
{
FILE *input,*outfile;
int i=0,t,u,j,k,l;
char *tempDef,var[15];
input=fopen("input.c","r");
tempDef=(char*)malloc(200*sizeof(char));
sourceCode=(char*)malloc(1500*sizeof(char));
while((ch=getc(input))!=EOF)
 {
 sourceCode[i++]=ch;
 }
sourceCode[i]='\0';
printf("%s",sourceCode);
fclose(input);
scan();
output=(char*)malloc(1200*sizeof(char));
*output='\0';

if(MacroUsed==1)
 {
    for(l=0;l<MacroCount;l++)
        {
        printf("\nMacro Name:%s, Macro def:%s, args: ",MacroTab[l].name,MacroTab[l].def);
  for(i=0;i<MacroTab[l].argCount;i++)
            printf("%s ",MacroTab[l].args[i]);
        }

 while((line=NextLine(sourceCode))!=NULL)
  {
  if(indexof("#define",0,line)!=-1)
   continue;
  for(i=0;i<MacroCount;i++)
   {
   t=indexof(MacroTab[i].name,0,line);
   if(t!=-1)
    {
    t=0;
    while((t=indexof(MacroTab[i].name,t,line))!=-1)
     {
     strcpy(tempDef,MacroTab[i].def);
     u=indexof("(",t,line)+1;
     j=0;
     while((k=indexof(",",u,line))!=-1)
      {
      strcpy(var,subString(line,u,k-1));
      tempDef=replace(tempDef,MacroTab[i].args[j],var);
      u=k+1;
      j++;
      }
     k=indexof(")",u,line)-1;
     strcpy(var,subString(line,u,k));
     tempDef=replace(tempDef,MacroTab[i].args[j],var);
     j=indexof(")",t,line);
     line=replace(line,subString(line,t,j),tempDef);
     t=t+strlen(MacroTab[i].name);
     }
    }
   }
   strcat(output,line);
   if(indexof("\n",0,line)<0)
    strcat(output,"\n");
  }

 }
else
 {
 strcpy(output,sourceCode);
 }

outfile=fopen("output.c","w");
l=0;
printf("\nCode After macro preprocessing:\n");
while(l<strlen(output))
{
 putc(*(output+l),outfile);
    printf("%c",*(output+l));
 l++;
}
fclose(outfile);
}


Sample Input Program (input.c)

#include<stdio.h>
#define cube(x) x*x*x
#define min(x,y) (x<y)?x:y
void main()
{
printf("\nCube of 4=%d",cube(4));
printf("\nMin of 3 and 4 =%d",min(3,4));
printf("\nMin of 10 and 15 =%d",min(15,10));
}

Corresponding Output (output.c)

#include<stdio.h>


void main()

{

printf("\nCube of 4=%d",4*4*4);

printf("\nMin of 3 and 4 =%d",(3<4)?3:4);

printf("\nMin of 10 and 15 =%d",(15<10)?15:10);

}

No comments: