Return to parse.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / libaitcfg / src |
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.5.2.1 ! misho 6: * $Id: parse.c,v 1.5 2010/03/22 15:15:48 misho Exp $
1.2 misho 7: *
8: *************************************************************************/
1.1 misho 9: #include "global.h"
10: #include "aitcfg.h"
11:
12:
13: // cfgDbg() Debug/Log operation
14: static inline int cfgDbg(FILE *f, char *fmt, ...)
15: {
16: int ret = 0;
17: va_list lst;
18:
19: va_start(lst, fmt);
20: ret = vfprintf(f, fmt, lst);
21: va_end(lst);
22:
23: return ret;
24: }
25:
1.3 misho 26: /*
27: * InvertQueue() InvertQueue order //{cfg} list of elements for revert
28: * @cfg = Head list element for revert
29: */
30: static inline void InvertQueue(sl_config * __restrict cfg)
31: {
32: struct tagPair *item, *next, *prev = NULL;
33:
34: for (item = cfg->slh_first; item; item = next) {
35: next = item->sle_next;
36: item->sle_next = prev;
37: prev = item;
38: }
39: cfg->slh_first = prev;
40: }
41:
42: // cfgWrite() Write to file from config list
43: static inline int cfgWrite(FILE *f, sl_config * __restrict cfg, int whitespace)
44: {
45: struct tagPair *av;
46: time_t tim;
47: char szTime[MAX_STR + 1];
48: u_char szSection[MAX_STR + 1];
49:
50: bzero(szSection, MAX_STR + 1);
51:
52: bzero(szTime, MAX_STR + 1);
53: time(&tim);
54: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
55: if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) {
56: LOGERR;
57: return -1;
58: }
59:
60: InvertQueue(cfg);
61: for (av = cfg->slh_first; av; av = av->sle_next) {
62: if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) {
63: strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1);
64: if (!cfgDbg(f, "\n[%s]\n", av->psSection)) {
65: LOGERR;
66: return -1;
67: }
68: }
69: if (!av->psSection && *szSection) {
70: bzero(szSection, MAX_STR + 1);
71: if (!cfgDbg(f, "\n[]\n")) {
72: LOGERR;
73: return -1;
74: }
75: }
76:
77: if (whitespace) {
78: if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) {
79: LOGERR;
80: return -1;
81: }
82: } else {
83: if (!cfgDbg(f, "%s=%s\n", av->psAttribute, av->psValue)) {
84: LOGERR;
85: return -1;
86: }
87: }
88: }
89: InvertQueue(cfg);
90:
91: bzero(szTime, MAX_STR + 1);
92: time(&tim);
93: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
94: if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) {
95: LOGERR;
96: return -1;
97: }
98:
99: return 0;
100: }
101:
102: // ---------------------------------------------------
1.1 misho 103:
104: /*
105: * ReadConfig() Read from file and add new item to config list
106: * @f = file resource
107: * @cfg = Head list element
108: * return: 0 ok; -1 error:: can`t allocate memory
109: */
110: int ReadConfig(FILE *f, sl_config * __restrict cfg)
111: {
112: u_char szLine[MAX_STR + 1];
113: u_char szSection[MAX_STR + 1], *psAttr, *psVal;
114: int pos;
115: struct tagPair *av;
116:
117: memset(szSection, 0, MAX_STR + 1);
118: while (!feof(f)) {
119: memset(szLine, 0, MAX_STR + 1);
120: fgets((char*) szLine, MAX_STR, f);
121: trim(szLine);
122: #ifdef __DEBUG
123: cfgDbg(stdout, "DEBUG:: RAW |%s|\n", szLine);
124: #endif
125:
126: // End of config
127: if (*szLine == '.')
128: break;
129: // Comment
130: if (*szLine == '#' || *szLine == ';' || !*szLine)
131: continue;
132:
133: #ifdef __DEBUG
134: cfgDbg(stdout, "DEBUG:: Clean |%s|\n", szLine);
135: #endif
136:
137: // Section
138: if (*szLine == '[') {
139: pos = strlen((char*) szLine) - 1;
140: if (szLine[pos] != ']') {
1.2 misho 141: #ifdef __DEBUG
1.1 misho 142: cfgDbg(stdout, "WARNING:: Ignore section %s ... not closed breket\n", szLine);
1.2 misho 143: #endif
1.1 misho 144: } else {
145: szLine[pos] = 0;
146: strncpy((char*) szSection, (char*) szLine + 1, MAX_STR);
147: #ifdef __DEBUG
148: cfgDbg(stdout, "DEBUG:: Section %s\n", szSection);
149: #endif
150: }
151: continue;
152: }
153:
154: // Devide pairs
155: pos = strchr((char*) szLine, '=') ? strchr((char*) szLine, '=') - (char*) szLine : 0;
156: if (!pos) {
1.2 misho 157: #ifdef __DEBUG
1.1 misho 158: cfgDbg(stdout, "WARNING:: Ignore a/v %s ... format error!\n", szLine);
1.2 misho 159: #endif
1.1 misho 160: continue;
161: } else {
162: av = malloc(sizeof(struct tagPair));
163: if (!av) {
164: LOGERR;
165: return -1;
166: } else {
1.2 misho 167: memset(av, 0, sizeof(struct tagPair));
1.1 misho 168: // added new element
169: av->sle_next = cfg->slh_first;
170: cfg->slh_first = av;
171: }
172: // added section name to element
173: if (*szSection) {
174: av->psSection = malloc(strlen((char*) szSection) + 1);
175: if (!av->psSection) {
176: LOGERR;
177: free(av);
178: return -1;
179: } else
1.2 misho 180: strlcpy((char*) av->psSection, (char*) szSection, strlen((char*) szSection) + 1);
1.1 misho 181: } else
182: av->psSection = NULL;
183:
184: psAttr = szLine;
185: psVal = (szLine + pos + 1);
186: szLine[pos] = 0;
187: rtrim(psAttr);
188: ltrim(psVal);
1.4 misho 189: unquot(psVal);
1.1 misho 190: #ifdef __DEBUG
191: cfgDbg(stdout, "DEBUG:: Attr(%p) ->%s size=%d Value(%p) ->%s size=%d\n",
192: psAttr, psAttr, strlen((char*) psAttr), psVal, psVal, strlen((char*) psVal));
193: #endif
194: // added attribute to element
195: av->psAttribute = malloc(strlen((char*) psAttr) + 1);
196: if (!av->psAttribute) {
197: LOGERR;
198: free(av->psSection);
199: free(av);
200: return -1;
201: } else
1.2 misho 202: strlcpy((char*) av->psAttribute, (char*) psAttr, strlen((char*) psAttr) + 1);
1.1 misho 203: // added value to element
204: av->psValue = malloc(strlen((char*) psVal) + 1);
205: if (!av->psValue) {
206: LOGERR;
207: free(av->psAttribute);
208: free(av->psSection);
209: free(av);
210: return -1;
211: } else
1.2 misho 212: strlcpy((char*) av->psValue, (char*) psVal, strlen((char*) psVal) + 1);
1.1 misho 213: }
214: }
215:
216: return 0;
217: }
218:
219: /*
220: * WriteConfig() Write to file from items in config list
221: * @f = file resource
222: * @cfg = Head list element
223: * return: 0 ok; -1 error:: can`t write to file
224: */
225: int WriteConfig(FILE *f, sl_config * __restrict cfg)
226: {
1.3 misho 227: return cfgWrite(f, cfg, 1);
228: }
229:
230: /*
231: * cfg_WriteConfig() Write to file from items in config list without whitespaces!
232: * @f = file resource
233: * @cfg = Head list element
234: * return: 0 ok; -1 error:: can`t write to file
235: */
236: int cfg_WriteConfig(FILE *f, sl_config * __restrict cfg)
237: {
238: return cfgWrite(f, cfg, 0);
239: }
240:
241: /*
242: * ConcatConfig() Concat two list in one
243: * @cfg = Head list element of main list
244: * @add_cfg = Head list element of added list
245: * return: 0 ok; -1 error:: can`t concat lists
246: */
247: int ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
248: {
249: struct tagPair *item;
250: int ret = 0;
251:
252: if (!cfg || !add_cfg)
253: return -1;
254:
255: for (item = cfg->slh_first; item->sle_next; item = item->sle_next);
256: item->sle_next = add_cfg->slh_first;
257:
258: add_cfg->slh_first = NULL;
259:
260: return ret;
261: }
1.1 misho 262:
1.3 misho 263: /*
264: * MergeConfig() Marge two list in one cfg and destroy add_cfg
265: * @cfg = Head list element of main list
266: * @add_cfg = Head list element of merged list (destroy after all!)
267: * return: 0 ok; -1 error:: can`t merge lists
268: */
269: int MergeConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
270: {
271: struct tagPair *item, *merge, *add_next, *next = NULL;
272: int flg;
1.1 misho 273:
1.3 misho 274: if (!cfg || !add_cfg)
1.1 misho 275: return -1;
276:
1.3 misho 277: item = add_cfg->slh_first;
278: while (item) {
279: add_next = item->sle_next;
280:
281: for (flg = 0, merge = cfg->slh_first, next = merge->sle_next; next;
282: merge = merge->sle_next, next = merge->sle_next) {
283: if (!merge->psSection && !item->psSection) {
284: flg = 1;
285: merge->sle_next = item;
286: item->sle_next = next;
287: break;
288: }
289: if (merge->psSection && item->psSection &&
290: !strcmp((char*) merge->psSection, (char*) item->psSection)) {
291: flg = 1;
292: merge->sle_next = item;
293: item->sle_next = next;
294: break;
1.1 misho 295: }
296: }
1.3 misho 297:
298: if (!flg) {
299: if (!merge->sle_next) {
300: merge->sle_next = item;
301: item->sle_next = NULL;
302: } else
1.1 misho 303: return -1;
304: }
305:
1.3 misho 306: item = add_next;
1.1 misho 307: }
308:
1.3 misho 309: add_cfg->slh_first = NULL;
1.1 misho 310:
311: return 0;
312: }