From 7b837ddf86c67a2cad42a595317f6c4944beb5e3 Mon Sep 17 00:00:00 2001 From: cdez Date: Wed, 31 Jan 2024 02:33:40 -0700 Subject: [PATCH] Completed Sim01 afaik +- configops.c/h +- metadataops.c/h +- StandardConstants.h --- Sim01/StandardConstants.h | 3 + Sim01/configops.c | 385 ++++++++++++++++++++++++++++++++++---- Sim01/configops.h | 30 ++- Sim01/metadataops.c | 360 +++++++++++++++++++++++++++++++---- Sim01/metadataops.h | 32 ++-- 5 files changed, 723 insertions(+), 87 deletions(-) diff --git a/Sim01/StandardConstants.h b/Sim01/StandardConstants.h index e536c24..1a91d6c 100644 --- a/Sim01/StandardConstants.h +++ b/Sim01/StandardConstants.h @@ -13,6 +13,9 @@ //constant for a COLON #define COLON ':' +//constant for a SEMICOLON +#define SEMICOLON ';' + //constant for a COMMA #define COMMA ',' diff --git a/Sim01/configops.c b/Sim01/configops.c index c393b41..ad604d7 100644 --- a/Sim01/configops.c +++ b/Sim01/configops.c @@ -11,15 +11,20 @@ Function Output/Parameters: none Function Output/Returned: NULL (ConfigDataType *) Device Input/Device: none Device Output/Device: none -Dependencies: ??? +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; } @@ -37,8 +42,11 @@ 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. } @@ -50,13 +58,36 @@ Function Output/Parameters: none Function Output/Returned: none Device Input/Device: none Device Output/Monitor: displayed as spec'd -Dependencies: ??? +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. } @@ -69,104 +100,274 @@ Function Output/Parameters: pointer to config data pointer (ConfigDataType **) 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, - setStrToLowerCase, valueInRange, getCpuSchedCode, getLogToCode +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 - // close file access - // fct: fclose - // set end state message to corrupt leader line error - // fct: copyString - // return corrupt file data + 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: setStrToLowerCase + // 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 - // assign to data pointer depending on config item - // (all config line possibilities) - // fct: copyString, getCpuSchedCode, - // compareString, getLogToCode, as needed + 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 - // free temp struct memory - // fct: free - // close file access - // fct: fclose - // set end state message to corrupt configuration end line - // fct: copyString - // return corrupt file data + 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 false (temp) - return false; + 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; } /* @@ -185,34 +386,82 @@ 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 zero (temp) - return 0; + return CFG_CORRUPT_PROMPT_ERR; } /* Name: getLogToCode -Process: ??? -Function Input/Parameters: none +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: none +Function Output/Returned: configuration data code value Device Input/Device: none Device Output/Device: none -Dependencies: ??? +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 zero (temp) - return 0; + return returnVal; } /* @@ -228,9 +477,15 @@ 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. } @@ -253,37 +508,101 @@ bool valueInRange(int lineCode, int intVal, double doubleVal, { // 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 false; + return result; } \ No newline at end of file diff --git a/Sim01/configops.h b/Sim01/configops.h index 174f9b3..10dd498 100644 --- a/Sim01/configops.h +++ b/Sim01/configops.h @@ -34,7 +34,16 @@ typedef enum {CPU_SCHED_SJF_N_CODE, typedef struct ConfigDataTypeStruct { + double version; char metaDataFileName[STD_STR_LEN]; + int cpuSchedCode; // will need to be changed? + int quantumCycles; + bool memDisplay; // will need to be changed? + int memAvailable; + int procCycleRate; + int ioCycleRate; + int logToCode; // will need to be changed? + char logToFileName[STD_STR_LEN]; // will need to be changed? } ConfigDataType; /* @@ -90,6 +99,18 @@ Dependencies: copyString, fopen, getStringToDelimiter, compareString, fclose, bool getConfigData(const char *fileName, ConfigDataType **configData, char *endStateMsg); +/* +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); + /* Name: getDataLineCode Process: converts leader line string to configuration code value @@ -105,13 +126,14 @@ ConfigCodeMessages getDataLineCode(const char *dataBuffer); /* Name: getLogToCode -Process: ??? -Function Input/Parameters: none +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: none +Function Output/Returned: configuration data code value Device Input/Device: none Device Output/Device: none -Dependencies: ??? +Dependencies: compareString */ ConfigDataCodes getLogToCode(const char *lowerCaseLogToStr); diff --git a/Sim01/metadataops.c b/Sim01/metadataops.c index 13379dc..8f4395a 100644 --- a/Sim01/metadataops.c +++ b/Sim01/metadataops.c @@ -17,17 +17,31 @@ OpCodeType *addNode(OpCodeType *localPtr, OpCodeType *newNode) { // initialize function and variables // check for local pointer assigned to null + if(localPtr == NULL) + { // access memory for new link/node // fct: malloc + localPtr = (OpCodeType *) malloc(sizeof(OpCodeType)); // assign all three values to newly created node // assign next pointer to null // fct: copyString + localPtr->pid = newNode->pid; + copyString(localPtr->command, newNode->command); + copyString(localPtr->inOutArg, newNode->inOutArg); + copyString(localPtr->strArg1, newNode->strArg1); + localPtr->intArg2 = newNode->intArg2; + localPtr->intArg3 = newNode->intArg3; + localPtr->opEndTime = newNode->opEndTime; + localPtr->nextNode = NULL; // return current local pointer + return localPtr; + } // assume end of list not found // assign recursive fct to current node's next link // fct: addNode + localPtr->nextNode = addNode(localPtr->nextNode, newNode); // return current local ptr - return NULL; + return localPtr; } /* @@ -44,11 +58,17 @@ OpCodeType *clearMetaDataList(OpCodeType *localPtr) { // initialize function and variables // check for local pointer not set to null (list not empty) + if(localPtr != NULL) + { // call recursive function with next pointer // fct: clearMetaDataList + clearMetaDataList(localPtr->nextNode); // after recursive call, release mem to OS // fct: free + free(localPtr); // set given pointer to NULL + localPtr = NULL; + } // return NULL to calling fct return NULL; } @@ -69,29 +89,51 @@ void displayMetaData(const OpCodeType *localPtr) // initialize function and variables // display title, with underline // fct: printf + printf("Metadata File Display\n"); + printf("---------------------\n\n"); // loop to end of linked list + while(localPtr != NULL) + { // print leader // fct: printf + printf("Opcode: "); // print opcode pid // fct: printf + printf("/pid: %d", localPtr->pid); // print opcode command // fct: printf + printf("/cmd: %s", localPtr->command); // check for dev op + if(compareString(localPtr->command, "dev") == 0) + { // print in/out parameter // fct: printf + printf("/io: %s", localPtr->inOutArg); + } // otherwise, assume other than dev + else + { // print NA // fct: printf + printf("/io: NA"); + } // print first string argument // fct: printf + printf("\n\t /arg1: %s", localPtr->strArg1); // print first int argument // fct: printf + printf("/arg2: %d", localPtr->intArg2); // print second int argument // fct: printf + printf("/arg3: %d", localPtr->intArg3); // print op end time + printf("/op end time: %8.6f", localPtr->opEndTime); // endline print // fct: printf + printf("\n\n"); // assign local pointer to next node + localPtr = localPtr->nextNode; + } // void function, no return. } @@ -109,12 +151,19 @@ Dependencies: none int getCommand(char *cmd, const char *inputStr, int index) { // initialize function and variables + int lengthOfCommand = 3; // loop across command length + while(index < lengthOfCommand) + { // assign character from input string to buffer string + cmd[index] = inputStr[index]; // increment index + index = index + 1; // set next character to null character + cmd[index] = NULL_CHAR; + } // return current index - return 0; + return index; } /* @@ -136,81 +185,160 @@ bool getMetaData(const char *fileName, { // initialize function and variables // iniitialize read only constant + const char READ_ONLY_FLAG[] = "r"; // initialize variables + int accessResult, startCount = 0, endCount = 0; + char dataBuffer[MAX_STR_LEN]; + bool returnState = true; + OpCodeType *newNodePtr; + OpCodeType *localHeadPtr = NULL; + FILE *fileAccessPtr; // initialize opcode data pointer in case of return error + *opCodeDataHead = NULL; // initialize end state message // fct: copyString + copyString(endStateMsg, "Metadata file upload successful"); // open file for reading // fct: fopen + fileAccessPtr = fopen(fileName, READ_ONLY_FLAG); // check for file open failure + if(fileAccessPtr == NULL) + { // set end state message // fct: copyString + copyString(endStateMsg, "Metadata file access error"); // return file access error + return false; + } // check first line for correct leader // fct: getStringToDelimiter, compareString - // close file - // fct: fclose - // set end state message - // fct: copyString - // return corrupt descriptor error - // allocate memory for the temporary data structure - // fct: malloc - // get the first op command - // fct: getOpCommand - // get start and end counts for later comparison - // fct: updateStartCount, updateEndCount - // check for failure of first complete op command + if(!getStringToDelimiter(fileAccessPtr, COLON, dataBuffer) || + compareString(dataBuffer, "Start Program Meta-Data Code") != 0) + { // close file // fct: fclose + fclose(fileAccessPtr); + // set end state message + // fct: copyString + copyString(endStateMsg, "Corrupt metadata leader line error"); + // return corrupt descriptor error + return false; + } + // allocate memory for the temporary data structure + // fct: malloc + newNodePtr = (OpCodeType *) malloc(sizeof(OpCodeType)); + // get the first op command + // fct: getOpCommand + accessResult = getOpCommand(fileAccessPtr, newNodePtr); + // get start and end counts for later comparison + // fct: updateStartCount, updateEndCount + startCount = updateStartCount(startCount, newNodePtr->strArg1); + endCount = updateEndCount(endCount, newNodePtr->strArg1); + // check for failure of first complete op command + if(accessResult != COMPLETE_OPCMD_FOUND_MSG) + { + // close file + // fct: fclose + fclose(fileAccessPtr); // clear data from the structure list // fct: clearMetaDataList + *opCodeDataHead = clearMetaDataList(localHeadPtr); // free temporary structure memory // fct: free + free(newNodePtr); // set end state message // fct: copyString + copyString(endStateMsg, "Metadata incomplete first op command found"); // return result of operation + return false; + } // loop across all remaining op commands // (while complete op commands are found) + while(accessResult == COMPLETE_OPCMD_FOUND_MSG) + { // add the new op command to the linked list // fct: addNode + localHeadPtr = addNode(localHeadPtr, newNodePtr); // get a new op command // fct: getOpCommand + accessResult = getOpCommand(fileAccessPtr, newNodePtr); // update start and end counts for later comparison // fct: updateStartCount, updateEndCount + startCount = updateStartCount(startCount, newNodePtr->strArg1); + endCount = updateEndCount(startCount, newNodePtr->strArg1); + } // end loop across all remaining op commands // check for last op command found + if(accessResult == LAST_OPCMD_FOUND_MSG) + { // check for start and end opcode counts equal + if(startCount == endCount) + { // add the last node to the linked list // fct: addNode + localHeadPtr = addNode(localHeadPtr, newNodePtr); // set access result to no error for later operation + accessResult = NO_ACCESS_ERR; // check last line for incorrect end descriptor // fct: getStringToDelimiter, compareString - // set access result to corrupted descriptor error - // set end state message - // fct: copyString + if(!getStringToDelimiter(fileAccessPtr, PERIOD, dataBuffer) || + compareString(dataBuffer, "End Program Meta-Data Code") != 0) + { + // set access result to corrupted descriptor error + accessResult = MD_CORRUPT_DESCRIPTOR_ERR; + // set end state message + // fct: copyString + copyString(endStateMsg, "Metadata corrupted descriptor error"); + } + } // otherwise, assume start/end counts not equal + else + { // close file // fct: fclose + fclose(fileAccessPtr); // clear data from the structure list // fct: clearMetaDataList + *opCodeDataHead = clearMetaDataList(localHeadPtr); // free temporary structure memory // fct: free + free(newNodePtr); // set access result to error + accessResult = UNBALANCED_START_END_ERR; // set end state message // fct: copyString + copyString(endStateMsg, + "Unbalanced start and end arguments in metadata"); // return result of operation + return false; + } + } // otherwise, assume didn't find end + else + { // set end state message // fct: copyString + copyString(endStateMsg, "Corrupted metadata opcode"); // unset return state + returnState = false; + } // check for any errors found (not no error) + if(accessResult != NO_ACCESS_ERR) + { // clear the op command list // fct: clearMetaDataList + localHeadPtr = clearMetaDataList(localHeadPtr); + } // close access file + // fct: fclose + fclose(fileAccessPtr); + // release temporary structure memory // fct: free + free(newNodePtr); // assign temporary local head ptr to parameter return ptr + *opCodeDataHead = localHeadPtr; // return access result - return false; + return returnState; } /* @@ -230,63 +358,167 @@ OpCodeMessages getOpCommand(FILE *filePtr, OpCodeType *inData) { // initialize function and variables // initialize local constants + const int MAX_CMD_LENGTH = 5; + const int MAX_ARG_STR_LENGTH = 15; // initialize other variables + int numBuffer = 0; + char strBuffer[STD_STR_LEN]; + char cmdBuffer[MAX_CMD_LENGTH]; + char argStrBuffer[MAX_ARG_STR_LENGTH]; + int runningStringIndex = 0; + bool arg2FailureFlag = false; + bool arg3FailureFlag = false; // get whole op command as string, check for successful access // fct: getStringToDelimiter + if(getStringToDelimiter(filePtr, SEMICOLON, strBuffer)) + { // get three-letter command // fct: getCommand + runningStringIndex = getCommand(cmdBuffer, + strBuffer, runningStringIndex); // assign op command to node // fct: copyString + copyString(inData->command, cmdBuffer); + } // otherwise, assume unsuccessful access + else + { // set ptr to data structure to null + inData = NULL; // return op command access failure + return OPCMD_ACCESS_ERR; + } // verify op command + if(!verifyValidCommand(cmdBuffer)) + { // return op command error + return CORRUPT_OPCMD_ERR; + } // set all struct values that may not be initialized to defaults + inData->pid = 0; + inData->inOutArg[0] = NULL_CHAR; + inData->intArg2 = 0; + inData->intArg3 = 0; + inData->opEndTime = 0.0; + inData->nextNode = NULL; // check for device command + if(compareString(cmdBuffer, "dev") == 0) + { // get in/out arg + runningStringIndex = getStringArg(argStrBuffer, + strBuffer, runningStringIndex); // set device in/out arg + copyString(inData->inOutArg, argStrBuffer); // check correct argument + if(compareString(argStrBuffer, "in") != 0 && + compareString(argStrBuffer, "out") != 0) + { // return argument error + return CORRUPT_OPCMD_ARG_ERR; + } + } // get first string arg + runningStringIndex = getStringArg(argStrBuffer, + strBuffer, runningStringIndex); // set device in/out arg + copyString(inData->strArg1, argStrBuffer); // check for legit first string arg + if(!verifyFirstStringArg(argStrBuffer)) + { // return arg error + return CORRUPT_OPCMD_ARG_ERR; + } // check for last op command found - // return last op command found message + if(compareString(inData->command, "sys") == 0 && + compareString(inData->strArg1, "end") == 0) + { + // return last op command found message + return LAST_OPCMD_FOUND_MSG; + } // check for app start seconds argument + if(compareString(inData->command, "app") == 0 && + compareString(inData->strArg1, "start") == 0) + { // get number argument // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { // set failure flag - // set first int argument to number + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + } // check for cpu cycle time + else if(compareString(inData->command, "cpu") == 0) + { // get number argument // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { // set failure flag - // set first int argument to number + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + } // check for device cycle time + else if(compareString(inData->command, "dev") == 0) + { // get number argument // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { // set failure flag - // set first int argument to number + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; + } // check for memory base and offset - // get number argument for base + else if(compareString(inData->command, "mem") == 0) + { + // get number argument // fct: getNumberArg + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); // check for failed number access + if(numBuffer <= BAD_ARG_VAL) + { // set failure flag - // set first int argument to number + arg2FailureFlag = true; + } + // set first int argument to number + inData->intArg2 = numBuffer; // get number argument for offset // fct: getNumberArg - // check for failed number access + runningStringIndex = getNumberArg(&numBuffer, + strBuffer, runningStringIndex); + if(numBuffer <= BAD_ARG_VAL) + { // set failure flag + arg3FailureFlag = true; + } // set second int argument to number + inData->intArg3 = numBuffer; + } // check int args for upload failure + if(arg2FailureFlag || arg3FailureFlag) + { // return corrupt op command found message + return CORRUPT_OPCMD_ARG_ERR; + } // return complete op command found message - return 0; + return COMPLETE_OPCMD_FOUND_MSG; } /* @@ -303,16 +535,35 @@ Dependencies: isDigit int getNumberArg(int *number, const char *inputStr, int index) { // initialize function and variables + bool foundDigit = false; + *number = 0; + int multiplier = 1; // loop to skip whitespace + while(inputStr[index] <= SPACE || inputStr[index] == COMMA) + { // increment the index + index = index + 1; + } // loop across string length + while(isDigit(inputStr[index]) == true && + inputStr[index] != NULL_CHAR) + { // set digit found flag + foundDigit = true; // assign digit to output + (*number) = (*number) * multiplier + inputStr[index] - '0'; // increment index and multiplier - // check for digit not founf + index = index + 1; + multiplier = multiplier + 1; + } + // check for digit not found + if(!foundDigit) + { // set number to BAD_ARG_VAL, use dereference for ptr + *number = BAD_ARG_VAL; + } // return current index - return 0; + return index; } /* @@ -329,14 +580,26 @@ Dependencies: none int getStringArg(char *strArg, const char *inputStr, int index) { // initialize function and variables + int localIndex = 0; // loop to skip whitespace - // increment index + while(inputStr[index] <= SPACE || inputStr[index] == COMMA) + { + // increment the index + index = index + 1; + } // loop across string length + while(inputStr[index] != COMMA && inputStr[index] != NULL_CHAR) + { // assign character from input string to buffer string + strArg[localIndex] = inputStr[index]; // increment index + index = index + 1; + localIndex = localIndex + 1; // set next character to null character + strArg[localIndex] = NULL_CHAR; + } // return current index - return 0; + return index; } /* @@ -355,7 +618,7 @@ bool isDigit(char testChar) // check for test character between characters '0' - '9' // return true // otherwise, assume character if not digit, return false - return false; + return testChar >= '0' && testChar <= '9'; } /* @@ -375,9 +638,13 @@ int updateEndCount(int count, const char *opString) { // check for "end" in op string // fct: compareString + if(compareString(opString, "end") == 0) + { // return incremented end count + return count + 1; + } // return unchanged end count - return 0; + return count; } /* @@ -397,9 +664,13 @@ int updateStartCount(int count, const char *opString) { // check for "start" in op string // fct: compareString - // return incremented start count + if (compareString(opString, "start") == 0) + { + // return incremented start count + return count + 1; + } // return unchanged start count - return 0; + return count; } /* @@ -418,7 +689,20 @@ bool verifyFirstStringArg(const char *strArg) // fct: compareString // return true // otherwise, assume test fail, return false - return false; + return compareString(strArg, "access") == 0 || + compareString(strArg, "allocate") == 0 || + compareString(strArg, "end") == 0 || + compareString(strArg, "ethernet") == 0 || + compareString(strArg, "hard drive") == 0 || + compareString(strArg, "keyboard") == 0 || + compareString(strArg, "monitor") == 0 || + compareString(strArg, "printer") == 0 || + compareString(strArg, "process") == 0 || + compareString(strArg, "serial") == 0 || + compareString(strArg, "sound signal") == 0 || + compareString(strArg, "start") == 0 || + compareString(strArg, "usb") == 0 || + compareString(strArg, "video signal") == 0; } /* @@ -437,5 +721,9 @@ bool verifyValidCommand(char *testCmd) // fct: compareString // return true // otherwise, assume test failure, return false - return false; + return compareString(testCmd, "sys") == 0 || + compareString(testCmd, "app") == 0 || + compareString(testCmd, "cpu") == 0 || + compareString(testCmd, "mem") == 0 || + compareString(testCmd, "dev") == 0; } \ No newline at end of file diff --git a/Sim01/metadataops.h b/Sim01/metadataops.h index 62a88a4..44c98a2 100644 --- a/Sim01/metadataops.h +++ b/Sim01/metadataops.h @@ -4,24 +4,28 @@ #include "StandardConstants.h" #include "StringUtils.h" -typedef enum {UNKNOWN_ERR +typedef enum {BAD_ARG_VAL = -1, + NO_ACCESS_ERR, + MD_FILE_ACCESS_ERR, + MD_CORRUPT_DESCRIPTOR_ERR, + OPCMD_ACCESS_ERR, + CORRUPT_OPCMD_ERR, + CORRUPT_OPCMD_ARG_ERR, + UNBALANCED_START_END_ERR, + COMPLETE_OPCMD_FOUND_MSG, + LAST_OPCMD_FOUND_MSG } OpCodeMessages; -// typedef enum {CPU_SCHED_SJF_N_CODE, -// CPU_SCHED_SRTF_P_CODE, -// CPU_SCHED_FCFS_P_CODE, -// CPU_SCHED_RR_P_CODE, -// CPU_SCHED_FCFS_N_CODE, -// LOGTO_MONITOR_CODE, -// LOGTO_FILE_CODE, -// LOGTO_BOTH_CODE, -// NON_PREEMPTIVE_CODE, -// PREEMPTIVE_CODE -// } ConfigDataCodes; - typedef struct OpCodeTypeStruct { - int temp; + int pid; + char command[MAX_STR_LEN]; + char inOutArg[MAX_STR_LEN]; + char strArg1[MAX_STR_LEN]; + int intArg2; + int intArg3; + int opEndTime; + struct OpCodeTypeStruct *nextNode; } OpCodeType; /*