remove obcl. shrimpx may work on this in the future but we are not usnig it now.

This commit is contained in:
Dana Jansens 2003-05-24 07:29:40 +00:00
parent b1fe0dbbc2
commit d61b48a2ef
10 changed files with 0 additions and 736 deletions

View file

@ -1,3 +0,0 @@
obcl.lo
libobcl.la
.libs

View file

@ -1,23 +0,0 @@
CFLAGS=-ansi -pedantic -Wall `pkg-config --cflags glib-2.0`
LIBS=`pkg-config --libs glib-2.0` -ll
targets = cltest
sources = obcl.c main.c parse.c lex.c process.c
headers = obcl.h
.PHONY: all clean
all: $(targets)
$(targets): $(sources:.c=.o)
$(CC) -o $@ $^ $(LIBS)
parse.c: parse.y
$(YACC) -d -o$@ $^
lex.c: lex.l
$(LEX) -o$@ $^
clean:
$(RM) $(targets) *.o core *~ lex.c parse.c parse.h

View file

@ -1,130 +0,0 @@
Note: this is not really a README but more of a thought dump, for now.
overall
-------
obcl wants to be a generic configuration file loader. generic not in
the sense that it will parse every single configuration format on the
planet, but in the sense that it will parse a versatile, multi purpose
format.
parser
------
this is the part of obcl that when given a configuration file, it will
return a parse tree. the parse tree can be mucked with by the
programmer, or it can be checked and processed using the handy checker
and processor. (for the most part; the programmer will do some
processing work.)
GList *config = cl_parse_file("foo.conf");
checker
-------
the checker is supposed to help the programmer/application ensure that
the configuration file is in the correct format. since obcl has a very
general, the parser itself cannot guarantee that the user will enter a
correct config file:
foo { }
fpp { }
will both be parsed, but 'fpp' might be a mistake. the checker is
intended to fix this.
foo 5;
blef "foo";
bar 5, "foo", "hi", 43.4;
woop "hello" {
foo 5;
}
CLChecker *check = cl_checker_new();
cl_checker_add(check, "foo", CL_NUM, 0);
cl_checker_add(check, "blef", CL_STRING, 0);
cl_checker_add(check, "bar", CL_NUM, CL_STRING, CL_STRING, CL_NUM, 0);
cl_checker_add(check, "woop", CL_STRING, CL_BLOCK, 0);
cl_checker_add_checker(check, "woop", check); /* add checker for block */
int val = cl_check(checker, config, stderr); /* write errors to stderr */
if (!val) {
fprintf(stderr, "Parse errors found. Loading default settings\n");
...
}
cl_checker_free(check);
processor
---------
the processor is intended to be run after the checker, to do actual
'stuff' with the parse tree. once the parse tree has been checked, we
know that we can just access stuff in the parse tree willy nilly
without sprinkling asserts all over the code. the processing is done
via callbacks.
typedef gpointer (*CLCallback)(CLNode *node, gpointer val);
gpointer handle_foo(CLNode *node, gpointer conf)
{
/* here numval is a macro that expands to something like
node->u.num. we know we can access this safely since the checker
has verified that 'foo' nodes indeed contain numbers.
same with NTH. it expands to somethign that we don't have to
worry about. */
((Config*)conf)->foo = NUMVAL(NTH(node, 1));
return 0;
}
gpointer handle_woop(CLNode *node, gpointer conf, CLProc *proc)
{
Config *conf1 = new_conf();
conf1->name = STRVAL(NTH(node,1));
cl_process(proc, BLOCK(node), conf1);
conf_add_child((Config*)conf, conf1);
return 0;
}
...
Config *process_config_file(char *file)
{
Config *conf;
GList *parse_tree;
CLProc *proc;
CLChecker *check;
int err;
config = new_conf();
parse_tree = cl_parse_file(file);
if (!parse_tree) {
fprintf(stderr, "your config file is completely borked. loading defaults\n");
conf_load_defaults(conf);
return conf;
}
checker = checker_new();
...
/* add checker stuff to checker, as per above */
err = cl_check(checker, parse_tree);
if (err) {
fprintf(stderr, "you fucked up. loading defaults\n");
config_load_defaults(conf);
return conf;
}
CLProc *proc = cl_proc_new();
cl_proc_add(proc, "foo", handle_foo, conf); /* conf will be passed to callback */
...
cl_proc_add_block(proc, "woop", handle_woop, conf, proc);
cl_process(proc, parse_tree);
return conf;
}
something like that. lalala.

View file

@ -1,9 +0,0 @@
foo "marius", 23;
foo "kyle", 15;
foo "soren", 7;
bah "blef","bummy";
meh {
foo "marius", 24;
foo "blef", 542;
bah "hi";
}

View file

@ -1,86 +0,0 @@
%{
#include "obcl.h"
#include "parse.h"
%}
%option yylineno
DGT [0-9]
ID [a-zA-Z_][a-zA-Z_\.\-0-9]*
/* string bummy */
%x str
%%
char str_buf[1024];
char *str_buf_ptr;
int str_char;
/* begin a string */
[\"\'] {
str_buf_ptr = str_buf;
str_char = yytext[0];
BEGIN(str);
}
/* end a string */
<str>[\"\'] {
if (yytext[0] == str_char) {
BEGIN(INITIAL);
*str_buf_ptr = '\0';
yylval.string = g_strdup(str_buf);
return TOK_STRING;
} else {
*str_buf_ptr++ = yytext[0];
}
}
/* can't have newlines in strings */
<str>\n {
printf("Error: Unterminated string constant.\n");
BEGIN(INITIAL);
}
/* handle \" and \' */
<str>"\\"[\"\'] {
if (yytext[1] == str_char)
*str_buf_ptr++ = yytext[1];
else {
*str_buf_ptr++ = yytext[0];
*str_buf_ptr++ = yytext[1];
}
}
/* eat valid string contents */
<str>[^\\\n\'\"]+ {
char *yptr = yytext;
while (*yptr) {
*str_buf_ptr++ = *yptr++;
}
}
/* numberz */
{DGT}+ {
yylval.num = atof(yytext);
return TOK_NUM;
}
/* real numbers */
{DGT}+"."{DGT}* {
yylval.num = atof(yytext);
return TOK_NUM;
}
/* identifiers -- names without spaces and other crap in them */
{ID} {
yylval.string = g_strdup(yytext);
return TOK_ID;
}
/* skip comments */
"#".*\n ;
/* skip other whitespace */
[ \n\t]+ ;
. { return yytext[0]; }
%%

View file

@ -1,33 +0,0 @@
#include "obcl.h"
void process_foo(CLNode *node)
{
if (CL_IS_NODE(node)) {
printf("foo name: %s\n"
"foo age: %.2f\n",
CL_STRVAL(CL_LIST_NTH(node,0)),
CL_NUMVAL(CL_LIST_NTH(node,1)));
}
}
void process_bah(CLNode *node)
{
printf("handling bah\n");
}
int main()
{
GList *lst = cl_parse("foo.conf");
/* cl_tree_print(lst,0); */
/* cl_tree_free(lst); */
CLProc *p = cl_proc_new();
cl_proc_add_handler_func(p, "foo", process_foo);
cl_proc_add_handler_func(p, "bah", process_bah);
cl_proc_add_handler_proc(p,"meh",p);
cl_process(lst, p);
return 0;
}

View file

@ -1,84 +0,0 @@
#include "obcl.h"
void cl_tree_free(GList *tree)
{
CLNode *tmp;
if (!tree) return;
for (; tree; tree = tree->next) {
tmp = (CLNode*)tree->data;
switch(tmp->type) {
case CL_ID:
case CL_STR:
g_free(tmp->u.str);
break;
case CL_LIST:
case CL_BLOCK:
case CL_LISTBLOCK:
g_free(tmp->u.lb.id);
cl_tree_free(tmp->u.lb.list);
cl_tree_free(tmp->u.lb.block);
break;
default:
break;
}
g_free(tmp);
}
g_list_free(tree);
}
GList *cl_parse(gchar *file)
{
FILE *fh = fopen(file, "r");
GList *ret = NULL;
if (fh) {
ret = cl_parse_fh(fh);
fclose(fh);
} else {
perror(file);
}
return ret;
}
void cl_tree_print(GList *tree, int depth)
{
CLNode *tmp;
int tmpd = depth;
for (; tree; tree = tree->next) {
tmp = (CLNode*)tree->data;
while (tmpd-- > 0)
printf(" ");
tmpd = depth;
switch(tmp->type) {
case CL_ID:
printf("[ID] '%s'\n", tmp->u.str);
break;
case CL_STR:
printf("[STR] '%s'\n", tmp->u.str);
break;
case CL_NUM:
printf("[NUM] %.2f\n", tmp->u.num);
break;
case CL_LIST:
printf("[LIST] '%s'\n", tmp->u.lb.id);
cl_tree_print(tmp->u.lb.list, depth+2);
break;
case CL_BLOCK:
printf("[BLOCK] '%s'\n", tmp->u.lb.id);
cl_tree_print(tmp->u.lb.block, depth+2);
break;
case CL_LISTBLOCK:
printf("[LISTBLOCK] %s\n", tmp->u.lb.id);
cl_tree_print(tmp->u.lb.list, depth+2);
printf("\n");
cl_tree_print(tmp->u.lb.block, depth+2);
break;
}
}
}

View file

@ -1,99 +0,0 @@
#ifndef __obcl_h
#define __obcl_h
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <stdarg.h>
/* TEH MACROS FROM MOUNT DOOM */
#define CL_IS_NODE(X) \
(((CLNode*)(X))->type == CL_LIST || \
((CLNode*)(X))->type == CL_BLOCK || \
((CLNode*)(X))->type == CL_LISTBLOCK)
#define CL_NODE(X) ((CLNode*)(X))
#define CL_ID(X) (((CLNode*)(X))->u.lb.id)
#define CL_LIST(X) (((CLNode*)(X))->u.lb.list)
#define CL_BLOCK(X) (((CLNode*)(X))->u.lb.block)
#define CL_NUMVAL(X) (((CLNode*)(X))->u.num)
#define CL_STRVAL(X) (((CLNode*)(X))->u.str)
#define CL_LINE(X) (((CLNode*)(X))->lineno)
#define CL_ASSERT_NODE(X) \
g_assert(CL_IS_NODE(X))
#define CL_ASSERT_NUM(X) \
g_assert(((CLNode*)(X))->type == CL_NUM)
#define CL_ASSERT_STR(X) \
g_assert(((CLNode*)(X))->type == CL_STR)
#define CL_LIST_NTH(X,Y)\
CL_NODE(g_list_nth(CL_LIST(X),(Y))->data)
typedef enum CLNodeType {
CL_ID,
CL_NUM,
CL_STR,
CL_LIST,
CL_BLOCK,
CL_LISTBLOCK
} CLNodeType;
typedef struct CLNode {
CLNodeType type;
int lineno;
union {
struct {
gchar *id;
GList *list;
GList *block;
} lb;
double num;
gchar *str;
} u;
} CLNode;
typedef void (*CLProcFunc)(CLNode *);
struct CLProcHandler;
typedef struct CLProc {
GHashTable *table;
struct CLProcHandler *default_h;
} CLProc;
typedef enum CLProcHandlerType {
CLPROC_FUNC,
CLPROC_PROC
} CLProcHandlerType;
typedef struct CLProcHandler {
CLProcHandlerType type;
union {
CLProcFunc func;
CLProc *proc;
} u;
} CLProcHandler;
GList *cl_parse(gchar *file);
GList *cl_parse_fh(FILE *file);
void cl_tree_free(GList *tree);
void cl_tree_print(GList *tree, int depth);
CLProcHandler *cl_proc_handler_new_func(CLProcFunc f);
CLProcHandler *cl_proc_handler_new_proc(CLProc *cp);
CLProc *cl_proc_new(void);
void cl_proc_free(CLProc *proc);
void cl_proc_add_handler(CLProc *proc, gchar *str,
CLProcHandler *handler);
void cl_proc_add_handler_func(CLProc *proc, gchar *str,
CLProcFunc func);
void cl_proc_add_handler_proc(CLProc *proc, gchar *str,
CLProc *hproc);
void cl_proc_set_default(CLProc *proc, CLProcHandler *pf);
void cl_proc_register_keywords(CLProc *proc, ...);
void cl_process(GList *tree, CLProc *proc);
#endif /* __obcl_h */

View file

@ -1,154 +0,0 @@
%{
#include "obcl.h"
int yylex(void);
void yyerror(char *msg, ...);
extern int yylineno;
extern char *yytext;
GList *config; /* this is what we parse into */
%}
%union {
double num;
gchar *string;
CLNode *node;
GList *glist;
};
%token <num> TOK_NUM
%token <string> TOK_ID TOK_STRING
%token TOK_SEP
%type <glist> config
%type <glist> stmts
%type <node> stmt
%type <glist> list
%type <glist> block
%type <node> value
%expect 2 /* for now */
%%
config: stmts
{
config = $$ = $1;
}
;
stmts:
{ $$ = NULL; }
| stmt
{ $$ = g_list_append(NULL, $1); }
| stmts stmt
{ $$ = g_list_append($1, $2); }
;
stmt: TOK_ID list ';'
{
CLNode *s = g_new(CLNode,1);
s->type = CL_LIST;
s->u.lb.list = $2;
s->u.lb.block = NULL;
s->u.lb.id = $1;
s->lineno = yylineno;
$$ = s;
}
| TOK_ID list block
{
CLNode *s = g_new(CLNode,1);
s->type = CL_LISTBLOCK;
s->u.lb.list = $2;
s->u.lb.block = $3;
s->u.lb.id = $1;
s->lineno = yylineno;
$$ = s;
}
| TOK_ID block
{
CLNode *s = g_new(CLNode,1);
s->type = CL_BLOCK;
s->u.lb.block = $2;
s->u.lb.list = NULL;
s->u.lb.id = $1;
s->lineno = yylineno;
$$ = s;
}
;
list: value
{
$$ = g_list_append(NULL, $1);
}
| list ',' value
{
$$ = g_list_append($1, $3);
}
;
block: '{' stmts '}'
{
$$ = $2;
}
;
value: TOK_ID
{
CLNode *node = g_new(CLNode,1);
node->type = CL_ID;
node->u.str = $1;
node->lineno = yylineno;
$$ = node;
}
| TOK_STRING
{
CLNode *node = g_new(CLNode,1);
node->type = CL_STR;
node->u.str = $1;
node->lineno = yylineno;
$$ = node;
}
| TOK_NUM
{
CLNode *node = g_new(CLNode,1);
node->type = CL_NUM;
node->u.num = $1;
node->lineno = yylineno;
$$ = node;
}
;
%%
int yywrap()
{
return 1;
}
/* void yyerror(const char *err) */
/* { */
/* fprintf(stderr, "Parse error on line %d, near '%s': %s\n", */
/* yylineno, yytext, err); */
/* } */
void yyerror(char *msg, ...)
{
va_list args;
va_start(args,msg);
fprintf(stderr, "Error on line %d, near '%s': ", yylineno, yytext);
vfprintf(stderr, msg, args);
fprintf(stderr,"\n");
va_end(args);
}
GList *cl_parse_fh(FILE *fh)
{
extern FILE *yyin;
yyin = fh;
yyparse();
return config;
}

View file

@ -1,115 +0,0 @@
#include "obcl.h"
static void cl_proc_intern_handler(CLNode *node)
{
CL_ASSERT_NODE(node);
g_warning("Unhandled node %s on line %d\n",
CL_ID(node), CL_LINE(node));
}
static CLProcHandler *default_handler(void)
{
static CLProcHandler *ph = 0;
if (!ph)
ph = cl_proc_handler_new_func(cl_proc_intern_handler);
return ph;
}
CLProcHandler *cl_proc_handler_new_func(CLProcFunc f)
{
CLProcHandler *cph = g_new(CLProcHandler,1);
cph->type = CLPROC_FUNC;
cph->u.func = f;
return cph;
}
CLProcHandler *cl_proc_handler_new_proc(CLProc *cp)
{
CLProcHandler *cph = g_new(CLProcHandler,1);
cph->type = CLPROC_PROC;
cph->u.proc = cp;
return cph;
}
CLProc *cl_proc_new(void)
{
CLProc *ret = g_new(CLProc,1);
ret->table = g_hash_table_new(g_str_hash,g_str_equal);
ret->default_h = default_handler();
return ret;
}
void cl_proc_free(CLProc *proc)
{
}
void cl_proc_add_handler(CLProc *proc, gchar *str,
CLProcHandler *handler)
{
g_assert(proc != NULL);
g_hash_table_replace(proc->table, str, handler);
}
void cl_proc_add_handler_func(CLProc *proc, gchar *str,
CLProcFunc func)
{
CLProcHandler *ph;
g_assert(proc != NULL);
ph = cl_proc_handler_new_func(func);
cl_proc_add_handler(proc, str, ph);
}
void cl_proc_add_handler_proc(CLProc *proc, gchar *str,
CLProc *hproc)
{
CLProcHandler *ph;
g_assert(proc != NULL);
ph = cl_proc_handler_new_proc(hproc);
cl_proc_add_handler(proc, str, ph);
}
void cl_proc_set_default(CLProc *proc, CLProcHandler *ph)
{
g_assert(proc != NULL);
proc->default_h = ph;
}
void cl_proc_register_keywords(CLProc *proc, ...)
{
va_list args;
g_assert(proc != NULL);
va_start(args,proc);
for (;;) {
gchar *k = va_arg(args, gchar*);
if (k == NULL)
break;
if (g_hash_table_lookup(proc->table, k) != NULL)
g_hash_table_insert(proc->table, k, default_handler());
}
va_end(args);
}
void cl_process(GList *tree, CLProc *proc)
{
GList *lst;
CLProcHandler *handler;
g_assert(proc != NULL);
if (!tree) return;
for (lst = tree; lst != NULL; lst = lst->next) {
CL_ASSERT_NODE(lst->data);
handler = g_hash_table_lookup(proc->table, CL_ID(lst->data));
if (!handler)
handler = default_handler();
if (handler->type == CLPROC_FUNC)
handler->u.func(CL_NODE(lst->data));
else
cl_process(CL_BLOCK(lst->data), handler->u.proc);
}
}