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>