-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2nd_run.c
404 lines (348 loc) · 13 KB
/
2nd_run.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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
/*
* HEADERS
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "externs.h"
#include "utilities.h"
#include "prototypes.h"
#include "structs.h"
/* external list is declared only in the second run */
ext ext1;
extPtr ext_list = &ext1;
extPtr head_ext;
void second_run(FILE *fp, char *filename){
/* resetting global linked lists to start */
char line[LINE_LENGTH]; /* This string will contain each line at a time */
int line_num = 1; /* Line numbers start from 1 */
word_list = head_word;
head_ext = ext_list;
while(fgets(line, LINE_LENGTH, fp) != NULL) /* Read lines until end of file */
{
err = NO_ERROR;
if (!ignore(line))
read_line_2nd(line); /* line parser and decision maker */
if (err != NO_ERROR) { /* print lines and error */
printf("%d - 'n", line_num);
write_error(line_num);
}
line_num++;
}
if (err == NO_ERROR) /* write output files only if no err raised along the program */
write_output_files(filename);
/* Free dynamic allocated elements */
free_labels(&symbols_table);
/* free_ext(&(head_ext->next)); */
/* free_words(&(head_word->next)); */
}
void read_line_2nd(char *line) {
char curr_token[LINE_LENGTH];
int directive_name = -1 ;
int command_name = -1;
line = skip_spaces(line); /* Proceeding to first non-blank character */
if (end_of_line(line)) return;
tokenize(curr_token, line); /* parsing line to tokens proccess */
if (is_label_declaration(curr_token)) {
line = next_token(line);
tokenize(curr_token, line);
}
if ((directive_name = which_directive(curr_token)) != NOT_FOUND) {
/* in the second pass only the entry directive is relevant, to edit entry values*/
line = next_token(line);
if (directive_name == ENTRY) {
tokenize(curr_token, line);
edit_entry(symbols_table, curr_token);
}
}
else if ((command_name = which_command(curr_token)) != NOT_FOUND) /* Encoding command's additional words */
{
line = next_token(line);
command_manipulation_2nd(command_name, line);
}
}
/* This function handles commands for the second pass - encoding additional words */
int command_manipulation_2nd(int type, char *line)
{
char first_op[LINE_LENGTH], second_op[LINE_LENGTH]; /* will hold first and second operands */
char *src = first_op, *dest = second_op; /* after the check below, src will point to source and
* dest to destination operands */
boolean is_src = FALSE, is_dest = FALSE; /* Source/destination operands existence */
int src_method = UNKNOWN_ADDRESS, dest_method = UNKNOWN_ADDRESS; /* Their addressing methods */
int is_src_label = 0, is_dest_label =0;
check_operands_exist(type, &is_src, &is_dest);
/* Matching src and dest pointers to the correct operands (first or second or both) */
if(is_src || is_dest)
{
line = next_list_token(first_op, line);
if(is_src && is_dest) /* There are 2 operands */
{
line = next_list_token(second_op, line);
next_list_token(second_op, line);
}
else
{
dest = first_op; /* If there's only one operand, it's a destination operand */
src = NULL;
}
}
/* check which operands are labels */
is_src_label = is_src && is_operand_label(src);
is_dest_label =is_dest && is_operand_label(dest);
/* Extracting source and destination addressing methods */
if (is_src_label) {
if (src[0] == '&') /* remove '&' from operand to use only the value */
memmove(src, src + 1, strlen(src));
proceed_to_blank_word(&word_list); /* reach the next unencoded word to fill with data */
if (get_label(symbols_table, src)->external) {
add_label_to_extern(word_list->address, src); /* add to external */
}
/* finds the addressing used in its main word */
src_method = get_from_previous_main_word(SOURCE_ADDRESSING, *word_list);
encode_additional_words(src, src_method);
}
if (is_dest_label) {
if (dest[0] == '&') /* remove '&' from operand to use only the value */
memmove(dest, dest + 1, strlen(dest));
proceed_to_blank_word(&word_list); /* reach the next unencoded word to fill with data */
if (get_label(symbols_table, dest)->external) {
add_label_to_extern(word_list->address, dest); /* add to external */
}
/* finds the addressing used in its main word */
dest_method = get_from_previous_main_word(DEST_ADDRESSING, *word_list);
encode_additional_words(dest, dest_method);
}
return 0;
}
/* this function finds for a word node its last main word
* seeks only in the last 2 since max additional words are 2 */
int get_from_previous_main_word(int field, wordMeta word){
unsigned address = -1;
if (word_list->prev->wordType == MAIN_WORD) {
switch (field) {
case SOURCE_ADDRESSING:
address = word.prev->word_code.mainWord.source_addressing;
break;
case DEST_ADDRESSING:
address = word.prev->word_code.mainWord.dest_addressing;
break;
}
}
else if (word_list->prev->prev->wordType == MAIN_WORD)
switch (field) {
case SOURCE_ADDRESSING:
address = word.prev->prev->word_code.mainWord.source_addressing;
break;
case DEST_ADDRESSING:
address = word.prev->prev->word_code.mainWord.dest_addressing;
break;
}
else
err = COMMAND_LABEL_DOES_NOT_EXIST;
return address;
}
/* this method iterates word list to find the next unencoded word */
void proceed_to_blank_word(wordPtr *word){
while ((*word)->next != NULL && (*word)->wordType != 0) { /*@@EXC_BAD_ACCESS */
*word = (*word)->next;
}
}
/* this method adds external labels to the external linked list */
void add_label_to_extern(unsigned int address, char *label_name){
extPtr tmpNode = (extPtr)malloc(sizeof(ext));
memset(tmpNode, 0, sizeof(*tmpNode));
extern_existence = TRUE;
ext_list->address = address;
strcpy(ext_list->name,label_name);
/* add new node */
ext_list->next = tmpNode;
ext_list = ext_list->next;
}
/* this method assigns every field of and additional word based on its properties */
void encode_additional_words(char *operand, int method) {
unsigned address = 0;
unsigned distance = 0;
labelPtr lbl;
boolean is_external = -1;
lbl = get_label(symbols_table, operand); /* find the matching label is symbol table */
if (lbl != NULL) {
address = lbl->address;
is_external = lbl->external;
if (method == DIRECT_ADDRESS) {
if (is_external == TRUE) {
word_list->word_code.word21bits.E = 1; /* external get E = 1 */
} else {
word_list->word_code.word21bits.R = 1;
}
word_list->word_code.word21bits.content = address;
} else if (method == RELATIVE_ADDRESS) {
word_list->word_code.word21bits.A = 1;
distance = address - (word_list->address - 1); /* calculates and assigns the distance
* from label address to node address */
word_list->word_code.word21bits.content = distance;
}
word_list->wordType = BIT21_WORD;
}
else {
err = COMMAND_LABEL_DOES_NOT_EXIST;
}
}
/* This function determines if source and destination operands exist by opcode */
void check_operands_exist(int type, boolean *is_src, boolean *is_dest)
{
switch (type)
{
/* this commands can have both src and dest */
case MOV:
case CMP:
case ADD:
case SUB:
case LEA:
*is_src = TRUE;
*is_dest = TRUE;
break;
/* this commands can have only dest */
case CLR:
case NOT:
case INC:
case DEC:
case JMP:
case BNE:
case JSR:
case RED:
case PRN:
*is_src = FALSE;
*is_dest = TRUE;
break;
/* this commands get no operands */
case RTS:
case STOP:
*is_src = FALSE;
*is_dest = FALSE;
}
}
/* This function writes all 3 output files (if they should be created)*/
int write_output_files(char *original)
{
FILE *file;
file = open_file(original, FILE_OBJECT);
write_output_ob(file);
printf("Output file at %s%s\n", original,".ob");
if(entry_existence) { /* write to output only if there are entries*/
file = open_file(original, FILE_ENTRY);
write_output_entry(file);
printf("Output file at %s%s\n", original,".ent");
}
if(extern_existence) /* write to output only if there are entries*/
{
file = open_file(original, FILE_EXTERN);
write_output_extern(file);
printf("Output file at %s%s\n", original,".ent");
}
return NO_ERROR;
}
/* This function opens a file with writing permissions, given the original input filename and the
* wanted file extension (by type)
*/
FILE *open_file(char *filename, int type)
{
FILE *file;
filename = create_file_name(filename, type); /* Creating filename with extension */
file = fopen(filename, "w"); /* Opening file with permissions */
free(filename); /* Allocated modified filename is no longer needed */
if(file == NULL)
{
err = CANNOT_OPEN_FILE;
return NULL;
}
return file;
}
/* this function converts a decimal num to binary string */
void b10tob2(char* dst, int n, int num)
{
int c, d, count;
char *bin_word = (char*)malloc(24+1);
count = 0;
if (bin_word == NULL)
exit(EXIT_FAILURE);
/* iterates the num and appends binary result with bit shifting */
for (c = n-1 ; c >= 0 ; c--)
{
d = num >> c;
if (d & 1)
*(bin_word+count) = 1 + '0';
else
*(bin_word+count) = 0 + '0';
count++;
}
*(bin_word+count) = '\0'; /* append end of string */
strcat(dst, bin_word);
free(bin_word);
}
/* this method orchestrates creation of a binary word from a word, while appending each field */
void storeBinary(wordMeta word, char final_bin_word[]) {
if (word.wordType == MAIN_WORD) {
b10tob2(final_bin_word, 6, word.word_code.mainWord.opcode);
b10tob2(final_bin_word, 2, word.word_code.mainWord.source_addressing);
b10tob2(final_bin_word, 3, word.word_code.mainWord.source_register);
b10tob2(final_bin_word, 2, word.word_code.mainWord.dest_addressing);
b10tob2(final_bin_word, 3, word.word_code.mainWord.dest_register);
b10tob2(final_bin_word, 5, word.word_code.mainWord.funct);
b10tob2(final_bin_word, 1, word.word_code.mainWord.A);
b10tob2(final_bin_word, 1, word.word_code.mainWord.R);
b10tob2(final_bin_word, 1, word.word_code.mainWord.E);
}
else if (word.wordType == BIT21_WORD) {
b10tob2(final_bin_word, 21, word.word_code.word21bits.content);
b10tob2(final_bin_word, 1, word.word_code.word21bits.A);
b10tob2(final_bin_word, 1, word.word_code.word21bits.R);
b10tob2(final_bin_word, 1, word.word_code.word21bits.E);
}
else if (word.wordType == BIT24_WORD) {
b10tob2(final_bin_word, 24, word.word_code.word24bits.content);
}
}
/* converts binary string to hex num*/
long hexify(char bin_string[]) {
char *ptr;
long hex_num;
hex_num = strtol(bin_string, &ptr, 2);
return hex_num;
}
/* print ob file with address and word as hex, instructions first and data img after */
void write_output_ob(FILE *fp){
wordPtr tmpWord = head_word;
char binary_word[WORD_LENGTH+1] = {0};
int hexNum;
fprintf(fp, "%d %d\n", ic-100, dc); /* print the final ic and dc */
while (tmpWord) {
memset(binary_word, '\0', sizeof(binary_word));
storeBinary(*tmpWord, binary_word); /* word fields to binary string */
hexNum = hexify(binary_word); /* binary string to hex num */
fprintf(fp, "%07d %06x\n", tmpWord->address, hexNum); /* print to file with predefined length */
tmpWord = tmpWord->next;
}
fclose(fp);
}
/* print ent file: goes over symbol list and prints to file if its an entry */
void write_output_entry(FILE *fp){
labelPtr tmpLabels = symbols_table;
while (tmpLabels) {
if (tmpLabels->entry == TRUE) {
fprintf(fp, "%s %07d\n", tmpLabels->name, tmpLabels->address);
}
tmpLabels = tmpLabels->next;
}
fclose(fp);
}
/* prints externals to file: goes over the external linked list and prints every node */
void write_output_extern(FILE *fp){
extPtr tmpExterns = head_ext;
while (tmpExterns->next) {
fprintf(fp,"%s %07d\n", tmpExterns->name, tmpExterns->address);
tmpExterns = tmpExterns->next;
}
fclose(fp);
}