xref: /aosp_15_r20/external/libconfig/lib/scanctx.c (revision 2e9d491483b805f09ea864149eadd5680efcc72a)
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