1*2e9d4914SAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
2*2e9d4914SAndroid Build Coastguard Worker libconfig - A library for processing structured configuration files
3*2e9d4914SAndroid Build Coastguard Worker Copyright (C) 2005-2020 Mark A Lindner
4*2e9d4914SAndroid Build Coastguard Worker
5*2e9d4914SAndroid Build Coastguard Worker This file is part of libconfig.
6*2e9d4914SAndroid Build Coastguard Worker
7*2e9d4914SAndroid Build Coastguard Worker This library is free software; you can redistribute it and/or
8*2e9d4914SAndroid Build Coastguard Worker modify it under the terms of the GNU Lesser General Public License
9*2e9d4914SAndroid Build Coastguard Worker as published by the Free Software Foundation; either version 2.1 of
10*2e9d4914SAndroid Build Coastguard Worker the License, or (at your option) any later version.
11*2e9d4914SAndroid Build Coastguard Worker
12*2e9d4914SAndroid Build Coastguard Worker This library is distributed in the hope that it will be useful, but
13*2e9d4914SAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
14*2e9d4914SAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15*2e9d4914SAndroid Build Coastguard Worker Lesser General Public License for more details.
16*2e9d4914SAndroid Build Coastguard Worker
17*2e9d4914SAndroid Build Coastguard Worker You should have received a copy of the GNU Library General Public
18*2e9d4914SAndroid Build Coastguard Worker License along with this library; if not, see
19*2e9d4914SAndroid Build Coastguard Worker <http://www.gnu.org/licenses/>.
20*2e9d4914SAndroid Build Coastguard Worker ----------------------------------------------------------------------------
21*2e9d4914SAndroid Build Coastguard Worker */
22*2e9d4914SAndroid Build Coastguard Worker
23*2e9d4914SAndroid Build Coastguard Worker #include "scanctx.h"
24*2e9d4914SAndroid Build Coastguard Worker #include "strvec.h"
25*2e9d4914SAndroid Build Coastguard Worker #include "wincompat.h"
26*2e9d4914SAndroid Build Coastguard Worker #include "util.h"
27*2e9d4914SAndroid Build Coastguard Worker
28*2e9d4914SAndroid Build Coastguard Worker #include <stddef.h>
29*2e9d4914SAndroid Build Coastguard Worker #include <stdlib.h>
30*2e9d4914SAndroid Build Coastguard Worker #include <string.h>
31*2e9d4914SAndroid Build Coastguard Worker
32*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
33*2e9d4914SAndroid Build Coastguard Worker
34*2e9d4914SAndroid Build Coastguard Worker static const char *err_bad_include = "cannot open include file";
35*2e9d4914SAndroid Build Coastguard Worker static const char *err_include_too_deep = "include file nesting too deep";
36*2e9d4914SAndroid Build Coastguard Worker
37*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
38*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_init(struct scan_context * ctx,const char * top_filename)39*2e9d4914SAndroid Build Coastguard Worker void libconfig_scanctx_init(struct scan_context *ctx, const char *top_filename)
40*2e9d4914SAndroid Build Coastguard Worker {
41*2e9d4914SAndroid Build Coastguard Worker __zero(ctx);
42*2e9d4914SAndroid Build Coastguard Worker if(top_filename)
43*2e9d4914SAndroid Build Coastguard Worker {
44*2e9d4914SAndroid Build Coastguard Worker ctx->top_filename = strdup(top_filename);
45*2e9d4914SAndroid Build Coastguard Worker libconfig_strvec_append(&(ctx->filenames), ctx->top_filename);
46*2e9d4914SAndroid Build Coastguard Worker }
47*2e9d4914SAndroid Build Coastguard Worker }
48*2e9d4914SAndroid Build Coastguard Worker
49*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
50*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_cleanup(struct scan_context * ctx)51*2e9d4914SAndroid Build Coastguard Worker const char **libconfig_scanctx_cleanup(struct scan_context *ctx)
52*2e9d4914SAndroid Build Coastguard Worker {
53*2e9d4914SAndroid Build Coastguard Worker int i;
54*2e9d4914SAndroid Build Coastguard Worker
55*2e9d4914SAndroid Build Coastguard Worker for(i = 0; i < ctx->stack_depth; ++i)
56*2e9d4914SAndroid Build Coastguard Worker {
57*2e9d4914SAndroid Build Coastguard Worker struct include_stack_frame *frame = &(ctx->include_stack[i]);
58*2e9d4914SAndroid Build Coastguard Worker
59*2e9d4914SAndroid Build Coastguard Worker if(frame->current_stream)
60*2e9d4914SAndroid Build Coastguard Worker fclose(frame->current_stream);
61*2e9d4914SAndroid Build Coastguard Worker
62*2e9d4914SAndroid Build Coastguard Worker __delete(frame->files);
63*2e9d4914SAndroid Build Coastguard Worker }
64*2e9d4914SAndroid Build Coastguard Worker
65*2e9d4914SAndroid Build Coastguard Worker __delete(libconfig_strbuf_release(&(ctx->string)));
66*2e9d4914SAndroid Build Coastguard Worker
67*2e9d4914SAndroid Build Coastguard Worker return(libconfig_strvec_release(&(ctx->filenames)));
68*2e9d4914SAndroid Build Coastguard Worker }
69*2e9d4914SAndroid Build Coastguard Worker
70*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
71*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_push_include(struct scan_context * ctx,void * prev_buffer,const char * path,const char ** error)72*2e9d4914SAndroid Build Coastguard Worker FILE *libconfig_scanctx_push_include(struct scan_context *ctx, void *prev_buffer,
73*2e9d4914SAndroid Build Coastguard Worker const char *path, const char **error)
74*2e9d4914SAndroid Build Coastguard Worker {
75*2e9d4914SAndroid Build Coastguard Worker struct include_stack_frame *frame;
76*2e9d4914SAndroid Build Coastguard Worker const char **files = NULL, **f;
77*2e9d4914SAndroid Build Coastguard Worker FILE *fp;
78*2e9d4914SAndroid Build Coastguard Worker
79*2e9d4914SAndroid Build Coastguard Worker if(ctx->stack_depth == MAX_INCLUDE_DEPTH)
80*2e9d4914SAndroid Build Coastguard Worker {
81*2e9d4914SAndroid Build Coastguard Worker *error = err_include_too_deep;
82*2e9d4914SAndroid Build Coastguard Worker return(NULL);
83*2e9d4914SAndroid Build Coastguard Worker }
84*2e9d4914SAndroid Build Coastguard Worker
85*2e9d4914SAndroid Build Coastguard Worker *error = NULL;
86*2e9d4914SAndroid Build Coastguard Worker
87*2e9d4914SAndroid Build Coastguard Worker if(ctx->config->include_fn)
88*2e9d4914SAndroid Build Coastguard Worker files = ctx->config->include_fn(ctx->config, ctx->config->include_dir,
89*2e9d4914SAndroid Build Coastguard Worker path, error);
90*2e9d4914SAndroid Build Coastguard Worker
91*2e9d4914SAndroid Build Coastguard Worker if(*error || !files)
92*2e9d4914SAndroid Build Coastguard Worker {
93*2e9d4914SAndroid Build Coastguard Worker libconfig_strvec_delete(files);
94*2e9d4914SAndroid Build Coastguard Worker return(NULL);
95*2e9d4914SAndroid Build Coastguard Worker }
96*2e9d4914SAndroid Build Coastguard Worker
97*2e9d4914SAndroid Build Coastguard Worker if(!*files)
98*2e9d4914SAndroid Build Coastguard Worker {
99*2e9d4914SAndroid Build Coastguard Worker libconfig_strvec_delete(files);
100*2e9d4914SAndroid Build Coastguard Worker return(NULL);
101*2e9d4914SAndroid Build Coastguard Worker }
102*2e9d4914SAndroid Build Coastguard Worker
103*2e9d4914SAndroid Build Coastguard Worker frame = &(ctx->include_stack[ctx->stack_depth]);
104*2e9d4914SAndroid Build Coastguard Worker
105*2e9d4914SAndroid Build Coastguard Worker for(f = files; *f; ++f)
106*2e9d4914SAndroid Build Coastguard Worker libconfig_strvec_append(&(ctx->filenames), *f);
107*2e9d4914SAndroid Build Coastguard Worker
108*2e9d4914SAndroid Build Coastguard Worker frame->files = files;
109*2e9d4914SAndroid Build Coastguard Worker frame->current_file = NULL;
110*2e9d4914SAndroid Build Coastguard Worker frame->current_stream = NULL;
111*2e9d4914SAndroid Build Coastguard Worker frame->parent_buffer = prev_buffer;
112*2e9d4914SAndroid Build Coastguard Worker ++(ctx->stack_depth);
113*2e9d4914SAndroid Build Coastguard Worker
114*2e9d4914SAndroid Build Coastguard Worker fp = libconfig_scanctx_next_include_file(ctx, error);
115*2e9d4914SAndroid Build Coastguard Worker if(!fp)
116*2e9d4914SAndroid Build Coastguard Worker (void)libconfig_scanctx_pop_include(ctx);
117*2e9d4914SAndroid Build Coastguard Worker
118*2e9d4914SAndroid Build Coastguard Worker return(fp);
119*2e9d4914SAndroid Build Coastguard Worker }
120*2e9d4914SAndroid Build Coastguard Worker
121*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
122*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_next_include_file(struct scan_context * ctx,const char ** error)123*2e9d4914SAndroid Build Coastguard Worker FILE *libconfig_scanctx_next_include_file(struct scan_context *ctx,
124*2e9d4914SAndroid Build Coastguard Worker const char **error)
125*2e9d4914SAndroid Build Coastguard Worker {
126*2e9d4914SAndroid Build Coastguard Worker struct include_stack_frame *include_frame;
127*2e9d4914SAndroid Build Coastguard Worker
128*2e9d4914SAndroid Build Coastguard Worker *error = NULL;
129*2e9d4914SAndroid Build Coastguard Worker
130*2e9d4914SAndroid Build Coastguard Worker if(ctx->stack_depth == 0)
131*2e9d4914SAndroid Build Coastguard Worker return(NULL);
132*2e9d4914SAndroid Build Coastguard Worker
133*2e9d4914SAndroid Build Coastguard Worker include_frame = &(ctx->include_stack[ctx->stack_depth - 1]);
134*2e9d4914SAndroid Build Coastguard Worker
135*2e9d4914SAndroid Build Coastguard Worker if(include_frame->current_file)
136*2e9d4914SAndroid Build Coastguard Worker ++(include_frame->current_file);
137*2e9d4914SAndroid Build Coastguard Worker else
138*2e9d4914SAndroid Build Coastguard Worker include_frame->current_file = include_frame->files;
139*2e9d4914SAndroid Build Coastguard Worker
140*2e9d4914SAndroid Build Coastguard Worker if(include_frame->current_stream)
141*2e9d4914SAndroid Build Coastguard Worker {
142*2e9d4914SAndroid Build Coastguard Worker fclose(include_frame->current_stream);
143*2e9d4914SAndroid Build Coastguard Worker include_frame->current_stream = NULL;
144*2e9d4914SAndroid Build Coastguard Worker }
145*2e9d4914SAndroid Build Coastguard Worker
146*2e9d4914SAndroid Build Coastguard Worker if(!*(include_frame->current_file))
147*2e9d4914SAndroid Build Coastguard Worker return(NULL);
148*2e9d4914SAndroid Build Coastguard Worker
149*2e9d4914SAndroid Build Coastguard Worker include_frame->current_stream = fopen(*(include_frame->current_file), "rt");
150*2e9d4914SAndroid Build Coastguard Worker if(!include_frame->current_stream)
151*2e9d4914SAndroid Build Coastguard Worker *error = err_bad_include;
152*2e9d4914SAndroid Build Coastguard Worker
153*2e9d4914SAndroid Build Coastguard Worker return(include_frame->current_stream);
154*2e9d4914SAndroid Build Coastguard Worker }
155*2e9d4914SAndroid Build Coastguard Worker
156*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
157*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_pop_include(struct scan_context * ctx)158*2e9d4914SAndroid Build Coastguard Worker void *libconfig_scanctx_pop_include(struct scan_context *ctx)
159*2e9d4914SAndroid Build Coastguard Worker {
160*2e9d4914SAndroid Build Coastguard Worker struct include_stack_frame *frame;
161*2e9d4914SAndroid Build Coastguard Worker
162*2e9d4914SAndroid Build Coastguard Worker if(ctx->stack_depth == 0)
163*2e9d4914SAndroid Build Coastguard Worker return(NULL); /* stack underflow */
164*2e9d4914SAndroid Build Coastguard Worker
165*2e9d4914SAndroid Build Coastguard Worker frame = &(ctx->include_stack[--(ctx->stack_depth)]);
166*2e9d4914SAndroid Build Coastguard Worker
167*2e9d4914SAndroid Build Coastguard Worker __delete(frame->files);
168*2e9d4914SAndroid Build Coastguard Worker frame->files = NULL;
169*2e9d4914SAndroid Build Coastguard Worker
170*2e9d4914SAndroid Build Coastguard Worker if(frame->current_stream)
171*2e9d4914SAndroid Build Coastguard Worker {
172*2e9d4914SAndroid Build Coastguard Worker fclose(frame->current_stream);
173*2e9d4914SAndroid Build Coastguard Worker frame->current_stream = NULL;
174*2e9d4914SAndroid Build Coastguard Worker }
175*2e9d4914SAndroid Build Coastguard Worker
176*2e9d4914SAndroid Build Coastguard Worker return(frame->parent_buffer);
177*2e9d4914SAndroid Build Coastguard Worker }
178*2e9d4914SAndroid Build Coastguard Worker
179*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
180*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_take_string(struct scan_context * ctx)181*2e9d4914SAndroid Build Coastguard Worker char *libconfig_scanctx_take_string(struct scan_context *ctx)
182*2e9d4914SAndroid Build Coastguard Worker {
183*2e9d4914SAndroid Build Coastguard Worker char *r = libconfig_strbuf_release(&(ctx->string));
184*2e9d4914SAndroid Build Coastguard Worker
185*2e9d4914SAndroid Build Coastguard Worker return(r ? r : strdup(""));
186*2e9d4914SAndroid Build Coastguard Worker }
187*2e9d4914SAndroid Build Coastguard Worker
188*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
189*2e9d4914SAndroid Build Coastguard Worker
libconfig_scanctx_current_filename(struct scan_context * ctx)190*2e9d4914SAndroid Build Coastguard Worker const char *libconfig_scanctx_current_filename(struct scan_context *ctx)
191*2e9d4914SAndroid Build Coastguard Worker {
192*2e9d4914SAndroid Build Coastguard Worker if(ctx->stack_depth > 0)
193*2e9d4914SAndroid Build Coastguard Worker return(*(ctx->include_stack[ctx->stack_depth - 1].current_file));
194*2e9d4914SAndroid Build Coastguard Worker
195*2e9d4914SAndroid Build Coastguard Worker return(ctx->top_filename);
196*2e9d4914SAndroid Build Coastguard Worker }
197*2e9d4914SAndroid Build Coastguard Worker
198*2e9d4914SAndroid Build Coastguard Worker /* ------------------------------------------------------------------------- */
199