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.
/*
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
/*************************************************************************************/
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 :
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
#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
*/
@sarang
You haven't written the processline function
@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
*/
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
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