Annotation of libaitcfg/src/parse.c, revision 1.6

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>