Experiment no 6


Problem Statement: To study & implementation of the macro expansion.
Theory: Definition of Macro:
“A macro is a unit of specification for program generation through expansion.”
A macro definition is enclosed between a macro header statement and a macro end statement of
the macro.
A macro definition consists of:

  1. A macro prototype statement
  2. One or more model statements
  3. Macro pre-processor statement.
A macro prototype statement declares the name of a macro & the names & kinds of its parameters.
Syntax:
<macro name> [<formal parameter specification> [ ,….]]
Where,
<macro name> apperes in the mnemonic field of an assembly statement.
<formal parameter specification> is of the form
&<parameter name>[<parameter kind>].
A model statement is a statement from which an assembly language statement may be generated during macro expansion.
A pre-processor statement is used to perform auxiliary functions during macro expansion.


Example of macro:
macro
incr &mem_val,&incr_val,&reg=areg
mover &reg,&mem_val
add &reg,&incr_val
movem &reg,&mem_val
mend






Macro call:
A macro call is called by writing the macro name in the mnemonic field of an assembly statement.
Syntax:
<macro name> [<actual parameter spec> [..,…] ]
Where,
An actual parameter typically resembles an operand specification in an assembly language statement.
e.g. incr A,B
In the example we can see that A, B are actual parameters.


To implement the macro expansion we need to know the variety of tables as follows:
  1. APTAB=actual parameter table:
This table contains the list of actual parameters which are required at the time of expansion of the macro.


  1. PNTAB= parameter name table:
This table contains the list of parameters which includes both keyword as well as positional parameters.


  1. KPDTAB=keyword parameter default table:
This table contains the list of all default parameters that must be used while expanding the code that is at the time of macro expansion.


  1. MDT= macro definition table:
This table contains the information about each parameter used in the macro definition. The entries for each statement will decide the actual parameters in the expanded code.
e.g. mover &reg,&mem_val from the macro definition will be changed in the MDT as follows:
mover (p,2),(p,0)
(p,2) stands for areg, because we know parameter at second second location is the areg only.
(p,0) stands for A, as A is one of the memory location used in the statement.




Let’s see the example:
Input file:
macro
incr &mem_val,&incr_val,&reg=areg
mover &reg,&mem_val
add &reg,&incr_val
movem &reg,&mem_val
mend
start 200
read A
read B
incr A,B
A dc '2'
B dc '4'
End
Output:

1. What is macro? Explain macro expansion.

2. What are different types of parameters used in macro? Explain in detail.

3. Explain the processing steps of Macro expansion in short.

4. Explain macro definition in detail.


CODE::


main program::


#include<conio.h>
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#include<stdlib.h>
# define MAX 80
# define SI 50
fstream f;
char pnt[SI][SI],mdt[SI][SI],apt[SI][SI],default_value[SI];
int pntab_ptr=0,kpdtp1,mdtp1,kpdtab_ptr=0,mdt_ptr=0,aptab_ptr=0,mnt_i=0;
int mnt_entry;
class mnt
{
  char name[SI];
  int kpdtp,mdtp,pp,kp;
  public:
 void  set(char name1[],int pp1,int kp1,int mdtp1,int kpdtp1)
 {
    strcpy(name,name1);
    pp=pp1;
    kp=kp1;
    mdtp=mdtp1;
    kpdtp=kpdtp1;
    mnt_i++;
 }
 int get_pp()
 {
  return pp;
  }
  int get_kp()
  {
    return kp;
    }
int search(char str[])
{
  if(strcmp(str,name)==0)
  return 1;
  return 0;
}
void modify(int kpdtp1)
{
  kpdtp=kpdtp1;
}
}mn;
class kpdtab
{
  char para[SI];
  char val[SI];
  public:
  void set(char str_kp[])
  {
    strcpy(str_kp,strtok(str_kp,"&"));
    strcpy(para,strtok(str_kp,"="));
    strcpy(val,strtok(NULL,"="));
  }
  void display()
  {
    cout<<"\n\n"<<para;
    cout<<"\t"<<val;
  }
  void get_default()
  {
    strcpy(default_value,val);
  }
}kpdt[20];

void macro_expansion( char str[])
{
  char str1[SI],str2[SI];
  int i;
  if(strstr(str,","))
  {
    strcpy(apt[aptab_ptr],strtok(str,","));
     while(strcmp(apt[aptab_ptr],NULL)!=0)
    {
      aptab_ptr++;
      strcpy(apt[aptab_ptr],strtok(NULL,","));
    }
    int pp1=mn.get_pp();
    int kp1=mn.get_kp();
    int j=0;
    while(aptab_ptr<pp1+kp1)
    {
      kpdt[j].get_default();
      strcpy(apt[aptab_ptr],default_value);
      aptab_ptr++;
      j++;
    }
    mdt_ptr=0;
    char buf[50];
    while(strcmp(mdt[mdt_ptr],"mend")!=0)
    {
     strcpy(str,mdt[mdt_ptr]);
     strcpy(buf,"+");
     strcat(buf,strtok(str," "));
     strcat(buf," ");
     strcpy(str1,strtok(NULL," "));
     strcpy(str1,strtok(str1,")"));
     strcpy(str2,strtok(NULL,")"));
     strcpy(str1,strtok(str1,","));
     strcpy(str1,strtok(NULL,","));
     int index=atoi(str1);
     strcat(buf,apt[index]);
     if(str2)
     {
      strcpy(str2,strtok(str2,","));
      strcpy(str2,strtok(NULL,","));
       index=atoi(str2);
      strcat(buf,",");
      strcat(buf,apt[index]);
     }

  cout<<"\n\n"<<buf;
  mdt_ptr++;

  }
 }
}
void macro_def()
{
  int flag=0,i=0,j=0,nofor,pp1=0,kp1=0;
  char str[SI],str1[SI],temp[SI],str_name[SI],str2[SI];
  char str_p[SI][SI],str_kp[SI][SI];
  while(f.getline(str,MAX))
  {
    if(strcmp(str,"mend")==0)
    {
      if(kp1==0)
      {
        kpdtp1=0;
        mn.modify(kpdtp1);
      }
      strcpy(mdt[mdt_ptr],str);
      mdt_ptr++;
      break;
    }
    if(flag==0)
    {
      strcpy(str_name,strtok(str," "));
      strcpy(str1,strtok(NULL," "));
      strcpy(str_p[i],strtok(str1,","));
      while(strcmp(str_p[i],NULL)!=0)
      {
        i++;
        strcpy(str_p[i],strtok(NULL,","));
      }
      nofor=i;
      for(i=0;i<nofor;i++)
      {
        if(strstr(str_p[i],"="))
        {
          strcpy(str_kp[j],str_p[i]);
          strcpy(str_p[i],strtok(str_p[i],"="));
          kp1++;
          j++;
       }
       else
       pp1++;
       strcpy(temp,strtok(str_p[i],"&"));
       strcpy(pnt[pntab_ptr],temp);
       pntab_ptr++;
      }
      j=0;
      kpdtp1=kpdtab_ptr;
      for(j=0;j<kp1;j++)
      {
        kpdt[kpdtab_ptr].set(str_kp[j]);
        kpdtab_ptr++;
      }
      mdtp1=mdt_ptr;
      mn.set(str_name,pp1,kp1,mdtp1,kpdtp1);
      flag=1;
      }
      else
      {
        char buf[20];
        strcpy(buf,strtok(str," "));
        strcat(buf," ");
        strcpy(str1,strtok(NULL," "));
        if(strstr(str1,","))
        {
         strcpy(str1,strtok(str1,","));
         strcpy(str2,strtok(NULL,","));
         if(strstr(str1,"&"))
         {
           strcpy(str1,strtok(str1,"&"));
           for(i=0;i<pp1+kp1;i++)
           {
             if(strcmp(str1,pnt[i])==0)
             {
               strcat(buf,"(p,");
               char a[10];
               itoa(i,a,10);
               strcat(buf,a);
               strcat(buf,")");
               strcat(buf,",");
               break;
             }
          }
        }
        else
        strcpy(buf,str1);
      }
      else
      strcpy(str2,str1);
      if(strstr(str2,"&"))
         {
           strcpy(str2,strtok(str2,"&"));
           for(i=0;i<pp1+kp1;i++)
           {
             if(strcmp(str2,pnt[i])==0)
             {
               strcat(buf,"(p,");
               char a[10];
               itoa(i,a,10);
               strcat(buf,a);
               strcat(buf,")");
               break;
             }
          }
        }
        else
        strcat(buf,str2);
        strcpy(mdt[mdt_ptr],buf);
        mdt_ptr++;
   }
}
cout<<"\n\n\n"<<"PNTAB ::";
for(i=0;i<pp1+kp1;i++)
{
   cout<<"\n\n"<<pnt[i];
}
cout<<"\n\n\n"<<"KPDTAB ::";
for(i=kpdtp1;i<kp1;i++)
{
  kpdt[i].display();
}
cout<<"\n\n\n"<<"MDT ::";
for(i=mdtp1;i<mdt_ptr;i++)
{
   cout<<"\n\n"<<mdt[i];
}
getch();
}

void main()
{
  char str[SI],str1[SI],strc[SI],strap[SI];
  int macro_flag=0,flag1;
  clrscr();
  f.open("in.txt",ios::beg|ios::in);
  while(f.getline(str,MAX))
  {
    if(macro_flag==0&&strcmp(str,"macro")==0)
    macro_def();
    else
    {
          strcpy(strc,str);
          strcpy(str1,strtok(str," "));
         if(strcmp(str1,"start")==0)
         {
          cout<<"\n Program Without Macro Call:-";
          macro_flag=1;
          cout<<"\n\n"<<strc;
         }
         else
         {
           strcpy(strap,strtok(NULL," "));
           for(int i=0;i<mnt_i;i++)
           {
             flag1=mn.search(str1);
             if(flag1==1)
             {
             mnt_entry=i;
             macro_expansion(strap);
             break;
             }
           }
          if(flag1==0)
          cout<<"\n\n"<<strc;
         }
         if(strcmp(str,"end")==0)
         break;
      }
   }
 f.close();
 getch();
}

Comments