Vedant Patil
Practical 02
Data Structure & Implementation for Pass 1 & Pass 2 Macroprocessor
Input file :-
INCR MACRO X
MOV R 1
ADD X R
MEND
.CODE
MOV AX, 5
INCR AX
CLC
END
Code:-
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// --- Data Structures ---
int MDTC = 1, MNTC = 1;
struct argumentListArray {
int index;
char* arg;
struct argumentListArray* next;
};
struct definitionTable {
int index;
char* definition;
struct argumentListArray* arg[2];
struct definitionTable* next;
};
struct nameTable {
int index;
char* name;
struct definitionTable* dtIndex;
struct argumentListArray* args;
int arg_count;
struct nameTable* next;
};
// --- Global Table Pointers ---
struct definitionTable* dtHead = NULL;
struct nameTable* ntHead = NULL;
// --- Helper Functions ---
struct nameTable* findMacroInNT(char* name) {
if (!name) return NULL;
struct nameTable* temp = ntHead;
while (temp != NULL) {
if (strcmp(temp->name, name) == 0) {
return temp;
}
temp = temp->next;
}
return NULL;
}
// --- Pass 1: Define Macros ---
void pass1(FILE* fp) {
char* line = NULL;
size_t len = 0;
ssize_t read;
struct nameTable* ntTemp = NULL;
struct definitionTable* dtTemp = NULL;
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, "MACRO")) {
char* line_copy = strdup(line);
char* macro_name = strtok(line_copy, " \t\n");
strtok(NULL, " \t\n");
if (ntHead == NULL) {
ntHead = (struct nameTable*)malloc(sizeof(struct nameTable));
ntTemp = ntHead;
} else {
ntTemp = ntHead;
while(ntTemp->next != NULL) ntTemp = ntTemp->next;
ntTemp->next = (struct nameTable*)malloc(sizeof(struct nameTable));
ntTemp = ntTemp->next;
}
ntTemp->index = MNTC++;
ntTemp->name = strdup(macro_name);
ntTemp->next = NULL;
ntTemp->args = NULL;
ntTemp->arg_count = 0;
char* arg_token = strtok(NULL, " \t\n,");
struct argumentListArray* alTemp = NULL;
while (arg_token != NULL) {
ntTemp->arg_count++;
struct argumentListArray* new_arg = (struct argumentListArray*)malloc(sizeof(struct
argumentListArray));
new_arg->arg = strdup(arg_token);
new_arg->index = ntTemp->arg_count;
new_arg->next = NULL;
if (ntTemp->args == NULL) {
ntTemp->args = new_arg;
alTemp = new_arg;
} else {
alTemp->next = new_arg;
alTemp = alTemp->next;
}
arg_token = strtok(NULL, " \t\n,");
}
free(line_copy);
if (dtHead == NULL) {
dtHead = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtHead;
} else {
dtTemp = dtHead;
while(dtTemp->next != NULL) dtTemp = dtTemp->next;
dtTemp->next = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtTemp->next;
}
ntTemp->dtIndex = dtTemp;
dtTemp->definition = strdup(ntTemp->name);
dtTemp->index = MDTC++;
dtTemp->next = NULL;
while ((read = getline(&line, &len, fp)) != -1 && strncmp(line, "MEND", 4) != 0) {
dtTemp->next = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtTemp->next;
line[strcspn(line, "\r\n")] = 0;
dtTemp->definition = strdup(line);
dtTemp->index = MDTC++;
dtTemp->next = NULL;
}
dtTemp->next = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtTemp->next;
dtTemp->definition = strdup("MEND");
dtTemp->index = MDTC++;
dtTemp->next = NULL;
}
}
printf("Pass 1 Complete!\n");
}
// --- Pass 2: Expand Macros ---
void pass2(FILE* fp) {
char* line = NULL;
size_t len = 0;
ssize_t read;
FILE* ofp = fopen("output.txt", "w");
// --- FIX: Added a flag to skip all lines inside a macro definition ---
int in_macro_definition = 0;
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, "MACRO")) {
in_macro_definition = 1;
continue;
}
if (strncmp(line, "MEND", 4) == 0) {
in_macro_definition = 0;
continue;
}
if (in_macro_definition) {
continue;
}
char* line_copy = strdup(line);
char* token = strtok(line_copy, " \t\n");
struct nameTable* macro = findMacroInNT(token);
if (macro != NULL) { // It's a macro invocation
char* actual_args[10];
int actual_arg_count = 0;
char* arg_token = strtok(NULL, " \t\n,");
while(arg_token != NULL && actual_arg_count < 10) {
actual_args[actual_arg_count++] = strdup(arg_token);
arg_token = strtok(NULL, " \t\n,");
}
struct definitionTable* def_line = macro->dtIndex->next;
while(def_line != NULL && strcmp(def_line->definition, "MEND") != 0) {
char* template_line = strdup(def_line->definition);
char* template_token = strtok(template_line, " \t\n");
while(template_token != NULL) {
int replaced = 0;
struct argumentListArray* formal_arg = macro->args;
for(int i = 0; i < macro->arg_count; i++) {
if (strcmp(template_token, formal_arg->ar#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// --- Data Structures ---
int MDTC = 1, MNTC = 1;
struct argumentListArray {
int index;
char* arg;
struct argumentListArray* next;
};
struct definitionTable {
int index;
char* definition;
struct argumentListArray* arg[2];
struct definitionTable* next;
};
struct nameTable {
int index;
char* name;
struct definitionTable* dtIndex;
struct argumentListArray* args;
int arg_count;
struct nameTable* next;
};
// --- Global Table Pointers ---
struct definitionTable* dtHead = NULL;
struct nameTable* ntHead = NULL;
// --- Helper Functions ---
struct nameTable* findMacroInNT(char* name) {
if (!name) return NULL;
struct nameTable* temp = ntHead;
while (temp != NULL) {
if (strcmp(temp->name, name) == 0) {
return temp;
}
temp = temp->next;
}
return NULL;
}
// --- Pass 1: Define Macros ---
void pass1(FILE* fp) {
char* line = NULL;
size_t len = 0;
ssize_t read;
struct nameTable* ntTemp = NULL;
struct definitionTable* dtTemp = NULL;
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, "MACRO")) {
char* line_copy = strdup(line);
char* macro_name = strtok(line_copy, " \t\n");
strtok(NULL, " \t\n");
if (ntHead == NULL) {
ntHead = (struct nameTable*)malloc(sizeof(struct nameTable));
ntTemp = ntHead;
} else {
ntTemp = ntHead;
while(ntTemp->next != NULL) ntTemp = ntTemp->next;
ntTemp->next = (struct nameTable*)malloc(sizeof(struct nameTable));
ntTemp = ntTemp->next;
}
ntTemp->index = MNTC++;
ntTemp->name = strdup(macro_name);
ntTemp->next = NULL;
ntTemp->args = NULL;
ntTemp->arg_count = 0;
char* arg_token = strtok(NULL, " \t\n,");
struct argumentListArray* alTemp = NULL;
while (arg_token != NULL) {
ntTemp->arg_count++;
struct argumentListArray* new_arg = (struct argumentListArray*)malloc(sizeof(struct
argumentListArray));
new_arg->arg = strdup(arg_token);
new_arg->index = ntTemp->arg_count;
new_arg->next = NULL;
if (ntTemp->args == NULL) {
ntTemp->args = new_arg;
alTemp = new_arg;
} else {
alTemp->next = new_arg;
alTemp = alTemp->next;
}
arg_token = strtok(NULL, " \t\n,");
}
free(line_copy);
if (dtHead == NULL) {
dtHead = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtHead;
} else {
dtTemp = dtHead;
while(dtTemp->next != NULL) dtTemp = dtTemp->next;
dtTemp->next = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtTemp->next;
}
ntTemp->dtIndex = dtTemp;
dtTemp->definition = strdup(ntTemp->name);
dtTemp->index = MDTC++;
dtTemp->next = NULL;
while ((read = getline(&line, &len, fp)) != -1 && strncmp(line, "MEND", 4) != 0) {
dtTemp->next = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtTemp->next;
line[strcspn(line, "\r\n")] = 0;
dtTemp->definition = strdup(line);
dtTemp->index = MDTC++;
dtTemp->next = NULL;
}
dtTemp->next = (struct definitionTable*)malloc(sizeof(struct definitionTable));
dtTemp = dtTemp->next;
dtTemp->definition = strdup("MEND");
dtTemp->index = MDTC++;
dtTemp->next = NULL;
}
}
printf("Pass 1 Complete!\n");
}
// --- Pass 2: Expand Macros ---
void pass2(FILE* fp) {
char* line = NULL;
size_t len = 0;
ssize_t read;
FILE* ofp = fopen("output.txt", "w");
// --- FIX: Added a flag to skip all lines inside a macro definition ---
int in_macro_definition = 0;
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, "MACRO")) {
in_macro_definition = 1;
continue;
}
if (strncmp(line, "MEND", 4) == 0) {
in_macro_definition = 0;
continue;
}
if (in_macro_definition) {
continue;
}
char* line_copy = strdup(line);
char* token = strtok(line_copy, " \t\n");
struct nameTable* macro = findMacroInNT(token);
if (macro != NULL) { // It's a macro invocation
char* actual_args[10];
int actual_arg_count = 0;
char* arg_token = strtok(NULL, " \t\n,");
while(arg_token != NULL && actual_arg_count < 10) {
actual_args[actual_arg_count++] = strdup(arg_token);
arg_token = strtok(NULL, " \t\n,");
}
struct definitionTable* def_line = macro->dtIndex->next;
while(def_line != NULL && strcmp(def_line->definition, "MEND") != 0) {
char* template_line = strdup(def_line->definition);
char* template_token = strtok(template_line, " \t\n");
while(template_token != NULL) {
int replaced = 0;
struct argumentListArray* formal_arg = macro->args;
for(int i = 0; i < macro->arg_count; i++) {
if (strcmp(template_token, formal_arg->arg) == 0) {
if (i < actual_arg_count) {
fprintf(ofp, "%s", actual_args[i]);
}
replaced = 1;
break;
}
formal_arg = formal_arg->next;
}
if (!replaced) {
fprintf(ofp, "%s", template_token);
}
template_token = strtok(NULL, " \t\n");
if (template_token != NULL) {
fprintf(ofp, " ");
}
}
fprintf(ofp, "\n");
free(template_line);
def_line = def_line->next;
}
for(int i = 0; i < actual_arg_count; i++) free(actual_args[i]);
} else { // It's a regular line of code
fprintf(ofp, "%s", line);
}
free(line_copy);
}
fclose(ofp);
free(line);
printf("Pass 2 Complete! Output generated.\n");
}
int main() {
FILE* fp1 = fopen("input.asm", "r");
if (fp1 == NULL) {
perror("Failed to open input.asm for Pass 1");
return 1;
}
printf("Pass 1 in progress...\n");
pass1(fp1);
fclose(fp1);
FILE* fp2 = fopen("input.asm", "r");
if (fp2 == NULL) {
perror("Failed to open input.asm for Pass 2");
return 1;
}
printf("Pass 2 in progress...\n");
pass2(fp2);
fclose(fp2);
return 0;
}g) == 0) {
if (i < actual_arg_count) {
fprintf(ofp, "%s", actual_args[i]);
}
replaced = 1;
break;
}
formal_arg = formal_arg->next;
}
if (!replaced) {
fprintf(ofp, "%s", template_token);
}
template_token = strtok(NULL, " \t\n");
if (template_token != NULL) {
fprintf(ofp, " ");
}
}
fprintf(ofp, "\n");
free(template_line);
def_line = def_line->next;
}
for(int i = 0; i < actual_arg_count; i++) free(actual_args[i]);
} else { // It's a regular line of code
fprintf(ofp, "%s", line);
}
free(line_copy);
}
fclose(ofp);
free(line);
printf("Pass 2 Complete! Output generated.\n");
}
int main() {
FILE* fp1 = fopen("input.asm", "r");
if (fp1 == NULL) {
perror("Failed to open input.asm for Pass 1");
return 1;
}
printf("Pass 1 in progress...\n");
pass1(fp1);
fclose(fp1);
FILE* fp2 = fopen("input.asm", "r");
if (fp2 == NULL) {
perror("Failed to open input.asm for Pass 2");
return 1;
}
printf("Pass 2 in progress...\n");
pass2(fp2);
fclose(fp2);
return 0;
}
Output:-
[rllab-09@DESKTOP-9JESCI5 ~]$ g++ spos2.cpp -o spos2
[rllab-09@DESKTOP-9JESCI5 ~]$ ./spos2
Pass 1 in progress...
Pass 1 Complete!
Pass 2 in progress...
Pass 2 Complete! Output generated.
Output File :-
.CODE
MOV AX, 5
MOV R 1
ADD X R
CLC
END