remove obcl. shrimpx may work on this in the future but we are not usnig it now.
This commit is contained in:
parent
b1fe0dbbc2
commit
d61b48a2ef
10 changed files with 0 additions and 736 deletions
|
@ -1,3 +0,0 @@
|
|||
obcl.lo
|
||||
libobcl.la
|
||||
.libs
|
|
@ -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
|
130
obcl/README
130
obcl/README
|
@ -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.
|
|
@ -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";
|
||||
}
|
86
obcl/lex.l
86
obcl/lex.l
|
@ -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]; }
|
||||
%%
|
33
obcl/main.c
33
obcl/main.c
|
@ -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;
|
||||
}
|
84
obcl/obcl.c
84
obcl/obcl.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
99
obcl/obcl.h
99
obcl/obcl.h
|
@ -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 */
|
154
obcl/parse.y
154
obcl/parse.y
|
@ -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;
|
||||
}
|
115
obcl/process.c
115
obcl/process.c
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue