1 #include "first.h" 2 3 #include "array.h" 4 #include "configfile.h" 5 6 #include <string.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #ifdef HAVE_PCRE_H 11 #include <pcre.h> 12 #endif 13 14 __attribute_cold__ 15 static data_unset *data_config_copy(const data_unset *s) { 16 data_config *src = (data_config *)s; 17 data_config *ds = data_config_init(); 18 19 ds->comp = src->comp; 20 if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&ds->key, &src->key); 21 buffer_copy_buffer(ds->comp_tag, src->comp_tag); 22 buffer_copy_buffer(ds->comp_key, src->comp_key); 23 array_copy_array(ds->value, src->value); 24 return (data_unset *)ds; 25 } 26 27 __attribute_cold__ 28 static void data_config_free(data_unset *d) { 29 data_config *ds = (data_config *)d; 30 31 free(ds->key.ptr); 32 buffer_free(ds->comp_tag); 33 buffer_free(ds->comp_key); 34 35 array_free(ds->value); 36 vector_config_weak_clear(&ds->children); 37 38 free(ds->string.ptr); 39 #ifdef HAVE_PCRE_H 40 if (ds->regex) pcre_free(ds->regex); 41 if (ds->regex_study) pcre_free(ds->regex_study); 42 #endif 43 44 free(d); 45 } 46 47 __attribute_cold__ 48 static int data_config_insert_dup(data_unset *dst, data_unset *src) { 49 UNUSED(dst); 50 51 src->fn->free(src); 52 53 return 0; 54 } 55 56 __attribute_cold__ 57 static void data_config_print(const data_unset *d, int depth) { 58 data_config *ds = (data_config *)d; 59 array *a = (array *)ds->value; 60 size_t i; 61 size_t maxlen; 62 63 if (0 == ds->context_ndx) { 64 fprintf(stdout, "config {\n"); 65 } 66 else { 67 if (ds->cond != CONFIG_COND_ELSE) { 68 fprintf(stdout, "$%s %s \"%s\" {\n", 69 ds->comp_key->ptr, ds->op, ds->string.ptr); 70 } else { 71 fprintf(stdout, "{\n"); 72 } 73 array_print_indent(depth + 1); 74 fprintf(stdout, "# block %d\n", ds->context_ndx); 75 } 76 depth ++; 77 78 maxlen = array_get_max_key_length(a); 79 for (i = 0; i < a->used; i ++) { 80 data_unset *du = a->data[i]; 81 size_t len = buffer_string_length(&du->key); 82 size_t j; 83 84 array_print_indent(depth); 85 fprintf(stdout, "%s", du->key.ptr); 86 for (j = maxlen - len; j > 0; j --) { 87 fprintf(stdout, " "); 88 } 89 fprintf(stdout, " = "); 90 du->fn->print(du, depth); 91 fprintf(stdout, "\n"); 92 } 93 94 fprintf(stdout, "\n"); 95 for (i = 0; i < ds->children.used; i ++) { 96 data_config *dc = ds->children.data[i]; 97 98 /* only the 1st block of chaining */ 99 if (NULL == dc->prev) { 100 fprintf(stdout, "\n"); 101 array_print_indent(depth); 102 dc->fn->print((data_unset *) dc, depth); 103 fprintf(stdout, "\n"); 104 } 105 } 106 107 depth --; 108 array_print_indent(depth); 109 fprintf(stdout, "}"); 110 if (0 != ds->context_ndx) { 111 if (ds->cond != CONFIG_COND_ELSE) { 112 fprintf(stdout, " # end of $%s %s \"%s\"", 113 ds->comp_key->ptr, ds->op, ds->string.ptr); 114 } else { 115 fprintf(stdout, " # end of else"); 116 } 117 } 118 119 if (ds->next) { 120 fprintf(stdout, "\n"); 121 array_print_indent(depth); 122 fprintf(stdout, "else "); 123 ds->next->fn->print((data_unset *)ds->next, depth); 124 } 125 } 126 127 data_config *data_config_init(void) { 128 static const struct data_methods fn = { 129 data_config_copy, 130 data_config_free, 131 data_config_insert_dup, 132 data_config_print, 133 }; 134 data_config *ds; 135 136 ds = calloc(1, sizeof(*ds)); 137 138 ds->comp_tag = buffer_init(); 139 ds->comp_key = buffer_init(); 140 ds->value = array_init(4); 141 vector_config_weak_init(&ds->children); 142 143 ds->type = TYPE_CONFIG; 144 ds->fn = &fn; 145 146 return ds; 147 } 148 149 int data_config_pcre_compile(data_config *dc) { 150 #ifdef HAVE_PCRE_H 151 /* (use fprintf() on error, as this is called from configparser.y) */ 152 const char *errptr; 153 int erroff, captures; 154 155 if (dc->regex) pcre_free(dc->regex); 156 if (dc->regex_study) pcre_free(dc->regex_study); 157 158 dc->regex = pcre_compile(dc->string.ptr, 0, &errptr, &erroff, NULL); 159 if (NULL == dc->regex) { 160 fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", 161 dc->string.ptr, errptr, erroff); 162 return 0; 163 } 164 165 dc->regex_study = pcre_study(dc->regex, 0, &errptr); 166 if (NULL == dc->regex_study && errptr != NULL) { 167 fprintf(stderr, "studying regex failed: %s -> %s\n", 168 dc->string.ptr, errptr); 169 return 0; 170 } 171 172 erroff = pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, 173 &captures); 174 if (0 != erroff) { 175 fprintf(stderr, "getting capture count for regex failed: %s\n", 176 dc->string.ptr); 177 return 0; 178 } else if (captures > 9) { 179 fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n", 180 dc->string.ptr); 181 return 0; 182 } 183 return 1; 184 #else 185 fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n" 186 "(perhaps just a missing pcre-devel package ?) \n", 187 dc->comp_key->ptr, dc->comp_tag->ptr); 188 return 0; 189 #endif 190 } 191