Saturday, July 30

C PROGRAM TO IMPLEMENT MACRO PROCESSOR

 Here is my C program implementing a Macro Processor. We know that Macro is a single line abbreviation for a group of statements. We should define that sentence - cluster before using them in actual program. Macro processor will analyse the program and on encountering  macro variable, it will replace that 'Macro invocation' to corresponding Macro definition. It should also take care the number  and position of arguments used in Macro invocation.



ALGORITHM

MACROPROCESSOR
  • EXPANDING=FALSE.
  • Read each line and call GETLINE() and PROCESSLINE() until END encounters.

PROCESSLINE ( )
  • If OPCODE is a macroname then EXPAND ( ).
  • Else if OPCODE is MACRO ,then DEFINE ( ).
  • Else write line to expanded file as such.
DEFINE( )
  • Enter Macro name into NMATAB.
  • Enter macro prototype into DEFTAB.
  • Set LEVEL=1.
  • Substitute parameters with positional notations and enter to DEFTAB.
  • If OPCODE=MACRO, LEVEL++;
  • If OPCODE=MEND, LEVEL--;
  • Continue this until LEVEL=0
  • Store beginning and end of definition as pointers within NAMTAB

EXPAND ( )
  • EXPANDING = TRUE
  • Set up arguments from macro invocation in ARGTAB.
  • Write macro invocation statement to expanded file  as a comment line.
  • Call GETLINE() and PROCESSLINE() till macro definition ends.
  • Set EXPANDING=FALSE.


GETLINE ( )
  • If EXPANDING is TRUE, read from DEFTAB (data structure where macro body is stored) and substitute arguments for positional notations.
  • If  EXPANDING is FALSE , read next line from input file.




MACROPROCESSOR.C

 /*
PROGRAM NAME:MACRO.C
AIM: TO IMPLEMENT MACRO PROCESSOR.
INPUT : "INPUT.TXT"
OUTPUT: "EXPANDED.TXT"
DATE: 07/28/2011
*/


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

void GETLINE();
void PROCESSLINE();
void DEFINE();
void EXPAND();


 FILE *expanded;
 FILE *input;

 char label[10],opcode[10],operand[25];
 char line[20];
 int namcount=0, defcount=0;
 int EXPANDING;
 int curr;



 struct namtab
 {
 char name[10];
 int start,end;
}mynamtab[15];
     
 struct deftab
 {
        char macroline[25];
  }mydeftab[25];

struct argtab
{
       char arg[3][9];
 }myargtab;
///MACRO MAIN
int main()

{
    EXPANDING=0;

    input =fopen("input.txt","r");                          
 expanded=fopen("expanded.txt","w");
GETLINE();
 
     while(strcmp(opcode,"END")!=0)
{  

     PROCESSLINE();
       GETLINE();
 }
              fprintf(expanded,"%s",line);
      getch();
     return 1;
  }
                            


//   GETLINE
     void GETLINE()
     {    char word1[10],word2[10],word3[10],buff[10];
int count=0,i,j=0;
if(EXPANDING)strcpy(line,mydeftab[curr++].macroline);
 else fgets(line,20,input);
        opcode[0]='\0';label[0]='\0';operand[0]='\0';word1[0]='\0';word2[0]='\0';word3[0]='\0';
        
                      for(i=0;line[i]!='\0';i++)
                      {
                                        
                                                if(line[i]!=' ')
                                                buff[j++]=line[i];
                    
                                                 else
                      {
                                                   
                      buff[j]='\0';
                 
                   
                      strcpy(word3,word2);
                      strcpy(word2,word1);
                       strcpy(word1,buff);
                     j=0;count++;
                      }
                    
                    
                      }

                       buff[j-1]='\0';
                      strcpy(word3,word2);
                      strcpy(word2,word1);
                       strcpy(word1,buff);
                   
   
      switch(count)
                       {
                                    case 0:strcpy(opcode,word1);break;
                                    case 1:{strcpy(opcode,word2);strcpy(operand,word1);}break;
                                    case 2:{strcpy(label,word3);strcpy(opcode,word2);strcpy(operand,word1);}break;
                       }
                   
                     
                       }
                   



//     PROCESSLINE
                       void PROCESSLINE()
                       {
                            int i;
                        for(    i=0;i<namcount;i++)
                      
                                if(!strcmp(opcode,mynamtab[i].name))
                                {
                                                               
                                                                  EXPAND();return;
                                                          
                                                        
                                                             
                                                                  }
                                                           
                                                               { 
                                                                  if(!strcmp(opcode,"MACRO"))
                                                                
                                                                 DEFINE();
                                                               
                                                                 else fprintf(expanded,"%s",line);
                                                                   }
                                                                   }
   
   
     void DEFINE()
     {
          int LEVEL,i=0,j=0,k=0;
       char param[5][9];
       char s[3];
      strcpy(s,"123");
 
          strcpy(mynamtab[namcount].name,label);
          mynamtab[namcount].start=defcount;
          strcpy(mydeftab[defcount].macroline,line);
      
       
          while(operand[i]!='\0')
          {
                                if(operand[i]!=',')
                                param[j][k++]=operand[i];
                                else
                                {
                                    param[j++][k]='\0';
                                
                                    k=0;
                                    }
                              
                               i++;
                                }
                                param[j][k]='\0';
                             
        
          LEVEL=1;
     
        while(LEVEL>0)
          {
                   
            GETLINE();
           
              if(operand[0]!='\0')
             {
            for(i=0;i<3;i++)
            {
            if(!strcmp(operand,param[i]))
            {

            operand[0]='?';
            operand[1]=s[i];
            operand[2]='\0';
             }
             }
             }
           if(!strcmp(opcode,"MACRO"))
            LEVEL++;
           else if(!strcmp(opcode,"MEND"))
            LEVEL--;

            strcpy(mydeftab[defcount].macroline,opcode);
            if(operand[0]!='\0')
            {
            strcat(mydeftab[defcount].macroline," ");
            strcat(mydeftab[defcount].macroline,operand);
            strcat(mydeftab[defcount].macroline,"\n");
            }
            strcat(mydeftab[defcount++].macroline,"\n");

                        }
                        mynamtab[namcount++].end=defcount;
                   
                    
                        }
                      
         

//Expand
        
    void EXPAND()
                        {
                             int i,end=0,j=0,k=0;
                             EXPANDING=1;
                             int arg=0;
                      
                         fprintf(expanded,"//%s",line);
                             for(i=0;i<namcount;i++)
                             {
                             if(!strcmp(opcode,mynamtab[i].name))
                             {
                                                             
                             curr=mynamtab[i].start;
                             end=mynamtab[i].end;
                          
                           
                                   while(operand[i]!='\0')
                                {
                                if(operand[i]!=',')
                                myargtab.arg[j][k++]=operand[i];
                                else
                                {
                                    myargtab.arg[j++][k]='\n';
                                
                                    k=0;
                                    }
                              
                               i++;
                                }                              
                                 myargtab.arg[j][k]='\n';
                           
                        
                             }
                             }
                           
                             while(curr<(end-1))
                             {
                                              GETLINE();
                           if(operand[0]=='?')
                                         
                          strcpy(operand,myargtab.arg[operand[1]-'0'-1]);

                           fprintf(expanded,"%s %s %s",label,opcode,operand);
                        
                             }
                             EXPANDING=0;
                           
                           
                         }



/*************************************************************************************/


  Let us have a look on what will be the output of the program for a sample input.


input.txt



COPY START 1000

RDBUFF MACRO P,Q,R
CLEAR A
CLEAR S
CLEAR X
+LDT #4096
TD P
JEQ *-3
RD P
STCH Q
JLT *-19
LDA R
COMP #0
STX R
MEND

//main program





FIRST STL RETADR
RDBUFF F1,BUFF1,L1
CLEAR X
RDBUFF F2,BUFF2,L2
RDBUFF F3,BUFF3,L3
JLT *-19
STA
END



The output produced will be,

expanded.txt

COPY START 1000
//main program
FIRST STL RETADR
//RDBUFF F1,BUFF1,L1
 CLEAR A
 CLEAR S
 CLEAR X
 +LDT #4096
 TD F1
 JEQ *-3
 RD F1
 STCH BUFF1
 JLT *-19
 LDA L1
 COMP #0
 STX L1
CLEAR X
//RDBUFF F2,BUFF2,L2
 CLEAR A
 CLEAR S
 CLEAR X
 +LDT #4096
 TD F2
 JEQ *-3
 RD F2
 STCH BUFF2
 JLT *-19
 LDA L2
 COMP #0
 STX L2
//RDBUFF F3,BUFF3,L3
 CLEAR A
 CLEAR S
 CLEAR X
 +LDT #4096
 TD F3
 JEQ *-3
 RD F3
 STCH BUFF3
 JLT *-19
 LDA L3
 COMP #0
 STX L3
JLT *-19
STA
END



















        


6 comments :

Unknown said... Best Blogger Tips [Reply to comment] Best Blogger Templates

The code is getting converted.. but the last end statement is written in the expanded.txt file hundreds of times and the program doesn't end execution

sarang said... Best Blogger Tips [Reply to comment] Best Blogger Templates

#include
#include

FILE *fp,*fo;
int expn=0;
char buf[80],name[20],mac[20],*arg;
int getl();
void expand();
void define();
void strrep(char[],char[],char[]);
int currline=0;
struct def
{
char name[20];
char arg[50];
char d[20][80];
int argc;
int di;
}deftab[20];

char argtab[10][20];
int defi=0;
int i;
int argc=0;
int search(char m[])
{
int i;
for(i=0;i0)
{
getl();
for(x=0;x<argc;x++)
{
sprintf(rep,"?%d",x+1);
strrep(arg,argtab[x],rep);
}
sprintf(deftab[defi].d[currline],"%s %s %s",name,mac,arg);
if(strcmp(mac,"MACRO")==0)
level++;
else if(strcmp(mac,"MEND")==0)
level--;
currline++;
}
deftab[defi++].di=currline;
}

void expand()
{
i=search(mac);
expn=1;
argc=0;
currline=0;
while(1)
{
sscanf(arg,"%[^, ] ",argtab[argc++]);
arg=strstr(arg,argtab[argc-1])+strlen(argtab[argc-1])+1;
if(arg[0]=='\0')
break;
}
if(deftab[i].argc!=argc)
{
printf("Error: Argument Number doesn't match at macro call to %s\n",mac);
expn=0;
return;
}
int j;
for(j=0;j<deftab[i].di-1;j++)
{
getl();
processline();
}
expn=0;
}

int getl()
{
int x;
if(expn!=1)
{
strcpy(name,"");
strcpy(mac,"");
strcpy(arg,"");
fscanf(fp,"%[^\n] ",buf);
x=sscanf(buf,"%s %s %s",name,mac,arg);
if(x!=3)
{
strcpy(arg,mac);
strcpy(mac,name);
strcpy(name,"");
}
if(feof(fp))
return 0;
}
else
{
strcpy(name,"");
strcpy(mac,"");
strcpy(arg,"");
x=sscanf(deftab[i].d[currline],"%s %s %s",name,mac,arg);
if(x!=3)
{
strcpy(arg,mac);
strcpy(mac,name);
strcpy(name,"");
}
while(1)
{
char *p=strstr(arg,"?"),q[5];
if(p==NULL)
break;
sscanf(p,"%[^, ] ",q);
sscanf(p+1,"%d",&x);
strrep(arg,q,argtab[x-1]);
}
currline++;
}
return 1;
}

void strrep(char a[],char b[],char c[])
{
char *p;
char res[50];
strcpy(res,"");
while(1)
{

p=strstr(a,b);
if(p==NULL)
break;
strncat(res,a,p-a);
strcat(res,c);
strcat(res,p+strlen(b));
strcpy(a,res);
}
}

void main()
{
int x;
fp=fopen("min","r");
arg=malloc(80);
if(fp==NULL)
printf("ERROR");
fo=fopen("mout","w");
expn=0;
getl();
while(strcmp(mac,"END")!=0)
{
processline();
if(!getl())
break;
}
fprintf(fo,"%s\t%s\t%s\n",name,mac,arg);
printf("Macro Processor completed its running. Output is in mout\n");
}

/*
INPUT:
------
COPY START 1000
RDREC MACRO P,Q,R
CLEAR Q,P
CLEAR P,R
RSUB P,Q
JSUB R,P
MEND
WRREC MACRO S,T,U,V
CLEAR S,T
ADD S,V
MUL U,S
MEND
FIRST STL MUD
RDREC F1,F2,F3
RDREC F4,F5,F6
RDREC F5,F6,F7
WRREC A1,A2,A3,A4
END START

OUTPUT:
-------
COPY START 1000
FIRST STL MUD
//Macro Expansion: RDREC
CLEAR F2,F1
CLEAR F1,F3
RSUB F1,F2
JSUB F3,F1
//Macro Expansion: RDREC
CLEAR F5,F4
CLEAR F4,F6
RSUB F4,F5
JSUB F6,F4
//Macro Expansion: RDREC
CLEAR F6,F5
CLEAR F5,F7
RSUB F5,F6
JSUB F7,F5
//Macro Expansion: WRREC
CLEAR A1,A2
ADD A1,A4
MUL A3,A1
END START

*/

Unknown said... Best Blogger Tips [Reply to comment] Best Blogger Templates

@sarang

You haven't written the processline function

sarang said... Best Blogger Tips [Reply to comment] Best Blogger Templates

@Utsav Sheth


/*****************************************************************************

MACRO PROCESSSOR

******************************************************************************/
#include
#include

FILE *fp,*fo;
int expn=0;
char buf[80],name[20],mac[20],*arg;
int getl();
void expand();
void define();
void strrep(char[],char[],char[]);
int currline=0;
struct def
{
char name[20];
char arg[50];
char d[20][80];
int argc;
int di;
}deftab[20];

char argtab[10][20];
int defi=0;
int i;
int argc=0;
int search(char m[])
{
int i;
for(i=0;i0)
{
getl();
for(x=0;x<argc;x++)
{
sprintf(rep,"?%d",x+1);
strrep(arg,argtab[x],rep);
}
sprintf(deftab[defi].d[currline],"%s %s %s",name,mac,arg);
if(strcmp(mac,"MACRO")==0)
level++;
else if(strcmp(mac,"MEND")==0)
level--;
currline++;
}
deftab[defi++].di=currline;
}

void expand()
{
i=search(mac);
expn=1;
argc=0;
currline=0;
while(1)
{
sscanf(arg,"%[^, ] ",argtab[argc++]);
arg=strstr(arg,argtab[argc-1])+strlen(argtab[argc-1])+1;
if(arg[0]=='\0')
break;
}
if(deftab[i].argc!=argc)
{
printf("Error: Argument Number doesn't match at macro call to %s\n",mac);
expn=0;
return;
}
int j;
for(j=0;j<deftab[i].di-1;j++)
{
getl();
processline();
}
expn=0;
}

int getl()
{
int x;
if(expn!=1)
{
strcpy(name,"");
strcpy(mac,"");
strcpy(arg,"");
fscanf(fp,"%[^\n] ",buf);
x=sscanf(buf,"%s %s %s",name,mac,arg);
if(x!=3)
{
strcpy(arg,mac);
strcpy(mac,name);
strcpy(name,"");
}
if(feof(fp))
return 0;
}
else
{
strcpy(name,"");
strcpy(mac,"");
strcpy(arg,"");
x=sscanf(deftab[i].d[currline],"%s %s %s",name,mac,arg);
if(x!=3)
{
strcpy(arg,mac);
strcpy(mac,name);
strcpy(name,"");
}
while(1)
{
char *p=strstr(arg,"?"),q[5];
if(p==NULL)
break;
sscanf(p,"%[^, ] ",q);
sscanf(p+1,"%d",&x);
strrep(arg,q,argtab[x-1]);
}
currline++;
}
return 1;
}

void strrep(char a[],char b[],char c[])
{
char *p;
char res[50];
strcpy(res,"");
while(1)
{

p=strstr(a,b);
if(p==NULL)
break;
strncat(res,a,p-a);
strcat(res,c);
strcat(res,p+strlen(b));
strcpy(a,res);
}
}

void main()
{
int x;
fp=fopen("min","r");
arg=malloc(80);
if(fp==NULL)
printf("ERROR");
fo=fopen("mout","w");
expn=0;
getl();
while(strcmp(mac,"END")!=0)
{
processline();
if(!getl())
break;
}
fprintf(fo,"%s\t%s\t%s\n",name,mac,arg);
printf("Macro Processor completed its running. Output is in mout\n");
}

/*
INPUT:
------
COPY START 1000
RDREC MACRO P,Q,R
CLEAR Q,P
CLEAR P,R
RSUB P,Q
JSUB R,P
MEND
WRREC MACRO S,T,U,V
CLEAR S,T
ADD S,V
MUL U,S
MEND
FIRST STL MUD
RDREC F1,F2,F3
RDREC F4,F5,F6
RDREC F5,F6,F7
WRREC A1,A2,A3,A4
END START

OUTPUT:
-------
COPY START 1000
FIRST STL MUD
//Macro Expansion: RDREC
CLEAR F2,F1
CLEAR F1,F3
RSUB F1,F2
JSUB F3,F1
//Macro Expansion: RDREC
CLEAR F5,F4
CLEAR F4,F6
RSUB F4,F5
JSUB F6,F4
//Macro Expansion: RDREC
CLEAR F6,F5
CLEAR F5,F7
RSUB F5,F6
JSUB F7,F5
//Macro Expansion: WRREC
CLEAR A1,A2
ADD A1,A4
MUL A3,A1
END START

*/

Pankaj Patil said... Best Blogger Tips [Reply to comment] Best Blogger Templates

MACRO PROCESSSOR

******************************************************************************/
#include
#include

FILE *fp,*fo;
int expn=0;
char buf[80],name[20],mac[20],*arg;
int getl();
void expand();
void define();
void strrep(char[],char[],char[]);
int currline=0;
struct def
{
char name[20];
char arg[50];
char d[20][80];
int argc;
int di;
}deftab[20];

char argtab[10][20];
int defi=0;
int i;
int argc=0;
int search(char m[])
{
int i;
for(i=0;i0)
{
getl();
for(x=0;x<argc;x++)
{
sprintf(rep,"?%d",x+1);
strrep(arg,argtab[x],rep);
}
sprintf(deftab[defi].d[currline],"%s %s %s",name,mac,arg);
if(strcmp(mac,"MACRO")==0)
level++;
else if(strcmp(mac,"MEND")==0)
level--;
currline++;
}
deftab[defi++].di=currline;
}

void expand()
{
i=search(mac);
expn=1;
argc=0;
currline=0;
while(1)
{
sscanf(arg,"%[^, ] ",argtab[argc++]);
arg=strstr(arg,argtab[argc-1])+strlen(argtab[argc-1])+1;
if(arg[0]=='\0')
break;
}
if(deftab[i].argc!=argc)
{
printf("Error: Argument Number doesn't match at macro call to %s\n",mac);
expn=0;
return;
}
int j;
for(j=0;j<deftab[i].di-1;j++)
{
getl();
processline();
}
expn=0;
}

int getl()
{
int x;
if(expn!=1)
{
strcpy(name,"");
strcpy(mac,"");
strcpy(arg,"");
fscanf(fp,"%[^\n] ",buf);
x=sscanf(buf,"%s %s %s",name,mac,arg);
if(x!=3)
{
strcpy(arg,mac);
strcpy(mac,name);
strcpy(name,"");
}
if(feof(fp))
return 0;
}
else
{
strcpy(name,"");
strcpy(mac,"");
strcpy(arg,"");
x=sscanf(deftab[i].d[currline],"%s %s %s",name,mac,arg);
if(x!=3)
{
strcpy(arg,mac);
strcpy(mac,name);
strcpy(name,"");
}
while(1)
{
char *p=strstr(arg,"?"),q[5];
if(p==NULL)
break;
sscanf(p,"%[^, ] ",q);
sscanf(p+1,"%d",&x);
strrep(arg,q,argtab[x-1]);
}
currline++;
}
return 1;
}

void strrep(char a[],char b[],char c[])
{
char *p;
char res[50];
strcpy(res,"");
while(1)
{

p=strstr(a,b);
if(p==NULL)
break;
strncat(res,a,p-a);
strcat(res,c);
strcat(res,p+strlen(b));
strcpy(a,res);
}
}

void main()
{
int x;
fp=fopen("min","r");
arg=malloc(80);
if(fp==NULL)
printf("ERROR");
fo=fopen("mout","w");
expn=0;
getl();
while(strcmp(mac,"END")!=0)
{
processline();
if(!getl())
break;
}
fprintf(fo,"%s\t%s\t%s\n",name,mac,arg);
printf("Macro Processor completed its running. Output is in mout\n");
}

/*
INPUT:
------
COPY START 1000
RDREC MACRO P,Q,R
CLEAR Q,P
CLEAR P,R
RSUB P,Q
JSUB R,P
MEND
WRREC MACRO S,T,U,V
CLEAR S,T
ADD S,V
MUL U,S
MEND
FIRST STL MUD
RDREC F1,F2,F3
RDREC F4,F5,F6
RDREC F5,F6,F7
WRREC A1,A2,A3,A4
END START

OUTPUT:
-------
COPY START 1000
FIRST STL MUD
//Macro Expansion: RDREC
CLEAR F2,F1
CLEAR F1,F3
RSUB F1,F2
JSUB F3,F1
//Macro Expansion: RDREC
CLEAR F5,F4
CLEAR F4,F6
RSUB F4,F5
JSUB F6,F4
//Macro Expansion: RDREC
CLEAR F6,F5
CLEAR F5,F7
RSUB F5,F6
JSUB F7,F5
//Macro Expansion: WRREC
CLEAR A1,A2
ADD A1,A4
MUL A3,A1
END START

NASI said... Best Blogger Tips [Reply to comment] Best Blogger Templates

macro2.c: In function ‘search’:
macro2.c:28:9: error: ‘i0’ undeclared (first use in this function)
for(i=0;i0)
^
macro2.c:28:9: note: each undeclared identifier is reported only once for each function it appears in
macro2.c:28:11: error: expected ‘;’ before ‘)’ token
for(i=0;i0)
^
macro2.c:31:5: error: ‘x’ undeclared (first use in this function)
for(x=0;x<argc;x++)
^
macro2.c:33:9: error: ‘rep’ undeclared (first use in this function)
sprintf(rep,"?%d",x+1);
^
macro2.c:38:1: error: ‘level’ undeclared (first use in this function)
level++;
^
macro2.c: In function ‘main’:
macro2.c:141:5: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
arg=malloc(80);
^

Post a Comment