-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfunctions.c
480 lines (385 loc) · 12.3 KB
/
functions.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
473
474
475
476
477
478
479
480
#include "assembler.h"
#include "external_vars.h"
#include "scanFunctions.h"
#include "functions.h"
/*This file include functions for all program use*/
/*********functions for main**********/
/* Function for creates the filename */
char* create_file_name(char* original, int type) {
char* modified = (char*)malloc(strlen(original) + 1); /* A memory will be assigned for the part after the "." */
char* tmp;
if (modified == NULL)/*if there is a problem at malloc*/
{
fprintf(stderr, "Problem at the allocation of memory.");
exit(ERROR);
}
strcpy(modified, original); /* Copying file name to a bigger string */
tmp = strchr(modified,'.');/* Cut .as end */
*tmp='\0';
/* add filetype extension */
switch (type)
{
case FILE_OBJECT:
strcat(modified, ".ob");
break;
case FILE_ENTRY:
strcat(modified, ".ent");
break;
case FILE_EXTERN:
strcat(modified, ".ext");
}
return modified;
}
/* Checks if it's empty line or line needs to be ignored (;) */
int ignore_line(char* line) {
line = skip_spaces(line);
if (*line == ';' || *line == '\0' || *line == '\n') {
return TRUE;
}
return FALSE;
}
/*This function check if was a error , and sign the errors's flag*/
int if_error() {
if (error != EMPTY_ERROR)
return 1;
else
return 0;
}
/* This function skips white space*/
char* skip_spaces(char* ch) {
if (ch == NULL)
return NULL;
while (isspace(*ch))/* Skip a white char */
ch++;
return ch;/* Return if isn't a white char */
}
/* Checking if it's end of line */
int end_of_line(char* line) {
return (line == NULL || *line == '\0' || *line == '\n');
}
/* Copies the next word from the line to the destination */
void copy_word(char* destination, char* line) {
int i = 0;
if (destination == NULL || line == NULL) /*If one of them is not defined*/
return;
while (i < MAX_INPUT && !isspace(line[i]) && line[i] != '\0') /* Copy the line to *dest */
{
destination[i] = line[i];
i++;
}
destination[i] = '\0'; /* Add ending to the string */
}
/* This function extracts bits */
unsigned int extract_bits(unsigned int word, int start, int end) {
unsigned int result;
int length = end - start + 1; /* Length bit-sequence */
unsigned int mask = (int)pow(2, length) - 1; /* Creating a '111...1' mask */
mask <<= start; /* Moving mask to the location of extraction */
result = word & mask; /* The bits are now in their original position, and the rest is 0's */
result >>= start; /* Moving the sequence to LSB */
return result;
}
/* Divite int to hex */
unsigned int int_to_hex(unsigned int word,int i) {
int j= word;
j= (word>>(8*i)) & 0xff;
return j;
}
/* Check if it's a label word */
boolean is_label(char* word, int colon) {
boolean has_digits = FALSE; /* If it's has a digits it's can be a command */
int word_len = strlen(word);
int i;
/* Check if the length isn't too short */
if (colon == TRUE) {
if (word == NULL || word_len < 2) /* If colon ,2 is the min lengths label*/
return FALSE;
}
if (colon && (word[word_len - 1] != ':'))
return FALSE; /* If colon , must be a colon at the end */
if (word_len > MAX_LABEL) {
if (colon) {
error = LABEL_TOO_LONG; /* Max length label is 32 */
}
return FALSE;
}
if (!isalpha(*word)) {
if (colon) {
error = LABEL_INVALID_FIRST_CHAR;/* First char must be a letter */
}
return FALSE;
}
if (colon) { /* Remove colon */
word[word_len - 1] = '\0';
word_len--;
}
/* Check if all the charcters are digits or letters */
for (i = 0; i < word_len; i++)
{
if (isdigit(word[i]))
has_digits = TRUE;
}
if (!has_digits) /* If there not digits it can't be a command */
{
if (find_command(word) != NO_MATCH) {
if (colon) {
error = LABEL_CANT_BE_COMMAND; /* Label can't be a command name */
}
return FALSE;
}
}
if (is_register(word)) /* Label can't be a register name */
{
if (colon) {
error = LABEL_CANT_BE_REGISTER;
}
return FALSE;
}
return TRUE; /* Its a label */
}
/* gets next word */
char* next_word(char* seq) {
if (seq == NULL)
return NULL;
while (!isspace(*seq) && !end_of_line(seq)) {/* Skip characters while aren't space or end of line */
seq++;
}
seq = skip_spaces(seq); /* Skip white space */
if (end_of_line(seq)) {
return NULL;
}
return seq;
}
/* Check if the word is register name */
boolean is_register(char* word) {
/* check if the first char is '$' and the register num between 0-31 */
if (word[0] == '$') {
int r = find_reg_number(word);
if(0<=r && r<32)
return TRUE;
else{
error = UNVALID_REG;
return FALSE;
}
}
else return FALSE;
}
/* Find the register num */
int find_reg_number(char* word) {
int number = -1;
if (word[0] == '$')
{
word++;
if(is_number(word)){/*divite to a digits*/
number = atoi(word);
}
}
return number;
}
/*Finds an index of a string in an strings array */
int find_index(char* word, const char* arr[], int n) {
int i;
for (i = 0; i < n; i++)
if (strcmp(word, arr[i]) == 0) {
return i;
}
return NO_MATCH;
}
/* Check if the word is a guidance */
int find_guidance(char* word) {
if (word == NULL || *word != '.') {
return NO_MATCH;
}/* Check in unum of guidance if the num there*/
return find_index(word, guidance, 6);
}
/* Check if the word is a command */
int find_command(char* word) {
int enum_index;
int word_len = strlen(word);
if (word_len > 4 || word_len < 2)/* A command must be between 2 and 4 chars */
return NO_MATCH;
else
enum_index = find_index(word, commands, NUMBER_OF_COMMANDS);
return enum_index;
}
/* Copies the next word to dest array */
char* next_list_word(char* dest, char* line) {
char* temp = dest;
if (end_of_line(line)) /* If it's empty line, copy an empty word */
{
dest[0] = '\0';
return NULL;
}
if (isspace(*line)) /* If the word start with white spaces , skip them */
line = skip_spaces(line);
if (*line == ',') /* if it's a ',' */
{
strcpy(dest, ",");
return ++line;
}
/* Copy the word until is a ',', white space or line end */
while (!end_of_line(line) && *line != ',' && !isspace(*line))
{
*temp = *line;
temp++;
line++;
}
*temp = '\0'; /* Add end to the word*/
return line;
}
/* Checks if it's a num ( can be with a +/- signs) */
boolean is_number(char* seq) {
if (end_of_line(seq))
return FALSE;
if (*seq == '+' || *seq == '-') {/*check if there is a +/- sign*/
seq++;
if (!isdigit(*seq++))/*check if isn't a digit*/
return FALSE;
}
/* Check until the end if are's a digits*/
while (!end_of_line(seq)) {
if (!isdigit(*seq++)) return FALSE;
}
return TRUE;
}
/* Copies next string to dest */
char* next_word_string(char* dest, char* line) {
char temp[MAX_INPUT];
line = next_list_word(dest, line);/* Creat function */
if (*dest != '"')
return line;
while (!end_of_line(line) && dest[strlen(dest) - 1] != '"')
{
line = next_list_word(temp, line);
if (line) strcat(dest, temp);
}
return line;
}
/* Checks if the sequence is a valid string (with "") */
boolean is_string(char* string) {
if (string == NULL)
return FALSE;
if (*string == '"') /* Start with " */
string++;
else
return FALSE;
while (*string && *string != '"') { /* loop until the end of string */
string++;
}
if (*string != '"') /* check the string end with " */
return FALSE;
string++;
if (*string != '\0') /* check that the string isn't continue after the '"' */
return FALSE;
return TRUE; /* return it's a string */
}
/* If it's a string add to data_image */
void add_string_to_data_image(char* str) {
while (!end_of_line(str))
{
data_image[dc++] = *str; /* Insert a char to data_image array */
str++;
}
data_image[dc++] = '\0';
}
/* Inserts this machine_code to instructions_image memory */
void add_to_instructions_image(unsigned int machine_code) {
instructions_image[ic] = machine_code;
}
/* print errors */
void print_error(int line_number) {
fprintf(stderr, "ERROR (line %d): ", line_number);
switch (error)
{
case INVALID_SYNTAX:
fprintf(stderr, "the first character after white characters must be a alphanumeric or a dot.\n");
break;
case LABEL_ALREADY_EXISTS:
fprintf(stderr, "this is a label that already exists.\n");
break;
case LABEL_TOO_LONG:
fprintf(stderr, "The length of the label is too long (MAX_LABEL_LENGTH: %d).\n", MAX_LABEL);
break;
case LABEL_INVALID_FIRST_CHAR:
fprintf(stderr, "a label must begin with a alphanumeric character.\n");
break;
case LABEL_CANT_BE_COMMAND:
fprintf(stderr, "a label cannot have a command name.\n");
break;
case LABEL_CANT_BE_REGISTER:
fprintf(stderr, "a label cannot have a register nam.\n");
break;
case INVALID_LABEL_LINE:
fprintf(stderr, "label must be followed by a command or guidance.\n");
break;
case NO_PARAMETER_AVAILABLE:
fprintf(stderr, "guidance must have parameters.\n");
break;
case GUIDANCE_INVALID_NUM_PARAMS:
fprintf(stderr, "illegal number of parameters for a guidance.\n");
break;
case DATA_COMMAS_IN_A_ROW:
fprintf(stderr, "problem using commas in a .data_image guidance.\n");
break;
case DATA_EXPECTED_NUM:
fprintf(stderr, ".data_image expecting a numeric parameter.\n");
break;
case DATA_EXPECTED_COMMA_AFTER_NUM:
fprintf(stderr, ".data_image expecting a comma after a numeric parameter.\n");
break;
case DATA_UNEXPECTED_COMMA:
fprintf(stderr, "it a unexpected comma after the last number at .data_image.\n");
break;
case STRING_TOO_MANY_OPERANDS:
fprintf(stderr, ".asciz must contain only one parameter.\n");
break;
case STRING_OPERAND_NOT_VALID:
fprintf(stderr, ".asciz operand is invalid.\n");
break;
case EXTERN_NO_LABEL:
fprintf(stderr, ".extern guidance must be followed by a label.\n");
break;
case EXTERN_INVALID_LABEL:
fprintf(stderr, ".extern guidance received an invalid label.\n");
break;
case EXTERN_TOO_MANY_OPERANDS:
fprintf(stderr, ".extern can only accept one operand that must be labeled.\n");
break;
case MISSING_SYNTAX:
fprintf(stderr, "invalid command or guidance.\n");
break;
case COMMAND_UNEXPECTED_CHAR:
fprintf(stderr, "invalid syntax of a command.\n");
break;
case COMMAND_TOO_MANY_OPERANDS:
fprintf(stderr, "this command can't get more than 2 operands.\n");
break;
case COMMAND_INVALID_NUMBER_OF_OPERANDS:
fprintf(stderr, "the amount of operands does not match the command requirements.\n");
break;
case COMMAND_INVALID_OPERANDS_METHODS:
fprintf(stderr, "operands' addressing methods do not match to the command requirement.\n");
break;
case ENTRY_LABEL_DOES_NOT_EXIST:
fprintf(stderr, ".entry must get an exsiting label.\n");
break;
case ENTRY_CANT_BE_EXTERN:
fprintf(stderr, ".entry can't get a label that use by external.\n");
break;
case COMMAND_LABEL_DOES_NOT_EXIST:
fprintf(stderr, "label doesn't exist.\n");
break;
case CANNOT_OPEN_FILE:
fprintf(stderr, "problem opening this file.\n");
break;
case UNVALID_REG:
fprintf(stderr, "the register number is invalid.\n");
break;
case NO_LABEL_FOUND:
fprintf(stderr, "there isn't label in file for this method.\n");
break;
case UNVALID_LABEL:
fprintf(stderr, "the syntax of this label is incorrect.\n");
break;
}
}