/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config_option.h"
unsigned int parse_config_file(const char *filename) {
/* -----------------------------------------------------------------------------
* Parse a config file and create all option
*
* @param const char *, the filename
* @param int
* -------------------------------------------------------------------------- */
FILE * stream;
char *buffer = NULL;
struct chain_string *strings = NULL, *strings_value = NULL, *strings_tmp = NULL;
char *parameter_name = NULL, *parameter_value = NULL, *one_value = NULL;
char *old_parameter_name = NULL;
int nb_chain_string = 0, int_val = 0;
stream = fopen(filename, "r");
if (stream == NULL) {
return 0;
}
safefgets(&buffer, FGETS_BUF_SIZE, stream);
while(!feof(stream)) {
/* On a lu une ligne dans le fichier */
if ((*buffer != '#')
&& (*buffer != '\r')
&& (*buffer != '\n')) {
/* On skippe les lignes vides et les lignes commentées */
stripcrlf(buffer);
strings = explode_to_chain_string(buffer, "=");
nb_chain_string = get_nb_chain_string(strings);
/* Format type :
name = string value
name = int value
name = string value1, string value2, string value3
name = string value1
string value2
string value3
*/
if (nb_chain_string >= 2) {
/* On est sur un paramètre */
parameter_name = trim(get_chain_string(strings, 0)->value);
parameter_value = trim(get_chain_string(strings, 1)->value);
strings_value = explode_to_chain_string(parameter_value, ",");
nb_chain_string = get_nb_chain_string(strings_value);
if (nb_chain_string >= 2) {
/* On est sur un paramètre multi valeurs */
for (strings_tmp = strings_value; strings_tmp != NULL; strings_tmp = strings_tmp->next) {
one_value = trim(strings_tmp->value);
if ((int_val = str2int(one_value)) == -1)
add_option(parameter_name, OPTION_STRING, one_value);
else
add_option(parameter_name, OPTION_INT, &int_val);
free(one_value);
}
}
else {
/* On est sur un paramètre à une seule valeur */
if (*parameter_value) {
if ((int_val = str2int(parameter_value)) == -1)
set_option(parameter_name, OPTION_STRING, parameter_value);
else
set_option(parameter_name, OPTION_INT, &int_val);
}
}
free(old_parameter_name);
old_parameter_name = strdup(parameter_name);
if (old_parameter_name == NULL)
return 0;
free(parameter_name);
free(parameter_value);
drop_all_chain_string(strings_value);
strings_value = NULL;
}
else if (((*buffer == ' ') || (*buffer == '\t'))
&& (old_parameter_name != NULL)) {
/* On est sur un paramètre multi valeurs, sur plusieurs lignes */
parameter_value = trim(get_chain_string(strings, 0)->value);
if (*parameter_value) {
if ((int_val = str2int(parameter_value)) == -1)
add_option(old_parameter_name, OPTION_STRING, parameter_value);
else
add_option(old_parameter_name, OPTION_INT, &int_val);
}
free(parameter_value);
}
drop_all_chain_string(strings);
strings = NULL;
}
free(buffer);
buffer = NULL;
safefgets(&buffer, FGETS_BUF_SIZE, stream);
}
free(old_parameter_name);
free(buffer);
fclose(stream);
return 1;
}
size_t safefgets(char **buffer, int size, FILE * stream) {
/* -----------------------------------------------------------------------------
* Safe implementation of fgets()
*
* @param char **, address to the buffer to fill and dynamically allocated
* @param int, block size for fread()
* @param FILE *, the file stream
* @param size_t, number of character read
* -------------------------------------------------------------------------- */
char *tmp_buffer = NULL;
char *buffer2 = NULL;
int i = 0;
size_t size_read = 0;
size_t total_size_read = 0;
tmp_buffer = (char *)malloc((size + 1) * sizeof(char));
if (tmp_buffer == NULL)
return -1;
for (;;) {
size_read = fread(tmp_buffer, sizeof(char), size, stream);
if ((size_read <= 0) || (ferror(stream)))
return -1;
total_size_read += size_read;
buffer2 = (char *)realloc(*buffer, (total_size_read + 1) * sizeof(char));
if (buffer2 == NULL)
return -1;
*buffer = buffer2;
memcpy(*buffer + total_size_read - size_read, tmp_buffer, size_read * sizeof(char));
for(i = 0; i < size_read; i++) {
if (tmp_buffer[i] == '\n') {
break;
}
}
if (i < size_read) {
/* On a récupéré une ligne */
*(*buffer + total_size_read - size_read + i + 1) = '\0';
fseek(stream, i - size_read + 1, SEEK_CUR);
free(tmp_buffer);
return total_size_read - size_read + i + 1;
}
if (feof(stream)) {
free(tmp_buffer);
return total_size_read;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1