-
Notifications
You must be signed in to change notification settings - Fork 0
/
assembler.c
198 lines (181 loc) · 8.53 KB
/
assembler.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*********************************FILE__HEADER*********************************\
*
* File: assembler.c
* Authors: Daniel Brodsky & Lior Katav
* Date: August-2023
* Description: The purpose of this program is to act as an assembler,
* converting assembly commands into their binary counterparts.
* The conversion process involves multiple stages, including
* preprocessing, label checking, parsing, and file writing.
*
* This program also generates various types of output files
* to provide a comprehensive view of the assembly-to-binary
* conversion process. These include a processed file (*.am),
* an entry labels file (*.ent), an extern labels file (*.ext),
* and a binary code file (*.ob).
*
* With a strong focus on error handling and memory management,
* this program ensures that all conversions are accurate and
* that all allocated memory is appropriately freed after use.
*
\******************************************************************************/
/******************************** Header Files ********************************/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "program_constants.h"
#include "macro_processing.h"
#include "label_processing.h"
#include "am_file_processing.h"
#include "binary_and_ob_processing.h"
#include "utils.h"
/**************************** Forward Declarations ****************************/
void initProgramState(ProgramState *);
void freeProgramState(ProgramState *programState);
void freeAllFiles(char *, char *, char *, char *, char *, char *);
/******************************************************************************/
/******************************* Main Function *******************************/
/**
* Serves as the program's entry point. The flow of the program includes:
* 1. Initiation of the program state. The assumption of the program is that the starting memory block is
* located at address '100'.
* 2. Reading files and appending appropriate extensions(.am, .ext, .ent, .ob).
* 3. Preprocessing: reading and expanding macros.
* 4. Checking labels for any discrepancies.
* 5. Parsing files to understand and validate the syntax.
* 6. Writing all labels, both entry & external to separated files(.ext, .ent).
* 7. Conversion from binary to base64 and save in a file (.ob).
* Note: If any of the stages encounters an error or fails, the program will not produce a base64 *.ob file.
* 8. Finally, freeing the program state after processing.
*
* @param argc - The number of command-line arguments.
* @param argv[] - An array of command-line arguments, which are expected to be names of the files to be processed.
*
* @return int - Returns 0 on successful execution.
*/
int main(int argc, char *argv[]) {
/* Initialization of structures and variables */
ProgramState programState;
Status stages_status = SUCCESS;
FILE *file = NULL;
int i = 0;
char *file_name_as = NULL, *file_name_am = NULL, *file_name_ent = NULL,
*file_name_ext = NULL, *file_name_bin = NULL, *file_name_ob = NULL;
/* validate that at least one file for processing was provided */
if (argc < 2) {
printf("Please provide file names as command-line arguments.\n");
return FAILURE;
}
for (i = 1; i < argc; i++) {
size_t argLength = strlen(argv[i]);
/* Memory allocation with validation */
if ((file_name_as = malloc(argLength + 4)) == NULL ||
/* 4 for ".as\0" */
(file_name_am = malloc(argLength + 4)) == NULL ||
/* 4 for ".am\0" */
(file_name_ent = malloc(argLength + 5)) == NULL ||
/* 5 for ".ent\0" */
(file_name_ext = malloc(argLength + 5)) == NULL ||
/* 5 for ".ext\0" */
(file_name_bin = malloc(argLength + 5)) == NULL ||
/* 5 for ".bin\0" */
(file_name_ob = malloc(argLength + 4)) ==
NULL) { /* 4 for ".ob\0" */
printf("Error: Memory allocation for info files was failed!\n");
exit(1);
}
/* Construct file names with proper extensions */
sprintf(file_name_as, "%s.as", argv[i]);
sprintf(file_name_am, "%s.am", argv[i]);
sprintf(file_name_ent, "%s.ent", argv[i]);
sprintf(file_name_ext, "%s.ext", argv[i]);
sprintf(file_name_bin, "%s.bin", argv[i]);
sprintf(file_name_ob, "%s.ob", argv[i]);
/* File opening with validation */
if ((file = fopen(file_name_as, "r")) == NULL) {
printf("Failed to open the file: %s\n", file_name_as);
freeAllFiles(file_name_as, file_name_am, file_name_ent,
file_name_ext, file_name_bin, file_name_ob);
continue; /* Skip to the next file */
}
/* Initialize program state settings */
initProgramState(&programState);
/* Process the file */
stages_status += preProcess(file_name_as, file_name_am, &programState);
if (SUCCESS != stages_status) {
remove(file_name_am);
} else {
stages_status += checkLabels(file_name_am, &programState);
stages_status += ParseFile(file_name_am, file_name_bin,
&programState);
/** Only if all previous stages (pre process, syntax validation and parsing) were successful,
* write labels to file and convert binary to Base64 */
if (SUCCESS == stages_status) {
WriteLabelsToFile(file_name_ent, file_name_ext, &programState);
binaryToBase64(file_name_bin, file_name_ob, programState.IC,
programState.DC);
}
}
remove(file_name_bin);
fclose(file);
freeAllFiles(file_name_as, file_name_am, file_name_ent, file_name_ext,
file_name_bin, file_name_ob);
/* Free the program state */
freeProgramState(&programState);
}
return 0;
}
/******************************************************************************/
/**
* Initializes a ProgramState structure by allocating memory for the
* labels and externalLabels vectors and setting initial values for all members.
*
* @param programState - A pointer to the ProgramState structure to initialize.
*/
void initProgramState(ProgramState *programState) {
programState->labels = new_vector();
programState->externalLabels = new_vector();
programState->IC = 0;
programState->DC = 0;
programState->current_line_number = 100; /* assumed starting memory block address */
}
/******************************************************************************/
/**
* Frees up allocated memory for labels and external labels,
* to prevent memory leaks and manage memory of dynamic memory allocated arrays
* in the program.
*
* @param programState - Pointer to the ProgramState object to be freed.
*/
void freeProgramState(ProgramState *programState) {
if (programState->labels != NULL) {
free_vector(programState->labels);
programState->labels = NULL; /* Set the pointer to NULL to avoid dangling pointer */
}
if (programState->externalLabels != NULL) {
free_vector(programState->externalLabels);
programState->externalLabels = NULL; /* Set the pointer to NULL to avoid dangling pointer */
}
}
/******************************************************************************/
/**
* Frees all dynamically allocated memory used for file name strings.
*
* @param file_name_as - Pointer to the string used for the ".as" file name.
* @param file_name_am - Pointer to the string used for the ".am" file name.
* @param file_name_ent - Pointer to the string used for the ".ent" file name.
* @param file_name_ext - Pointer to the string used for the ".ext" file name.
* @param file_name_bin - Pointer to the string used for the ".bin" file name.
* @param file_name_ob - Pointer to the string used for the ".ob" file name.
*/
void freeAllFiles(char *file_name_as, char *file_name_am, char *file_name_ent,
char *file_name_ext, char *file_name_bin,
char *file_name_ob) {
free(file_name_as);
free(file_name_am);
free(file_name_ent);
free(file_name_ext);
free(file_name_bin);
free(file_name_ob);
}
/******************************************************************************/