1 #ifndef CONF_H
2 #define CONF_H
3 
4 #include <vstr.h>
5 
6 #define CONF_PARSE_ERR 0
7 #define CONF_PARSE_FIN 1
8 
9 #define CONF_PARSE_STATE_BEG              0
10 #define CONF_PARSE_STATE_WS               1
11 #define CONF_PARSE_STATE_LIST_END_OR_WS   2
12 #define CONF_PARSE_STATE_CHOOSE           3
13 #define CONF_PARSE_STATE_QUOTE_D_BEG      4
14 #define CONF_PARSE_STATE_QUOTE_S_BEG      5
15 #define CONF_PARSE_STATE_UNQUOTE_BEG      6
16 #define CONF_PARSE_STATE_QUOTE_D_END      7
17 #define CONF_PARSE_STATE_QUOTE_DDD_END    8
18 #define CONF_PARSE_STATE_QUOTE_S_END      9
19 #define CONF_PARSE_STATE_QUOTE_SSS_END   10
20 #define CONF_PARSE_STATE_UNQUOTE_D_END   11 /* unescaped quoted */
21 #define CONF_PARSE_STATE_UNQUOTE_DDD_END 12
22 #define CONF_PARSE_STATE_UNQUOTE_S_END   13
23 #define CONF_PARSE_STATE_UNQUOTE_SSS_END 14
24 #define CONF_PARSE_STATE_SYMBOL_END      15
25 #define CONF_PARSE_STATE_END             16
26 
27 #define CONF_PARSE_STATE_QUOTE_X2XXX                                    \
28     (CONF_PARSE_STATE_QUOTE_DDD_END - CONF_PARSE_STATE_QUOTE_D_END)
29 #define CONF_PARSE_STATE_QUOTE2UNQUOTE_END                              \
30     (CONF_PARSE_STATE_UNQUOTE_D_END - CONF_PARSE_STATE_QUOTE_D_END)
31 
32 #define CONF_PARSE_LIST_DEPTH_SZ 64
33 
34 #define CONF_TOKEN_TYPE_ERR              0
35 #define CONF_TOKEN_TYPE_CLIST            1
36 #define CONF_TOKEN_TYPE_SLIST            2
37 #define CONF_TOKEN_TYPE_QUOTE_D          3
38 #define CONF_TOKEN_TYPE_QUOTE_ESC_D      4
39 #define CONF_TOKEN_TYPE_QUOTE_DDD        5
40 #define CONF_TOKEN_TYPE_QUOTE_ESC_DDD    6
41 #define CONF_TOKEN_TYPE_QUOTE_S          7
42 #define CONF_TOKEN_TYPE_QUOTE_ESC_S      8
43 #define CONF_TOKEN_TYPE_QUOTE_SSS        9
44 #define CONF_TOKEN_TYPE_QUOTE_ESC_SSS   10
45 #define CONF_TOKEN_TYPE_SYMBOL          11
46 #define CONF_TOKEN_TYPE_USER_BEG        12
47 
48 #define CONF_TOKEN_TYPE_2ESC                                    \
49     (CONF_TOKEN_TYPE_QUOTE_ESC_D - CONF_TOKEN_TYPE_QUOTE_D)
50 
51 #define CONF_SC_TYPE_RET_OK 0
52 /* #define CONF_SC_TYPE_RET_ERR_TOO_MANY  1 */
53 #define CONF_SC_TYPE_RET_ERR_NO_MATCH  2
54 #define CONF_SC_TYPE_RET_ERR_NOT_EXIST 3
55 #define CONF_SC_TYPE_RET_ERR_PARSE     4
56 
57 #define CONF_SC_PARSE_DEPTH_TOKEN_RET(c, t, d, ret) do {         \
58       if (!conf_token_list_num(t, d))                            \
59         return ret ;                                             \
60       conf_parse_token(c, t);                                    \
61       if (conf_token_at_depth(t) != (d))                         \
62         return ret ;                                             \
63     } while (0)
64 
65 #define CONF_SC_PARSE_TYPE_DEPTH_TOKEN_RET(c, t, d, T, ret) do {        \
66       CONF_SC_PARSE_DEPTH_TOKEN_RET(c, t, d, ret);                      \
67       if (token->type != T)                                             \
68         return ret ;                                                    \
69     } while (0)
70 
71 #define CONF_SC_PARSE_CLIST_DEPTH_TOKEN_RET(c, t, d, ret)       \
72     CONF_SC_PARSE_TYPE_DEPTH_TOKEN_RET(c, t, d, CONF_TOKEN_TYPE_CLIST, ret)
73 #define CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(c, t, d, ret)       \
74     CONF_SC_PARSE_TYPE_DEPTH_TOKEN_RET(c, t, d, CONF_TOKEN_TYPE_SLIST, ret)
75 
76 #define CONF_SC_PARSE_TOP_TOKEN_RET(c, t, ret) do {                     \
77       unsigned int conf_sc__token_depth = (t)->depth_num;               \
78       CONF_SC_PARSE_DEPTH_TOKEN_RET(c, t, conf_sc__token_depth, ret);   \
79     } while (0)
80 #define CONF_SC_PARSE_CLIST_TOP_TOKEN_RET(c, t, ret) do {               \
81       unsigned int conf_sc__token_depth = (t)->depth_num;               \
82       CONF_SC_PARSE_CLIST_DEPTH_TOKEN_RET(c, t, conf_sc__token_depth, ret); \
83     } while (0)
84 #define CONF_SC_PARSE_SLIST_TOP_TOKEN_RET(c, t, ret) do {               \
85       unsigned int conf_sc__token_depth = (t)->depth_num;               \
86       CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(c, t, conf_sc__token_depth, ret); \
87     } while (0)
88 
89 #define CONF_SC_TOGGLE_CLIST_VAR(x)  do {               \
90       if (token->type == CONF_TOKEN_TYPE_CLIST)         \
91       {                                                 \
92         (x) = 1;                                        \
93         CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, 0);    \
94       }                                                 \
95       else                                              \
96         (x) = 0;                                        \
97     } while (0)
98 
99 #define CONF_SC_MAKE_CLIST_MID(x, y)                                    \
100     while (conf_token_list_num(token, x))                               \
101     {                                                                   \
102       CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, x, 0);                 \
103       CONF_SC_TOGGLE_CLIST_VAR(y);                                      \
104                                                                         \
105       if (0)
106 
107 #define CONF_SC_MAKE_CLIST_BEG(x, y)                                    \
108     unsigned int conf_sc__depth_ ## x = token->depth_num;               \
109     CONF_SC_MAKE_CLIST_MID(conf_sc__depth_ ## x, y)
110 
111 #define CONF_SC_MAKE_CLIST_END()                \
112     else                                        \
113       return (0);                               \
114     }                                           \
115     do { } while (0)
116 
117 
118 typedef struct Conf__uval_store
119 {
120  Vstr_ref *ref;
121  unsigned int nxt;
122 } Conf__uval_store;
123 
124 typedef struct Conf_parse
125 {
126  Vstr_sects *sects;
127  Vstr_base *data;
128  Vstr_base *tmp;
129  unsigned int  types_sz;
130  unsigned int *types_ptr;
131  unsigned int      uvals_sz;
132  unsigned int      uvals_num;
133  Conf__uval_store *uvals_ptr;
134  unsigned int state;
135  unsigned int depth;
136 } Conf_parse;
137 
138 typedef struct Conf_token
139 {
140  union
141  {
142   const Vstr_sect_node *node;
143   unsigned int list_num;
144   unsigned int uval_num;
145  } u;
146 
147  unsigned int type;
148  unsigned int num;
149  unsigned int depth_num;
150  unsigned int depth_nums[CONF_PARSE_LIST_DEPTH_SZ + 1];
151 } Conf_token;
152 #define CONF_TOKEN_INIT {{NULL}, CONF_TOKEN_TYPE_ERR, 0, 0, {0}}
153 
154 extern Conf_parse *conf_parse_make(Vstr_conf *)
155    VSTR__COMPILE_ATTR_MALLOC();
156 extern void        conf_parse_free(Conf_parse *);
157 
158 extern int conf_parse_lex(Conf_parse *, size_t, size_t);
159 
160 extern Conf_token *conf_token_make(void)
161    VSTR__COMPILE_ATTR_MALLOC();
162 extern void        conf_token_free(Conf_token *);
163 
164 extern int conf_parse_token(const Conf_parse *, Conf_token *);
165 extern int conf_parse_end_token(const Conf_parse *, Conf_token *, unsigned int);
166 extern int conf_parse_num_token(const Conf_parse *, Conf_token *, unsigned int);
167 
168 extern unsigned int conf_token_at_depth(const Conf_token *);
169 
170 extern const char *conf_token_name(const Conf_token *);
171 extern const Vstr_sect_node *conf_token_value(const Conf_token *);
172 
173 extern Vstr_ref *conf_token_get_user_value(const Conf_parse *,
174                                            const Conf_token *, unsigned int *);
175 extern int conf_token_set_user_value(Conf_parse *, Conf_token *,
176                                      unsigned int, Vstr_ref *, unsigned int);
177 
178 extern int conf_token_cmp_val_eq(const Conf_parse *, const Conf_token *,
179                                  const Vstr_base *, size_t, size_t);
180 extern int conf_token_cmp_val_buf_eq(const Conf_parse *, const Conf_token *,
181                                      const char *, size_t);
182 extern int conf_token_cmp_val_cstr_eq(const Conf_parse *, const Conf_token *,
183                                       const char *);
184 extern int conf_token_cmp_val_beg_eq(const Conf_parse *, const Conf_token *,
185                                      const Vstr_base *, size_t, size_t);
186 extern int conf_token_cmp_case_val_eq(const Conf_parse *,
187                                       const Conf_token *,
188                                       const Vstr_base *, size_t, size_t);
189 extern int conf_token_cmp_case_val_cstr_eq(const Conf_parse *,
190                                            const Conf_token *,
191                                            const char *);
192 extern int conf_token_cmp_case_val_beg_eq(const Conf_parse *,
193                                           const Conf_token *,
194                                           const Vstr_base *, size_t, size_t);
195 extern int conf_token_cmp_sym_eq(const Conf_parse *, const Conf_token *,
196                                  const Vstr_base *, size_t, size_t);
197 extern int conf_token_cmp_sym_buf_eq(const Conf_parse *, const Conf_token *,
198                                      const char *, size_t);
199 extern int conf_token_cmp_sym_cstr_eq(const Conf_parse *, const Conf_token *,
200                                       const char *);
201 extern int conf_token_cmp_case_sym_cstr_eq(const Conf_parse *,
202                                            const Conf_token *,
203                                            const char *);
204 
205 extern int conf_token_srch_case_val(const Conf_parse *, const Conf_token *,
206                                     const Vstr_base *, size_t, size_t);
207 
208 extern unsigned int conf_token_list_num(const Conf_token *, unsigned int);
209 
210 extern int conf_sc_token_parse_toggle(const Conf_parse *, Conf_token *, int *);
211 extern int conf_sc_token_parse_uint(const Conf_parse *, Conf_token *,
212                                     unsigned int *);
213 extern int conf_sc_token_app_vstr(const Conf_parse *, Conf_token *,
214                                   Vstr_base *,
215                                   const Vstr_base **, size_t *, size_t *);
216 extern int conf_sc_token_sub_vstr(const Conf_parse *, Conf_token *,
217                                   Vstr_base *, size_t, size_t);
218 extern int conf_sc_conv_unesc(Vstr_base *, size_t, size_t, size_t *);
219 
220 extern void conf_parse_compress(Conf_parse *);
221 extern void conf_parse_backtrace(Vstr_base *, const char *,
222                                  const Conf_parse *, const Conf_token *);
223 
224 #if !defined(CONF_COMPILE_INLINE)
225 # ifdef VSTR_AUTOCONF_NDEBUG
226 #  define CONF_COMPILE_INLINE 1
227 # else
228 #  define CONF_COMPILE_INLINE 0
229 # endif
230 #endif
231 
232 #if defined(VSTR_AUTOCONF_HAVE_INLINE) && CONF_COMPILE_INLINE
233 
234 #ifndef VSTR_AUTOCONF_NDEBUG
235 # define CONF__ASSERT ASSERT
236 #else
237 # define CONF__ASSERT(x)
238 #endif
239 
240 #define CONF__FALSE  0
241 #define CONF__TRUE   1
242 
conf_parse_token(const Conf_parse * conf,Conf_token * token)243 extern inline int conf_parse_token(const Conf_parse *conf, Conf_token *token)
244 {
245   CONF__ASSERT(conf && conf->sects && token);
246   CONF__ASSERT(!conf->depth); /* finished lex */
247   CONF__ASSERT(conf->state == CONF_PARSE_STATE_END); /* finished lex */
248 
249   if (!token->num)
250     token->depth_nums[0] = conf->sects->num;
251 
252   if (token->num >= conf->sects->num)
253     return (CONF__FALSE);
254   ++token->num;
255 
256   while (token->depth_nums[token->depth_num] < token->num)
257   {
258     CONF__ASSERT(token->depth_nums[token->depth_num] == (token->num - 1));
259     --token->depth_num;
260   }
261 
262   token->type = conf->types_ptr[token->num - 1];
263   if ((token->type >= CONF_TOKEN_TYPE_QUOTE_D) &&
264       (token->type <= CONF_TOKEN_TYPE_SYMBOL))
265     token->u.node = VSTR_SECTS_NUM(conf->sects, token->num);
266   else if ((token->type == CONF_TOKEN_TYPE_CLIST) ||
267            (token->type == CONF_TOKEN_TYPE_SLIST))
268   {
269     token->u.list_num = VSTR_SECTS_NUM(conf->sects, token->num)->len;
270     token->depth_nums[++token->depth_num] = token->num + token->u.list_num;
271   }
272   else
273     token->u.uval_num = VSTR_SECTS_NUM(conf->sects, token->num)->pos;
274 
275   return (CONF__TRUE);
276 }
277 
conf_parse_end_token(const Conf_parse * conf,Conf_token * token,unsigned int depth)278 extern inline int conf_parse_end_token(const Conf_parse *conf,
279                                        Conf_token *token,
280                                        unsigned int depth)
281 {
282   if (depth > token->depth_num)
283     return (CONF__FALSE);
284 
285   if (token->depth_nums[depth] >= token->num)
286     token->num = token->depth_nums[depth] - 1;
287 
288   return (conf_parse_token(conf, token));
289 }
290 
conf_parse_num_token(const Conf_parse * conf,Conf_token * token,unsigned int num)291 extern inline int conf_parse_num_token(const Conf_parse *conf,
292                                        Conf_token *token,
293                                        unsigned int num)
294 {
295   if (token->num == num)
296   { /* refresh info... */
297     token->type = conf->types_ptr[token->num - 1];
298 
299     if ((token->type >= CONF_TOKEN_TYPE_QUOTE_D) &&
300         (token->type <= CONF_TOKEN_TYPE_SYMBOL))
301     { }
302     else if ((token->type == CONF_TOKEN_TYPE_CLIST) ||
303              (token->type == CONF_TOKEN_TYPE_SLIST))
304       token->u.list_num = VSTR_SECTS_NUM(conf->sects, token->num)->len;
305     else
306       token->u.uval_num = VSTR_SECTS_NUM(conf->sects, token->num)->pos;
307 
308     return (CONF__TRUE);
309   }
310 
311   if (token->num > num)
312     return (CONF__FALSE);
313 
314   while (token->num < num)
315   {
316     if (!conf_parse_token(conf, token))
317       return (CONF__FALSE);
318   }
319 
320   return (CONF__TRUE);
321 }
322 
conf_token_at_depth(const Conf_token * token)323 extern inline unsigned int conf_token_at_depth(const Conf_token *token)
324 {
325   unsigned int depth = 0;
326 
327   CONF__ASSERT(token);
328 
329   depth = token->depth_num;
330   if ((token->type == CONF_TOKEN_TYPE_CLIST) ||
331       (token->type == CONF_TOKEN_TYPE_SLIST))
332     --depth;
333 
334   return (depth);
335 }
336 
conf_token_value(const Conf_token * token)337 extern inline const Vstr_sect_node *conf_token_value(const Conf_token *token)
338 {
339   CONF__ASSERT(token);
340 
341   if ((token->type >= CONF_TOKEN_TYPE_QUOTE_D) &&
342       (token->type <= CONF_TOKEN_TYPE_SYMBOL))
343     return (token->u.node);
344 
345   return (NULL);
346 }
347 
conf_token_get_user_value(const Conf_parse * conf,const Conf_token * token,unsigned int * nxt)348 extern inline Vstr_ref *conf_token_get_user_value(const Conf_parse *conf,
349                                                   const Conf_token *token,
350                                                   unsigned int *nxt)
351 {
352   unsigned int dummy;
353 
354   CONF__ASSERT(conf && token);
355 
356   if (!nxt) nxt = &dummy;
357   *nxt = 0;
358 
359   if (token->type <= CONF_TOKEN_TYPE_SYMBOL)
360     return (NULL);
361 
362   if (token->u.uval_num >= conf->uvals_sz)
363     return (NULL);
364 
365   CONF__ASSERT(conf->uvals_sz);
366 
367   *nxt = conf->uvals_ptr[token->u.uval_num].nxt;
368   if (!conf->uvals_ptr[token->u.uval_num].ref)
369     return (NULL);
370 
371   return (vstr_ref_add(conf->uvals_ptr[token->u.uval_num].ref));
372 }
373 
conf_token_cmp_val_eq(const Conf_parse * conf,const Conf_token * token,const Vstr_base * s1,size_t pos,size_t len)374 extern inline int conf_token_cmp_val_eq(const Conf_parse *conf,
375                                         const Conf_token *token,
376                                         const Vstr_base *s1,
377                                         size_t pos, size_t len)
378 {
379   const Vstr_sect_node *val = conf_token_value(token);
380 
381   CONF__ASSERT(conf && token && conf->data && s1);
382 
383   if (!val) return (CONF__FALSE);
384 
385   return (vstr_cmp_eq(conf->data, val->pos, val->len, s1, pos, len));
386 }
387 
conf_token_cmp_val_buf_eq(const Conf_parse * conf,const Conf_token * token,const char * buf,size_t len)388 extern inline int conf_token_cmp_val_buf_eq(const Conf_parse *conf,
389                                             const Conf_token *token,
390                                             const char *buf, size_t len)
391 {
392   const Vstr_sect_node *val = conf_token_value(token);
393 
394   CONF__ASSERT(conf && token && conf->data && buf);
395 
396   if (!val) return (CONF__FALSE);
397 
398   return (vstr_cmp_buf_eq(conf->data, val->pos, val->len, buf, len));
399 }
400 
conf_token_cmp_val_cstr_eq(const Conf_parse * conf,const Conf_token * token,const char * cstr)401 extern inline int conf_token_cmp_val_cstr_eq(const Conf_parse *conf,
402                                              const Conf_token *token,
403                                              const char *cstr)
404 {
405   return (conf_token_cmp_val_buf_eq(conf, token, cstr, strlen(cstr)));
406 }
407 
conf_token_cmp_val_beg_eq(const Conf_parse * conf,const Conf_token * token,const Vstr_base * s1,size_t pos,size_t len)408 extern inline int conf_token_cmp_val_beg_eq(const Conf_parse *conf,
409                                             const Conf_token *token,
410                                             const Vstr_base *s1,
411                                             size_t pos, size_t len)
412 {
413   const Vstr_sect_node *val = conf_token_value(token);
414 
415   CONF__ASSERT(conf && token && conf->data && s1);
416 
417   if (!val) return (CONF__FALSE);
418 
419   if (len > val->len)
420     len = val->len;
421 
422   return (vstr_cmp_eq(conf->data, val->pos, val->len, s1, pos, len));
423 }
424 
conf_token_cmp_case_val_eq(const Conf_parse * conf,const Conf_token * token,const Vstr_base * s1,size_t pos,size_t len)425 extern inline int conf_token_cmp_case_val_eq(const Conf_parse *conf,
426                                              const Conf_token *token,
427                                              const Vstr_base *s1,
428                                              size_t pos, size_t len)
429 {
430   const Vstr_sect_node *val = conf_token_value(token);
431 
432   CONF__ASSERT(conf && token && conf->data && s1);
433 
434   if (!val) return (CONF__FALSE);
435 
436   return (vstr_cmp_case_eq(conf->data, val->pos, val->len, s1, pos, len));
437 }
438 
conf_token_cmp_case_val_cstr_eq(const Conf_parse * conf,const Conf_token * token,const char * cstr)439 extern inline int conf_token_cmp_case_val_cstr_eq(const Conf_parse *conf,
440                                                   const Conf_token *token,
441                                                   const char *cstr)
442 {
443   const Vstr_sect_node *val = conf_token_value(token);
444 
445   CONF__ASSERT(conf && token && conf->data && cstr);
446 
447   if (!val) return (CONF__FALSE);
448 
449   return (vstr_cmp_case_cstr_eq(conf->data, val->pos, val->len, cstr));
450 }
451 
conf_token_cmp_case_val_beg_eq(const Conf_parse * conf,const Conf_token * token,const Vstr_base * s1,size_t pos,size_t len)452 extern inline int conf_token_cmp_case_val_beg_eq(const Conf_parse *conf,
453                                                  const Conf_token *token,
454                                                  const Vstr_base *s1,
455                                                  size_t pos, size_t len)
456 {
457   const Vstr_sect_node *val = conf_token_value(token);
458 
459   CONF__ASSERT(conf && token && conf->data && s1);
460 
461   if (!val) return (CONF__FALSE);
462 
463   if (len > val->len)
464     len = val->len;
465 
466   return (vstr_cmp_case_eq(conf->data, val->pos, val->len, s1, pos, len));
467 }
468 
conf_token_cmp_sym_eq(const Conf_parse * conf,const Conf_token * token,const Vstr_base * s1,size_t pos,size_t len)469 extern inline int conf_token_cmp_sym_eq(const Conf_parse *conf,
470                                         const Conf_token *token,
471                                         const Vstr_base *s1,
472                                         size_t pos, size_t len)
473 {
474   CONF__ASSERT(token);
475 
476   if (token->type == CONF_TOKEN_TYPE_SYMBOL)
477     return (conf_token_cmp_val_eq(conf, token, s1, pos, len));
478   return (CONF__FALSE);
479 }
480 
conf_token_cmp_sym_buf_eq(const Conf_parse * conf,const Conf_token * token,const char * buf,size_t len)481 extern inline int conf_token_cmp_sym_buf_eq(const Conf_parse *conf,
482                                             const Conf_token *token,
483                                             const char *buf, size_t len)
484 {
485   CONF__ASSERT(token);
486 
487   if (token->type == CONF_TOKEN_TYPE_SYMBOL)
488     return (conf_token_cmp_val_buf_eq(conf, token, buf, len));
489   return (CONF__FALSE);
490 }
491 
conf_token_cmp_sym_cstr_eq(const Conf_parse * conf,const Conf_token * token,const char * cstr)492 extern inline int conf_token_cmp_sym_cstr_eq(const Conf_parse *conf,
493                                              const Conf_token *token,
494                                              const char *cstr)
495 {
496   CONF__ASSERT(token);
497 
498   if (token->type == CONF_TOKEN_TYPE_SYMBOL)
499     return (conf_token_cmp_val_cstr_eq(conf, token, cstr));
500   return (CONF__FALSE);
501 }
502 
conf_token_cmp_case_sym_cstr_eq(const Conf_parse * conf,const Conf_token * token,const char * cstr)503 extern inline int conf_token_cmp_case_sym_cstr_eq(const Conf_parse *conf,
504                                                   const Conf_token *token,
505                                                   const char *cstr)
506 {
507   CONF__ASSERT(token);
508 
509   if (token->type == CONF_TOKEN_TYPE_SYMBOL)
510     return (conf_token_cmp_case_val_cstr_eq(conf, token, cstr));
511   return (CONF__FALSE);
512 }
513 
conf_token_srch_case_val(const Conf_parse * conf,const Conf_token * token,const Vstr_base * s1,size_t pos,size_t len)514 extern inline int conf_token_srch_case_val(const Conf_parse *conf,
515                                            const Conf_token *token,
516                                            const Vstr_base *s1,
517                                            size_t pos, size_t len)
518 {
519   const Vstr_sect_node *val = conf_token_value(token);
520 
521   CONF__ASSERT(conf && token && conf->data && s1);
522 
523   if (!val) return (CONF__FALSE);
524 
525   return (vstr_srch_case_vstr_fwd(conf->data, val->pos, val->len,
526                                   s1, pos, len));
527 }
528 
conf_token_list_num(const Conf_token * token,unsigned int depth)529 extern inline unsigned int conf_token_list_num(const Conf_token *token,
530                                                unsigned int depth)
531 {
532   CONF__ASSERT(token);
533 
534   if (depth > token->depth_num)
535     return (CONF__FALSE);
536 
537   CONF__ASSERT(token->depth_nums[depth] >= token->num);
538 
539   return (token->depth_nums[depth] - token->num);
540 }
541 
conf_sc_token_parse_toggle(const Conf_parse * conf,Conf_token * token,int * val)542 extern inline int conf_sc_token_parse_toggle(const Conf_parse *conf,
543                                              Conf_token *token, int *val)
544 {
545   unsigned int num = conf_token_list_num(token, token->depth_num);
546   int ern = CONF_SC_TYPE_RET_OK;
547 
548   CONF__ASSERT(val);
549 
550   if (!num)
551   {
552     *val = !*val;
553     return (ern);
554   }
555 
556   conf_parse_token(conf, token);
557   if (0) { }
558   else if (conf_token_cmp_val_cstr_eq(conf, token, "on") ||
559            conf_token_cmp_val_cstr_eq(conf, token, "true") ||
560            conf_token_cmp_val_cstr_eq(conf, token, "yes") ||
561            conf_token_cmp_val_cstr_eq(conf, token, "ON") ||
562            conf_token_cmp_val_cstr_eq(conf, token, "TRUE") ||
563            conf_token_cmp_val_cstr_eq(conf, token, "YES") ||
564            conf_token_cmp_val_cstr_eq(conf, token, "1"))
565     *val = CONF__TRUE;
566   else if (conf_token_cmp_val_cstr_eq(conf, token, "off") ||
567            conf_token_cmp_val_cstr_eq(conf, token, "false") ||
568            conf_token_cmp_val_cstr_eq(conf, token, "no") ||
569            conf_token_cmp_val_cstr_eq(conf, token, "OFF") ||
570            conf_token_cmp_val_cstr_eq(conf, token, "FALSE") ||
571            conf_token_cmp_val_cstr_eq(conf, token, "NO") ||
572            conf_token_cmp_val_cstr_eq(conf, token, "0"))
573     *val = CONF__FALSE;
574   else
575     ern = CONF_SC_TYPE_RET_ERR_NO_MATCH;
576 
577   return (ern);
578 }
579 
580 #endif
581 
582 #endif
583