1 /* 2 * Copyright 2011 Tresys Technology, LLC. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS 15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * The views and conclusions contained in the software and documentation are those 26 * of the authors and should not be interpreted as representing official policies, 27 * either expressed or implied, of Tresys Technology, LLC. 28 */ 29 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <stdint.h> 34 #include <sepol/errcodes.h> 35 36 #include "cil_internal.h" 37 #include "cil_log.h" 38 #include "cil_mem.h" 39 #include "cil_tree.h" 40 #include "cil_lexer.h" 41 #include "cil_strpool.h" 42 43 int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree) 44 { 45 46 int paren_count = 0; 47 48 struct cil_tree *tree = NULL; 49 struct cil_tree_node *node = NULL; 50 struct cil_tree_node *item = NULL; 51 struct cil_tree_node *current = NULL; 52 char *path = cil_strpool_add(_path); 53 54 struct token tok; 55 56 cil_lexer_setup(buffer, size); 57 58 tree = *parse_tree; 59 current = tree->root; 60 61 do { 62 cil_lexer_next(&tok); 63 switch (tok.type) { 64 case OPAREN: 65 paren_count++; 66 cil_tree_node_init(&node); 67 node->parent = current; 68 node->flavor = CIL_NODE; 69 node->line = tok.line; 70 node->path = path; 71 if (current->cl_head == NULL) { 72 current->cl_head = node; 73 } else { 74 current->cl_tail->next = node; 75 } 76 current->cl_tail = node; 77 current = node; 78 break; 79 case CPAREN: 80 paren_count--; 81 if (paren_count < 0) { 82 cil_log(CIL_ERR, "Close parenthesis without matching open at line %d of %s\n", tok.line, path); 83 return SEPOL_ERR; 84 } 85 current = current->parent; 86 break; 87 case SYMBOL: 88 case QSTRING: 89 if (paren_count == 0) { 90 cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path); 91 return SEPOL_ERR; 92 } 93 cil_tree_node_init(&item); 94 item->parent = current; 95 if (tok.type == QSTRING) { 96 tok.value[strlen(tok.value) - 1] = '\0'; 97 item->data = cil_strpool_add(tok.value + 1); 98 } else { 99 item->data = cil_strpool_add(tok.value); 100 } 101 item->flavor = CIL_NODE; 102 item->line = tok.line; 103 item->path = path; 104 if (current->cl_head == NULL) { 105 current->cl_head = item; 106 } else { 107 current->cl_tail->next = item; 108 } 109 current->cl_tail = item; 110 break; 111 case END_OF_FILE: 112 if (paren_count > 0) { 113 cil_log(CIL_ERR, "Open parenthesis without matching close at line %d of %s\n", tok.line, path); 114 return SEPOL_ERR; 115 } 116 break; 117 case COMMENT: 118 // ignore 119 break; 120 case UNKNOWN: 121 cil_log(CIL_ERR, "Invalid token '%s' at line %d of %s\n", tok.value, tok.line, path); 122 return SEPOL_ERR; 123 default: 124 cil_log(CIL_ERR, "Unknown token type '%d' at line %d of %s\n", tok.type, tok.line, path); 125 return SEPOL_ERR; 126 } 127 } 128 while (tok.type != END_OF_FILE); 129 130 cil_lexer_destroy(); 131 132 *parse_tree = tree; 133 134 return SEPOL_OK; 135 } 136