Annotation of libaitcfg/src/parse.c, revision 1.6.2.1
1.2 misho 1: /*************************************************************************
2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.6.2.1 ! misho 6: * $Id: parse.c,v 1.6 2011/05/01 17:24:28 misho Exp $
1.2 misho 7: *
1.6 misho 8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
1.1 misho 46: #include "global.h"
47: #include "aitcfg.h"
48:
49:
50: // cfgDbg() Debug/Log operation
1.6.2.1 ! misho 51: static inline int
! 52: cfgDbg(FILE *f, char *fmt, ...)
1.1 misho 53: {
54: int ret = 0;
55: va_list lst;
56:
57: va_start(lst, fmt);
58: ret = vfprintf(f, fmt, lst);
59: va_end(lst);
60:
61: return ret;
62: }
63:
1.3 misho 64: /*
65: * InvertQueue() InvertQueue order //{cfg} list of elements for revert
66: * @cfg = Head list element for revert
67: */
1.6.2.1 ! misho 68: static inline void
! 69: InvertQueue(sl_config * __restrict cfg)
1.3 misho 70: {
71: struct tagPair *item, *next, *prev = NULL;
72:
73: for (item = cfg->slh_first; item; item = next) {
74: next = item->sle_next;
75: item->sle_next = prev;
76: prev = item;
77: }
78: cfg->slh_first = prev;
79: }
80:
81: // cfgWrite() Write to file from config list
1.6.2.1 ! misho 82: static inline int
! 83: cfgWrite(FILE *f, sl_config * __restrict cfg, int whitespace)
1.3 misho 84: {
85: struct tagPair *av;
86: time_t tim;
87: char szTime[MAX_STR + 1];
88: u_char szSection[MAX_STR + 1];
89:
90: bzero(szSection, MAX_STR + 1);
91:
92: bzero(szTime, MAX_STR + 1);
93: time(&tim);
94: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
95: if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) {
96: LOGERR;
97: return -1;
98: }
99:
100: InvertQueue(cfg);
101: for (av = cfg->slh_first; av; av = av->sle_next) {
102: if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) {
103: strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1);
104: if (!cfgDbg(f, "\n[%s]\n", av->psSection)) {
105: LOGERR;
106: return -1;
107: }
108: }
109: if (!av->psSection && *szSection) {
110: bzero(szSection, MAX_STR + 1);
111: if (!cfgDbg(f, "\n[]\n")) {
112: LOGERR;
113: return -1;
114: }
115: }
116:
117: if (whitespace) {
118: if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) {
119: LOGERR;
120: return -1;
121: }
122: } else {
123: if (!cfgDbg(f, "%s=%s\n", av->psAttribute, av->psValue)) {
124: LOGERR;
125: return -1;
126: }
127: }
128: }
129: InvertQueue(cfg);
130:
131: bzero(szTime, MAX_STR + 1);
132: time(&tim);
133: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
134: if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) {
135: LOGERR;
136: return -1;
137: }
138:
139: return 0;
140: }
141:
142: // ---------------------------------------------------
1.1 misho 143:
144: /*
145: * ReadConfig() Read from file and add new item to config list
146: * @f = file resource
147: * @cfg = Head list element
148: * return: 0 ok; -1 error:: can`t allocate memory
149: */
1.6.2.1 ! misho 150: int
! 151: ReadConfig(FILE *f, sl_config * __restrict cfg)
1.1 misho 152: {
153: u_char szLine[MAX_STR + 1];
154: u_char szSection[MAX_STR + 1], *psAttr, *psVal;
155: int pos;
156: struct tagPair *av;
157:
158: memset(szSection, 0, MAX_STR + 1);
159: while (!feof(f)) {
160: memset(szLine, 0, MAX_STR + 1);
161: fgets((char*) szLine, MAX_STR, f);
1.6 misho 162: io_TrimStr(szLine);
1.1 misho 163: #ifdef __DEBUG
164: cfgDbg(stdout, "DEBUG:: RAW |%s|\n", szLine);
165: #endif
166:
167: // End of config
168: if (*szLine == '.')
169: break;
170: // Comment
171: if (*szLine == '#' || *szLine == ';' || !*szLine)
172: continue;
173:
174: #ifdef __DEBUG
175: cfgDbg(stdout, "DEBUG:: Clean |%s|\n", szLine);
176: #endif
177:
178: // Section
179: if (*szLine == '[') {
180: pos = strlen((char*) szLine) - 1;
181: if (szLine[pos] != ']') {
1.2 misho 182: #ifdef __DEBUG
1.1 misho 183: cfgDbg(stdout, "WARNING:: Ignore section %s ... not closed breket\n", szLine);
1.2 misho 184: #endif
1.1 misho 185: } else {
186: szLine[pos] = 0;
187: strncpy((char*) szSection, (char*) szLine + 1, MAX_STR);
188: #ifdef __DEBUG
189: cfgDbg(stdout, "DEBUG:: Section %s\n", szSection);
190: #endif
191: }
192: continue;
193: }
194:
195: // Devide pairs
196: pos = strchr((char*) szLine, '=') ? strchr((char*) szLine, '=') - (char*) szLine : 0;
197: if (!pos) {
1.2 misho 198: #ifdef __DEBUG
1.1 misho 199: cfgDbg(stdout, "WARNING:: Ignore a/v %s ... format error!\n", szLine);
1.2 misho 200: #endif
1.1 misho 201: continue;
202: } else {
203: av = malloc(sizeof(struct tagPair));
204: if (!av) {
205: LOGERR;
206: return -1;
207: } else {
1.2 misho 208: memset(av, 0, sizeof(struct tagPair));
1.1 misho 209: // added new element
210: av->sle_next = cfg->slh_first;
211: cfg->slh_first = av;
212: }
213: // added section name to element
214: if (*szSection) {
215: av->psSection = malloc(strlen((char*) szSection) + 1);
216: if (!av->psSection) {
217: LOGERR;
218: free(av);
219: return -1;
220: } else
1.2 misho 221: strlcpy((char*) av->psSection, (char*) szSection, strlen((char*) szSection) + 1);
1.1 misho 222: } else
223: av->psSection = NULL;
224:
225: psAttr = szLine;
226: psVal = (szLine + pos + 1);
227: szLine[pos] = 0;
1.6 misho 228: io_RTrimStr(psAttr);
229: io_LTrimStr(psVal);
230: io_UnquotStr(psVal);
1.1 misho 231: #ifdef __DEBUG
232: cfgDbg(stdout, "DEBUG:: Attr(%p) ->%s size=%d Value(%p) ->%s size=%d\n",
233: psAttr, psAttr, strlen((char*) psAttr), psVal, psVal, strlen((char*) psVal));
234: #endif
235: // added attribute to element
236: av->psAttribute = malloc(strlen((char*) psAttr) + 1);
237: if (!av->psAttribute) {
238: LOGERR;
239: free(av->psSection);
240: free(av);
241: return -1;
242: } else
1.2 misho 243: strlcpy((char*) av->psAttribute, (char*) psAttr, strlen((char*) psAttr) + 1);
1.1 misho 244: // added value to element
245: av->psValue = malloc(strlen((char*) psVal) + 1);
246: if (!av->psValue) {
247: LOGERR;
248: free(av->psAttribute);
249: free(av->psSection);
250: free(av);
251: return -1;
252: } else
1.2 misho 253: strlcpy((char*) av->psValue, (char*) psVal, strlen((char*) psVal) + 1);
1.1 misho 254: }
255: }
256:
257: return 0;
258: }
259:
260: /*
261: * WriteConfig() Write to file from items in config list
262: * @f = file resource
263: * @cfg = Head list element
264: * return: 0 ok; -1 error:: can`t write to file
265: */
1.6.2.1 ! misho 266: int
! 267: WriteConfig(FILE *f, sl_config * __restrict cfg)
1.1 misho 268: {
1.3 misho 269: return cfgWrite(f, cfg, 1);
270: }
271:
272: /*
273: * cfg_WriteConfig() Write to file from items in config list without whitespaces!
274: * @f = file resource
275: * @cfg = Head list element
276: * return: 0 ok; -1 error:: can`t write to file
277: */
1.6.2.1 ! misho 278: int
! 279: cfg_WriteConfig(FILE *f, sl_config * __restrict cfg)
1.3 misho 280: {
281: return cfgWrite(f, cfg, 0);
282: }
283:
284: /*
285: * ConcatConfig() Concat two list in one
286: * @cfg = Head list element of main list
287: * @add_cfg = Head list element of added list
288: * return: 0 ok; -1 error:: can`t concat lists
289: */
1.6.2.1 ! misho 290: int
! 291: ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
1.3 misho 292: {
293: struct tagPair *item;
294: int ret = 0;
295:
296: if (!cfg || !add_cfg)
297: return -1;
298:
299: for (item = cfg->slh_first; item->sle_next; item = item->sle_next);
300: item->sle_next = add_cfg->slh_first;
301:
302: add_cfg->slh_first = NULL;
303:
304: return ret;
305: }
1.1 misho 306:
1.3 misho 307: /*
308: * MergeConfig() Marge two list in one cfg and destroy add_cfg
309: * @cfg = Head list element of main list
310: * @add_cfg = Head list element of merged list (destroy after all!)
311: * return: 0 ok; -1 error:: can`t merge lists
312: */
1.6.2.1 ! misho 313: int
! 314: MergeConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
1.3 misho 315: {
316: struct tagPair *item, *merge, *add_next, *next = NULL;
317: int flg;
1.1 misho 318:
1.3 misho 319: if (!cfg || !add_cfg)
1.1 misho 320: return -1;
321:
1.3 misho 322: item = add_cfg->slh_first;
323: while (item) {
324: add_next = item->sle_next;
325:
326: for (flg = 0, merge = cfg->slh_first, next = merge->sle_next; next;
327: merge = merge->sle_next, next = merge->sle_next) {
328: if (!merge->psSection && !item->psSection) {
329: flg = 1;
330: merge->sle_next = item;
331: item->sle_next = next;
332: break;
333: }
334: if (merge->psSection && item->psSection &&
335: !strcmp((char*) merge->psSection, (char*) item->psSection)) {
336: flg = 1;
337: merge->sle_next = item;
338: item->sle_next = next;
339: break;
1.1 misho 340: }
341: }
1.3 misho 342:
343: if (!flg) {
344: if (!merge->sle_next) {
345: merge->sle_next = item;
346: item->sle_next = NULL;
347: } else
1.1 misho 348: return -1;
349: }
350:
1.3 misho 351: item = add_next;
1.1 misho 352: }
353:
1.3 misho 354: add_cfg->slh_first = NULL;
1.1 misho 355:
356: return 0;
357: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>