0% found this document useful (0 votes)
21 views11 pages

SPOS Assignment 2

The document describes the implementation of a macroprocessor with two passes for macro definition and expansion. It includes code for defining macros, handling arguments, and generating output based on macro invocations. The output file reflects the expanded code after processing the input assembly file.

Uploaded by

siddhi.wani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views11 pages

SPOS Assignment 2

The document describes the implementation of a macroprocessor with two passes for macro definition and expansion. It includes code for defining macros, handling arguments, and generating output based on macro invocations. The output file reflects the expanded code after processing the input assembly file.

Uploaded by

siddhi.wani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

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

You might also like