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>