Mercurial > mplayer.hg
annotate m_config.c @ 13784:7d3b84ddd2fd
Remove hardcoded filenames in favor of command line parameters, some error
checking added, patch by Reza Jelveh.
author | diego |
---|---|
date | Thu, 28 Oct 2004 01:02:24 +0000 |
parents | 11b249ef87b0 |
children | bad703951cf9 |
rev | line source |
---|---|
8164 | 1 #include "config.h" |
2 | |
3 #include <stdlib.h> | |
4 #include <stdio.h> | |
5 #include <errno.h> | |
6 #include <string.h> | |
7 #ifdef MP_DEBUG | |
8 #include <assert.h> | |
9 #endif | |
10 | |
11 #include "m_config.h" | |
12 #include "m_option.h" | |
13 #include "mp_msg.h" | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
14 #include "help_mp.h" |
8164 | 15 |
16 m_config_t* | |
17 m_config_new(void) { | |
18 m_config_t* config; | |
19 | |
20 config = (m_config_t*)calloc(1,sizeof(m_config_t)); | |
21 config->lvl = 1; // 0 Is the defaults | |
22 return config; | |
23 } | |
24 | |
25 void | |
26 m_config_free(m_config_t* config) { | |
27 m_config_option_t *i = config->opts, *ct; | |
28 m_config_save_slot_t *sl,*st; | |
29 | |
30 #ifdef MP_DEBUG | |
31 assert(config != NULL); | |
32 #endif | |
33 | |
34 while(i) { | |
35 sl = i->slots; | |
36 while(sl) { | |
37 m_option_free(i->opt,sl->data); | |
38 st = sl->prev; | |
39 free(sl); | |
40 sl = st; | |
41 } | |
42 if(i->name != i->opt->name) | |
43 free(i->name); | |
44 ct = i->next; | |
45 free(i); | |
46 ct = i; | |
47 } | |
48 free(config); | |
49 } | |
50 | |
51 void | |
52 m_config_push(m_config_t* config) { | |
53 m_config_option_t *co; | |
54 m_config_save_slot_t *slot; | |
55 | |
56 #ifdef MP_DEBUG | |
57 assert(config != NULL); | |
58 assert(config->lvl > 0); | |
59 #endif | |
60 | |
61 config->lvl++; | |
62 | |
63 for(co = config->opts ; co ; co = co->next ) { | |
64 if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) | |
65 continue; | |
66 if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) | |
67 continue; | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
68 if((co->opt->flags & M_OPT_OLD) && !(co->flags && M_CFG_OPT_SET)) |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
69 continue; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
70 if(co->flags & M_CFG_OPT_ALIAS) |
8164 | 71 continue; |
72 | |
73 // Update the current status | |
74 m_option_save(co->opt,co->slots->data,co->opt->p); | |
75 | |
76 // Allocate a new slot | |
77 slot = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + co->opt->type->size); | |
78 slot->lvl = config->lvl; | |
79 slot->prev = co->slots; | |
80 co->slots = slot; | |
81 m_option_copy(co->opt,co->slots->data,co->slots->prev->data); | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
82 // Reset our set flag |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
83 co->flags &= ~M_CFG_OPT_SET; |
8164 | 84 } |
85 | |
86 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config pushed level is now %d\n",config->lvl); | |
87 } | |
88 | |
89 void | |
90 m_config_pop(m_config_t* config) { | |
91 m_config_option_t *co; | |
92 m_config_save_slot_t *slot; | |
93 | |
94 #ifdef MP_DEBUG | |
95 assert(config != NULL); | |
96 assert(config->lvl > 1); | |
97 #endif | |
98 | |
99 for(co = config->opts ; co ; co = co->next ) { | |
100 int pop = 0; | |
101 if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) | |
102 continue; | |
103 if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) | |
104 continue; | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
105 if(co->flags & M_CFG_OPT_ALIAS) |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
106 continue; |
8164 | 107 if(co->slots->lvl > config->lvl) |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
108 mp_msg(MSGT_CFGPARSER, MSGL_WARN,MSGTR_SaveSlotTooOld,config->lvl,co->slots->lvl); |
8164 | 109 |
110 while(co->slots->lvl >= config->lvl) { | |
111 m_option_free(co->opt,co->slots->data); | |
112 slot = co->slots; | |
113 co->slots = slot->prev; | |
114 free(slot); | |
115 pop++; | |
116 } | |
117 if(pop) // We removed some ctx -> set the previous value | |
118 m_option_set(co->opt,co->opt->p,co->slots->data); | |
119 } | |
120 | |
121 config->lvl--; | |
122 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config poped level=%d\n",config->lvl); | |
123 } | |
124 | |
125 static void | |
126 m_config_add_option(m_config_t *config, m_option_t *arg, char* prefix) { | |
127 m_config_option_t *co; | |
128 m_config_save_slot_t* sl; | |
129 | |
130 #ifdef MP_DEBUG | |
131 assert(config != NULL); | |
132 assert(config->lvl > 0); | |
133 assert(arg != NULL); | |
134 #endif | |
135 | |
136 // Allocate a new entry for this option | |
137 co = (m_config_option_t*)calloc(1,sizeof(m_config_option_t) + arg->type->size); | |
138 co->opt = arg; | |
139 | |
140 // Fill in the full name | |
141 if(prefix && strlen(prefix) > 0) { | |
142 int l = strlen(prefix) + 1 + strlen(arg->name) + 1; | |
143 co->name = (char*) malloc(l); | |
144 sprintf(co->name,"%s:%s",prefix,arg->name); | |
145 } else | |
146 co->name = arg->name; | |
147 | |
148 // Option with childs -> add them | |
149 if(arg->type->flags & M_OPT_TYPE_HAS_CHILD) { | |
150 m_option_t *ol = arg->p; | |
151 int i; | |
152 for(i = 0 ; ol[i].name != NULL ; i++) | |
153 m_config_add_option(config,&ol[i], co->name); | |
154 } else { | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
155 m_config_option_t *i; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
156 // Check if there is alredy an option pointing to this address |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
157 if(arg->p) { |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
158 for(i = config->opts ; i ; i = i->next ) { |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
159 if(i->opt->p == arg->p) { // So we don't save the same vars more than 1 time |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
160 co->slots = i->slots; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
161 co->flags |= M_CFG_OPT_ALIAS; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
162 break; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
163 } |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
164 } |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
165 } |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
166 if(!(co->flags & M_CFG_OPT_ALIAS)) { |
8164 | 167 // Allocate a slot for the defaults |
168 sl = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); | |
169 m_option_save(arg,sl->data,(void**)arg->p); | |
170 // Hack to avoid too much trouble with dynamicly allocated data : | |
171 // We always use a dynamic version | |
172 if((arg->type->flags & M_OPT_TYPE_DYNAMIC) && arg->p && (*(void**)arg->p)) { | |
173 *(void**)arg->p = NULL; | |
174 m_option_set(arg,arg->p,sl->data); | |
175 } | |
176 sl->lvl = 0; | |
177 co->slots = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); | |
178 co->slots->prev = sl; | |
179 co->slots->lvl = config->lvl; | |
180 m_option_copy(co->opt,co->slots->data,sl->data); | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
181 } // !M_OPT_ALIAS |
8164 | 182 } |
183 co->next = config->opts; | |
184 config->opts = co; | |
185 } | |
186 | |
187 int | |
188 m_config_register_options(m_config_t *config, m_option_t *args) { | |
189 int i; | |
190 | |
191 #ifdef MP_DEBUG | |
192 assert(config != NULL); | |
193 assert(config->lvl > 0); | |
194 assert(args != NULL); | |
195 #endif | |
196 | |
197 for(i = 0 ; args[i].name != NULL ; i++) | |
198 m_config_add_option(config,&args[i],NULL); | |
199 | |
200 return 1; | |
201 } | |
202 | |
203 static m_config_option_t* | |
204 m_config_get_co(m_config_t *config, char* arg) { | |
205 m_config_option_t *co; | |
206 | |
207 for(co = config->opts ; co ; co = co->next ) { | |
208 int l = strlen(co->name) - 1; | |
209 if((co->opt->type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && | |
210 (co->name[l] == '*')) { | |
211 if(strncasecmp(co->name,arg,l) == 0) | |
212 return co; | |
213 } else if(strcasecmp(co->name,arg) == 0) | |
214 return co; | |
215 } | |
216 return NULL; | |
217 } | |
218 | |
219 static int | |
220 m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { | |
221 m_config_option_t *co; | |
222 int r = 0; | |
223 | |
224 #ifdef MP_DEBUG | |
225 assert(config != NULL); | |
226 assert(config->lvl > 0); | |
227 assert(arg != NULL); | |
228 #endif | |
229 | |
230 co = m_config_get_co(config,arg); | |
8892 | 231 if(!co){ |
8894 | 232 // mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Unknown option: %s\n",arg); |
10595
522afd56703c
100l to albeu for his english grammar, and 10l to me becouse I noticed that lately (my backward compatibilty macro uses M_OPT_UNKNOWN)
alex
parents:
10594
diff
changeset
|
233 return M_OPT_UNKNOWN; |
8892 | 234 } |
8164 | 235 |
236 #ifdef MP_DEBUG | |
237 // This is the only mandatory function | |
238 assert(co->opt->type->parse); | |
239 #endif | |
240 | |
241 // Check if this option isn't forbiden in the current mode | |
242 if((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) { | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
243 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidCfgfileOption,arg); |
8164 | 244 return M_OPT_INVALID; |
245 } | |
246 if((config->mode == M_COMMAND_LINE) && (co->opt->flags & M_OPT_NOCMD)) { | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
247 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidCmdlineOption,arg); |
8164 | 248 return M_OPT_INVALID; |
249 } | |
250 | |
251 // Option with childs are a bit different to parse | |
252 if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) { | |
253 char** lst = NULL; | |
254 int i,sr; | |
255 // Parse the child options | |
9593
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
9222
diff
changeset
|
256 r = m_option_parse(co->opt,arg,param,&lst,M_COMMAND_LINE); |
8164 | 257 // Set them now |
8894 | 258 if(r >= 0) |
8164 | 259 for(i = 0 ; lst && lst[2*i] ; i++) { |
260 int l = strlen(co->name) + 1 + strlen(lst[2*i]) + 1; | |
261 if(r >= 0) { | |
262 // Build the full name | |
263 char n[l]; | |
264 sprintf(n,"%s:%s",co->name,lst[2*i]); | |
265 sr = m_config_parse_option(config,n,lst[2*i+1],set); | |
8894 | 266 if(sr < 0){ |
10595
522afd56703c
100l to albeu for his english grammar, and 10l to me becouse I noticed that lately (my backward compatibilty macro uses M_OPT_UNKNOWN)
alex
parents:
10594
diff
changeset
|
267 if(sr == M_OPT_UNKNOWN){ |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
268 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidSuboption,co->name,lst[2*i]); |
8894 | 269 r = M_OPT_INVALID; |
270 } else | |
9222 | 271 if(sr == M_OPT_MISSING_PARAM){ |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
272 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_MissingSuboptionParameter,lst[2*i],co->name); |
9222 | 273 r = M_OPT_INVALID; |
274 } else | |
8894 | 275 r = sr; |
276 } | |
8164 | 277 } |
278 free(lst[2*i]); | |
279 free(lst[2*i+1]); | |
280 } | |
281 if(lst) free(lst); | |
282 } else | |
283 r = m_option_parse(co->opt,arg,param,set ? co->slots->data : NULL,config->mode); | |
284 | |
285 // Parsing failed ? | |
286 if(r < 0) | |
287 return r; | |
288 // Set the option | |
289 if(set) { | |
290 m_option_set(co->opt,co->opt->p,co->slots->data); | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
291 co->flags |= M_CFG_OPT_SET; |
8164 | 292 } |
293 | |
294 return r; | |
295 } | |
296 | |
297 int | |
298 m_config_set_option(m_config_t *config, char* arg, char* param) { | |
299 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Setting %s=%s\n",arg,param); | |
300 return m_config_parse_option(config,arg,param,1); | |
301 } | |
302 | |
303 int | |
304 m_config_check_option(m_config_t *config, char* arg, char* param) { | |
9222 | 305 int r; |
8164 | 306 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Checking %s=%s\n",arg,param); |
9222 | 307 r=m_config_parse_option(config,arg,param,0); |
308 if(r==M_OPT_MISSING_PARAM){ | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
309 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_MissingOptionParameter,arg); |
9222 | 310 return M_OPT_INVALID; |
311 } | |
312 return r; | |
8164 | 313 } |
314 | |
315 | |
316 m_option_t* | |
317 m_config_get_option(m_config_t *config, char* arg) { | |
318 m_config_option_t *co; | |
319 | |
320 #ifdef MP_DEBUG | |
321 assert(config != NULL); | |
322 assert(config->lvl > 0); | |
323 assert(arg != NULL); | |
324 #endif | |
325 | |
326 co = m_config_get_co(config,arg); | |
327 if(co) | |
328 return co->opt; | |
329 else | |
330 return NULL; | |
331 } | |
332 | |
333 void* | |
334 m_config_get_option_ptr(m_config_t *config, char* arg) { | |
335 m_option_t* conf; | |
336 | |
337 #ifdef MP_DEBUG | |
338 assert(config != NULL); | |
339 assert(arg != NULL); | |
340 #endif | |
341 | |
342 conf = m_config_get_option(config,arg); | |
343 if(!conf) return NULL; | |
344 return conf->p; | |
345 } | |
346 | |
347 void | |
348 m_config_print_option_list(m_config_t *config) { | |
349 char min[50],max[50]; | |
350 m_config_option_t* co; | |
351 int count = 0; | |
352 | |
353 if(!config->opts) return; | |
354 | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
355 mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_OptionListHeader); |
8164 | 356 for(co = config->opts ; co ; co = co->next) { |
357 m_option_t* opt = co->opt; | |
358 if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; | |
359 if(opt->flags & M_OPT_MIN) | |
360 sprintf(min,"%-8.0f",opt->min); | |
361 else | |
362 strcpy(min,"No"); | |
363 if(opt->flags & M_OPT_MAX) | |
364 sprintf(max,"%-8.0f",opt->max); | |
365 else | |
366 strcpy(max,"No"); | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
367 mp_msg(MSGT_FIXME, MSGL_FIXME, " %-20.20s %-15.15s %-10.10s %-10.10s %-3.3s %-3.3s %-3.3s\n", |
8164 | 368 co->name, |
369 co->opt->type->name, | |
370 min, | |
371 max, | |
372 opt->flags & CONF_GLOBAL ? "Yes" : "No", | |
373 opt->flags & CONF_NOCMD ? "No" : "Yes", | |
374 opt->flags & CONF_NOCFG ? "No" : "Yes"); | |
375 count++; | |
376 } | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
377 mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_TotalOptions,count); |
8164 | 378 } |