2008-08-06 09:39:48 +02:00
/*
config . c - Lumiera configuration system
Copyright ( C ) Lumiera . org
2008 , Christian Thaeter < ct @ pipapo . org >
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of the
License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
//TODO: Support library includes//
2008-08-07 06:09:50 +02:00
# include "lib/safeclib.h"
2008-08-06 09:39:48 +02:00
//TODO: Lumiera header includes//
# include "backend/config.h"
//TODO: internal/static forward declarations//
//TODO: System includes//
2008-08-07 06:09:50 +02:00
# include <stdint.h>
2008-08-07 11:15:23 +02:00
# include <stdlib.h>
2008-08-19 22:32:54 +02:00
# include <ctype.h>
2008-08-06 09:39:48 +02:00
/**
* @ file
*
*/
NOBUG_DEFINE_FLAG_PARENT ( config_all , backend ) ;
NOBUG_DEFINE_FLAG_PARENT ( config , config_all ) ;
2008-08-07 08:10:23 +02:00
NOBUG_DEFINE_FLAG_PARENT ( config_typed , config_all ) ;
NOBUG_DEFINE_FLAG_PARENT ( config_file , config_all ) ;
2008-08-12 08:13:15 +02:00
NOBUG_DEFINE_FLAG_PARENT ( config_item , config_all ) ;
2008-08-12 21:24:41 +02:00
NOBUG_DEFINE_FLAG_PARENT ( config_lookup , config_all ) ;
2008-08-06 09:39:48 +02:00
2008-08-07 11:43:06 +02:00
LUMIERA_ERROR_DEFINE ( CONFIG_SYNTAX , " syntax error in configfile " ) ;
LUMIERA_ERROR_DEFINE ( CONFIG_SYNTAX_KEY , " syntax error in key " ) ;
2008-08-08 08:21:38 +02:00
LUMIERA_ERROR_DEFINE ( CONFIG_SYNTAX_VALUE , " syntax error in value " ) ;
2008-08-07 11:43:06 +02:00
LUMIERA_ERROR_DEFINE ( CONFIG_NO_ENTRY , " no configuration entry " ) ;
LUMIERA_ERROR_DEFINE ( CONFIG_DEFAULT , " illegal default value " ) ;
2008-08-06 09:39:48 +02:00
2008-09-06 08:00:55 +02:00
/**
* defaults for the configuraton system itself
*/
const char * lumiera_config_defaults [ ] =
{
/* Low level formating, don't change these */
" config.formatstr.link = '< %s' " ,
" config.formatstr.number.dec = '= %lld' " ,
" config.formatstr.number.hex = '= 0x%llX' " ,
" config.formatstr.number.oct = '= 0%llo' " ,
" config.formatstr.real = '= %Lg' " ,
" config.formatstr.real.dec = '= %Lf' " ,
" config.formatstr.real.sci = '= %Le' " ,
" config.formatstr.string = '=%s' " ,
" config.formatstr.string.dquoted = '= \" %s \" ' " ,
" config.formatstr.string.quoted = '= ''%s''' " ,
" config.formatstr.word = '= %s' " ,
" config.formatstr.bool = '= %d' " ,
/* default representations per type */
" config.formatdef.link < config.formatstr.link " ,
" config.formatdef.number < config.formatstr.number.dec " ,
" config.formatdef.real < config.formatstr.real " ,
" config.formatdef.string < config.formatstr.string " ,
" config.formatdef.word < config.formatstr.word " ,
" config.formatdef.bool < config.formatstr.bool " ,
/* per key formatting override stored under */
" config.formatkey ='config.format.%s' " ,
NULL
} ;
2008-08-06 09:39:48 +02:00
2008-08-06 10:11:43 +02:00
/* singleton config */
2008-08-07 11:15:23 +02:00
LumieraConfig lumiera_global_config = NULL ;
2008-08-06 10:11:43 +02:00
2008-08-06 09:39:48 +02:00
2008-08-06 10:11:04 +02:00
int
2008-08-06 09:39:48 +02:00
lumiera_config_init ( const char * path )
{
2008-08-07 08:10:23 +02:00
TRACE ( config ) ;
REQUIRE ( ! lumiera_global_config , " Configuration subsystem already initialized " ) ;
REQUIRE ( path ) ;
NOBUG_INIT_FLAG ( config_all ) ;
NOBUG_INIT_FLAG ( config ) ;
NOBUG_INIT_FLAG ( config_typed ) ;
NOBUG_INIT_FLAG ( config_file ) ;
2008-08-12 08:13:15 +02:00
NOBUG_INIT_FLAG ( config_item ) ;
2008-08-12 21:24:41 +02:00
NOBUG_INIT_FLAG ( config_lookup ) ;
2008-08-07 08:10:23 +02:00
lumiera_global_config = lumiera_malloc ( sizeof ( * lumiera_global_config ) ) ;
2008-08-12 21:24:41 +02:00
lumiera_config_lookup_init ( & lumiera_global_config - > keys ) ;
2008-08-19 22:32:54 +02:00
lumiera_configitem_init ( & lumiera_global_config - > defaults ) ;
lumiera_configitem_init ( & lumiera_global_config - > files ) ;
lumiera_configitem_init ( & lumiera_global_config - > TODO_unknown ) ;
2008-08-10 06:46:31 +02:00
lumiera_rwlock_init ( & lumiera_global_config - > lock , " config rwlock " , & NOBUG_FLAG ( config ) ) ;
2008-08-07 06:09:50 +02:00
2008-09-06 08:00:55 +02:00
lumiera_config_setdefault ( lumiera_tmpbuf_snprintf ( SIZE_MAX , " config.path = %s " , path ) ) ;
for ( const char * * itr = lumiera_config_defaults ; * itr ; + + itr )
{
lumiera_config_setdefault ( * itr ) ;
}
2008-08-19 22:32:54 +02:00
2008-08-07 06:09:50 +02:00
return 0 ;
2008-08-06 09:39:48 +02:00
}
2008-08-07 06:09:50 +02:00
void
lumiera_config_destroy ( )
2008-08-06 09:39:48 +02:00
{
2008-08-07 08:10:23 +02:00
TRACE ( config ) ;
if ( lumiera_global_config )
2008-08-07 06:09:50 +02:00
{
2008-08-10 06:46:31 +02:00
lumiera_rwlock_destroy ( & lumiera_global_config - > lock , & NOBUG_FLAG ( config ) ) ;
2008-08-19 22:32:54 +02:00
lumiera_configitem_destroy ( & lumiera_global_config - > defaults , & lumiera_global_config - > keys ) ;
lumiera_configitem_destroy ( & lumiera_global_config - > files , & lumiera_global_config - > keys ) ;
lumiera_configitem_destroy ( & lumiera_global_config - > TODO_unknown , & lumiera_global_config - > keys ) ;
2008-08-12 21:24:41 +02:00
lumiera_config_lookup_destroy ( & lumiera_global_config - > keys ) ;
2008-08-07 08:10:23 +02:00
lumiera_free ( lumiera_global_config ) ;
lumiera_global_config = NULL ;
2008-08-07 06:09:50 +02:00
}
else
WARN ( config , " Tried to destroy non initialized config subsystem " ) ;
2008-08-06 09:39:48 +02:00
}
2008-08-06 10:11:04 +02:00
int
2008-08-06 09:39:48 +02:00
lumiera_config_load ( const char * file )
{
2008-08-07 11:16:42 +02:00
TRACE ( config ) ;
2008-08-06 09:39:48 +02:00
UNIMPLEMENTED ( ) ;
2008-08-06 10:11:04 +02:00
return - 1 ;
2008-08-06 09:39:48 +02:00
}
2008-08-06 10:11:04 +02:00
int
2008-08-06 09:39:48 +02:00
lumiera_config_save ( )
{
2008-08-07 11:16:42 +02:00
TRACE ( config ) ;
2008-08-06 09:39:48 +02:00
UNIMPLEMENTED ( ) ;
2008-08-06 10:11:04 +02:00
return - 1 ;
2008-08-06 09:39:48 +02:00
}
2008-08-06 10:11:04 +02:00
int
2008-08-06 09:39:48 +02:00
lumiera_config_purge ( const char * filename )
{
2008-08-07 11:16:42 +02:00
TRACE ( config ) ;
2008-08-06 09:39:48 +02:00
UNIMPLEMENTED ( ) ;
2008-08-06 10:11:04 +02:00
return - 1 ;
2008-08-06 09:39:48 +02:00
}
2008-08-06 10:11:04 +02:00
int
2008-08-06 09:39:48 +02:00
lumiera_config_get ( const char * key , const char * * value )
{
2008-08-07 11:15:23 +02:00
TRACE ( config ) ;
REQUIRE ( key ) ;
REQUIRE ( value ) ;
int ret = - 1 ;
2008-08-10 19:38:31 +02:00
/* we translate the key for the env var override by making it uppercase and replace . with _,
2008-08-07 11:15:23 +02:00
as side effect , this also checks the key syntax */
char * tr_key = lumiera_tmpbuf_tr ( key ,
2008-08-10 19:38:31 +02:00
LUMIERA_CONFIG_KEY_CHARS ,
LUMIERA_CONFIG_ENV_CHARS ,
2008-08-07 11:15:23 +02:00
NULL ) ;
2008-08-19 22:32:54 +02:00
if ( tr_key )
2008-08-07 11:15:23 +02:00
{
char * env = lumiera_tmpbuf_snprintf ( 2048 , " LUMIERA_%s " , tr_key ) ;
* value = getenv ( env ) ;
if ( * value )
{
ret = 0 ;
NOTICE ( config , " envvar override for config %s = %s " , env , * value ) ;
}
else
{
2008-08-19 22:32:54 +02:00
TODO ( " follow '<' delegates? " ) ;
LumieraConfigitem item = lumiera_config_lookup_item_find ( & lumiera_global_config - > keys , key ) ;
if ( item )
{
* value = item - > delim + 1 ;
ret = 0 ;
}
else
LUMIERA_ERROR_SET ( config , CONFIG_NO_ENTRY ) ;
2008-08-07 11:15:23 +02:00
}
}
2008-08-19 22:32:54 +02:00
else
{
LUMIERA_ERROR_SET ( config , CONFIG_SYNTAX_KEY ) ;
}
return ret ;
}
int
lumiera_config_get_default ( const char * key , const char * * value )
{
TRACE ( config ) ;
REQUIRE ( key ) ;
REQUIRE ( value ) ;
int ret = - 1 ;
TODO ( " follow '<' delegates? " ) ;
2008-09-05 06:47:10 +02:00
TODO ( " refactor _get and get_default to iterator access (return LList or Lookupentry) " ) ;
2008-08-19 22:32:54 +02:00
LumieraConfigitem item = lumiera_config_lookup_item_tail_find ( & lumiera_global_config - > keys , key ) ;
if ( item & & item - > parent = = & lumiera_global_config - > defaults )
{
* value = item - > delim + 1 ;
ret = 0 ;
}
2008-08-06 10:11:04 +02:00
2008-08-07 11:15:23 +02:00
return ret ;
2008-08-06 09:39:48 +02:00
}
2008-08-06 10:11:04 +02:00
int
2008-08-19 22:32:54 +02:00
lumiera_config_set ( const char * key , const char * delim_value )
2008-08-06 09:39:48 +02:00
{
2008-08-07 11:16:42 +02:00
TRACE ( config ) ;
2008-08-19 22:32:54 +02:00
TODO ( " if does this item already exist in a user writeable file? " ) ;
TODO ( " replace delim_value " ) ;
TODO ( " else " ) ;
TODO ( " find matching prefix " ) ;
TODO ( " find matching suffix " ) ;
TODO ( " find proper prefix indentation, else use config.indent " ) ;
TODO ( " create configitem with prefix/suffix removed " ) ;
2008-09-05 06:47:10 +02:00
2008-08-19 22:32:54 +02:00
// * set a value by key
// * handles internally everything as string:string key:value pair.
// * lowlevel function
// * tag file as dirty
// * set will create a new user configuration file if it does not exist yet or will append a line to the existing one in RAM. These files, tagged as 'dirty', will be only written if save() is called.
2008-08-06 09:39:48 +02:00
UNIMPLEMENTED ( ) ;
2008-08-06 10:11:04 +02:00
return - 1 ;
2008-08-06 09:39:48 +02:00
}
2008-08-19 22:32:54 +02:00
LumieraConfigitem
lumiera_config_setdefault ( const char * line )
{
TRACE ( config ) ;
REQUIRE ( line ) ;
LumieraConfigitem item = NULL ;
LUMIERA_WRLOCK_SECTION ( config , & lumiera_global_config - > lock )
{
const char * key = line ;
while ( * key & & isspace ( * key ) )
key + + ;
key = lumiera_tmpbuf_strndup ( line , strspn ( line , LUMIERA_CONFIG_KEY_CHARS ) ) ;
if ( ! ( item = lumiera_config_lookup_item_find ( & lumiera_global_config - > keys , key ) ) | | item - > parent ! = & lumiera_global_config - > defaults )
{
item = lumiera_configitem_new ( line ) ;
if ( item )
{
ENSURE ( item - > delim , " default must be a configentry with key=value or key<delegate syntax " )
ENSURE ( * item - > delim = = ' = ' | | * item - > delim = = ' < ' , " default must be a configentry with key=value or key<delegate syntax " ) ;
TRACE ( config , " registering default: '%s' " , item - > line ) ;
llist_insert_head ( & lumiera_global_config - > defaults . childs , & item - > link ) ;
item - > parent = & lumiera_global_config - > defaults ;
lumiera_config_lookup_insert_default ( & lumiera_global_config - > keys , item ) ;
}
}
}
return item ;
}
2008-09-05 06:44:42 +02:00
void
lumiera_config_dump ( FILE * out )
{
fprintf ( out , " # registered defaults: \n " ) ;
LLIST_FOREACH ( & lumiera_global_config - > defaults . childs , node )
fprintf ( out , " %s \n " , ( ( LumieraConfigitem ) node ) - > line ) ;
fprintf ( out , " # end of defaults \n \n " ) ;
#if 0 /*TODO UNIMPLEMENTED */
fprintf ( out , " # files: \n " ) ;
lumiera_configitem files ;
fprintf ( out , " # volatiles: " )
lumiera_configitem TODO_unknown ;
# endif
}
2008-08-06 10:11:04 +02:00
int
2008-08-07 11:16:42 +02:00
lumiera_config_reset ( const char * key )
2008-08-06 09:39:48 +02:00
{
2008-08-07 11:16:42 +02:00
TRACE ( config ) ;
2008-08-06 09:39:48 +02:00
UNIMPLEMENTED ( ) ;
2008-08-06 10:11:04 +02:00
return - 1 ;
2008-08-06 09:39:48 +02:00
}
2008-08-06 10:11:04 +02:00
int
2008-08-06 09:39:48 +02:00
lumiera_config_info ( const char * key , const char * * filename , unsigned * line )
{
2008-08-07 11:16:42 +02:00
TRACE ( config ) ;
2008-08-06 09:39:48 +02:00
UNIMPLEMENTED ( ) ;
2008-08-06 10:11:04 +02:00
return - 1 ;
2008-08-06 09:39:48 +02:00
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/