1 /* 2 * Copyright (c) 2001, 2002, 2003, 2004, 2005 Netli, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: ncnf_cr_y.y,v 1.1 2005/05/26 12:08:19 vlm Exp $ 27 */ 28 %{ 29 30 #undef NDEBUG 31 #include "headers.h" 32 #include "ncnf_int.h" 33 #include "ncnf.h" 34 35 #define YYPARSE_PARAM paramp 36 37 int yylex(void); 38 int yyerror(char *s); 39 40 extern int __ncnf_cr_lineno; 41 42 #define RELAXED_NS ((int)*((void **)YYPARSE_PARAM+1)) 43 #define ALLOC_NOBJ(_class) _ncnf_obj_new(0, _class, NULL, NULL, __ncnf_cr_lineno) 44 45 46 /* 47 * Quick wrapper around object attachment. 48 */ 49 #define ATTACH_OBJ(dst,src) do { \ 50 if(_ncnf_attach_obj(dst, src, RELAXED_NS)) { \ 51 int lineno = src->config_line; \ 52 _ncnf_obj_destroy(src); \ 53 _ncnf_obj_destroy(dst); \ 54 dst = NULL; \ 55 if(errno == EEXIST) { \ 56 __ncnf_cr_lineno = lineno; \ 57 yyerror("Similarly named entity already defined"); \ 58 } \ 59 YYABORT; \ 60 } \ 61 } while(0) 62 63 %} 64 65 /* 66 * Token value definition 67 */ 68 %union { 69 int tv_int; 70 bstr_t tv_str; 71 struct ncnf_obj_s *tv_obj; 72 } 73 74 /* 75 * Token types returned by scanner 76 */ 77 %token <tv_str> TOK_NAME 78 %token <tv_str> TOK_STRING 79 80 /* 81 * Reserved words 82 */ 83 %token ERROR 84 %token AT 85 %token SEMICOLON 86 %token INSERT INHERIT REF ATTACH 87 88 89 %type <tv_obj> sequence 90 %type <tv_obj> block 91 %type <tv_obj> object 92 %type <tv_obj> attribute 93 %type <tv_obj> insertion 94 %type <tv_obj> reference 95 %type <tv_obj> entity 96 %type <tv_int> reftype 97 98 %% 99 cfg_file: { 100 **(void ***)YYPARSE_PARAM = ALLOC_NOBJ(NOBJ_ROOT); 101 if(**(void ***)YYPARSE_PARAM == NULL) 102 YYABORT; 103 } 104 | sequence { 105 struct ncnf_obj_s *param_value = NULL; 106 107 if($1 == NULL) { 108 errno = EINVAL; 109 YYABORT; 110 } 111 112 if($1->obj_class == NOBJ_ROOT) { 113 param_value = $1; 114 } else { 115 param_value = ALLOC_NOBJ(NOBJ_ROOT); 116 if(param_value == NULL) { 117 _ncnf_obj_destroy($1); 118 YYABORT; 119 } else { 120 ATTACH_OBJ(param_value, $1); 121 } 122 } 123 124 /* Propagate root up to the caller */ 125 **(void ***)YYPARSE_PARAM = param_value; 126 } 127 ; 128 129 ps: 130 | SEMICOLON; 131 132 sequence: block ps { 133 if($1 == NULL) { 134 $$ = NULL; 135 yyclearin; 136 yyerrok; 137 break; 138 } 139 140 $$ = ALLOC_NOBJ(NOBJ_ROOT); 141 if($$ == NULL) { 142 _ncnf_obj_destroy($1); 143 $1 = NULL; 144 $$ = NULL; 145 YYABORT; 146 } else { 147 ATTACH_OBJ($$, $1); 148 } 149 } 150 | sequence block ps { 151 152 $$ = NULL; 153 if($1 == NULL) { 154 if($2) _ncnf_obj_destroy($2); 155 break; 156 } else if($2 == NULL) { 157 if($1) _ncnf_obj_destroy($1); 158 break; 159 } 160 161 if($1->obj_class == NOBJ_ROOT) { 162 $$ = $1; 163 164 ATTACH_OBJ($$, $2); 165 } else { 166 $$ = ALLOC_NOBJ(NOBJ_ROOT); 167 if($$ == NULL) { 168 _ncnf_obj_destroy($1); 169 _ncnf_obj_destroy($2); 170 $$ = NULL; 171 YYABORT; 172 } 173 174 /* Join two blocks under root */ 175 176 /* Insert a nested object 1 */ 177 if(_ncnf_attach_obj($$, $1, RELAXED_NS)) { 178 _ncnf_obj_destroy($1); 179 _ncnf_obj_destroy($2); /* Don't forget */ 180 _ncnf_obj_destroy($$); 181 $$ = NULL; 182 if(errno == EEXIST) 183 yyerror("Similarly named entity " 184 "already defined"); 185 YYABORT; 186 } else { 187 /* Insert object 2 */ 188 ATTACH_OBJ($$, $2); 189 } 190 } 191 } 192 ; 193 194 block: 195 object { $$ = $1; } 196 | attribute SEMICOLON { $$ = $1; } 197 | insertion SEMICOLON { $$ = $1; } 198 | reference SEMICOLON { $$ = $1; } 199 ; 200 201 object: 202 entity '{' '}' { 203 $$ = $1; 204 if($$) { 205 $$->obj_class = NOBJ_COMPLEX; 206 } 207 } 208 | entity '{' sequence '}' { 209 int c; 210 211 $$ = NULL; 212 if($1 == NULL) { 213 if($3) _ncnf_obj_destroy($3); 214 break; 215 } else if($3 == NULL) { 216 if($1) _ncnf_obj_destroy($1); 217 break; 218 } 219 220 assert($3->obj_class == NOBJ_ROOT); 221 222 $$ = $1; 223 $$->obj_class = NOBJ_COMPLEX; 224 225 for(c = 0; c < MAX_COLLECTIONS; c++) { 226 collection_t *coll_to = &($$)->m_collection[c]; 227 collection_t *coll_from = &($3)->m_collection[c]; 228 if(_ncnf_coll_join(($$)->mr, 229 coll_to, coll_from, $$, 230 (RELAXED_NS ? MERGE_NOFLAGS : MERGE_DUPCHECK) 231 | MERGE_EMPTYSRC)) 232 break; 233 } 234 235 /* Dispose the NCNF_ROOT wrapper around $3 */ 236 _ncnf_obj_destroy($3); 237 238 if(c < MAX_COLLECTIONS) { 239 _ncnf_obj_destroy($$); 240 $$ = NULL; 241 YYABORT; 242 } 243 } 244 ; 245 246 attribute: 247 entity { 248 $$ = $1; 249 if($$) { 250 $$->obj_class = NOBJ_ATTRIBUTE; 251 } 252 } 253 | TOK_NAME '=' TOK_NAME { 254 $$ = ALLOC_NOBJ(NOBJ_ATTRIBUTE); 255 if($$) { 256 $$->type = bstr_ref($1); 257 $$->value = bstr_ref($3); 258 $$->m_attr_flags |= 1; 259 } else { 260 YYABORT; 261 } 262 } 263 ; 264 265 insertion: 266 INSERT entity { 267 $$ = $2; 268 if($$) { 269 $$->obj_class = NOBJ_INSERTION; 270 } 271 } 272 | INHERIT entity { 273 $$ = $2; 274 if($$) { 275 $$->obj_class = NOBJ_INSERTION; 276 $$->m_insert_flags |= 1; 277 } 278 } 279 ; 280 281 reference: 282 reftype TOK_NAME TOK_STRING '=' TOK_NAME TOK_STRING { 283 $$ = ALLOC_NOBJ(NOBJ_REFERENCE); 284 if($$) { 285 $$->type = bstr_ref($2); 286 $$->value = bstr_ref($3); 287 $$->m_ref_type = bstr_ref($5); 288 $$->m_ref_value = bstr_ref($6); 289 $$->m_ref_flags = $1; 290 } else { 291 YYABORT; 292 } 293 } 294 | reftype TOK_NAME '=' TOK_NAME TOK_STRING { 295 $$ = ALLOC_NOBJ(NOBJ_REFERENCE); 296 if($$) { 297 $$->type = bstr_ref($2); 298 $$->value = bstr_ref($5); 299 $$->m_ref_type = bstr_ref($4); 300 $$->m_ref_value = bstr_ref($5); 301 $$->m_ref_flags = $1; 302 } else { 303 YYABORT; 304 } 305 } 306 | reftype '=' TOK_NAME TOK_STRING { 307 $$ = ALLOC_NOBJ(NOBJ_REFERENCE); 308 if($$) { 309 $$->type = bstr_ref($3); 310 $$->value = bstr_ref($4); 311 $$->m_ref_type = bstr_ref($3); 312 $$->m_ref_value = bstr_ref($4); 313 $$->m_ref_flags = $1; 314 } else { 315 YYABORT; 316 } 317 } 318 | reftype TOK_NAME TOK_STRING '=' TOK_STRING { 319 $$ = ALLOC_NOBJ(NOBJ_REFERENCE); 320 if($$) { 321 $$->type = bstr_ref($2); 322 $$->value = bstr_ref($3); 323 $$->m_ref_type = bstr_ref($2); 324 $$->m_ref_value = bstr_ref($5); 325 $$->m_ref_flags = $1; 326 } else { 327 YYABORT; 328 } 329 } 330 ; 331 332 reftype: 333 REF { 334 $$ = 0; 335 } 336 | ATTACH { 337 $$ = 1; 338 } 339 ; 340 341 entity: 342 TOK_NAME TOK_STRING { 343 $$ = ALLOC_NOBJ(-2); 344 if($$) { 345 $$->type = bstr_ref($1); 346 $$->value = bstr_ref($2); 347 } else { 348 YYABORT; 349 } 350 } 351 ; 352 353 354 %% 355 356 int 357 yyerror(char *s) { 358 if(s == NULL) { 359 switch(errno) { 360 case EEXIST: 361 s = "Entity already defined this context"; 362 break; 363 default: 364 s = strerror(errno); 365 } 366 } 367 368 _ncnf_debug_print(1, 369 "Config parse error near line %d: %s", 370 __ncnf_cr_lineno, s); 371 return -1; 372 }; 373 374