Annotation of libaitcfg/src/parse.c, revision 1.6.4.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.4.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:
1.6.4.1 ! misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.6 misho 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:
1.6.4.1 ! misho 50: #if 0
1.1 misho 51: // cfgDbg() Debug/Log operation
52: static inline int cfgDbg(FILE *f, char *fmt, ...)
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: */
68: static inline void InvertQueue(sl_config * __restrict cfg)
69: {
70: struct tagPair *item, *next, *prev = NULL;
71:
72: for (item = cfg->slh_first; item; item = next) {
73: next = item->sle_next;
74: item->sle_next = prev;
75: prev = item;
76: }
77: cfg->slh_first = prev;
78: }
79:
80: // cfgWrite() Write to file from config list
81: static inline int cfgWrite(FILE *f, sl_config * __restrict cfg, int whitespace)
82: {
83: struct tagPair *av;
84: time_t tim;
85: char szTime[MAX_STR + 1];
86: u_char szSection[MAX_STR + 1];
87:
88: bzero(szSection, MAX_STR + 1);
89:
90: bzero(szTime, MAX_STR + 1);
91: time(&tim);
92: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
93: if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) {
94: LOGERR;
95: return -1;
96: }
97:
98: InvertQueue(cfg);
99: for (av = cfg->slh_first; av; av = av->sle_next) {
100: if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) {
101: strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1);
102: if (!cfgDbg(f, "\n[%s]\n", av->psSection)) {
103: LOGERR;
104: return -1;
105: }
106: }
107: if (!av->psSection && *szSection) {
108: bzero(szSection, MAX_STR + 1);
109: if (!cfgDbg(f, "\n[]\n")) {
110: LOGERR;
111: return -1;
112: }
113: }
114:
115: if (whitespace) {
116: if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) {
117: LOGERR;
118: return -1;
119: }
120: } else {
121: if (!cfgDbg(f, "%s=%s\n", av->psAttribute, av->psValue)) {
122: LOGERR;
123: return -1;
124: }
125: }
126: }
127: InvertQueue(cfg);
128:
129: bzero(szTime, MAX_STR + 1);
130: time(&tim);
131: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
132: if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) {
133: LOGERR;
134: return -1;
135: }
136:
137: return 0;
138: }
139:
140: // ---------------------------------------------------
1.6.4.1 ! misho 141: #endif
1.1 misho 142:
143: /*
1.6.4.1 ! misho 144: * cfgReadConfig() - Read file and add new item at config root
! 145: *
! 146: * @f = File resource
! 147: * @cfg = Config root
! 148: * return: -1 error or 0 ok
! 149: */
! 150: int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg)
1.1 misho 151: {
1.6.4.1 ! misho 152: char line[BUFSIZ];
! 153: struct tagCfg *av = NULL;
! 154: int flg = 0;
! 155: char *psAttr, *psVal, szSection[STRSIZ] = { 0 };
1.1 misho 156:
157: while (!feof(f)) {
1.6.4.1 ! misho 158: memset(line, 0, sizeof line);
! 159: fgets(line, sizeof line - 1, f);
! 160: #ifdef SUPPORT_USER_EOF
! 161: /* check for user end-of-file */
! 162: if (line[0] == '.' && line[1] == '\n')
! 163: break;
1.1 misho 164: #endif
1.6.4.1 ! misho 165: if (!(psAttr = strpbrk(line, "\r\n"))) {
! 166: /* skip line, too long */
! 167: continue;
! 168: } else {
! 169: *psAttr = 0;
! 170: io_TrimStr(line);
! 171: }
1.1 misho 172:
1.6.4.1 ! misho 173: if (flg) {
! 174: /* continues line */
! 175: if (!av)
! 176: continue;
! 177: else
! 178: psAttr = line + strlen(line) - 1;
! 179: if (*psAttr == '\\')
! 180: *psAttr = 0;
! 181: else
! 182: flg = 0;
! 183: /* concat line to value */
! 184: AIT_SET_STRCAT(&av->cfg_val, line);
! 185: if (!flg)
! 186: io_UnquotStr((char*) AIT_GET_STR(&av->cfg_val));
1.1 misho 187: continue;
1.6.4.1 ! misho 188: }
1.1 misho 189:
1.6.4.1 ! misho 190: /* *NEW PAIR* alloc new pair element */
! 191: av = malloc(sizeof(struct tagCfg));
! 192: if (!av) {
! 193: LOGERR;
! 194: return -1;
! 195: } else {
! 196: memset(av, 0, sizeof(struct tagCfg));
! 197: CFG_RC_LOCK(cfg);
! 198: SLIST_INSERT_HEAD(cfg, av, cfg_next);
! 199: CFG_RC_UNLOCK(cfg);
! 200: }
1.1 misho 201:
1.6.4.1 ! misho 202: /* check for continues line */
! 203: psAttr = line + strlen(line) - 1;
! 204: if (*psAttr == '\\') {
! 205: *psAttr = 0;
! 206: flg = 1;
1.1 misho 207: }
208:
1.6.4.1 ! misho 209: /* check for comment or empty line */
! 210: if (!*line || *line == '#' || *line == ';') {
! 211: AIT_SET_STR(&av->cfg_val, line);
1.1 misho 212: continue;
1.6.4.1 ! misho 213: }
! 214: /* section */
! 215: if (*line == '[') {
! 216: AIT_SET_STR(&av->cfg_val, line);
! 217: psAttr = line + strlen(line) - 1;
! 218: if (*psAttr == ']') {
! 219: *psAttr = 0;
! 220: flg = 0;
! 221: strlcpy(szSection, line + 1, sizeof szSection);
1.1 misho 222: } else
1.6.4.1 ! misho 223: ioDEBUG(7, "Ignore section '%s' ... not found ']'", line);
! 224: continue;
! 225: }
! 226: /* parse pair */
! 227: if (!(psAttr = strchr(line, '='))) {
! 228: AIT_SET_STR(&av->cfg_val, line);
! 229: ioDEBUG(7, "Ignore a/v '%s' ... not found '='", line);
! 230: continue;
! 231: } else {
! 232: *psAttr = 0;
! 233: psVal = psAttr + 1;
! 234: psAttr = line;
! 235: }
1.1 misho 236:
1.6.4.1 ! misho 237: /* if exists, added section name to element */
! 238: if (*szSection) {
! 239: AIT_SET_STR(&av->cfg_sec, szSection);
! 240: AIT_KEY(&av->cfg_sec) = crcFletcher16(AIT_GET_LIKE(&av->cfg_sec, u_short*),
! 241: io_align(AIT_LEN(&av->cfg_sec) - 1, 1) / 2);
1.1 misho 242: }
1.6.4.1 ! misho 243:
! 244: io_RTrimStr(psAttr);
! 245: io_LTrimStr(psVal);
! 246: if (!flg)
! 247: io_UnquotStr(psVal);
! 248: AIT_SET_STR(&av->cfg_val, psVal);
! 249: AIT_SET_STR(&av->cfg_attr, psAttr);
! 250: AIT_KEY(&av->cfg_attr) = crcFletcher16(AIT_GET_LIKE(&av->cfg_attr, u_short*),
! 251: io_align(AIT_LEN(&av->cfg_attr) - 1, 1) / 2);
! 252:
! 253: CFG_RC_LOCK(cfg);
! 254: RB_INSERT(tagRC, cfg, av);
! 255: CFG_RC_UNLOCK(cfg);
1.1 misho 256: }
257:
258: return 0;
259: }
260:
1.6.4.1 ! misho 261: #if 0
1.1 misho 262: /*
263: * WriteConfig() Write to file from items in config list
264: * @f = file resource
265: * @cfg = Head list element
266: * return: 0 ok; -1 error:: can`t write to file
267: */
268: int WriteConfig(FILE *f, sl_config * __restrict cfg)
269: {
1.3 misho 270: return cfgWrite(f, cfg, 1);
271: }
272:
273: /*
274: * cfg_WriteConfig() Write to file from items in config list without whitespaces!
275: * @f = file resource
276: * @cfg = Head list element
277: * return: 0 ok; -1 error:: can`t write to file
278: */
279: int cfg_WriteConfig(FILE *f, sl_config * __restrict cfg)
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: */
290: int ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
291: {
292: struct tagPair *item;
293: int ret = 0;
294:
295: if (!cfg || !add_cfg)
296: return -1;
297:
298: for (item = cfg->slh_first; item->sle_next; item = item->sle_next);
299: item->sle_next = add_cfg->slh_first;
300:
301: add_cfg->slh_first = NULL;
302:
303: return ret;
304: }
1.1 misho 305:
1.3 misho 306: /*
307: * MergeConfig() Marge two list in one cfg and destroy add_cfg
308: * @cfg = Head list element of main list
309: * @add_cfg = Head list element of merged list (destroy after all!)
310: * return: 0 ok; -1 error:: can`t merge lists
311: */
312: int MergeConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
313: {
314: struct tagPair *item, *merge, *add_next, *next = NULL;
315: int flg;
1.1 misho 316:
1.3 misho 317: if (!cfg || !add_cfg)
1.1 misho 318: return -1;
319:
1.3 misho 320: item = add_cfg->slh_first;
321: while (item) {
322: add_next = item->sle_next;
323:
324: for (flg = 0, merge = cfg->slh_first, next = merge->sle_next; next;
325: merge = merge->sle_next, next = merge->sle_next) {
326: if (!merge->psSection && !item->psSection) {
327: flg = 1;
328: merge->sle_next = item;
329: item->sle_next = next;
330: break;
331: }
332: if (merge->psSection && item->psSection &&
333: !strcmp((char*) merge->psSection, (char*) item->psSection)) {
334: flg = 1;
335: merge->sle_next = item;
336: item->sle_next = next;
337: break;
1.1 misho 338: }
339: }
1.3 misho 340:
341: if (!flg) {
342: if (!merge->sle_next) {
343: merge->sle_next = item;
344: item->sle_next = NULL;
345: } else
1.1 misho 346: return -1;
347: }
348:
1.3 misho 349: item = add_next;
1.1 misho 350: }
351:
1.3 misho 352: add_cfg->slh_first = NULL;
1.1 misho 353:
354: return 0;
355: }
1.6.4.1 ! misho 356: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>