1 /**
2 * oconfig - src/oconfig.c
3 * Copyright (C) 2006,2007 Florian octo Forster <octo at verplant.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <assert.h>
23 #include <errno.h>
25 #include "oconfig.h"
27 extern FILE *yyin;
29 oconfig_item_t *ci_root;
30 const char *c_file;
32 static void yyset_in (FILE *fd)
33 {
34 yyin = fd;
35 } /* void yyset_in */
37 oconfig_item_t *oconfig_parse_fh (FILE *fh)
38 {
39 int status;
40 oconfig_item_t *ret;
42 char file[10];
44 yyset_in (fh);
46 if (NULL == c_file) {
47 int status;
49 status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
51 if ((status < 0) || (status >= sizeof (file))) {
52 c_file = "<unknown>";
53 }
54 else {
55 file[sizeof (file) - 1] = '\0';
56 c_file = file;
57 }
58 }
60 status = yyparse ();
61 if (status != 0)
62 {
63 fprintf (stderr, "yyparse returned error #%i\n", status);
64 return (NULL);
65 }
67 c_file = NULL;
69 ret = ci_root;
70 ci_root = NULL;
71 yyset_in ((FILE *) 0);
73 return (ret);
74 } /* oconfig_item_t *oconfig_parse_fh */
76 oconfig_item_t *oconfig_parse_file (const char *file)
77 {
78 FILE *fh;
79 oconfig_item_t *ret;
81 c_file = file;
83 fh = fopen (file, "r");
84 if (fh == NULL)
85 {
86 fprintf (stderr, "fopen (%s) failed: %s\n", file, strerror (errno));
87 return (NULL);
88 }
90 ret = oconfig_parse_fh (fh);
91 fclose (fh);
93 c_file = NULL;
95 return (ret);
96 } /* oconfig_item_t *oconfig_parse_file */
98 oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
99 {
100 oconfig_item_t *ci_copy;
102 ci_copy = (oconfig_item_t *) malloc (sizeof (*ci_copy));
103 if (ci_copy == NULL)
104 {
105 fprintf (stderr, "malloc failed.\n");
106 return (NULL);
107 }
108 memset (ci_copy, 0, sizeof (*ci_copy));
109 ci_copy->values = NULL;
110 ci_copy->parent = NULL;
111 ci_copy->children = NULL;
113 ci_copy->key = strdup (ci_orig->key);
114 if (ci_copy->key == NULL)
115 {
116 fprintf (stderr, "strdup failed.\n");
117 free (ci_copy);
118 return (NULL);
119 }
121 if (ci_orig->values_num > 0) /* {{{ */
122 {
123 int i;
125 ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
126 sizeof (*ci_copy->values));
127 if (ci_copy->values == NULL)
128 {
129 fprintf (stderr, "calloc failed.\n");
130 free (ci_copy->key);
131 free (ci_copy);
132 return (NULL);
133 }
134 ci_copy->values_num = ci_orig->values_num;
136 for (i = 0; i < ci_copy->values_num; i++)
137 {
138 ci_copy->values[i].type = ci_orig->values[i].type;
139 if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
140 {
141 ci_copy->values[i].value.string
142 = strdup (ci_orig->values[i].value.string);
143 if (ci_copy->values[i].value.string == NULL)
144 {
145 fprintf (stderr, "strdup failed.\n");
146 oconfig_free (ci_copy);
147 return (NULL);
148 }
149 }
150 else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
151 {
152 ci_copy->values[i].value = ci_orig->values[i].value;
153 }
154 }
155 } /* }}} if (ci_orig->values_num > 0) */
157 if (ci_orig->children_num > 0) /* {{{ */
158 {
159 int i;
161 ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
162 sizeof (*ci_copy->children));
163 if (ci_copy->children == NULL)
164 {
165 fprintf (stderr, "calloc failed.\n");
166 oconfig_free (ci_copy);
167 return (NULL);
168 }
169 ci_copy->children_num = ci_orig->children_num;
171 for (i = 0; i < ci_copy->children_num; i++)
172 {
173 oconfig_item_t *child;
175 child = oconfig_clone (ci_orig->children + i);
176 if (child == NULL)
177 {
178 oconfig_free (ci_copy);
179 return (NULL);
180 }
181 child->parent = ci_copy;
182 ci_copy->children[i] = *child;
183 free (child);
184 } /* for (i = 0; i < ci_copy->children_num; i++) */
185 } /* }}} if (ci_orig->children_num > 0) */
187 return (ci_copy);
188 } /* oconfig_item_t *oconfig_clone */
190 void oconfig_free (oconfig_item_t *ci)
191 {
192 int i;
194 if (ci == NULL)
195 return;
197 if (ci->key != NULL)
198 free (ci->key);
200 for (i = 0; i < ci->values_num; i++)
201 if ((ci->values[i].type == OCONFIG_TYPE_STRING)
202 && (NULL != ci->values[i].value.string))
203 free (ci->values[i].value.string);
205 if (ci->values != NULL)
206 free (ci->values);
208 for (i = 0; i < ci->children_num; i++)
209 oconfig_free (ci->children + i);
211 if (ci->children != NULL)
212 free (ci->children);
213 }
215 /*
216 * vim:shiftwidth=2:tabstop=8:softtabstop=2:fdm=marker
217 */