2 * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 #define INF_WAITDELIM 10
52 #define CHECKBUF do { \
53 if (bufptr-buf+1>=buflen) { \
54 int diff = bufptr-buf; \
56 buf=trealloc(buf,buflen); \
61 #define CHECKMAP do { \
62 if (mapptr-map+1>=maplen) { \
63 int diff = mapptr-map; \
65 map=trealloc(map,maplen); \
70 #define ISKEYNAME(c) ( (c)=='_' || isalnum(c) )
73 clrbackspace(char *ptr, char *buf) {
74 while(ptr>=buf && (*ptr==' '||*ptr=='\t') ) {
81 INFParse(char *file) {
83 int maplen=32, buflen=32;
85 int state=INF_WAIT, c;
89 if ( (in=fopen(file,"r"))==NULL )
90 tlog(TL_ALARM|TL_EXIT,"Can't open inf file '%s': %s", file, strerror(errno));
92 map=mapptr=(InfMap*)tmalloc(sizeof(InfMap)*maplen);
93 buf = bufptr = (char*)tmalloc(buflen);
96 while( (c=fgetc(in))!=EOF ) {
102 if ( state==INF_WAIT ) {
110 else if ( ISKEYNAME(c) ) {
111 if ( mapptr->section==NULL )
112 tlog(TL_ALARM|TL_EXIT, "Undefined section name at line %d, file %s", lineno, file);
118 } else if ( state==INF_SECTION ) {
121 tlog(TL_ALARM|TL_EXIT,
122 "Void section name at line %d, file %s", lineno, file);
124 if ( mapptr->section ) tfree(mapptr->section);
126 mapptr->section = tstrdup(buf);
130 } else if ( ISKEYNAME(c) ) {
134 tlog( TL_ALARM|TL_EXIT,"Syntax error at line %d, file %s", lineno, file);
135 } else if ( state==INF_COMMENT ) {
140 } else if ( state==INF_KEY ) {
146 mapptr->key = tstrdup(buf);
149 } else if (c==' ' || c=='\t') {
151 mapptr->key = tstrdup(buf);
155 tlog( TL_ALARM|TL_EXIT,"Syntax error at line %d, file %s", lineno, file);
156 } else if ( state==INF_WAITDELIM ) {
159 else if (!(c==' ' || c=='\t'))
160 tlog( TL_ALARM|TL_EXIT,"Syntax error at line %d, file %s", lineno, file);
161 } else if ( state==INF_WAITVAL ) {
165 mapptr->value=tstrdup(buf);
167 mapptr->section = tstrdup((mapptr-1)->section);
170 } else if ( c=='\\' ) {
173 } else if ( c=='"' ) {
176 } else if ( !(c==' ' || c=='\t') ) {
182 } else if ( state==INF_ESCAPE ) {
186 if (c=='\n') lineno++;
187 } else if ( state==INF_QESCAPE ) {
191 if (c=='\n') lineno++;
192 } else if ( state==INF_INVAL ) {
195 clrbackspace(bufptr,buf);
196 mapptr->value=tstrdup(buf);
198 mapptr->section = tstrdup((mapptr-1)->section);
201 } else if (c=='\n') {
203 clrbackspace(bufptr,buf);
204 mapptr->value=tstrdup(buf);
206 mapptr->section = tstrdup((mapptr-1)->section);
210 } else if (c=='\\') {
216 } else if ( state==INF_INQVAL ) {
219 } else if ( c=='"' ) {
221 mapptr->value=tstrdup(buf);
223 mapptr->section = tstrdup((mapptr-1)->section);
229 if (c=='\n') lineno++;
232 tlog( TL_CRIT|TL_EXIT,"INFParse: internal error, unknown state %d", state );
235 if ( state==INF_INVAL ) {
237 clrbackspace(bufptr,buf);
238 mapptr->value=tstrdup(buf);
240 mapptr->section=NULL;
242 } else if ( state!=INF_WAIT ) {
243 tlog( TL_ALARM|TL_EXIT,"Unexpected end of file %s", file);
244 } else if (mapptr->section) {
245 tfree(mapptr->section);
246 mapptr->section=NULL;
255 INFFree(InfMap *inf) {
257 while(ptr && ptr->section) {
259 if (ptr->key) tfree(ptr->key);
260 if (ptr->value) tfree(ptr->value);
267 INFFindInfMap(InfMap *inf, char *sect, char *key) {
268 while(inf && inf->section) {
270 (sect==NULL || strcmp(inf->section,sect)==0) &&
271 (key==NULL || strcmp(inf->key,key)==0)
281 INFGetInt(InfMap *inf, char *sect, char *key, int *val) {
282 inf = INFFindInfMap(inf, sect, key);
284 *val=atoi(inf->value);
291 INFGetUint(InfMap *inf, char *sect, char *key, u_int32_t *val) {
292 inf = INFFindInfMap(inf, sect, key);
294 *val=strtoul(inf->value, NULL,0);
301 INFGetFloat(InfMap *inf, char *sect, char *key, float *val) {
302 inf = INFFindInfMap(inf, sect, key);
304 *val=strtof(inf->value, NULL);
311 INFGetDouble(InfMap *inf, char *sect, char *key, double *val) {
312 inf = INFFindInfMap(inf, sect, key);
314 *val=strtod(inf->value, NULL);
321 INFGetString(InfMap *inf, char *sect, char *key, char **val) {
322 inf = INFFindInfMap(inf, sect, key);
324 *val=tstrdup(inf->value);