Implementing Macro Processor in C

A macro processor is a fundamental system program designed to streamline the programming process by replacing macro instructions within a source code with their pre-defined sequences of statements. This implementation provides a basic macro processor written in C.

This C program functions by reading an assembly language program that may contain macro definitions and macro calls. The input assembly code is expected to be provided in a file named MACIN.TXT. The core functionality of this processor involves:

  1. Macro Definition Detection: Identifying and parsing macro definitions within the input source code.
  2. Macro Definition Storage: Storing the identified macro definitions in a dedicated data structure known as the Macro Definition Table (MDT).
  3. Macro Expansion: When macro calls are encountered in the input, the processor retrieves the corresponding definition from the MDT and substitutes the macro call with the stored sequence of assembly language statements.

The final expanded assembly code, with all macro calls replaced by their respective bodies, is then written to an output file named MACOUT.TXT. This process effectively automates the expansion of commonly used code blocks, reducing redundancy and improving code readability and maintainability.

#include<stdio.h>
#include<conio.h>
#include<string.h>
 
struct mdt
{
    char lab[10];
    char opc[10];
    char oper[10];
}d[10];
 
void main()
{
    char label[10],opcode[10],operand[10],newlabel[10],newoperand[10];
    char macroname[10];
    int i,lines;
    FILE *f1,*f2,*f3;
    clrscr();
    f1 = fopen("MACIN.txt","r");
    f2 = fopen("MACOUT.txt","w");
    f3 = fopen("MDT.txt","w");
    fscanf(f1,"%s %s %s",label,opcode,operand);
 
    while(strcmp(opcode,"END")!=0)
    {
        if(strcmp(opcode,"MACRO")==0)
        {
            strcpy(macroname,label);
            fscanf(f1,"%s%s%s",label,opcode,operand);
            lines = 0;
            while(strcmp(opcode,"MEND")!=0)
            {
                fprintf(f3,"%s\t%s\t%s\n",label,opcode,operand);
                strcpy(d[lines].lab,label);
                strcpy(d[lines].opc,opcode);
                strcpy(d[lines].oper,operand);
                fscanf(f1,"%s %s %s",label,opcode,operand);
                lines++;
            }
        }
        else if(strcmp(opcode,macroname)==0)
        {
            printf("lines=%d\n",lines);
            for(i=0;i<lines;i++)
            {
                fprintf(f2,"%s\t%s\t%s\n",d[i].lab,d[i].opc,d[i].oper);
                printf("DLAB=%s\nDOPC=%\nDOPER=%s\n",d[i].lab,d[i].opc,d[i].oper);
            }
        }
        else
        fprintf(f2,"%s\t%s\t%s\n",label,opcode,operand);
        fscanf(f1,"%s%s%s",label,opcode,operand);
    }
    fprintf(f2,"%s\t%s\t%s\n",label,opcode,operand);
    fclose(f1);
    fclose(f2);
    fclose(f3);
    printf("FINISHED");
    getch();
}

Assembly program as input (MACIN.TXT)

CALC START 1000
SUM MACRO **
** LDA #5
** ADD #10
** sTA 2000
** MEND **
** LDA LENGTH
** COMP ZERO
** JEQ LOOP
** SUM **
LENGTH WORD S
ZERO WORD S
LOOP SUM **
** END **

Macro definition table (MDT.TXT)

**	LDA	#5
**	ADD	#10
**	sTA	2000

Explanation

  1. Reading Input File: The program begins by opening MACIN.TXT and reading the assembly instructions line by line.
  2. Identifying Macro Definitions: When the MACRO directive is encountered, the macro name and its instructions are stored in MDT.TXT. The macro body is stored in an array structure for later use.
  3. Expanding Macros: Whenever the macro name appears later in the assembly code, the processor expands it by inserting the stored instructions from the MDT.TXT file.
  4. Writing Expanded Code: The processed assembly code with expanded macros is written to MACOUT.TXT.
  5. Handling End of Program: When END is encountered, the macro processor completes execution and outputs the processed file.

Output (MACOUT.TXT)

CALC	START	1000
**	LDA	LENGTH
**	COMP	ZERO
**	JEQ	LOOP
**	LDA	#5
**	ADD	#10
**	sTA	2000
LENGTH	WORD	S
ZERO	WORD	S
**	LDA	#5
**	ADD	#10
**	sTA	2000
**	END	**

Step-by-Step Explanation of Output

  • CALC START 1000 remains unchanged.
  • LDA LENGTH, COMP ZERO, and JEQ LOOP are also copied as they are.
  • SUM is encountered, so the macro processor expands it:
LDA #5
ADD #10
STA 2000
  • Other lines (LENGTH WORD S, ZERO WORD S) remain unchanged.
  • LOOP SUM is encountered again, so the macro is expanded again:
LDA #5
ADD #10
STA 2000
  • END remains as it is.

4 thoughts on “Implementing Macro Processor in C”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.