#include "configops.h" #include "StandardConstants.h" #include "StringUtils.h" /* Name: clearConfigData Process: frees dynamically allocated config data structure if it has not already been freed Function Input/Parameters: pointer to config data structure (ConfigDataType *) Function Output/Parameters: none Function Output/Returned: NULL (ConfigDataType *) Device Input/Device: none Device Output/Device: none Dependencies: free */ ConfigDataType *clearConfigData(ConfigDataType *configData) { // initialize function and variables // check that config data pointer is not null if(configData != NULL) { // free data structure memory // fct: free free(configData); // set config pointer to NULL configData = NULL; } // set config data pointer to null return NULL; } /* Name: configCodeToString Process: utility fct converts configuration code numbers to string they represent Function Input/Parameters: configuration code (int) Function Output/Parameters: resulting output string (char *) Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: copyString */ void configCodeToString(int code, char *outString) { // define array with eight items, and short (10) lengths char displayStrings[8][10] = {"SJF-N","SRTF-P","FCFS-P","RR-P", "FCFS-N","Monitor", "File", "Both"}; // copy string to return parameter // fct: copyString copyString(outString, displayStrings[code]); // void function, no return. } /* Name: displayConfigData Process: screen dump/display of all config data Function Input/Parameters: pointer to config data structure (ConfigDataType *) Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Monitor: displayed as spec'd Dependencies: configCodeToString, printf */ void displayConfigData(ConfigDataType *configData) { // initialize function and variables char displayString[STD_STR_LEN]; // print lines of display for all member values // fct: printf, codeToString printf("Config File Display\n"); printf("-------------------\n"); printf("Version : %3.2f\n", configData->version); printf("Program File Name : %s\n", configData->metaDataFileName); configCodeToString(configData->cpuSchedCode, displayString); printf("CPU Schedule Selection: %s\n", displayString); printf("Quantum Time : %d\n", configData->quantumCycles); printf("Memory Display : "); if(configData->memDisplay) { printf("On\n"); } else { printf("Off\n"); } printf("Memory Available : %d\n", configData->memAvailable); printf("Process Cycle Rate : %d\n", configData->procCycleRate); printf("I/O Cycle Rate : %d\n", configData->ioCycleRate); configCodeToString(configData->logToCode, displayString); printf("Log to Selection : %s\n", displayString); printf("Log File Name : %s\n\n", configData->logToFileName); // void function, no return. } /* Name: getConfigData Process: driver function for capturing config data from config file Function Input/Parameters: file name (const char *) Function Output/Parameters: pointer to config data pointer (ConfigDataType **) end/result state message pointer (char *) Function Output/Returned: Boolean result of data access operation (bool) Device Input/File: config data uploaded Device Output/Device: none Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose, malloc, free, stripTrailingSpaces, getDataLineCode, fscanf, strToLowerCase, valueInRange, getCpuSchedCode, getLogToCode */ bool getConfigData(const char *fileName, ConfigDataType **configData, char *endStateMsg) { // initialize function and variables // set constant number of data lines const int NUM_DATA_LINES = 10; // set read only constant const char READ_ONLY_FLAG[] = "r"; // create pointer for data input ConfigDataType *tempData; // declare other variables FILE *fileAccessPtr; char dataBuffer[MAX_STR_LEN], lowerCaseDataBuffer[MAX_STR_LEN]; int intData, dataLineCode, lineCtr = 0; double doubleData; // set endStateMsg to success // fct: copyString char testMsg[] = "Configuration file upload successful"; copyString(endStateMsg, testMsg); // initialize config data pointer in case of return error *configData = NULL; // open file // fct: fopen fileAccessPtr = fopen(fileName, READ_ONLY_FLAG); // check for file open failure if(fileAccessPtr == NULL) { // set end state message to config file access error // fct: copyString char testMsg[] = "Configuration file access error"; copyString(endStateMsg, testMsg); // return file access error return false; } // get first line, check for failure // fct: getStringToDelimiter, compareString if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer) || compareString(dataBuffer, "Start Simulator Configuration File") != 0) { // close file access // fct: fclose fclose(fileAccessPtr); // set end state message to corrupt leader line error // fct: copyString copyString(endStateMsg, "Corrupt configuration leader line error"); // return corrupt file data return false; } // create temporary pointer to configuration data structure // fct: malloc tempData = (ConfigDataType *) malloc(sizeof(ConfigDataType)); // loop to end of config data items while(lineCtr < NUM_DATA_LINES) { // get line leader, check for failure // fct: getStringToDelimiter if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer)) { // free temp struct memory // fct: free free(tempData); // close file access // fct: fclose fclose(fileAccessPtr); // set end state message to line capture failure // fct: copyString copyString(endStateMsg, "Configuration data leader line capture error"); // return incomplete file error return false; } // strip trailing spaces of config leader lines // for use in other fcts // fct: stripTrailingSpaces stripTrailingSpaces(dataBuffer); // find correct data line code number from string // fct: getDataLineCode dataLineCode = getDataLineCode(dataBuffer); // check for data line found if(dataLineCode != CFG_CORRUPT_PROMPT_ERR) { // get data value // check for version number (double value) if(dataLineCode == CFG_VERSION_CODE) { // get version number // fct: fscanf fscanf(fileAccessPtr, "%lf", &doubleData); } // otherwise, check for metaData, fileNames, // CPU Scheduling names, or memory display setting (strings) else if(dataLineCode == CFG_MD_FILE_NAME_CODE || dataLineCode == CFG_LOG_FILE_NAME_CODE || dataLineCode == CFG_CPU_SCHED_CODE || dataLineCode == CFG_LOG_TO_CODE || dataLineCode == CFG_MEM_DISPLAY_CODE) { // get string input // fct: fscanf fscanf(fileAccessPtr, "%s", dataBuffer); // set string to lower case for testing in valueInRange // fct: strToLowerCase strToLowerCase(lowerCaseDataBuffer, dataBuffer); } // otherwise, assume integer data else { // get integer input // fct: fscanf fscanf(fileAccessPtr, "%d", &intData); } // check for data value in range // fct: valueInRange if(valueInRange(dataLineCode, intData, doubleData, lowerCaseDataBuffer)) { // assign to data pointer depending on config item // (all config line possibilities) // fct: copyString, getCpuSchedCode, // compareString, getLogToCode, as needed switch(dataLineCode) { case CFG_VERSION_CODE: tempData->version = doubleData; break; case CFG_MD_FILE_NAME_CODE: copyString(tempData->metaDataFileName, dataBuffer); break; case CFG_CPU_SCHED_CODE: tempData->cpuSchedCode = getCpuSchedCode(lowerCaseDataBuffer); break; case CFG_QUANT_CYCLES_CODE: tempData->quantumCycles = intData; break; case CFG_MEM_DISPLAY_CODE: tempData->memDisplay = compareString(lowerCaseDataBuffer, "on") == 0; break; case CFG_MEM_AVAILABLE_CODE: tempData->memAvailable = intData; break; case CFG_PROC_CYCLES_CODE: tempData->procCycleRate = intData; break; case CFG_IO_CYCLES_CODE: tempData->ioCycleRate = intData; break; case CFG_LOG_TO_CODE: tempData->logToCode = getLogToCode(lowerCaseDataBuffer); break; case CFG_LOG_FILE_NAME_CODE: copyString(tempData->logToFileName, dataBuffer); break; } } // otherwise, assume data value not in range else { // free temp struct memory // fct: free free(tempData); // close file access // fct: fclose fclose(fileAccessPtr); // set end state message to configuration data out of range // fct: copyString copyString(endStateMsg, "Configuration item out of range"); // return data out of range return false; } } // otherwise, check for data line not found else { // free temp struct memory // fct: free free(tempData); // close file access // fct: fclose fclose(fileAccessPtr); // set end state message to configuration corrupt prompt error // fct: copyString copyString(endStateMsg, "Corrupted configuration prompt"); // return corrupt config file code return false; } // increment line counter lineCtr = lineCtr + 1; } // end loop to end of config data items // acquire end of sim config string // fct: getStringToDelimiter, compareString if(!getStringToDelimiter(fileAccessPtr, PERIOD, dataBuffer) || compareString(dataBuffer, "End Simulator Configuration File") != 0) { // free temp struct memory // fct: free free(tempData); // close file access // fct: fclose fclose(fileAccessPtr); // set end state message to corrupt configuration end line // fct: copyString copyString(endStateMsg, "Configuration end line capture error"); // return corrupt file data return false; } // test for "file only" output so memory diagnostics do not display tempData->memDisplay = tempData->memDisplay && tempData->logToCode != LOGTO_FILE_CODE; // assign temp ptr to parameter return ptr *configData = tempData; // close file access // fct: fclose fclose(fileAccessPtr); // return no error code return true; } /* Name: getCpuSchedCode Process: converts cpu schedule string to code (all scheduling possibilities) Function Input/Parameters: lower case code string (const char *) Function Output/Parameters: none Function Output/Returned: cpu schedule code (ConfigDataCodes) Device Input/Device: none Device Output/Device: none Dependencies: compareString */ ConfigDataCodes getCpuSchedCode(const char *lowerCaseCodeStr) { // iniitalize function and variables // set default return to FCFS-N ConfigDataCodes returnVal = CPU_SCHED_FCFS_N_CODE; // check for SJF-N // fct: compareString if(compareString(lowerCaseCodeStr, "sjf-n") == 0) { // set SJF-N code returnVal = CPU_SCHED_SJF_N_CODE; } // check for SRTF-P // fct: compareString if(compareString(lowerCaseCodeStr, "srtf-p") == 0) { // set SRTF-P code returnVal = CPU_SCHED_SRTF_P_CODE; } // check for FCFS-P // fct: compareString if(compareString(lowerCaseCodeStr, "fcfs-p") == 0) { // set FCFS-P code returnVal = CPU_SCHED_FCFS_P_CODE; } // check for RR-P // fct: compareString if(compareString(lowerCaseCodeStr, "rr-p") == 0) { // set RR-P code returnVal = CPU_SCHED_RR_P_CODE; } return returnVal; } /* Name: getDataLineCode Process: converts leader line string to configuration code value (processes all config file leader lines) Function Input/Parameters: config leader line string (const char *) Function Output/Parameters: none Function Output/Returned: configuration code value (ConfigCodeMessages) Device Input/Device: none Device Output/Device: none Dependencies: compareString */ ConfigCodeMessages getDataLineCode(const char *dataBuffer) { // iniitalize function and variables // return appropriate code depending on prompt string provided // fct: compareString if(compareString(dataBuffer, "Version/Phase") == 0) { return CFG_VERSION_CODE; } if(compareString(dataBuffer, "File Path") == 0) { return CFG_MD_FILE_NAME_CODE; } if(compareString(dataBuffer, "CPU Scheduling Code") == 0) { return CFG_CPU_SCHED_CODE; } if(compareString(dataBuffer, "Quantum Time (cycles)") == 0) { return CFG_QUANT_CYCLES_CODE; } if(compareString(dataBuffer, "Memory Display (On/Off)") == 0) { return CFG_MEM_DISPLAY_CODE; } if(compareString(dataBuffer, "Memory Available (KB)") == 0) { return CFG_MEM_AVAILABLE_CODE; } if(compareString(dataBuffer, "Processor Cycle Time (msec)") == 0) { return CFG_PROC_CYCLES_CODE; } if(compareString(dataBuffer, "I/O Cycle Time (msec)") == 0) { return CFG_IO_CYCLES_CODE; } if(compareString(dataBuffer, "Log To") == 0) { return CFG_LOG_TO_CODE; } if(compareString(dataBuffer, "Log File Path") == 0) { return CFG_LOG_FILE_NAME_CODE; } // return corrupt leader line error code return CFG_CORRUPT_PROMPT_ERR; } /* Name: getLogToCode Process: converts "log to" text to configuration data code (three log to strings) Function Input/Parameters: lower case log to string (const char *) Function Output/Parameters: none Function Output/Returned: configuration data code value Device Input/Device: none Device Output/Device: none Dependencies: compareString */ ConfigDataCodes getLogToCode(const char *lowerCaseLogToStr) { // initialize function and variables // set default to log to monitor ConfigDataCodes returnVal = LOGTO_MONITOR_CODE; // check for BOTH // fct: compareString if(compareString(lowerCaseLogToStr, "both") == 0) { // set return value to both code returnVal = LOGTO_BOTH_CODE; } // check for FILE // fct: compareString if(compareString(lowerCaseLogToStr, "file") == 0) { // set return value to file code returnVal = LOGTO_FILE_CODE; } // return selected code return returnVal; } /* Name: stripTrailingSpaces Process: removes trailing spaces from input config leader lines Function Input/Parameters: config leader line string (char *) Function Output/Parameters: updates config leader line string (char *) Function Output/Returned: none Device Input/Device: none Device Output/Device: none Dependencies: getStringLength */ void stripTrailingSpaces(char *str) { // initialize index to length of string - 1 to get highest array index int index = getStringLength(str) - 1; // loop while space is found at the end of string while(str[index] == SPACE) { // set element to NULL_CHAR str[index] = NULL_CHAR; // decrement index index = index - 1; } // end loop from end of string // void function, no return. } /* Name: valueInRange Process: checks for config data values in range, including str values Function Input/Parameters: line code number for specific config value (int), integer value, as needed (int), double value, as needed (double), string value, as needed (const char *) Function Output/Parameters: none Function Output/Returned: Boolean result of the range test (bool) Device Input/Device: none Device Output/Device: none Dependencies: compareString */ bool valueInRange(int lineCode, int intVal, double doubleVal, const char *lowerCaseStringVal) { // initialize function and variables // set result to true, all tests are to find false bool result = true; // use line code to identify prompt line switch(lineCode) { // for version code case CFG_VERSION_CODE: // check if limits of version code are exceeded if(doubleVal < 0.00 || doubleVal > 10.00) { // set bool to false result = false; } // break break; // for cpu scheduling code case CFG_CPU_SCHED_CODE: // check for not finding one of the scheduling strings // fct: compareString if(compareString(lowerCaseStringVal, "fcfs-n") != 0 && compareString(lowerCaseStringVal, "sjf-n") != 0 && compareString(lowerCaseStringVal, "srtf-p") != 0 && compareString(lowerCaseStringVal, "fcfs-p") != 0 && compareString(lowerCaseStringVal, "rr-p") != 0) { // set bool to false result = false; } // break break; // for quantum cycles case CFG_QUANT_CYCLES_CODE: // check for quantum cycles limits exceeded if(intVal < 0 || intVal > 100) { // set bool to false result = false; } // break break; // for memory display case CFG_MEM_DISPLAY_CODE: // check for not finding either on or off // fct: compareString if(compareString(lowerCaseStringVal, "on") != 0 && compareString(lowerCaseStringVal, "off") != 0) { // set bool to false result = false; } // break break; // for memory available case CFG_MEM_AVAILABLE_CODE: // check for memory limits exceeded if(intVal < 1024 || intVal > 102400) { // set bool to false result = false; } // break break; // check for process cycles case CFG_PROC_CYCLES_CODE: // check for process cycles limits exceeded if(intVal < 1 || intVal > 100) { // set bool to false result = false; } // break break; // check for process cycles case CFG_IO_CYCLES_CODE: // check for process cycles limits exceeded if(intVal < 1 || intVal > 1000) { // set bool to false result = false; } // break break; // check for log to operation case CFG_LOG_TO_CODE: // check for not finding one of the log to strings // fct: compareString if(compareString(lowerCaseStringVal, "both") != 0 && compareString(lowerCaseStringVal, "monitor") != 0 && compareString(lowerCaseStringVal, "file") != 0) { // set bool to false result = false; } // break break; } // return result of limits analysis return result; }