Refuse to work on this anymore right now.
This commit is contained in:
parent
e3441e9fbd
commit
fda57566d8
26 changed files with 4988 additions and 94 deletions
608
Sim04/configops.c
Normal file
608
Sim04/configops.c
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
#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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue