UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "objconf.h" 30 31 #include <string.h> 32 33 /* dev notes: 34 * 35 * to free ObjectConfig, free: 36 * line dlist 37 * mempool 38 * object 39 */ 40 41 ObjectConfig *load_object_config(char *file) { 42 FILE *in = fopen(file, "r"); 43 if(in == NULL) { 44 return NULL; 45 } 46 47 ObjectConfig *conf = malloc(sizeof(ObjectConfig)); 48 conf->parser.parse = objconf_parse; 49 conf->file = file; 50 conf->conditions = NULL; 51 conf->levels = NULL; 52 conf->objects = NULL; 53 //conf->lines = NULL; 54 55 int r = cfg_parse_basic_file((ConfigParser*)conf, in); 56 if(r != 0) { 57 // TODO: free 58 return NULL; 59 } 60 61 fclose(in); 62 63 return conf; 64 } 65 66 void free_object_config(ObjectConfig *conf) { 67 // free other lists 68 if(conf->levels) { 69 //ucx_list_free(conf->levels); 70 } 71 72 // free mempool 73 ucx_mempool_destroy(conf->parser.mp->pool); 74 free(conf); 75 } 76 77 78 79 int objconf_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line) { 80 ObjectConfig *conf = p; 81 82 begin->type = cfg_get_line_type(line); 83 switch(begin->type) { 84 case LINE_BEGIN_TAG: { 85 ConfigTag *tag = cfg_parse_begin_tag(line, conf->parser.mp); 86 if(tag == NULL) { 87 log_ereport(LOG_FAILURE, "Parse error in %s", conf->file); 88 exit(-1); // TODO: better error handling 89 } 90 tag->begin = begin; 91 tag->end = end; 92 tag->type_num = cfg_get_tag_type(tag->name); 93 //printf("line {%s}\n", sstrdub(ll).ptr); 94 if(objconf_on_begin_tag(conf, tag) != 0) { 95 fprintf(stderr, "1error\n"); 96 exit(-1); 97 } 98 break; 99 } 100 case LINE_END_TAG: { 101 sstr_t tag = cfg_get_end_tag_name(line); 102 if(objconf_on_end_tag(conf, tag) != 0) { 103 fprintf(stderr, "2error\n"); 104 exit(-1); 105 } 106 107 break; 108 } 109 case LINE_DIRECTIVE: { 110 ConfigDirective *dir = cfg_parse_directive( 111 line, 112 conf->parser.mp); 113 dir->begin = begin; 114 dir->end = end; 115 if(objconf_on_directive(conf, dir) != 0) { 116 fprintf(stderr, "3error\n"); 117 exit(-1); 118 } 119 } 120 } 121 return 0; 122 } 123 124 int objconf_on_begin_tag(ObjectConfig *conf, ConfigTag *tag) { 125 UcxAllocator *mp = conf->parser.mp; 126 if(tag->type_num != TAG_OBJECT) { 127 ConfigParserLevel *l = conf->levels->data; 128 if(l->tag->type_num != TAG_OBJECT) { 129 tag->parent = l->tag; 130 } 131 } 132 133 134 switch(tag->type_num) { 135 case TAG_OBJECT: { 136 ConfigObject *obj = OBJ_NEW_N(mp, ConfigObject); 137 obj->begin = tag->begin; 138 obj->end = tag->end; 139 140 obj->name = cfg_param_get(tag->param, sstr("name")); 141 obj->ppath = cfg_param_get(tag->param, sstr("ppath")); 142 143 conf->obj = obj; 144 conf->objects = ucx_list_append_a(mp, conf->objects, obj); 145 146 // create tree level object 147 ConfigParserLevel *lvl = OBJ_NEW(mp, ConfigParserLevel); 148 lvl->iftag = NULL; 149 lvl->levelnum = 1; 150 lvl->tag = tag; 151 conf->levels = ucx_list_prepend_a(mp, conf->levels, lvl); 152 153 break; 154 } 155 case TAG_IF: { 156 // create tree level object 157 ConfigParserLevel *last_lvl = conf->levels->data; 158 159 ConfigParserLevel *lvl = OBJ_NEW(mp, ConfigParserLevel); 160 161 lvl->iftag = NULL; 162 lvl->levelnum = last_lvl->levelnum + 1; 163 lvl->tag = tag; 164 conf->levels = ucx_list_prepend_a(mp, conf->levels, lvl); 165 last_lvl->iftag = tag; 166 167 break; 168 } 169 case TAG_ELSEIF: { 170 } 171 case TAG_ELSE: { 172 // create tree level object 173 ConfigParserLevel *last_lvl = conf->levels->data; 174 tag->iftag = last_lvl->iftag; 175 176 ConfigParserLevel *lvl = OBJ_NEW( 177 conf->parser.mp, 178 ConfigParserLevel); 179 180 lvl->iftag = last_lvl->tag; 181 lvl->levelnum = last_lvl->levelnum + 1; 182 lvl->tag = tag; 183 conf->levels = ucx_list_prepend(conf->levels, lvl); 184 185 break; 186 } 187 case TAG_CLIENT: { 188 // create tree level object 189 190 // TODO 191 192 break; 193 } 194 default: { 195 log_ereport(LOG_FAILURE, "objconf: unknown tag"); 196 return 1; 197 } 198 } 199 200 return 0; 201 } 202 203 int objconf_on_end_tag(ObjectConfig *conf, sstr_t tagname) { 204 int type = cfg_get_tag_type(tagname); 205 if(type == -1) { 206 log_ereport(LOG_FAILURE, "objconf: unknown tag"); 207 return 1; 208 } else { 209 if(type == TAG_OBJECT) { 210 conf->obj = NULL; 211 } 212 213 // remove level 214 conf->levels = ucx_list_remove_a( 215 conf->parser.mp, 216 conf->levels, 217 conf->levels); 218 } 219 220 return 0; 221 } 222 223 int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir) { 224 ConfigParserLevel *lvl = conf->levels->data; 225 226 // check if we have a condition for the directive 227 // if the level tag is not an object tag, use it as condition 228 if(lvl->tag->type_num != TAG_OBJECT) { 229 dir->condition = lvl->tag; 230 } 231 232 // add directive to current object 233 conf->obj->directives[dir->type_num] = ucx_list_append_a( 234 conf->parser.mp, 235 conf->obj->directives[dir->type_num], 236 dir); 237 238 return 0; 239 } 240 241