This repository has been archived by the owner on Nov 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFirstPass.c
472 lines (421 loc) · 26.2 KB
/
FirstPass.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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
#include "Project.h"
/*
*
* In this file we will do the firstPass on the text
*
*/
int firstPass(FILE *newfp, int RAM[RAM_SIZE], label **labels, int *labelCount, command commands[],
char registerTable[MAX_LINE_SIZE][MAX_LINE_SIZE], int *DCF, int *extFlag, int *entryFlag) {
char line[MAX_LINE_SIZE]; /* Will contain the current line*/
int wordAmount = ZERO; /* Amount of words in the line*/
char *wordArray[MAX_LINE_SIZE]; /* Will contain an array of the line divided into words*/
int labelFlag = ZERO; /* Turned on if we came across a label */
label *tempLabels; /* Will be used to make sure a dynamically allocated labels array is not NULL*/
int IC = RAM_START; /* Will be used for RAM memory allocation*/
char intLine[MAX_LINE_SIZE]; /* The temp line of number in separated by "," */
int intArray[MAX_LINE_SIZE] = {ZERO}; /* Will be used to save the numbers in array */
int numInLineCounter = ZERO; /* Will be used to count how many numbers we have in the line */
int numOfCommas = ZERO; /* Will be used to count how many commas are in the line to check if the line is balanced */
int dataLineIndex = ZERO; /* Will be used to run on the numbers in int data entering */
int distance = ZERO; /* Will be used to track the size of the label in the memory*/
char strLabelWithoutColon[MAX_LINE_SIZE];/* Will be used to remove the colon at the end of label name*/
int labelStatus = ZERO; /* Will be used to hold the number returned from the method checkLabelName */
int commandIndex = ZERO; /* Will be used to hold the command number */
int lengthOfCommand = ZERO; /* Will be used to hold the variables of the command */
char commandOperands[MAX_LINE_SIZE][MAX_LINE_SIZE]; /* Will be used to hold the command number */
int operandsCounter = ZERO; /* Will be used to hold the number of operands in a line */
int firstOperandAddressMethod = ZERO; /* Will be used to hold the number of the first address method in a line */
int secondOperandAddressMethod = ZERO; /* Will be used to hold the number of the second address method in a line */
int lineCounter = ZERO; /* Will be used to index the lines*/
int errorFlag = FALSE; /* Will be used to Mark if we encountered an error*/
int DC = ZERO; /* Indicates the progress in the data set */
int DCTable[RAM_SIZE] = {ZERO}; /* Will be used to enter the data*/
int ICF; /* final IC */
int index = ZERO; /* Running index for the loop */
fseek(newfp, ZERO, SEEK_SET); /* Returns to the beginning of newfp*/
while (fgets(line, MAX_LINE_SIZE, newfp)) /* Reads a line from the file */
{
wordAmount = makeItArray(line, wordArray); /* Divides the line into array containing each word*/
lineCounter++;
if (wordArray[ZERO][ZERO] == ';' || strcmp(wordArray[ZERO], "\n") == ZERO ||
strcmp(wordArray[ZERO], "\t") == ZERO) /* If it's an empty or a comment line */
{
/* Ignores the line */
} else {
labelFlag = ZERO;
if ((wordArray[ZERO][strlen(wordArray[ZERO]) - ONE]) ==
':') /* The last char of the first word is ':' means is a label*/
{
labelWithoutColon(wordArray[ZERO], strLabelWithoutColon);
/* check if we already had that label */
if (checkLabelName(strLabelWithoutColon, *labels, *labelCount) == MINUS_TWO) {
printf("Line %d- Error - error in label name\n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration */
} else {
labelFlag = TRUE;/*means we are in a label*/
distance = ZERO;/*sets distance to zero*/
}
}
/* Check if it's a data command */
/*
* ZERO + labelFlag can be 0 or 1*/
if ((strcmp(wordArray[ZERO + labelFlag], ".data") == ZERO ||
strcmp(wordArray[ZERO + labelFlag], ".string") == ZERO)) /* If the second word is .data or .string */
{
if (labelFlag == TRUE) {
if (*labelCount == ZERO) /* If this is the first label encountere d*/
{
(*labels) = (label *) malloc(sizeof(label));
if ((*labels) == NULL) {
puts("Error - wasn't able to dynamically allocate a labels array, will stop the program from running \n");
exit(EXIT);
}
(*labelCount)++; /* Raise the label count*/
} else {
(*labelCount)++; /* Raise the label count*/
tempLabels = (label *) realloc((*labels), (*labelCount) * sizeof(label));
if (tempLabels == NULL) {
puts("Wasn't able to dynamically allocate a labels array, will stop the program from running \n");
exit(EXIT);
}
(*labels) = tempLabels;/* If realloc worked */
}
/* Enter the data */
removesNewLine(strLabelWithoutColon);
strcpy((*labels)[*labelCount - STEP].name, strLabelWithoutColon);
(*labels)[(*labelCount) - STEP].attributesCount = ZERO;
(*labels)[(*labelCount) - STEP].address = DC;
(*labels)[(*labelCount) -
STEP].attributesCount++; /* Num of attributes plus one because we add an attribute */
if (strcmp(wordArray[START], ".data") == ZERO) {
strcpy((*labels)[*labelCount - STEP].attributes[(*labels)[*labelCount - STEP].attributesCount -
STEP], "data");
/* Concat the numbers in to line seperated by commas */
makeIntLine(wordArray, wordAmount, intLine, labelFlag);
/* Count the number of commas */
numOfCommas = countCommas(intLine);
/* Make the line of numbers to an array. If there are problem with ine of the data we will get -2 */
numInLineCounter = makeItNumArray(intArray, intLine);
if (numInLineCounter < ZERO) {
printf("Line %d- Error - Wrong data was entered \n", lineCounter);
errorFlag = TRUE;
continue;/* Will continue to the next iteration*/
}
/*
* Check if the line is balanced in numbers and commas
*/
if (numOfCommas + ONE != numInLineCounter) {
printf("Line %d- Error - Numbers and commas are not balanced\n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
for (dataLineIndex = ZERO; dataLineIndex < numInLineCounter; dataLineIndex++) {
DCTable[DC] = intArray[dataLineIndex];
DCTable[DC] |= (ONE << INT_A);
DCTable[DC] &= TURN_OFF_BITS_FOR_NEGATIVE_NUMBERS;
DC++;
distance++;
}
} else if (strcmp(wordArray[START], ".string") == ZERO) {
strcpy((*labels)[(*labelCount) - STEP].attributes[
(*labels)[*labelCount - STEP].attributesCount - STEP], "data");
if (wordAmount != THREE) {
printf("Line %d- Error - To many arguments in the data line\n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
} else {
/*
* enter each letter as a word in the RAM until
* 1. enter each letter ascii value to line in RAM
* 2. RAMIndex++
* 3.label.length++
* 4. turn on 19 switch on (R is on)
*/
for (dataLineIndex = ZERO; wordArray[TWO][dataLineIndex] != '\0'; dataLineIndex++) {
if (wordArray[TWO][dataLineIndex] != '"' && wordArray[TWO][dataLineIndex] != '\n') {
DCTable[DC] = (int) wordArray[TWO][dataLineIndex];
DCTable[DC] |= (ONE << INT_A);
DC++;
distance++;
}
/*
* 1. Enter each letter ascii value to line in RAM
* 2. RAMIndex++
* 3. Label.length++
* 4. turn on 19 switch on (R is on)
*/
}
DCTable[DC] = ZERO;
DCTable[DC] |= (ONE << INT_A);
DC++;
distance++;
}
}
(*labels)[(*labelCount) - STEP].length = distance;
}
/*
* Data but label flag is off
*/
else {
/* Concat the numbers in to line seperated by commas */
makeIntLine(wordArray, wordAmount, intLine, labelFlag);
/* Count the number of commas */
numOfCommas = countCommas(intLine);
/* Make the line of numbers to an array. If there are problem with ine of the data we will get -2 */
numInLineCounter = makeItNumArray(intArray, intLine);
if (numInLineCounter < ZERO) {
printf("Line %d- Error - Wrong data was entered \n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
/*
* Check if the line is balanced in numbers and commas
*/
if (numOfCommas + ONE != numInLineCounter && numOfCommas != ZERO) {
printf("Line %d- Error - Numbers and commas are not balanced\n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
for (dataLineIndex = ZERO; dataLineIndex < numInLineCounter; dataLineIndex++) {
DCTable[DC] = intArray[dataLineIndex];
DCTable[DC] |= (ONE << INT_A);
DCTable[DC] &= TURN_OFF_BITS_FOR_NEGATIVE_NUMBERS;
DC++;
distance++;
}
}
}
/*
* Check if we encountered extern or entry type lines
*/
else if ((strcmp(wordArray[ZERO + labelFlag], ".extern") == ZERO) ||
(strcmp(wordArray[ZERO + labelFlag], ".entry")) == ZERO) {
labelWithoutColon(wordArray[START + labelFlag], strLabelWithoutColon);
labelStatus = checkLabelName(strLabelWithoutColon, (*labels), *labelCount);
if ((strcmp(wordArray[ZERO + labelFlag], ".entry")) == ZERO) {
*entryFlag = TRUE;
continue; /* Will continue to the next iteration */
} else if (labelStatus == MINUS_TWO) {
printf("Line %d-Error- error in label name\n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
} else if (labelStatus == MINUS_ONE) {
if (*labelCount == ZERO) /* If this is the first label encountered*/
{
(*labels) = (label *) malloc(sizeof(label));
if ((*labels) == NULL) {
puts("Error - wasn't able to dynamically allocate a labels array, will stop the program from running \n");
exit(EXIT);
}
(*labelCount)++; /* Raise the label count*/
} else {
(*labelCount)++; /* Raise the label count*/
tempLabels = (label *) realloc((*labels), (*labelCount) * sizeof(label));
if (tempLabels == NULL) {
puts("Error- wasn't able to dynamically allocate a labels array, will stop the program from running \n");
exit(EXIT);
}
(*labels) = tempLabels;/* If realloc worked*/
}
removesNewLine(wordArray[START + labelFlag]);
strcpy((*labels)[(*labelCount) - STEP].name, wordArray[START + labelFlag]);
(*labels)[(*labelCount) - STEP].attributesCount = ZERO;
(*labels)[(*labelCount) - STEP].attributesCount++; /* Num of attributes plus one because we add an attribute */
(*labels)[(*labelCount) - STEP].address = ZERO;
(*labels)[(*labelCount) - STEP].base = ZERO;
(*labels)[(*labelCount) - STEP].offset = ZERO;
strcpy((*labels)[(*labelCount) - STEP].attributes[(*labels)[(*labelCount) - STEP].attributesCount - STEP], "extern");
*extFlag = TRUE;
} else {
/* If the label already exist we need to check if it's have extern attribute to */
if (strcmp((*labels)[labelStatus].attributes[ZERO], "extern") != ZERO &&
(*labels)[labelStatus].attributesCount != START) {
/* Means the label has other attributes beside extern attribute which should result in an error */
printf("Line %d- Error - the label has other attributes beside extern attribute, a extern label should only have a extern attribute, extern was not added to the label\n",
lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
}
} else {
/*
* Line 11 page 37 - it's a command line!
*/
if (labelFlag == TRUE) {
labelWithoutColon(wordArray[ZERO], strLabelWithoutColon);
labelStatus = checkLabelName(strLabelWithoutColon, (*labels), *labelCount);
if (labelStatus == MINUS_TWO) {
printf("Line %d- Error - error in label name\n", lineCounter);
errorFlag = TRUE;
continue;/*will continue to the next iteration*/
} else if (labelStatus > MINUS_ONE) {
printf("Line %d- Error - label was already defined, not possible to define it again\n",
lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
} else {
if ((*labelCount) == ZERO) /* If this is the first label encountered*/
{
(*labels) = (label *) malloc(sizeof(label));
if ((*labels) == NULL) {
puts("Error - wasn't able to dynamically allocate a labels array, will stop the program from running \n");
exit(EXIT);
}
(*labelCount)++; /* Raise the label count*/
} else {
(*labelCount)++; /* Raise the label count*/
tempLabels = (label *) realloc((*labels), (*labelCount) * sizeof(label));
(*labels)[(*labelCount) - ONE].length = ZERO;
if (tempLabels == NULL) {
puts("Error- wasn't able to dynamically allocate a labels array, will stop the program from running \n");
exit(EXIT);
}
(*labels) = tempLabels; /* If realloc worked*/
}
removesNewLine(strLabelWithoutColon);
strcpy((*labels)[*labelCount - ONE].name, strLabelWithoutColon);
(*labels)[(*labelCount) - ONE].address = IC;
(*labels)[(*labelCount) - ONE].attributesCount = ZERO;
(*labels)[(*labelCount) - ONE].attributesCount++; /* Num of attributes plus one because we add an attribute */
enterBaseAndOffset(&(*labels)[*labelCount - ONE], IC);
strcpy((*labels)[*labelCount - ONE].attributes[(*labels)[(*labelCount) - ONE].attributesCount -
ONE], "code");
}
}
lengthOfCommand = ZERO;
/* Search the name of the command in the table */
commandIndex = searchCommand(commands, wordArray[ZERO + labelFlag]);
if (commandIndex == MINUS_ONE) {
printf("Line %d Error - command was not found, continuing to the next line \n", lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
} else {
removesNewLine(wordArray[ZERO + labelFlag]);
if ((strcmp(wordArray[ZERO + labelFlag], "rts")) == ZERO ||
(strcmp(wordArray[ZERO + labelFlag], "stop")) == ZERO) {
operandsCounter = ZERO;
} else {
operandsCounter = lineForCommand(wordArray, labelFlag, wordAmount, commandOperands,
lineCounter);
if (operandsCounter == MINUS_ONE) {
/* An error printing was made inside the lineForCommand function */
continue; /* Will continue to the next iteration*/
}
}
switch (commandIndex) {
/* The methods that get 2 operands */
case ZERO:
case ONE:
case TWO:
case THREE:
case FOUR:
/* Check if we have enough operands for that method*/
if (operandsCounter != TWO) {
numOfOperandsNotMatch(lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
/* Find the number of the Addressing Methods*/
firstOperandAddressMethod = findAddressMethod(commandOperands[ZERO], registerTable, lineCounter);
secondOperandAddressMethod = findAddressMethod(commandOperands[STEP], registerTable, lineCounter);
/* Checks whether there is a match between the method and the operand it can receive */
if (firstOperandAddressMethod == MINUS_ONE || secondOperandAddressMethod == MINUS_ONE) {
printf("Line %d- Error - Error in address operand \n", lineCounter);
errorFlag = TRUE;
}
if (commandIndex == FOUR &&
(firstOperandAddressMethod == ZERO || firstOperandAddressMethod == THREE)) {
printf("Line %d- lea command cant use this addressing method for source operand", lineCounter);
errorFlag = TRUE;
}
if (secondOperandAddressMethod == ZERO && commandIndex != ONE) {
printf("Line %d- this method cannot get immediate address method in the destination operand", lineCounter);
errorFlag = TRUE;
}
lengthOfCommand += TWO; /* Two more lines - One for the opceode - Second for funct and the addresing methods and source and destination registers */
/* Adds the number of rows according to the appropriate addressing method */
lengthOfCommand += addLength(firstOperandAddressMethod); /* Will add the length needed based on the addressing method */
lengthOfCommand += addLength(secondOperandAddressMethod); /* Will add the length needed based on the addressing method */
break;
/*The method gets 1 operand */
case FIVE:
case SIX:
case SEVEN:
case EIGHT:
case NINE:
case TEN:
case ELEVEN:
case TWELVE:
case THIRTEEN:
/* Check if we have enough operands for that method*/
if (operandsCounter != ONE) {
numOfOperandsNotMatch(lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
/* Find the number of the Addressing Methods*/
firstOperandAddressMethod = findAddressMethod(commandOperands[ZERO], registerTable, lineCounter);
/* Checking for errors*/
if (firstOperandAddressMethod == MINUS_ONE) {
printf("Line %d-Error - Error in address operand \n", lineCounter);
errorFlag = TRUE;
continue;
}
/* Checks whether there is a match between the method and the operand it can receive */
if (commandIndex != THIRTEEN && firstOperandAddressMethod == ZERO) {
printf("Line %d- this method cannot get immediate address method in the destination operand", lineCounter);
errorFlag = TRUE;
continue;
}
if (firstOperandAddressMethod == THREE &&
(commandIndex == NINE || commandIndex == TEN || commandIndex == ELEVEN)) {
printf("Line %d- this method cannot get register direct address method in the destination operand", lineCounter);
errorFlag = TRUE;
continue;
}
/* Adds the number of rows according to the appropriate addressing method */
lengthOfCommand += TWO; /* Two more lines - One for the opceode - Second for funct and the addresing methods and source and destination registers */
lengthOfCommand += addLength(firstOperandAddressMethod); /* Will add the length needed based on the addressing method */
break;
/* The method doesn't get any operand */
case FOURTEEN:
case FIFTEEN:
/* Check if we have enough operands for that method */
if (operandsCounter != ZERO) {
numOfOperandsNotMatch(lineCounter);
errorFlag = TRUE;
continue; /* Will continue to the next iteration*/
}
lengthOfCommand = ONE;
break;
}
/* The method will change the RAM to contain the values that are supposed to be inserted to the RAM*/
changeMemoryFirstCross(firstOperandAddressMethod, secondOperandAddressMethod, RAM, IC, commandIndex, commands, operandsCounter, registerTable, commandOperands);
/* The label length is change only if we have a label */
if (labelFlag == START) {
(*labels)[(*labelCount) - ONE].length = lengthOfCommand;
}
IC += lengthOfCommand; /* Setting RAMIndex to the next free index*/
}
}
}
}
if (errorFlag == TRUE) /* If there was en error in one of the lines*/
{
return FALSE;
}
*DCF = DC;
ICF = IC;
for (index = ZERO; index < *labelCount; index++) /* Setting the new addresses for data labels*/
{
if (strcmp((*labels)[index].attributes[ZERO], "data") == ZERO) {
enterBaseAndOffset(&(*labels)[index], ICF + (*labels)[index].address);
}
}
for (index = ZERO; index < *DCF; index++) /* Copying all data from DCTable to the end of the RAM*/
{
RAM[IC + index] = DCTable[index];
}
return ICF;
}