· 5 years ago · Oct 27, 2020, 05:08 AM
1/*H***********************************
2* FILENAME : Main.c
3* FILETYPE : C Source File
4*
5* DESCRIPTION :
6* Core for NBody Universe Simulator
7*
8* PUBLIC FUNCTIONS :
9* int FMCompressFile( FileHandle )
10* int FMDecompressFile( FileHandle )
11*
12* NOTES :
13* These classes are a part of the UniSim program;
14* See US-README.md for detailed description.
15*
16* Copyright SimonSaysITServices, 2020. All rights reserved.
17*
18* AUTHOR : Ben Gilchrist START DATE : 22, Jul 2020
19*
20- Stop printing on error line
21- File Extension
22-
23*H*/
24
25/* -------- Includes -------- */
26
27#include <stdio.h> /*For file & IO capabilities*/
28#include <stdlib.h> /*For memory management*/
29#include <errno.h> /*For error codes*/
30#include <unistd.h> /*For file existence checking*/
31#include <string.h> /*For string manipulation functions*/
32#include <stdbool.h> /*For access to Boolean values*/
33#include <sys/stat.h> /*For file data access*/
34#include <libgen.h> /*For parsing file paths*/
35#include "colour.h" /*For output colourisation*/
36#include "newSleep.h" /*For fractional time delays*/
37
38
39/* -------- Type Definitions -------- */
40
41/*Bracket Data Record*/
42typedef struct {
43 char type; /*Bracket type needed to complete the pair -- represented by a single opening bracket: angular ">", rounded ")", square "]" or curly "}"*/
44 unsigned int charNumber; /*Line opening bracket appears on*/
45 unsigned int matchLocation; /*Line closing bracket appears on*/
46} Record_t;
47
48/*Linked List Node*/
49typedef struct Node {
50 struct Node* prev;
51 Record_t data;
52 struct Node* next;
53} Node_t;
54
55/*Location Lookup Data Response*/
56typedef struct {
57 bool exists; /*Was there an existing record in the database*/
58 bool matching; /*If it was found in the matching table or the stack*/
59 Record_t record; /*Relevant record if exists*/
60} lookupResponse_t;
61
62/*Cursor Position Tuple*/
63typedef struct {
64 int lineIndex;
65 int charIndex;
66} cursorPosition_t;
67
68
69/* -------- Function Declarations -------- */
70
71void printBanner();
72void checkParams(int argc, char* argv[]);
73Node_t* push(char type, int charNumber, int* stackSize, Node_t* stackPointer, Node_t* basePointer);
74Node_t* pop(int matchLocation, int* stackSize, Node_t* stackPointer, int* matchCount, Record_t matchTable[]);
75char peek(const int* stackSize, Node_t* stackPointer);
76void empty(int* stackSize, Node_t* stackPointer);
77char* getFileContents(char** argv);
78int countLines(char* fileContents);
79char* colourise(char* target, char* colourCode);
80void clearForReprint(int numLines);
81void reprint(char* fileContents, int index, Record_t matchTable[], int matchCount, int stackSize, Node_t* stackPointer, Node_t* basePointer, bool mismatch);
82lookupResponse_t lookUp(int position, int matchCount, Record_t matchTable[], int stackSize, Node_t* basePointer);
83void padLine(int size);
84void clearLine(void);
85void cursorUL(int num);
86void summary(bool pass, int matchCount);
87int cursorLocator(char* fileContents, int programIndex);
88
89
90
91void printRecord(int index, Record_t record) {
92 printf("==============================================\nRecord 0x%x:\n", index);
93 printf(" Type: %c\n", record.type);
94 printf(" Address: %d\n", record.charNumber);
95 printf(" Match: %d\n==============================================\n\n", record.matchLocation);
96}
97
98
99/* -------- Main (Program Entry Point) -------- */
100
101int main(int argc, char* argv[]) {
102 //char* filename = calloc(strlen(argv[1]), sizeof(char)); /*Define file name to use for clarity*/
103 //memcpy(filename, argv[1], strlen(argv[1]) * sizeof(char));
104 puts("Loading...");
105 checkParams(argc, argv);
106 system("clear");
107 printBanner();
108 int lineIndex = 0;
109 char* input = getFileContents(argv); /*Stores the file contents as a string*/
110 newSleep(0.5);
111 int numLines = countLines(input); /*Stores the number of lines in the file*/
112 bool pass = true; /*Becomes false if any bracket mismatch occurs*/
113 Record_t matchTable[100];// = calloc(100, sizeof(char)); /*Store matches in here*/ //system("wc -c %s", FILENAME)/////////////////////
114 //Record_t** stack = calloc(100, sizeof(char)); /*Store unmatched brackets here*/
115 //Record_t stack[100]; /*Store unmatched brackets here*/
116 Node_t* stackPointer = NULL; /*Points to top of stack*/
117 Node_t* basePointer = NULL; /*Points to bottom of stack*/
118 int stackSize = -1; /*'Height' of the stack (count of contained Record_ts)*/
119 int matchCount = -1; /*Number of bracket matches - 1*/
120 puts("");
121 puts("==================================================\n");
122 //char* input = "int main(void) {puts(\"Test\"); return 0;}";
123 /******************* MAIN PROCESSING ***********************/
124 int index; /*Character index in file contents*/
125 for (index = 0; index <= strlen(input) - 1; index++) {
126 //printf("STACKSIZE: %d\n\n", stackSize);
127 if (input[index] == 0x0A) {
128 lineIndex++; /*Keep track of the line being processed*/
129 }
130 //puts("1");/////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 reprint(input, index, matchTable, matchCount, stackSize, stackPointer, basePointer, false); /*Reprint file with updated cursor & highlighting*/
132 if ((input[index] == 0x28) || (input[index] == 0x3C) || (input[index] == 0x5B) || (input[index] == 0x7B)) { /*If it's an open bracket*/
133 stackPointer = push(input[index], index, &stackSize, stackPointer, basePointer); /*Push it to the stack*/
134 //puts("2A");/////////////////////////////////////////////////////////////////////////////////////////////////////////////
135 } else if ((input[index] == 0x29) || (input[index] == 0x3E) || (input[index] == 0x5D) || (input[index] == 0x7D)) { /*If it's a closing bracket*/
136 //puts("2B");/////////////////////////////////////////////////////////////////////////////////////////////////////////////
137 char topValue = peek(&stackSize, stackPointer); /*Get the top value from the stack*/
138 if (input[index] == topValue) { /*If the top value matches the current bracket -- i.e. a matching pair is found*/
139 stackPointer = pop(index, &stackSize, stackPointer, &matchCount, matchTable); /*Pop the value from the stack, as it's now satisfied*/
140 //puts("3A");/////////////////////////////////////////////////////////////////////////////////////////////////////////////
141 } else if (topValue == 0x00) { /*If the stack is empty, there's an extra closing bracket.*/
142 pass = false;
143 clearForReprint(numLines); /*Clear printed output so it may be updated*/
144 reprint(input, (index + 1), matchTable, matchCount, stackSize, stackPointer, basePointer, pass); /*Reprint file with updated cursor & highlighting*/
145 //puts("3B");/////////////////////////////////////////////////////////////////////////////////////////////////////////////
146 /*For whichever type of bracket found, indicate which opening bracket was expected*/
147 if (input[index] == 0x29) {
148 printf("\n%sBracket mismatch! Closing bracket with no opening bracket. Expected '(' before ')'! (Line %d)%s\n", B_RED, (lineIndex + 1), RMF);
149 } else if (input[index] == 0x3E) {
150 printf("\n%sBracket mismatch! Closing bracket with no opening bracket. Expected '<' before '>'! (Line %d)%s\n", B_RED, (lineIndex + 1), RMF);
151 } else if (input[index] == 0x5D) {
152 printf("\n%sBracket mismatch! Closing bracket with no opening bracket. Expected '[' before ']'! (Line %d)%s\n", B_RED, (lineIndex + 1), RMF);
153 } else if (input[index] == 0x7D) {
154 printf("\n%sBracket mismatch! Closing bracket with no opening bracket. Expected '{' before '}'! (Line %d)%s\n", B_RED, (lineIndex + 1), RMF);
155 }
156 summary(pass, matchCount);
157 empty(&stackSize, stackPointer);
158 free(input);
159 exit(EXIT_SUCCESS);
160 } else { /*If the stack isn't empty and the brackets don't match, there's an incorrect bracket here*/
161 pass = false;
162 clearForReprint(numLines); /*Clear printed output so it may be updated*/
163 reprint(input, (index + 1), matchTable, matchCount, stackSize, stackPointer, basePointer, pass); /*Reprint file with updated cursor & highlighting*/
164 printf("\n%sBracket mismatch! Expected '%c' but instead got '%c'! (Line %d)%s\n", B_RED, topValue, input[index], (lineIndex + 1), RMF);
165 summary(pass, matchCount);
166 empty(&stackSize, stackPointer);
167 free(input);
168 exit(EXIT_SUCCESS);
169 }
170 }
171 //puts("");/////////////////////////////////////////////////////////////////////////////////////////////////////////
172 newSleep(0.4);
173 clearForReprint(numLines); /*Clear printed output so it may be updated*/
174 }
175 if (peek(&stackSize, stackPointer) != 0x00) { /*If the whole file has been processed & there's still a bracket on the stack, there's a bracket mismatch*/
176 pass = false;
177 clearForReprint(numLines); /*Clear printed output so it may be updated*/
178 reprint(input, (index + 1), matchTable, matchCount, stackSize, stackPointer, basePointer, pass); /*Reprint file with updated cursor & highlighting*/
179 printf("\n%sBracket mismatch! Opening bracket with no closing bracket. '%c' expected before end of code! (Line %d)%s\n", B_RED, peek(&stackSize, stackPointer), (lineIndex + 1), RMF);
180 summary(pass, matchCount);
181 empty(&stackSize, stackPointer);
182 free(input);
183 exit(EXIT_SUCCESS);
184 }
185 /******************* END MAIN PROCESSING ***********************/
186 // printf("%d\n", stackSize);
187 // for (index = 0; index <= stackSize; index++) {
188 // printRecord(stack, &stackSize);
189 // }
190 // for (int i = 0; i <= matchCount; i++) {
191 // printRecord(matchTable, &matchCount);
192 // }
193 reprint(input, (strlen(input) - 1), matchTable, matchCount, stackSize, stackPointer, basePointer, pass); /*Reprint file with updated cursor & highlighting*/
194 empty(&stackSize, stackPointer);
195 summary(pass, matchCount);
196 /*Clean up before exit*/
197 free(input);
198 return(EXIT_SUCCESS);
199}
200
201
202
203
204
205
206
207/* -------- Functions -------- */
208
209Node_t* push(char type, int charNumber, int* stackSize, Node_t* stackPointer, Node_t* basePointer) {
210 /**********************************
211 * NAME : addEntry
212 *
213 * DESCRIPTION : Adds a Record_t to the lookup table, setting the value at the supplied index.
214 *
215 * PARAMETERS (trailing underscore for differentiation from outer scope) :
216 * int key index to set
217 * int value value to assign to index
218 * char* input the input to search
219 * int* *stack array of binary integers representing where a replacement should be performed
220 *
221 * RETURNS :
222 * Void.
223 **********************************/
224 //puts("PUSH");
225 (*stackSize)++;
226 Node_t* newNode = calloc(1, sizeof(Node_t));
227 if (*stackSize == 0) {
228 basePointer = newNode;
229 newNode->prev = NULL;
230 } else {
231 newNode->prev = stackPointer;
232 stackPointer->next = newNode;
233 }
234 newNode->next = NULL;
235 newNode->data.charNumber = charNumber;
236 newNode->data.matchLocation = 0;
237 /*Set the type to look for to the matching close bracket*/
238 if (type == 0x28) {
239 newNode->data.type = 0x29;
240 } else if (type == 0x3C) {
241 newNode->data.type = 0x3E;
242 } else if (type == 0x5B) {
243 newNode->data.type = 0x5D;
244 } else if (type == 0x7B) {
245 newNode->data.type = 0x7D;
246 }
247 //printRecord(-1, newNode->data);
248 stackPointer = newNode;
249 //printRecord(stack, &stackSize);
250 //printRecord(stack[*stackSize]);
251 // stack[*stackSize]->type = type; /*Set bracket type*/
252 // puts("PUSH");
253 // stack[*stackSize]->charNumber = charNumber; /*Record_t the character coordinate of the bracket*/
254 // puts("PUSH");
255 // stack[*stackSize]->matchLocation = -1; /*Initialise closing bracket location to -1 (no match location)*/
256 // puts("PUSH");
257// Node_t* elem = basePointer;
258// for (int i = 0; i <= *stackSize; i++) {
259// printRecord((int)basePointer + i, elem->data);
260// elem++;
261// }
262 //puts("OUT");
263 return(stackPointer);
264}
265
266Node_t* pop(int matchLocation, int* stackSize, Node_t* stackPointer, int* matchCount, Record_t matchTable[]) {
267 /**********************************
268 * NAME : addEntry
269 *
270 * DESCRIPTION : Adds a Record_t to the lookup table, setting the value at the supplied index.
271 *
272 * PARAMETERS (trailing underscore for differentiation from outer scope) :
273 * int key index to set
274 * int value value to assign to index
275 * char* input the input to search
276 * int* *stack array of binary integers representing where a replacement should be performed
277 *
278 * RETURNS :
279 * Void.
280 **********************************/
281 //puts("POP");
282 Node_t* prev;
283 Node_t* stackPointerNew = NULL;
284 if (*stackSize > -1) {
285 stackPointer->data.matchLocation = matchLocation;
286 (*matchCount)++;
287 matchTable[*matchCount] = stackPointer->data;
288 (*stackSize)--;
289 if (*stackSize > -1) {
290 prev = stackPointer->prev;
291 free(stackPointer);
292 stackPointerNew = prev;
293 stackPointerNew->next = NULL;
294 } else {
295 free(stackPointer);
296 }
297 //puts("OUT");
298 return(stackPointerNew);
299 } else {
300 free(stackPointerNew);
301 //puts("OUT");
302 return(stackPointer);
303 }
304}
305
306char peek(const int* stackSize, Node_t* stackPointer) {
307 /**********************************
308 * NAME : addEntry
309 *
310 * DESCRIPTION : Adds a Record_t to the lookup table, setting the value at the supplied index.
311 *
312 * PARAMETERS (trailing underscore for differentiation from outer scope) :
313 * int key index to set
314 * int value value to assign to index
315 * char* input the input to search
316 * int* *stack array of binary integers representing where a replacement should be performed
317 *
318 * RETURNS :
319 * Void.
320 **********************************/
321 //puts("PEEK");
322 if (*stackSize <= -1) {
323 puts("OUT 0X00");
324 return(0x00);
325 }
326 //puts("OUT");
327 return(stackPointer->data.type);
328}
329
330void empty(int* stackSize, Node_t* stackPointer) {
331 /**********************************
332 * NAME : addEntry
333 *
334 * DESCRIPTION : Adds a Record_t to the lookup table, setting the value at the supplied index.
335 *
336 * PARAMETERS (trailing underscore for differentiation from outer scope) :
337 * int key index to set
338 * int value value to assign to index
339 * char* input the input to search
340 * int* *stack array of binary integers representing where a replacement should be performed
341 *
342 * RETURNS :
343 * Void.
344 **********************************/
345 //puts("EMPTY");
346 if (*stackSize > -1) {
347 int i;
348 Node_t* prev;
349 // for (i = 0; i <= *stackSize; i++) {
350 // memset(stack + i, 0x00, sizeof(Record_t));
351 // }
352 for (i = 0; i <= *stackSize; i++) { /*Delete every linked list node up until the last one, then delete the last one after*/
353 if (stackPointer->prev != NULL) {
354 prev = stackPointer->prev;
355 free(stackPointer);
356 stackPointer = prev;
357 } else {
358 free(stackPointer);
359 stackPointer = NULL;
360 }
361 }
362 *stackSize = -1;
363 }
364 //puts("OUT");
365}
366
367Node_t* linkedListByIndex(int index, Node_t* basePointer) {
368 int i;
369 Node_t* currentPointer;
370 currentPointer = basePointer;
371 for (i = 0; i < index; i++) {
372 currentPointer = currentPointer->next;
373 }
374 return(currentPointer);
375}
376
377lookupResponse_t lookUp(int position, int matchCount, Record_t matchTable[], int stackSize, Node_t* basePointer) {
378 lookupResponse_t response;
379 response.exists = false;
380 int recordIndex;
381 for (recordIndex = 0; recordIndex <= matchCount; recordIndex++) {
382 if ((matchTable[recordIndex].charNumber == position) || (matchTable[recordIndex].matchLocation == position)) {
383 response.record = matchTable[recordIndex];
384 response.matching = true;
385 response.exists = true;
386 }
387 }
388 if (!response.exists) {
389 for (recordIndex = 0; recordIndex <= stackSize; recordIndex++) {
390 Node_t* node = linkedListByIndex(recordIndex, basePointer);
391 if (node->data.charNumber == position) {
392 response.record = node->data;
393 response.matching = false;
394 response.exists = true;
395 }
396 }
397 }
398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
399 // if (response.exists) {
400 // puts("LOOKUP");
401 // printRecord(recordIndex, response.record);
402 // }
403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
404 return(response);
405}
406
407
408char* colourise(char* target, char* colourCode) {
409 /*******************************************************************
410 * NAME : colourise
411 *
412 * DESCRIPTION : Return the provided target string, prepended by the supplied colour/formatting ANSI escape string and appended by a clear formatting ANSI escape string.
413 * Colours/formats supplied string & returns modified value.
414 *
415 * PARAMETERS :
416 * char* target target string to format
417 * char* colourCode colour/formatting code to prepend to target
418 *
419 * RETURNS :
420 * char* tmp modified string with ANSI escape codes included
421 ********************************************************************/
422 char* tmp = calloc(30, sizeof(char));
423 //*tmp = "";
424 //*tmp = *colourCode;
425 strcpy(tmp, colourCode); /*Add formatting before word*/
426 strcat(tmp, target); /*Add word*/
427 strcat(tmp, RMF); /*Remove formatting after word*/
428 return(tmp);
429}
430
431void clearForReprint(int numLines) {
432 /*******************************************************************
433 * NAME : clearForReprint
434 *
435 * DESCRIPTION : Clears 3 above lines including current so graphics can be reprinted.
436 *
437 * PARAMETERS :
438 * Void.
439 *
440 * RETURNS :
441 * Void.
442 ********************************************************************/
443 int i;
444 for (i = 0; i <= (numLines + 1); i++) { /*Clear all lines printed from file, +1 for cursor indicator line*/
445 clearLine();
446 cursorUL(1);
447 }
448}
449
450int lineLen(int lineNum, char* fileContents) {
451 int length;
452 char* currChar;
453 currChar = fileContents;
454 int l;
455 for (l = 0; l <= lineNum; l++) { /*For each line in the file*/
456 length = 0;
457 while (*currChar != 0x0A) { /*If a newline is reached, finish counting for the line*/
458 currChar++;
459 length++;
460 }
461 }
462 return(length);
463}
464
465void reprint(char* fileContents, int index, Record_t matchTable[], int matchCount, int stackSize, Node_t* stackPointer, Node_t* basePointer, bool mismatch) {
466 //puts("CALL");/////////////////////////////////////////////////////////////////////////////////
467 ////////////////// IF MISMATCH, ONLY PRINT TO charTracker ON lineTracker -- STOP BEFORE END
468 //int l;
469 int c;
470 //int totalC = 0;
471 // for (l = 0; l <= numLines; l++) {
472 // if (l == lineTracker) {
473 // //print line
474 // //print cursor
475 // //cont.
476 // }
477 // //for (c = 0; c <= lineLen(l, fileContents); c++) {
478 //
479 // }
480 for (c = 0; c <= strlen(fileContents); c++) {
481 //puts("FOR");
482 //cursorPosition_t cursorLocation = cursorLocator(fileContents, c)
483 if (c == index) {
484 //puts("INDEX");
485 while (fileContents[c] != 0x0A) {
486 // puts("WHILE");
487 /*Continue to print the file until the end of the line*/
488 lookupResponse_t lookupResult = lookUp(c, matchCount, matchTable, stackSize, basePointer);
489 if (lookupResult.exists) {
490 //puts("EXISTS");
491 char* colour = NULL;
492 if (!lookupResult.matching) {
493 if (lookupResult.record.type == 0x29) {
494 colour = F_GREEN;
495 } else if (lookupResult.record.type == 0x3E) {
496 colour = F_RED;
497 } else if (lookupResult.record.type == 0x5D) {
498 colour = F_YELLOW;
499 } else if (lookupResult.record.type == 0x7D) {
500 colour = F_BLUE;
501 }
502 //puts("MATCH");
503 } else {
504 //puts("NMATCH");
505 if (lookupResult.record.type == 0x29) {
506 colour = B_GREEN;
507 } else if (lookupResult.record.type == 0x3E) {
508 colour = B_RED;
509 } else if (lookupResult.record.type == 0x5D) {
510 colour = B_YELLOW;
511 } else if (lookupResult.record.type == 0x7D) {
512 colour = B_BLUE;
513 }
514 }
515 char* toBeFormatted = calloc(30, sizeof(char));
516 strncat(toBeFormatted, (fileContents + c), 1);
517 printf("%s", colourise(toBeFormatted, colour));
518 } else {
519 //puts("NEXISTS");
520 printf("%c", fileContents[c]);
521 }
522 c++;
523 }
524 puts(""); padLine(cursorLocator(fileContents, (index - 1))); puts("^\n"); /*Print cursor to show which line is being processed*/
525 } else {
526 //puts("NINDEX");
527 lookupResponse_t lookupResult = lookUp(c, matchCount, matchTable, stackSize, basePointer);
528 //puts("NLOOKUP");
529 if (lookupResult.exists) {
530 //puts("EXISTS");
531 //sleep(5);
532 char* colour = NULL;
533 if (!lookupResult.matching) {
534 //puts("MATCH");
535 if (lookupResult.record.type == 0x29) {
536 colour = F_GREEN;
537 } else if (lookupResult.record.type == 0x3E) {
538 colour = F_RED;
539 } else if (lookupResult.record.type == 0x5D) {
540 colour = F_YELLOW;
541 } else if (lookupResult.record.type == 0x7D) {
542 colour = F_BLUE;
543 }
544 } else {
545 //puts("NMATCH");
546 if (lookupResult.record.type == 0x29) {
547 colour = B_GREEN;
548 } else if (lookupResult.record.type == 0x3E) {
549 colour = B_RED;
550 } else if (lookupResult.record.type == 0x5D) {
551 colour = B_YELLOW;
552 } else if (lookupResult.record.type == 0x7D) {
553 colour = B_BLUE;
554 }
555 }
556 //sleep(5);
557 char* toBeFormatted = calloc(30, sizeof(char));
558 strncat(toBeFormatted, (fileContents + c), 1);
559 printf("%s", colourise(toBeFormatted, colour));
560 } else {
561 //puts("NEXISTS");
562 printf("%c", fileContents[c]);///////////////////////////////////////FIX: UNCOMMENT
563 }
564 }
565 }
566 //puts("OUT");/////////////////////////////////////////////////////////////////////////////////
567 //sleep(5);
568}
569
570int cursorLocator(char* fileContents, int programIndex) {
571 int totalCharIndex;
572 //cursorPosition_t response;
573 int lineCount = -1;
574 int lineCharCount = -1;
575 for (totalCharIndex = 0; totalCharIndex <= programIndex; totalCharIndex++) {
576 if (fileContents[totalCharIndex] == 0x0A) {
577 lineCount++;
578 }
579 if (fileContents[(totalCharIndex - 1)] == 0x0A) {
580 lineCharCount = 0;
581 } else {
582 lineCharCount++;
583 }
584 }
585 //response.lineIndex = lineCharCount;
586 //response.charIndex = lineCount;
587 return(lineCharCount);
588}
589
590
591void padLine(int size) {
592 /*******************************************************************
593 * NAME : padLine
594 *
595 * DESCRIPTION : Pads line using a specified number of spaces. Used for graphics formatting.
596 *
597 * PARAMETERS :
598 * int size number of spaces to use
599 *
600 * RETURNS :
601 * Void.
602 ********************************************************************/
603 for (int n = 0; n <= (size - 1); n++) { /*Print a space $size$ times*/
604 printf("%c", 0x20); /*Print space*/
605 }
606}
607
608void clearLine(void) {
609 /*******************************************************************
610 * NAME : cleaLine
611 *
612 * DESCRIPTION : Clears line and performs carriage return.
613 *
614 * PARAMETERS :
615 * Void.
616 *
617 * RETURNS :
618 * Void.
619 *
620 * NOTES :
621 * Uses ANSI escape code '\033[2K' to clear line
622 ********************************************************************/
623 printf("\033[2K\r");
624}
625
626void cursorUL(int num) {
627 /*******************************************************************
628 * NAME : cursorUL
629 *
630 * DESCRIPTION : Moves the cursor up a line and specified number of times.
631 *
632 * PARAMETERS :
633 * int num number of lines to move up/
634 *
635 * RETURNS :
636 * Void.
637 *
638 * NOTES :
639 * Uses ANSI escape code '\033[#A' to move cursor up # lines
640 ********************************************************************/
641 printf("\033[%dA", num);
642}
643
644char* getFileContents(char** argv) {
645 int size;
646 int status;
647 FILE* filePointer = NULL;
648 char* fileContents = NULL;
649 char* filename = argv[1];
650 bool warning = false;
651 /*In order to create a file buffer of the appropriate size, we first need the file size*/
652 struct stat fileData;
653 status = stat(filename, &fileData); /*Load file data into $fileData$ struct*/
654 if (status == 0) {
655 size = fileData.st_size; /*Get file size in bytes*/
656 } else {
657 printf("%sERROR:%s Failed to get size of file '%s'.%s\n", UL_F_RED, F_RED, basename(filename), RMF);
658 exit(EXIT_FAILURE);
659 }
660 printf("%s[i]%s File: %s\n", F_YELLOW, RMF, filename);
661 printf("%s[i]%s File Size: %d Bytes\n", F_YELLOW, RMF, size);
662 if (size > 5000) {
663 warning = true;
664 printf("%s[!]%s File size is over 5000 Bytes! This may take a while!\n", F_RED, RMF);
665 }
666 fileContents = calloc(((size / sizeof(char)) + 1), sizeof(char)); /*Allocate memory of the size of the file to store the file contents*/
667 if (fileContents == NULL) { /*Memory allocation failed*/
668 printf("%sERROR:%s Failed to allocate memory of size %d B, when loading file. File may be too large.%s\n", UL_F_RED, F_RED, size, RMF);
669 exit(ENOMEM);
670 }
671 filePointer = fopen(filename, "r");
672 size_t readSize = fread(fileContents, sizeof(char), (size / sizeof(char)), filePointer); /*Read file contents into buffer*/
673 fclose(filePointer);
674 if (readSize != size) { /*If file was not completely read*/
675 if (feof(filePointer)) { /*If EOF was reached prematurely*/
676 printf("%sERROR:%s Unexpected EOF when reading file '%s'.%s\n", UL_F_RED, F_RED, basename(filename), RMF);
677 exit(EXIT_FAILURE);
678 } else { /*Some other error occurred*/
679 printf("%sERROR:%s Error reading file '%s'.%s\n", UL_F_RED, F_RED, basename(filename), RMF);
680 exit(EXIT_FAILURE);
681 }
682 }
683 //strcat(fileContents, "\0");
684 if (countLines(fileContents) > 47) {
685 warning = true;
686 printf("%s[!]%s This file might have more lines than your terminal.\n This may cause processing display issues, but the program will still give correct output.\n To fix this issue, reduce your font size so that the whole file may be comfortably displayed in the window.\n", F_RED, RMF);
687 }
688 if (warning) { /*Give time for the user to read the warning messages*/
689 sleep(7);
690 }
691 return(fileContents); /*Return the file contents to work with*/
692}
693
694int countLines(char* fileContents) {
695 int lineCount = 0;
696 int i;
697 for (i = 0; i <= strlen(fileContents); i++) { /*For each cahr in file contents*/
698 if (fileContents[i] == 0x0A) { /*If char is newline*/
699 lineCount++; /*Increment counter*/
700 }
701 }
702 return(lineCount);
703}
704
705void summary(bool pass, int matchCount) {
706 puts("\n==================================================");
707 if (pass) {
708 printf("%s[+]%s All brackets match.\n", F_GREEN, RMF);
709 } else {
710 printf("%s[-]%s Bracket mismatch.\n", F_RED, RMF);
711 }
712 printf("%s[i]%s %d pairs found.\n", F_YELLOW, RMF, (matchCount + 1));
713}
714
715void showHelp(void) {
716 printf("\nUsage:\n ./BraCheck <filename>\n\n");
717}
718
719void checkParams(int argc, char* argv[]) {
720 FILE* file = NULL;
721 char* filename = argv[1];
722 int exitStatus = 0;
723 puts(""); /*Newline for prettier output*/
724 if (argc != 2) { /*Check the number of supplied arguments*/
725 printf("%sERROR:%s Incorrect number of arguments! Expected 1 but instead got %d.%s\n", UL_F_RED, F_RED, (argc - 1), RMF);
726 exitStatus = EINVAL; /*Invalid argument*/
727 } else if (access(filename, F_OK) == -1) { /*Check if supplied file exists*/
728 printf("%sERROR:%s File '%s' does not exist! Please supply a valid filename/filepath.%s\n", UL_F_RED, F_RED, basename(filename), RMF);
729 exitStatus = ENOENT; /*No such file or directory*/
730 } else if (access(filename, R_OK) == -1) { /*Check if we have permission to read the file*/
731 printf("%sERROR:%s Don't have permission to read file '%s'!%s\n", UL_F_RED, F_RED, basename(filename), RMF);
732 exitStatus = EPERM; /*Don't have permission*/
733 }
734 /*Check if supplied file to check exists*/
735 //file = fopen(filename, "r");
736 //fprintf(stderr, "%d\n", access(filename, F_OK));
737 if (exitStatus != 0) { /*Display help & usage to user as parameters were invalid*/
738 showHelp();
739 printf("\a");
740 free(file); /*Cleanup*/
741 }
742 if (exitStatus != 0) { /*If an error occurred, exit*/
743 exit(exitStatus);
744 }
745}
746
747void printBanner(void) {
748 unsigned char bannerTxt[] = {
749 0x20, 0x5F, 0x5F, 0x5F, 0x5F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
750 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5F, 0x5F, 0x5F, 0x5F, 0x20, 0x5F,
751 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
752 0x20, 0x20, 0x20, 0x5F, 0x20, 0x20, 0x20, 0x20, 0x0A, 0x7C, 0x20, 0x5F,
753 0x5F, 0x20, 0x29, 0x20, 0x5F, 0x20, 0x5F, 0x5F, 0x20, 0x5F, 0x5F, 0x20,
754 0x5F, 0x20, 0x2F, 0x20, 0x5F, 0x5F, 0x5F, 0x7C, 0x20, 0x7C, 0x5F, 0x5F,
755 0x20, 0x20, 0x20, 0x5F, 0x5F, 0x5F, 0x20, 0x20, 0x5F, 0x5F, 0x5F, 0x7C,
756 0x20, 0x7C, 0x20, 0x5F, 0x5F, 0x0A, 0x7C, 0x20, 0x20, 0x5F, 0x20, 0x5C,
757 0x7C, 0x20, 0x27, 0x5F, 0x5F, 0x2F, 0x20, 0x5F, 0x60, 0x20, 0x7C, 0x20,
758 0x7C, 0x20, 0x20, 0x20, 0x7C, 0x20, 0x27, 0x5F, 0x20, 0x5C, 0x20, 0x2F,
759 0x20, 0x5F, 0x20, 0x5C, 0x2F, 0x20, 0x5F, 0x5F, 0x7C, 0x20, 0x7C, 0x2F,
760 0x20, 0x2F, 0x0A, 0x7C, 0x20, 0x7C, 0x5F, 0x29, 0x20, 0x7C, 0x20, 0x7C,
761 0x20, 0x7C, 0x20, 0x28, 0x5F, 0x7C, 0x20, 0x7C, 0x20, 0x7C, 0x5F, 0x5F,
762 0x5F, 0x7C, 0x20, 0x7C, 0x20, 0x7C, 0x20, 0x7C, 0x20, 0x20, 0x5F, 0x5F,
763 0x2F, 0x20, 0x28, 0x5F, 0x5F, 0x7C, 0x20, 0x20, 0x20, 0x3C, 0x20, 0x0A,
764 0x7C, 0x5F, 0x5F, 0x5F, 0x5F, 0x2F, 0x7C, 0x5F, 0x7C, 0x20, 0x20, 0x5C,
765 0x5F, 0x5F, 0x2C, 0x5F, 0x7C, 0x5C, 0x5F, 0x5F, 0x5F, 0x5F, 0x7C, 0x5F,
766 0x7C, 0x20, 0x7C, 0x5F, 0x7C, 0x5C, 0x5F, 0x5F, 0x5F, 0x7C, 0x5C, 0x5F,
767 0x5F, 0x5F, 0x7C, 0x5F, 0x7C, 0x5C, 0x5F, 0x5C, 0x0A, 0x0A, 0x09, 0x20,
768 0x20, 0x2D, 0x3D, 0x20, 0x5B, 0x20, 0x42, 0x72, 0x61, 0x63, 0x6B, 0x65,
769 0x74, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x65, 0x72, 0x20, 0x5D, 0x20,
770 0x3D, 0x2D, 0x0A, 0x09, 0x20, 0x20, 0x2D, 0x3D, 0x20, 0x5B, 0x20, 0x42,
771 0x65, 0x6E, 0x20, 0x47, 0x69, 0x6C, 0x63, 0x68, 0x72, 0x69, 0x73, 0x74,
772 0x20, 0x20, 0x20, 0x5D, 0x20, 0x3D, 0x2D, 0x0A, 0x20, 0x20, 0x20, 0x20,
773 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
774 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
775 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
776 0x20, 0x20, 0x20, 0x20, 0x0A, 0x00
777 };
778 printf("%s%s%s\n", F_GREEN, bannerTxt, RMF);
779}
780