rendered paste body#include "life.h"#include "lifeDisplay.h"#include <stdio.h>#include <stdbool.h>#include <unistd.h>#include <time.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <math.h>static void programUsage(void); //Display how to use this program.static void programUsage() { fprintf(stderr, "\nUsage : life [OPTION...] FILENAME\n"); fprintf(stderr, "Launching a Game Of Life initialized via FILENAME.\n\n"); fprintf(stderr, "Optional options :\n"); fprintf(stderr, "==================\n"); fprintf(stderr, "-b Curses not used, life displayed on stdout.\n"); fprintf(stderr, "-g <nGens> Life calculates <nGens> generations.\n"); fprintf(stderr, " (It runs during <nGens> + 1 generations.)\n"); fprintf(stderr, "-s <msecs> Life waits <msecs> between generations.\n"); fprintf(stderr, "-o <fstring> life outputs everything in <fstring>.\n"); fprintf(stderr, " <fstring> is a filename or equals to '-'.\n"); fprintf(stderr, " '-' makes life writing in stdout.\n"); fprintf(stderr, " <fstring> can contain %%lu in order to\n"); fprintf(stderr, " generate enumerated files with\n"); fprintf(stderr, " different names.\n\n"); fprintf(stderr, "Notes :\n"); fprintf(stderr, "=======\n"); fprintf(stderr, "-b -o - is illegal.\n\n"); return;}static char* generateOutputName(const char* outputName, char* finalOutputName, const char* luPosition, const long int i) { long int ilength = 1; //Number of characters needed to write i. for (int j = 1; i >= pow(10,j); j++, ilength++) { } //Checking the format of outputName : bla%lubla, %lublabla or blabla%lu. bool beginExists = false, endExists = false; char* beginOutputName = NULL, *endOutputName = NULL; if (outputName != luPosition) { beginExists = true; } if (luPosition != (outputName + strlen(outputName) - 1 - 2)) { endExists = true; } if (beginExists) { beginOutputName = (char*)malloc(sizeof(*beginOutputName) * (luPosition - outputName + 1)); strncpy(beginOutputName, outputName, sizeof(*beginOutputName) * (luPosition - outputName)); } if (endExists) { endOutputName = (char*)malloc(sizeof(*endOutputName) * (strlen(outputName) - (luPosition - outputName) - 3 + 1)); strncpy(endOutputName, luPosition + 3, sizeof(*endOutputName) * (strlen(outputName) - (luPosition - outputName) - 3)); } char* numberPart = (char*)malloc(sizeof(*numberPart) * (ilength + 1)); sprintf(numberPart, "%ld", i); char* tempName = NULL; if (beginExists && endExists) { tempName = (char*)realloc(finalOutputName, sizeof(*finalOutputName) * (strlen(beginOutputName) + strlen(numberPart) + strlen(endOutputName) + 1)); } else if (!beginExists && endExists) { tempName = (char*)realloc(finalOutputName, sizeof(*finalOutputName) * (strlen(numberPart) + strlen(endOutputName) + 1)); } else if (beginExists && !endExists) { tempName = (char*)realloc(finalOutputName, sizeof(*finalOutputName) * (strlen(beginOutputName) + strlen(numberPart) + 1)); } finalOutputName = tempName; finalOutputName[0] = '\0'; if (beginExists) { strcat(finalOutputName, beginOutputName); free(beginOutputName); } strcat(finalOutputName, numberPart); free(numberPart); if (endExists) { strcat(finalOutputName, endOutputName); free(endOutputName); } return finalOutputName;}int main(int argc, char** argv) { //xflag tells us if 'x' option has been found or not. bool bflag = false, gflag = false, sflag = false, oflag = false; int nGens = 0, tempTime = 0; char ch; int sscanfReturn; char* outputName = NULL; while ((ch = getopt(argc, argv, "bg:s:o:")) != -1) { switch(ch) { case 'b': bflag = true; break; case 'g': gflag = true; sscanfReturn = sscanf(optarg, "%d", &nGens); errno = 0; if (nGens < 0 || sscanfReturn < 1 || sscanfReturn == EOF || errno) { if (errno) { perror("\nAn error has occured parsing -g option."); } programUsage(); free(outputName); outputName = NULL; return 1; } break; case 's': sflag = true; sscanfReturn = sscanf(optarg, "%d", &tempTime); errno = 0; if (tempTime < 0 || sscanfReturn < 1 || sscanfReturn == EOF || errno) { if (errno) { perror("\nAn error has occured parsing -s option."); } programUsage(); free(outputName); outputName = NULL; return 1; } break; case 'o': oflag = true; outputName = (char*)malloc(sizeof(*outputName) * (strlen(optarg) + 1)); if (!outputName) { fprintf(stderr, "\nError while allocating memory.\n"); return 1; } strcpy(outputName, optarg); break; case '?': default: programUsage(); free(outputName); outputName = NULL; return 1; } } if (((argc - optind) != 1) || (bflag && oflag && !strcmp(outputName, "-"))) { //There isn't only one string left specifying FILENAME or -b -o - entered. programUsage(); free(outputName); outputName = NULL; return 1; } const char* initFilePath = argv[optind]; errno = 0; FILE* initFile = fopen(initFilePath, "r"); if (!initFile) { perror("\nAn error has occured opening the initialization file."); free(outputName); outputName = NULL; return 1; } World* world = worldReadNew(initFile); if (!world) { fprintf(stderr, "\nAn error has occured initializing the world.\n"); free(outputName); outputName = NULL; return 1; } errno = 0; if (fclose(initFile) == EOF) { perror("\nAn error has occured closing the initialization file."); free(outputName); outputName = NULL; worldDelete(world); return 1; } LifeDisplay* lifed = NULL; if (!bflag && !(oflag && !strcmp(outputName, "-"))) { //Ncurses must be used. lifed = lifedNew(world); if (!lifed) { fprintf(stderr, "\nAn error has occured initializing Ncurses mode.\n"); free(outputName); outputName = NULL; worldDelete(world); return 1; } } struct timespec waitTime; if (tempTime >= 1000) { waitTime.tv_sec = tempTime / 1000; waitTime.tv_nsec = (tempTime % 1000) * 1000000; } else { waitTime.tv_sec = 0; waitTime.tv_nsec = tempTime * 1000000; } bool programIsInfinite = nGens == 0 ? true : false; for(long int i = 0; programIsInfinite || i <= nGens; i++) { //i can be equal to nGens in order to really calculate nGens generations. //Selection of the display method. if (lifed) { lifedDisplay(lifed); } else if (bflag || (oflag && !strcmp(outputName, "-"))) { worldWrite(world, stdout); } //Output to real files, or not. FILE* outputFile = NULL; if (oflag && strcmp(outputName, "-")) { char* finalOutputName = (char*)malloc(sizeof(*finalOutputName) * (strlen(outputName) + 1)); for(size_t i = 0; i < strlen(outputName) + 1; i++) { finalOutputName[i] = '\0'; } char* luPosition = strstr(outputName, "%lu"); if (luPosition) { //User wants to generate numbered output files. finalOutputName = generateOutputName(outputName, finalOutputName, luPosition, i); } errno = 0; outputFile = fopen(finalOutputName, "w"); if (!outputFile) { perror("\nAn error has occured opening the output file."); free(outputName); free(finalOutputName); finalOutputName = NULL; outputName = NULL; worldDelete(world); if (lifed) { lifedDelete(lifed); } return 1; } if (worldWrite(world, outputFile)) { fprintf(stderr, "\nAn error has occured while writing output file.\n"); free(outputName); free(finalOutputName); finalOutputName = NULL; outputName = NULL; worldDelete(world); if (lifed) { lifedDelete(lifed); } return 1; } errno = 0; if (fclose(outputFile) == EOF) { perror("\nAn error has occured closing the initialization file."); free(outputName); free(finalOutputName); finalOutputName = NULL; outputName = NULL; worldDelete(world); if (lifed) { lifedDelete(lifed); } return 1; } free(finalOutputName); finalOutputName = NULL; if (tempTime) { nanosleep(&waitTime, NULL); } worldNextGeneration(world); } } worldDelete(world); if (lifed) { lifedDelete(lifed); } free(outputName); outputName = NULL; return 0;}