📄 parsecfg.c
字号:
} for (;;) { if (quote_flag == CFG_NO_QUOTE) { if (*(ptr + len) == ' ' || *(ptr + len) == '\t' || *(ptr + len) == '\0' || *(ptr + len) == '#' || (*(ptr + len) == '=' && word_type == CFG_PARAMETER) || (*(ptr + len) == ']' && word_type == CFG_SECTION)) { break; } } else if (quote_flag == CFG_DOUBLE_QUOTE) { if (*(ptr + len) == '\"') { break; } } else if (quote_flag == CFG_SINGLE_QUOTE) { if (*(ptr + len) == '\'') { break; } } if (*(ptr + len) == '\0') { return (NULL); } len++; } if ((*word = malloc(len + 1)) == NULL) { cfgFatalFunc(CFG_MEM_ALLOC_FAIL, "unknown", 0, ""); return (NULL); } strncpy(*word, ptr, len); *(*word + len) = '\0'; ptr += (len + (quote_flag == CFG_NO_QUOTE ? 0 : 1)); ptr = rm_first_spaces(ptr); switch (word_type) { case CFG_PARAMETER: if (*ptr != '=') { free(*word); return (NULL); } ptr++; ptr = rm_first_spaces(ptr); break; case CFG_VALUE: if (*ptr != '\0' && *ptr != '#') { free(*word); return (NULL); } break; case CFG_SECTION: if (*ptr != ']') { free(*word); return (NULL); } break; default: free(*word); return (NULL); } return (ptr);}/* -------------------------------------------------- NAME store_value FUNCTION store the value according to cfg INPUT cfg ......... array of possible variables parameter ... parameter value ....... value type ........ type of the configuration file section ..... section number OUTPUT error code -------------------------------------------------- */static int store_value(cfgStruct cfg[], const char *parameter, const char *value, cfgFileType type, int section){ int num; long tmp; unsigned long utmp; float ftmp; float dtmp; char *endptr; char *strptr; cfgList *listptr; for (num = 0; cfg[num].type != CFG_END; num++) { if (strcasecmp(parameter, cfg[num].parameterName) == 0) { errno = 0; switch (cfg[num].type) { case CFG_BOOL: if (strcasecmp(value, "TRUE") == 0 || strcasecmp(value, "YES") == 0 || strcasecmp(value, "T") == 0 || strcasecmp(value, "Y") == 0 || strcasecmp(value, "1") == 0) { if (type == CFG_INI) { *(*(int **) (cfg[num].value) + section) = 1; } else { *(int *) (cfg[num].value) = 1; } return (CFG_NO_ERROR); } else if (strcasecmp(value, "FALSE") == 0 || strcasecmp(value, "NO") == 0 || strcasecmp(value, "F") == 0 || strcasecmp(value, "N") == 0 || strcasecmp(value, "0") == 0) { if (type == CFG_INI) { *(*(int **) (cfg[num].value) + section) = 0; } else { *(int *) (cfg[num].value) = 0; } return (CFG_NO_ERROR); } return (CFG_BOOL_ERROR); case CFG_STRING: if ((strptr = malloc(strlen(value) + 1)) == NULL) { return (CFG_MEM_ALLOC_FAIL); } strcpy(strptr, value); if (type == CFG_INI) { *(*(char ***) (cfg[num].value) + section) = strptr; } else { *(char **) (cfg[num].value) = strptr; } return (CFG_NO_ERROR); case CFG_INT: tmp = strtol(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE || tmp > INT_MAX || tmp < INT_MIN) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(int **) (cfg[num].value) + section) = tmp; } else { *(int *) (cfg[num].value) = tmp; } return (CFG_NO_ERROR); case CFG_UINT: utmp = strtoul(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE || utmp > UINT_MAX) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(unsigned int **) (cfg[num].value) + section) = utmp; } else { *(unsigned int *) (cfg[num].value) = utmp; } return (CFG_NO_ERROR); case CFG_LONG: tmp = strtol(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(long **) (cfg[num].value) + section) = tmp; } else { *(long *) (cfg[num].value) = tmp; } return (CFG_NO_ERROR); case CFG_ULONG: utmp = strtoul(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(unsigned long **) (cfg[num].value) + section) = utmp; } else { *(unsigned long *) (cfg[num].value) = utmp; } return (CFG_NO_ERROR); case CFG_STRING_LIST: if (type == CFG_INI) { listptr = *(*(cfgList ***) (cfg[num].value) + section); } else { listptr = *(cfgList **) (cfg[num].value); } if (listptr != NULL) { while (listptr->next != NULL) { listptr = listptr->next; } if ((listptr = listptr->next = malloc(sizeof(cfgList))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } } else { if ((listptr = malloc(sizeof(cfgList))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } if (type == CFG_INI) { *(*(cfgList ***) (cfg[num].value) + section) = listptr; } else { *(cfgList **) (cfg[num].value) = listptr; } } if ((strptr = malloc(strlen(value) + 1)) == NULL) { return (CFG_MEM_ALLOC_FAIL); } strcpy(strptr, value); listptr->str = strptr; listptr->next = NULL; return (CFG_NO_ERROR); case CFG_FLOAT: ftmp = strtod(value, &endptr); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(float **) (cfg[num].value) + section) = ftmp; } else { *(float *) (cfg[num].value) = ftmp; } return (CFG_NO_ERROR); case CFG_DOUBLE: dtmp = strtod(value, &endptr); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(double **) (cfg[num].value) + section) = dtmp; } else { *(double *) (cfg[num].value) = dtmp; } return (CFG_NO_ERROR); default: return (CFG_INTERNAL_ERROR); } } } return (CFG_WRONG_PARAMETER);}/* -------------------------------------------------- NAME parse_values_between_braces FUNCTION parse values between braces INPUT file ....... file name fp ......... file pointer to the configuration file parameter .. parameter cfg ........ array of possible variables line ....... pointer to current working line type ....... file type section .... section number parameter_buf ... for error handling parameter_line .. for error handling OUTPUT CFG_NO_ERROR on success, CFG_JUST_RETURN_WITHOUT_MSG otherwise -------------------------------------------------- */static int parse_values_between_braces(const char *file, FILE *fp, const char *parameter, cfgStruct cfg[], int *line, cfgFileType type, int section, const char *parameter_buf, int parameter_line){ char *line_buf; char *value; char *ptr; int error_code; while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, line)) != NULL) { if (*ptr == '}') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, *line, line_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } free(line_buf); return (CFG_NO_ERROR); } if (parse_word(ptr, &value, CFG_VALUE) == NULL) { cfgFatal(CFG_SYNTAX_ERROR, file, *line, line_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } if ((error_code = store_value(cfg, parameter, value, type, section)) != CFG_NO_ERROR) { if (error_code == CFG_WRONG_PARAMETER) { cfgFatal(error_code, file, parameter_line, parameter_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } cfgFatal(error_code, file, *line, line_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } free(line_buf); free(value); } cfgFatal(CFG_NO_CLOSING_BRACE, file, *line, NULL); return (CFG_JUST_RETURN_WITHOUT_MSG);}/* -------------------------------------------------- NAME parse_ini FUNCTION parse the configuration file as Windows INI-like file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing strings cfg ... array of possible variables line .. pointer to current working line number section ... pointer to current section number OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */static int parse_ini(const char *file, FILE *fp, char *ptr, cfgStruct cfg[], int *line, int *section){ char *parameter; char *parameter_buf; int parameter_line; char *value; int error_code; int i; if (*ptr == '[') { if ((error_code = alloc_for_new_section(cfg, section)) != CFG_NO_ERROR) { return (error_code); } ptr = rm_first_spaces(ptr + 1); parsecfg_section_name = realloc(parsecfg_section_name, sizeof(char *) * (*section + 1)); if ((ptr = parse_word(ptr, &parsecfg_section_name[*section], CFG_SECTION)) == NULL) { return (CFG_SYNTAX_ERROR); } for (i = 0; i < *section; i++) { if (strcasecmp(parsecfg_section_name[*section], parsecfg_section_name[i]) == 0) { return (CFG_USED_SECTION); } } ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { return (CFG_SYNTAX_ERROR); } return (CFG_NO_ERROR); } else if (*section == -1) { return (CFG_SYNTAX_ERROR); } parameter_buf = ptr; parameter_line = *line; if ((ptr = parse_word(ptr, ¶meter, CFG_PARAMETER)) == NULL) { return (CFG_SYNTAX_ERROR); } if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { return (CFG_SYNTAX_ERROR); } if (parse_values_between_braces(file, fp, parameter, cfg, line, CFG_INI, *section, parameter_buf, parameter_line) != CFG_NO_ERROR) { return (CFG_JUST_RETURN_WITHOUT_MSG); /* error handling has already done */ } free(parameter); } else { if ((ptr = parse_word(ptr, &value, CFG_VALUE)) == NULL) { return (CFG_SYNTAX_ERROR); } if ((error_code = store_value(cfg, parameter, value, CFG_INI, *section)) != CFG_NO_ERROR) { return (error_code); } free(parameter); free(value); } return (CFG_NO_ERROR);}/* -------------------------------------------------- NAME alloc_for_new_section FUNCTION allocate memory for new section INPUT cfg ....... array of possible variables section ... pointer to current section number OUTPUT error code -------------------------------------------------- */static int alloc_for_new_section(cfgStruct cfg[], int *section){ int num; void *ptr; (*section)++; for (num = 0; cfg[num].type != CFG_END; num++) { switch (cfg[num].type) { case CFG_BOOL: case CFG_INT: case CFG_UINT: if (*section == 0) { *(int **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(int **) (cfg[num].value), sizeof(int) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(int **) (cfg[num].value) = ptr; if (cfg[num].type == CFG_BOOL) { *(*((int **) (cfg[num].value)) + *section) = -1; } else { *(*((int **) (cfg[num].value)) + *section) = 0; } break; case CFG_LONG: case CFG_ULONG: if (*section == 0) { *(long **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(long **) (cfg[num].value), sizeof(long) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(long **) (cfg[num].value) = ptr; *(*((long **) (cfg[num].value)) + *section) = 0; break; case CFG_STRING: if (*section == 0) { *(char ***) (cfg[num].value) = NULL; } if ((ptr = realloc(*(char ***) (cfg[num].value), sizeof(char *) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(char ***) (cfg[num].value) = ptr; *(*(char ***) (cfg[num].value) + *section) = NULL; break; case CFG_STRING_LIST: if (*section == 0) { *(cfgList ***) (cfg[num].value) = NULL; } if ((ptr = realloc(*(cfgList ***) (cfg[num].value), sizeof(cfgList *) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(cfgList ***) (cfg[num].value) = ptr; *(*(cfgList ***) (cfg[num].value) + *section) = NULL; break; case CFG_FLOAT: if (*section == 0) { *(float **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(float **) (cfg[num].value), sizeof(float) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(float **) (cfg[num].value) = ptr; *(*((float **) (cfg[num].value)) + *section) = 0; break; case CFG_DOUBLE: if (*section == 0) { *(double **) (cfg[num].value) = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -