Fix inclusion of <config.h> in Guile bindings.
[gnutls.git] / src / cfg / cfgfile.c
blob398ac47505a940232b3b3455a9d7d4e8f3f4e6c5
1 /*
2 * libcfg+ - precise command line & config file parsing library
4 * cfgfile.c - config file parsing
5 * ____________________________________________________________
7 * Developed by Ondrej Jombik <nepto@platon.sk>
8 * and Lubomir Host <rajo@platon.sk>
9 * Copyright (c) 2001-2003 Platon SDG, http://platon.sk/
10 * All rights reserved.
12 * See README file for more information about this software.
13 * See COPYING file for license information.
15 * Download the latest version from
16 * http://platon.sk/projects/libcfg+/
19 /* $Platon: libcfg+/src/cfgfile.c,v 1.26 2003/11/07 17:26:48 nepto Exp $ */
21 /* Includes {{{ */
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #if STDC_HEADERS
27 # include <stdlib.h>
28 #else
29 # if HAVE_STDLIB_H
30 # include <stdlib.h>
31 # endif
32 #endif
33 #if HAVE_STRING_H
34 # if !STDC_HEADERS && HAVE_MEMORY_H
35 # include <memory.h>
36 # endif
37 # include <string.h>
38 #endif
39 #if HAVE_STRINGS_H
40 # include <strings.h>
41 #endif
42 #if HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
46 #include <platon/str/strdyn.h>
47 #include <platon/str/strplus.h>
48 #include <platon/str/dynfgets.h>
50 #include "cfg+.h"
51 #include "shared.h"
52 /* }}} */
54 /* Static function declarations {{{ */
55 static int get_multi_line(const CFG_CONTEXT con, char **buf);
56 /* }}} */
58 int
59 cfg_cfgfile_get_next_opt(con)
60 const CFG_CONTEXT con;
61 { /* {{{ */
62 char *buf;
63 int ret_val;
65 con->error_code = CFG_OK;
67 /* Initial position seek */
68 if (con->fhandle == NULL) {
69 con->fhandle = con->filename != NULL
70 ? fopen(con->filename, "r")
71 : NULL;
72 if (con->fhandle == NULL) {
73 con->error_code = CFG_ERROR_FILE_NOT_FOUND;
74 return con->error_code;
77 if (con->flags & CFG_FILE_LINE_POS_USAGE) {
78 /* If negative line is specified, returns seek error.
79 If 0 is specified, do nothing.
80 If number > 0 is specified make appropriate line seek. */
81 if (con->begin_pos < 0) {
82 con->error_code = CFG_ERROR_SEEK_ERROR;
83 return con->error_code;
86 if (con->begin_pos > 0) {
87 con->cur_idx = 0;
88 con->cur_idx_tmp = 0;
90 /* Moving to begin_pos line */
91 while (con->cur_idx_tmp < con->begin_pos) {
92 switch (fgetc(con->fhandle)) {
93 case EOF:
94 con->error_code = CFG_ERROR_SEEK_ERROR;
95 return con->error_code;
96 case '\n':
97 con->cur_idx_tmp++;
102 else {
103 if (/* always do: con->begin_pos > 0 && */
104 fseek(con->fhandle, con->begin_pos, SEEK_SET) != 0) {
105 con->error_code = CFG_ERROR_SEEK_ERROR;
106 return con->error_code;
112 * Main loop
114 while (1) {
115 /* Updating cur_idx to set current line position */
116 if (con->flags & CFG_FILE_LINE_POS_USAGE) {
117 con->cur_idx += con->cur_idx_tmp;
118 con->cur_idx_tmp = 0;
121 /* Reading multi line and exit on error */
122 con->error_code = get_multi_line(con, &buf);
123 if (con->error_code != CFG_OK) {
124 if (buf != NULL)
125 free(buf);
127 return con->error_code;
130 /* Testing if file stop prefix was found */
131 if (buf != NULL && con->prop[CFG_FILE_STOP_PREFIX] != NULL) {
132 if (buf == PLATON_FUNC(strdyn_str2)(buf,
133 con->prop[CFG_FILE_STOP_PREFIX], NULL)) {
134 __cfg_free_currents(con);
135 con->cur_opt = buf;
136 con->error_code = CFG_ERROR_STOP_STR;
137 return con->error_code;
141 /* Finished? */
142 if ((con->size >= 0 && cfg_get_cur_idx(con) >= con->begin_pos + con->size)
143 || feof(con->fhandle)) {
144 if (buf != NULL)
145 free(buf);
147 return con->error_code; /* always CFG_OK */
150 __cfg_free_currents(con);
152 if (__cfg_cfgfile_set_currents(con, buf) != CFG_OK) {
153 con->error_code = CFG_ERROR_NOMEM;
154 return con->error_code;
157 free(buf);
159 con->error_code = __cfg_process_currents(con, &ret_val, NULL);
160 if (con->error_code != CFG_OK)
161 return con->error_code;
163 if (ret_val > 0)
164 return ret_val;
167 return con->error_code; /* CFG_OK */
168 } /* }}} */
171 * get_multi_line()
173 * Gets single line from file. If line continues on next line, returns
174 * the whole line concatenated. Coments, remarks and empty lines are
175 * skipped. If end of file is reached CFG_OK is returned and higher
176 * level should determine that fact using feof() function.
179 static int
180 get_multi_line(con, buf)
181 const CFG_CONTEXT con;
182 char **buf;
183 { /* {{{ */
184 register char **ar = NULL;
185 register char *my_buf = NULL;
186 register int state = 0;
188 *buf = NULL;
190 if ((ar = PLATON_FUNC(strdyn_create)()) == NULL)
191 return CFG_ERROR_NOMEM;
193 while (1) {
194 if (state > 1)
195 state = 1;
197 if (my_buf != NULL)
198 free(my_buf);
200 my_buf = PLATON_FUNC(dynamic_fgets)(con->fhandle);
201 if (my_buf == NULL) {
202 if (feof(con->fhandle))
203 return CFG_OK;
205 return CFG_ERROR_NOMEM;
208 str_trim(my_buf);
210 /* Is empty line or comment? */
211 if (strlen(my_buf) == 0 || strdyn_str(my_buf,
212 con->prop[CFG_FILE_COMMENT_PREFIX]) == my_buf) {
214 if (con->flags & CFG_FILE_LINE_POS_USAGE)
215 con->cur_idx++;
217 if (state == 0)
218 continue;
219 else
220 break;
222 else {
223 if (con->flags & CFG_FILE_LINE_POS_USAGE)
224 con->cur_idx_tmp++;
227 /* Multi line detection. */
229 register char **pos;
230 register int max_len = 0;
231 register int len;
233 for (pos = con->prop[CFG_FILE_MULTI_LINE_POSTFIX];
234 pos != NULL && *pos != NULL;
235 pos++) {
237 len = strlen(my_buf) - strlen(*pos);
239 if (len > max_len && ! strcmp(*pos, my_buf + len))
240 max_len = len;
243 /* Multi line postfix found? */
244 if (max_len > 0) {
245 my_buf[max_len] = '\0';
246 state = 2;
248 len = strlen(my_buf);
249 PLATON_FUNC(str_right_trim)(my_buf);
250 if (len - strlen(my_buf) > 0) {
251 /* Could be replaced with
252 strcpy(my_buf + strlen(my_buf), " "); */
253 my_buf[strlen(my_buf) + 1] = '\0';
254 my_buf[strlen(my_buf)] = ' ';
259 ar = PLATON_FUNC(strdyn_add)(ar, my_buf);
260 if (ar == NULL)
261 return CFG_ERROR_NOMEM;
263 if (state != 2)
264 break;
267 if (my_buf != NULL)
268 free(my_buf);
270 my_buf = PLATON_FUNC(str_right_trim)(strdyn_implode(ar, ""));
271 PLATON_FUNC(strdyn_free)(ar);
273 if (my_buf == NULL)
274 return CFG_ERROR_NOMEM;
276 *buf = my_buf;
278 return CFG_OK;
279 } /* }}} */
281 /* Modeline for ViM {{{
282 * vim:set ts=4:
283 * vim600:fdm=marker fdl=0 fdc=0:
284 * }}} */