Wed, 08 Jun 2022 19:26:43 +0200
revert optimization that does not harmonize with realloc()
/* * 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> /* 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 = NULL; //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, sstr_t 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(tag->name); //printf("line {%s}\n", sstrdub(ll).ptr); if(objconf_on_begin_tag(conf, tag) != 0) { fprintf(stderr, "1error\n"); exit(-1); } break; } case LINE_END_TAG: { sstr_t 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) { UcxAllocator *mp = conf->parser.mp; if(tag->type_num != TAG_OBJECT) { ConfigParserLevel *l = conf->levels->data; 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, sstr("name")); obj->ppath = cfg_param_get(tag->param, sstr("ppath")); conf->obj = obj; conf->objects = ucx_list_append_a(mp, conf->objects, obj); // create tree level object ConfigParserLevel *lvl = OBJ_NEW(mp, ConfigParserLevel); lvl->iftag = NULL; lvl->levelnum = 1; lvl->tag = tag; conf->levels = ucx_list_prepend_a(mp, conf->levels, lvl); break; } case TAG_IF: { // create tree level object ConfigParserLevel *last_lvl = conf->levels->data; 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); last_lvl->iftag = tag; break; } case TAG_ELSEIF: { } case TAG_ELSE: { // create tree level object ConfigParserLevel *last_lvl = conf->levels->data; 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); 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, sstr_t tagname) { int type = cfg_get_tag_type(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); } return 0; } int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir) { ConfigParserLevel *lvl = conf->levels->data; // 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); return 0; }