2009-08-18 00:53:58 +04:00
# include <stdio.h>
# include <pthread.h>
# include <string.h>
# include <malloc.h>
2010-01-09 00:40:31 +03:00
# include <stdlib.h>
# include <assert.h>
2009-08-18 00:53:58 +04:00
# include "simpleconfig.h"
# include "config-stack.h"
2010-01-14 21:38:37 +03:00
# include <static_map.h>
2009-08-18 00:53:58 +04:00
static pthread_mutex_t parser_mutex = PTHREAD_MUTEX_INITIALIZER ;
static int
print_value ( struct value * v , int depth , FILE * fp )
{
int x ;
2010-01-06 22:39:16 +03:00
if ( v - > val = = NULL )
return 0 ;
2009-08-18 00:53:58 +04:00
for ( x = 0 ; x < depth ; x + + )
fprintf ( fp , " \t " ) ;
fprintf ( fp , " %s = \" %s \" ; \n " , v - > id , v - > val ) ;
return 0 ;
}
static void
_sc_dump_d ( struct node * node , int depth , FILE * fp )
{
struct node * n ;
struct value * v ;
int x ;
if ( ! node ) {
//printf("Empty node\n");
return ;
}
for ( x = 0 ; x < depth ; x + + )
fprintf ( fp , " \t " ) ;
2010-01-09 00:40:31 +03:00
if ( node - > val ) {
fprintf ( fp , " %s = \" %s \" { \n " , node - > id , node - > val ) ;
} else {
fprintf ( fp , " %s { \n " , node - > id ) ;
}
2009-08-18 00:53:58 +04:00
for ( n = node - > nodes ; n ; n = n - > next ) {
_sc_dump_d ( n , depth + 1 , fp ) ;
}
for ( v = node - > values ; v ; v = v - > next ) {
print_value ( v , depth + 1 , fp ) ;
}
for ( x = 0 ; x < depth ; x + + )
fprintf ( fp , " \t " ) ;
fprintf ( fp , " } \n \n " ) ;
}
static void
2010-01-14 23:00:43 +03:00
_sc_dump ( void * config , FILE * fp )
2009-08-18 00:53:58 +04:00
{
struct node * n , * node ;
struct value * v , * values ;
if ( ! config )
return ;
values = ( ( struct parser_context * ) config ) - > val_list ;
node = ( ( struct parser_context * ) config ) - > node_list ;
for ( n = node ; n ; n = n - > next ) {
_sc_dump_d ( n , 0 , fp ) ;
}
for ( v = values ; v ; v = v - > next ) {
print_value ( v , 0 , fp ) ;
}
}
static int
free_value ( struct value * v )
{
int x ;
if ( v ) {
free ( v - > id ) ;
free ( v - > val ) ;
free ( v ) ;
}
return 0 ;
}
static void
_sc_free_node ( struct node * node )
{
struct node * n ;
struct value * v ;
int x ;
if ( ! node )
return ;
while ( node - > nodes ) {
n = node - > nodes ;
if ( n ) {
node - > nodes = node - > nodes - > next ;
_sc_free_node ( n ) ;
}
}
while ( node - > values ) {
v = node - > values ;
node - > values = node - > values - > next ;
free_value ( v ) ;
}
free ( node - > id ) ;
free ( node ) ;
}
static int
2010-01-14 23:00:43 +03:00
_sc_free ( void * config )
2009-08-18 00:53:58 +04:00
{
struct node * n , * nlist ;
struct value * v , * vlist ;
if ( ! config )
return - 1 ;
vlist = ( ( struct parser_context * ) config ) - > val_list ;
nlist = ( ( struct parser_context * ) config ) - > node_list ;
while ( nlist ) {
n = nlist ;
nlist = nlist - > next ;
_sc_free_node ( n ) ;
}
( ( struct parser_context * ) config ) - > node_list = NULL ;
while ( vlist ) {
v = vlist ;
vlist = vlist - > next ;
free_value ( v ) ;
}
( ( struct parser_context * ) config ) - > val_list = NULL ;
free ( config ) ;
return 0 ;
}
static int
2010-01-14 23:00:43 +03:00
_sc_get ( void * config , const char * key , char * value , size_t valuesz )
2009-08-18 00:53:58 +04:00
{
char buf [ 1024 ] ;
2012-10-17 19:28:42 +04:00
struct node * n , * node ;
struct value * v , * values ;
2009-08-18 00:53:58 +04:00
char * ptr ;
char * slash ;
2010-01-09 00:40:31 +03:00
char * bracket ;
char * id ;
int req_index = 0 ;
int curr_index = 0 ;
2009-08-18 00:53:58 +04:00
int found ;
2010-01-04 22:12:21 +03:00
if ( ! config )
2010-01-09 00:40:31 +03:00
return - 1 ;
2012-10-17 19:28:42 +04:00
node = ( ( struct parser_context * ) config ) - > node_list ;
values = ( ( struct parser_context * ) config ) - > val_list ;
2010-01-09 00:40:31 +03:00
assert ( strlen ( key ) < sizeof ( buf ) ) ;
2010-01-04 22:12:21 +03:00
2009-08-18 00:53:58 +04:00
ptr = ( char * ) key ;
2010-01-09 00:40:31 +03:00
top :
2009-08-18 00:53:58 +04:00
while ( ( slash = strchr ( ptr , ' / ' ) ) ) {
memset ( buf , 0 , sizeof ( buf ) ) ;
strncpy ( buf , ptr , ( slash - ptr ) ) ;
ptr = + + slash ;
2010-01-09 00:40:31 +03:00
id = NULL ;
bracket = strchr ( buf , ' [ ' ) ;
if ( bracket ) {
* bracket = 0 ;
+ + bracket ;
id = bracket ;
bracket = strchr ( bracket , ' ] ' ) ;
if ( ! bracket )
return 1 ;
* bracket = 0 ;
if ( id [ 0 ] = = ' @ ' ) {
+ + id ;
if ( ! strlen ( id ) ) {
return 1 ;
}
} else {
req_index = atoi ( id ) ;
if ( req_index < = 0 )
return 1 ;
id = NULL ;
}
}
2009-08-18 00:53:58 +04:00
found = 0 ;
2010-01-09 00:40:31 +03:00
curr_index = 0 ;
2009-08-18 00:53:58 +04:00
for ( n = node ; n ; n = n - > next ) {
2010-01-09 00:40:31 +03:00
if ( strcasecmp ( n - > id , buf ) )
continue ;
+ + curr_index ;
if ( req_index & & ( curr_index ! = req_index ) ) {
continue ;
} else if ( id & & strcasecmp ( n - > val , id ) ) {
continue ;
2009-08-18 00:53:58 +04:00
}
2010-01-09 00:40:31 +03:00
node = n - > nodes ;
values = n - > values ;
found = 1 ;
break ;
2009-08-18 00:53:58 +04:00
}
if ( ! found )
return 1 ;
}
2010-01-09 00:40:31 +03:00
if ( ptr [ 0 ] ! = ' @ ' ) {
2010-01-09 02:17:03 +03:00
strncpy ( buf , ptr , sizeof ( buf ) ) ;
id = NULL ;
bracket = strchr ( buf , ' [ ' ) ;
if ( bracket ) {
* bracket = 0 ;
+ + bracket ;
id = bracket ;
bracket = strchr ( bracket , ' ] ' ) ;
if ( ! bracket )
return 1 ;
* bracket = 0 ;
if ( id [ 0 ] = = ' @ ' ) {
+ + id ;
if ( ! strlen ( id ) ) {
return 1 ;
}
} else {
req_index = atoi ( id ) ;
if ( req_index < = 0 )
return 1 ;
id = NULL ;
}
}
found = 0 ;
curr_index = 0 ;
for ( n = node ; n ; n = n - > next ) {
if ( strcasecmp ( n - > id , buf ) )
continue ;
+ + curr_index ;
if ( req_index & & ( curr_index ! = req_index ) ) {
continue ;
} else if ( id & & strcasecmp ( n - > val , id ) ) {
continue ;
}
if ( node - > val ) {
strncpy ( value , node - > val , valuesz ) ;
return 0 ;
}
return 1 ;
2010-01-09 00:40:31 +03:00
}
}
2009-08-18 00:53:58 +04:00
2009-09-04 01:45:38 +04:00
+ + ptr ;
found = 0 ;
2010-01-09 00:40:31 +03:00
id = NULL ;
strncpy ( buf , ptr , sizeof ( buf ) ) ;
bracket = strchr ( buf , ' [ ' ) ;
req_index = 0 ;
curr_index = 0 ;
if ( bracket ) {
* bracket = 0 ;
+ + bracket ;
id = bracket ;
bracket = strchr ( bracket , ' ] ' ) ;
if ( ! bracket )
return 1 ;
* bracket = 0 ;
req_index = atoi ( id ) ;
if ( req_index < = 0 )
return 1 ;
id = NULL ;
}
2009-09-04 01:45:38 +04:00
for ( v = values ; v ; v = v - > next ) {
2010-01-09 00:40:31 +03:00
if ( strcasecmp ( v - > id , buf ) )
continue ;
+ + curr_index ;
if ( req_index & & ( curr_index ! = req_index ) )
continue ;
snprintf ( value , valuesz , " %s " , v - > val ) ;
return 0 ;
2009-08-18 00:53:58 +04:00
}
return 1 ;
}
2009-09-04 01:45:38 +04:00
static int
2010-01-14 23:00:43 +03:00
_sc_set ( void * config , const char * key , const char * value )
2009-09-04 01:45:38 +04:00
{
char buf [ 1024 ] ;
struct node * n , * * nodes = & ( ( struct parser_context * ) config ) - > node_list ;
struct value * v , * * values = & ( ( struct parser_context * ) config ) - > val_list ;
char * ptr ;
char * slash ;
char * id_dup , * val_dup ;
int found = 0 ;
ptr = ( char * ) key ;
while ( ( slash = strchr ( ptr , ' / ' ) ) ) {
memset ( buf , 0 , sizeof ( buf ) ) ;
strncpy ( buf , ptr , ( slash - ptr ) ) ;
ptr = + + slash ;
found = 0 ;
for ( n = * nodes ; n ; n = n - > next ) {
if ( strcasecmp ( n - > id , buf ) )
continue ;
nodes = & n - > nodes ;
values = & n - > values ;
found = 1 ;
break ;
}
if ( ! found ) {
id_dup = strdup ( buf ) ;
if ( ! id_dup )
return - 1 ;
2010-01-09 00:40:31 +03:00
_sc_node_add ( id_dup , NULL , NULL , NULL , nodes ) ;
2009-09-04 01:45:38 +04:00
n = * nodes ;
nodes = & n - > nodes ;
values = & n - > values ;
}
}
if ( ptr [ 0 ] ! = ' @ ' )
return 1 ;
+ + ptr ;
for ( v = * values ; v ; v = v - > next ) {
if ( strcasecmp ( v - > id , ptr ) )
continue ;
ptr = v - > val ;
2010-01-06 22:39:16 +03:00
if ( value ) {
v - > val = strdup ( value ) ;
if ( ! v - > val ) {
v - > val = ptr ;
return - 1 ;
}
} else {
v - > val = NULL ;
2009-09-04 01:45:38 +04:00
}
free ( ptr ) ;
return 0 ;
}
2010-01-06 22:44:19 +03:00
if ( ! value )
return 0 ;
2009-09-04 01:45:38 +04:00
id_dup = strdup ( ptr ) ;
if ( ! id_dup )
return - 1 ;
2014-06-23 23:49:05 +04:00
2009-09-04 01:45:38 +04:00
val_dup = strdup ( value ) ;
2014-06-23 23:49:05 +04:00
if ( ! val_dup ) {
free ( id_dup ) ;
2009-09-04 01:45:38 +04:00
return - 1 ;
2014-06-23 23:49:05 +04:00
}
2009-09-04 01:45:38 +04:00
_sc_value_add ( id_dup , val_dup , values ) ;
return 0 ;
}
2009-08-18 00:53:58 +04:00
static int
2010-01-14 23:00:43 +03:00
_sc_parse ( const char * filename , void * * config )
2009-08-18 00:53:58 +04:00
{
struct parser_context * c ;
FILE * fp = NULL ;
int ret = 0 ;
if ( ! config )
return - 1 ;
pthread_mutex_lock ( & parser_mutex ) ;
if ( filename ) {
fp = fopen ( filename , " r " ) ;
yyin = fp ;
2010-01-04 22:12:21 +03:00
if ( fp )
ret = yyparse ( ) ;
else
ret = 1 ;
} else {
ret = 1 ;
2009-08-18 00:53:58 +04:00
}
2010-01-04 22:12:21 +03:00
c = malloc ( sizeof ( * c ) ) ;
2012-10-17 19:00:21 +04:00
if ( ! c ) {
ret = - 1 ;
goto out_unlock ;
}
2010-01-04 22:12:21 +03:00
c - > node_list = node_list ;
c - > val_list = val_list ;
c - > next = NULL ;
val_list = NULL ;
node_list = NULL ;
2010-01-14 23:00:43 +03:00
* config = ( void * ) c ;
2009-08-18 00:53:58 +04:00
if ( fp )
fclose ( fp ) ;
2012-10-17 19:00:21 +04:00
out_unlock :
2009-08-18 00:53:58 +04:00
pthread_mutex_unlock ( & parser_mutex ) ;
return ret ;
}
static const config_object_t sc_object = {
. get = _sc_get ,
2009-09-04 01:45:38 +04:00
. set = _sc_set ,
2009-08-18 00:53:58 +04:00
. parse = _sc_parse ,
. free = _sc_free ,
. dump = _sc_dump ,
. info = NULL
} ;
config_object_t *
sc_init ( void )
{
config_object_t * o ;
o = malloc ( sizeof ( * o ) ) ;
if ( ! o )
return NULL ;
memset ( o , 0 , sizeof ( * o ) ) ;
memcpy ( o , & sc_object , sizeof ( * o ) ) ;
return o ;
}
void
sc_release ( config_object_t * c )
{
sc_free ( c ) ;
free ( c ) ;
}