Sun, 06 Nov 2022 17:41:39 +0100
prepare serverconfig parser to be also used for obj.conf and init.conf
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "objconf.h" #include <string.h> #include <cx/utils.h> /* dev notes: * * to free ObjectConfig, free: * line dlist * mempool * object */ ObjectConfig *load_object_config(char *file) { FILE *in = fopen(file, "r"); if(in == NULL) { return NULL; } ObjectConfig *conf = malloc(sizeof(ObjectConfig)); conf->parser.parse = objconf_parse; conf->file = file; //conf->conditions = NULL; conf->levels = NULL; conf->objects = cxPointerLinkedListCreate(cxDefaultAllocator, cx_cmp_ptr); //conf->lines = NULL; int r = cfg_parse_basic_file((ConfigParser*)conf, in); if(r != 0) { // TODO: free return NULL; } fclose(in); return conf; } void free_object_config(ObjectConfig *conf) { // free other lists if(conf->levels) { //ucx_list_free(conf->levels); } // free mempool //ucx_mempool_destroy(conf->parser.mp->pool); free(conf); } int objconf_parse(void *p, ConfigLine *begin, ConfigLine *end, cxmutstr line) { ObjectConfig *conf = p; begin->type = cfg_get_line_type(line); switch(begin->type) { case LINE_BEGIN_TAG: { ConfigTag *tag = cfg_parse_begin_tag(line, conf->parser.mp); if(tag == NULL) { log_ereport(LOG_FAILURE, "Parse error in %s", conf->file); exit(-1); // TODO: better error handling } tag->begin = begin; tag->end = end; tag->type_num = cfg_get_tag_type(cx_strcast(tag->name)); //printf("line {%s}\n", cx_strdub(ll).ptr); if(objconf_on_begin_tag(conf, tag) != 0) { fprintf(stderr, "1error\n"); exit(-1); } break; } case LINE_END_TAG: { cxmutstr tag = cfg_get_end_tag_name(line); if(objconf_on_end_tag(conf, tag) != 0) { fprintf(stderr, "2error\n"); exit(-1); } break; } case LINE_DIRECTIVE: { ConfigDirective *dir = cfg_parse_directive( line, conf->parser.mp); dir->begin = begin; dir->end = end; if(objconf_on_directive(conf, dir) != 0) { fprintf(stderr, "3error\n"); exit(-1); } } } return 0; } int objconf_on_begin_tag(ObjectConfig *conf, ConfigTag *tag) { CxAllocator *mp = conf->parser.mp; if(tag->type_num != TAG_OBJECT) { ConfigParserLevel *l = conf->levels; if(l->tag->type_num != TAG_OBJECT) { tag->parent = l->tag; } } switch(tag->type_num) { case TAG_OBJECT: { ConfigObject *obj = OBJ_NEW_N(mp, ConfigObject); obj->begin = tag->begin; obj->end = tag->end; obj->name = cfg_param_get(tag->param, cx_str("name")); obj->ppath = cfg_param_get(tag->param, cx_str("ppath")); conf->obj = obj; //conf->objects = ucx_list_append_a(mp, conf->objects, obj); cxListAdd(conf->objects, obj); // create tree level object ConfigParserLevel *lvl = OBJ_NEW(mp, ConfigParserLevel); lvl->iftag = NULL; lvl->levelnum = 1; lvl->tag = tag; lvl->next = NULL; //conf->levels = ucx_list_prepend_a(mp, conf->levels, lvl); CFG_LEVEL_PREPEND(&conf->levels, lvl); break; } case TAG_IF: { // create tree level object ConfigParserLevel *last_lvl = conf->levels; ConfigParserLevel *lvl = OBJ_NEW(mp, ConfigParserLevel); lvl->iftag = NULL; lvl->levelnum = last_lvl->levelnum + 1; lvl->tag = tag; //conf->levels = ucx_list_prepend_a(mp, conf->levels, lvl); CFG_LEVEL_PREPEND(&conf->levels, lvl); last_lvl->iftag = tag; break; } case TAG_ELSEIF: { } case TAG_ELSE: { // create tree level object ConfigParserLevel *last_lvl = conf->levels; tag->iftag = last_lvl->iftag; ConfigParserLevel *lvl = OBJ_NEW( conf->parser.mp, ConfigParserLevel); lvl->iftag = last_lvl->tag; lvl->levelnum = last_lvl->levelnum + 1; lvl->tag = tag; //conf->levels = ucx_list_prepend(conf->levels, lvl); CFG_LEVEL_PREPEND(&conf->levels, lvl); break; } case TAG_CLIENT: { // create tree level object // TODO break; } default: { log_ereport(LOG_FAILURE, "objconf: unknown tag"); return 1; } } return 0; } int objconf_on_end_tag(ObjectConfig *conf, cxmutstr tagname) { int type = cfg_get_tag_type(cx_strcast(tagname)); if(type == -1) { log_ereport(LOG_FAILURE, "objconf: unknown tag"); return 1; } else { if(type == TAG_OBJECT) { conf->obj = NULL; } // remove level /* conf->levels = ucx_list_remove_a( conf->parser.mp, conf->levels, conf->levels); */ conf->levels = conf->levels->next; } return 0; } int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir) { ConfigParserLevel *lvl = conf->levels; // check if we have a condition for the directive // if the level tag is not an object tag, use it as condition if(lvl->tag->type_num != TAG_OBJECT) { dir->condition = lvl->tag; } // add directive to current object /* conf->obj->directives[dir->type_num] = ucx_list_append_a( conf->parser.mp, conf->obj->directives[dir->type_num], dir); */ ConfigDirectiveList *dir_entry = cxMalloc(conf->parser.mp, sizeof(ConfigDirectiveList)); dir_entry->directive = dir; dir_entry->next = NULL; CFG_DIRECTIVES_ADD(&conf->obj->directives[dir->type_num], dir_entry); return 0; }