You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(10) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(9) |
Feb
(3) |
Mar
(2) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(3) |
Sep
|
Oct
(8) |
Nov
(18) |
Dec
(3) |
2003 |
Jan
|
Feb
(2) |
Mar
(4) |
Apr
(8) |
May
(7) |
Jun
(3) |
Jul
(12) |
Aug
(44) |
Sep
(31) |
Oct
(18) |
Nov
(43) |
Dec
(21) |
2004 |
Jan
(9) |
Feb
(4) |
Mar
(7) |
Apr
(3) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(5) |
Dec
|
2005 |
Jan
|
Feb
|
Mar
(7) |
Apr
(9) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <mr...@mr...> - 2005-05-09 21:37:43
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/05/09 23:37:14+02:00 mr...@fo... = # list: fix tclist_remove under strict locking # = # src/list.c # 2005/05/09 23:37:14+02:00 mr...@fo... +4 -2 # fix deadlock in tclist_remove under strict locking # = diff -Nru a/src/list.c b/src/list.c --- a/src/list.c 2005-05-09 23:37:29 +02:00 +++ b/src/list.c 2005-05-09 23:37:29 +02:00 @@ -135,12 +135,14 @@ extern void tclist_remove(tclist_t *lst, tclist_item_t *l, tcfree_fn fr) { - lock_list(lst); + if(lst->locking < TC_LOCK_STRICT) + lock_list(lst); l->deleted =3D 1; l->free =3D fr; lst->deleted++; list_deref(lst, l); - unlock_list(lst); + if(lst->locking < TC_LOCK_STRICT) + unlock_list(lst); } = extern int |
From: <mr...@mr...> - 2005-04-30 09:48:06
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/30 11:47:08+02:00 mr...@fo... = # list: fix deadlock with strict locking # = # src/list.c # 2005/04/30 11:47:07+02:00 mr...@fo... +3 -2 # fix tclist_unlock with strict locking # = diff -Nru a/src/list.c b/src/list.c --- a/src/list.c 2005-04-30 11:47:47 +02:00 +++ b/src/list.c 2005-04-30 11:47:47 +02:00 @@ -1,5 +1,5 @@ /** - Copyright (C) 2001-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2001-2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -124,7 +124,8 @@ extern int tclist_unlock(tclist_t *lst, tclist_item_t *l) { - lock_list(lst); + if(lst->locking < TC_LOCK_STRICT) + lock_list(lst); l->ic--; list_deref(lst, l); unlock_list(lst); |
From: <mr...@mr...> - 2005-04-09 21:16:15
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/09 23:12:16+02:00 mr...@fo... = # conf: fix floating point numbers # = # src/conf-lex.l # 2005/04/09 23:12:16+02:00 mr...@fo... +1 -1 # fix parsing of floating point numbers # = diff -Nru a/src/conf-lex.l b/src/conf-lex.l --- a/src/conf-lex.l 2005-04-09 23:16:01 +02:00 +++ b/src/conf-lex.l 2005-04-09 23:16:01 +02:00 @@ -60,7 +60,7 @@ {keyref} { tcc_lval.s =3D strdup(yytext); return IDENTD; } [+\-]?0x[[:xdigit:]]+ | [+\-]?[[:digit:]]+ { tcc_lval.i =3D strtoll(yytext, NULL, 0); return INT; } -[+\-]?[[:digit:]]+(\.[[:digit:]])*([eE][+\-]?[[:digit:]]+)? { tcc_lval.f =3D strtod(yytext, NULL); return FLOAT; } +[+\-]?[[:digit:]]*(\.[[:digit:]]+)([eE][+\-]?[[:digit:]]+)? { tcc_lval.f =3D strtod(yytext, NULL); return FLOAT; } \'[^\']*\' { yytext[yyleng-1]=3D0; tcc_lval.s =3D yytext + 1; return STRING; } \"([^\"]*(\\\")?)*[^\\]\" { yytext[yyleng-1]=3D0; tcc_lval.s =3D yytext + 1; return DSTRING; } = |
From: <mr...@mr...> - 2005-04-09 21:16:15
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/09 23:14:07+02:00 mr...@fo... = # conf: check type compatibilty in tcconf_getvalue() # = # src/conf.c # 2005/04/09 23:14:06+02:00 mr...@fo... +8 -0 # check compatibility between value type and requested type # = diff -Nru a/src/conf.c b/src/conf.c --- a/src/conf.c 2005-04-09 23:16:02 +02:00 +++ b/src/conf.c 2005-04-09 23:16:02 +02:00 @@ -395,6 +395,8 @@ { switch(tv->type & TCC_TYPEMASK){ case TCC_STRING: + if((type & TCC_TYPEMASK) !=3D TCC_STRING) + return -1; if(tv->type & TCC_EXPAND) *(char **) dst =3D tcstrexp(tv->value.string, "(", ")", ':', vtostr, ts, @@ -404,6 +406,8 @@ break; = case TCC_INTEGER: + if((type & TCC_TYPEMASK) !=3D TCC_INTEGER) + return -1; switch(type & ~TCC_TYPEMASK){ case 0: *(int32_t *) dst =3D (int32_t) tv->value.integer; @@ -417,10 +421,14 @@ case TCC_LONG|TCC_UNSIGNED: *(uint64_t *) dst =3D (uint64_t) tv->value.integer; break; + default: + return -1; } break; = case TCC_FLOAT: + if((type & TCC_TYPEMASK) !=3D TCC_FLOAT) + return -1; switch(type & ~TCC_TYPEMASK){ case 0: *(float *) dst =3D (float) tv->value.floating; |
From: <mr...@mr...> - 2005-04-03 12:49:07
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/03 14:48:27+02:00 mr...@fo... = # script: implement pointer values # = # src/script.c # 2005/04/03 14:48:27+02:00 mr...@fo... +25 -0 # implement pointer values # = diff -Nru a/src/script.c b/src/script.c --- a/src/script.c 2005-04-03 14:48:39 +02:00 +++ b/src/script.c 2005-04-03 14:48:39 +02:00 @@ -160,6 +160,31 @@ v->value.s =3D strdup(s); } = +extern void * +tcscript_getptr(tcscript_value_t *v) +{ + if(TCS_VAL_TYPE(v) !=3D TCS_VAL_POINTER) + return NULL; + return v->value.p; +} + +extern void +tcscript_setptr(tcscript_value_t *v, void *p, tcfree_fn f) +{ + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING) + free(v->value.s); + v->type =3D TCS_VAL_POINTER; + v->value.p =3D p; +} + +extern tcscript_value_t * +tcscript_mkptr(void *p, tcfree_fn f) +{ + tcscript_value_t *v =3D tcs_value_alloc(NULL, TCS_VAL_POINTER); + v->value.p =3D p; + return v; +} + extern tcscript_value_t * tcscript_mkfun(tcscript_function_t fun) { |
From: <mr...@mr...> - 2005-04-01 20:36:11
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/01 22:35:48+02:00 mr...@fo... = # script: fix null pointer, plug memory leak # = # src/script.c # 2005/04/01 22:35:48+02:00 mr...@fo... +6 -3 # plug memory leak # replace NULL return values with null values # = diff -Nru a/src/script.c b/src/script.c --- a/src/script.c 2005-04-01 22:35:58 +02:00 +++ b/src/script.c 2005-04-01 22:35:58 +02:00 @@ -257,6 +257,8 @@ val =3D tcs_value_alloc(NULL, type | TCS_VAL_CONST); val->value =3D v; tchash_replace(ns->constants, key, ks, val, NULL); + } else if(type =3D=3D STRING || type =3D=3D DSTRING){ + free(v.s); } = free(key); @@ -465,7 +467,7 @@ static tcscript_value_t * tcs_op_funcall(tcscript_t *tcs, int n, tcscript_value_t **args) { - tcscript_value_t *val; + tcscript_value_t *val =3D NULL; = if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_FUNCTION){ val =3D args[0]->value.fun(tcs, tcs->ns->data, args[0]->name, @@ -478,9 +480,10 @@ tcs->fp =3D &fr; tcs_stmt_exec(tcs, args[0]->value.sub, &val); tcs->fp =3D fr.up; - } else { - val =3D tcs_value_alloc(NULL, 0); } + + if(!val) + val =3D tcs_value_alloc(NULL, 0); = return val; } |
From: <mr...@mr...> - 2005-04-01 20:30:41
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/01 22:23:23+02:00 mr...@fo... = # script: add subroutine support # = # src/tcs-internal.h # 2005/04/01 22:23:23+02:00 mr...@fo... +18 -2 # add sub arg expression, sub call stack # = # src/script.c # 2005/04/01 22:23:23+02:00 mr...@fo... +29 -4 # subroutines and sub args # = # src/script-parse.y # 2005/04/01 22:23:23+02:00 mr...@fo... +27 -0 # add subroutines and sub arguments # = # src/script-lex.l # 2005/04/01 22:23:23+02:00 mr...@fo... +2 -0 # add sub keyword and $num tokens # = diff -Nru a/src/script-lex.l b/src/script-lex.l --- a/src/script-lex.l 2005-04-01 22:30:27 +02:00 +++ b/src/script-lex.l 2005-04-01 22:30:27 +02:00 @@ -60,6 +60,7 @@ else/[^[:alnum:]_] return ELSE; while/[^[:alnum:]_] return WHILE; break/[^[:alnum:]_] return BREAK; +sub/[^[:alnum:]_] return SUB; = [+\-*/<>&|^=3D~!] | [\(\){}\[\];,] RET(yytext[0]); @@ -80,3 +81,4 @@ [[:digit:]]+(\.[[:digit:]])*([eE][+\-]?[[:digit:]]+)? { tcs_lval.f =3D strtod(yytext, NULL); return FLOAT; } \'[^\']*\' { yytext[yyleng-1]=3D0; tcs_lval.s =3D yytext + 1; return STRING; } \"([^\"]*(\\\")?)*[^\\]\" { yytext[yyleng-1]=3D0; tcs_lval.s =3D yytext + 1; return DSTRING; } +\$[[:digit:]]+ { tcs_lval.i =3D strtoll(yytext + 1, NULL, 10); return ARG; } diff -Nru a/src/script-parse.y b/src/script-parse.y --- a/src/script-parse.y 2005-04-01 22:30:27 +02:00 +++ b/src/script-parse.y 2005-04-01 22:30:27 +02:00 @@ -42,6 +42,8 @@ static tcs_expr_t *tcs_expr_op(int op, int n, ...); static void tcs_expr_add(tcs_expr_t *e, tcs_expr_t *n); static tcs_expr_t *tcs_expr_val(tcscript_t *scr, int type, ...); +static tcs_expr_t *tcs_expr_arg(int num); +static void tcs_sub(tcscript_t *, char *, tcs_stmt_t *); = static void tcs_error(void *, tcio_fn, tcscript_t *, char *); %} @@ -68,12 +70,14 @@ %token <s> STRING %token <s> DSTRING %token <s> IDENTIFIER +%token <i> ARG = %token RETURN %token IF %token ELSE %token WHILE %token BREAK +%token SUB = %token <i> '+' %token <i> '-' @@ -138,8 +142,11 @@ %% = script: /* empty */ + | script sub | script statement { if($2) tcs_add_stmt(scr, $2); } ; +sub: SUB IDENTIFIER statement { tcs_sub(scr, $2, $3); } + ; statement: expression_stmt | compound_stmt | if_stmt @@ -179,6 +186,7 @@ | STRING { $$ =3D tcs_expr_val(scr, STRING, $1); } | DSTRING { $$ =3D tcs_expr_val(scr, DSTRING, $1); } | IDENTIFIER { $$ =3D tcs_expr_val(scr, TCS_VAL_VARIABLE, $1); } + | ARG { $$ =3D tcs_expr_arg($1); } ; op_expr: expression '+' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } | expression '-' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } @@ -399,6 +407,25 @@ = va_end(args); return e; +} + +static tcs_expr_t * +tcs_expr_arg(int num) +{ + tcs_expr_t *e =3D tcallocz(sizeof(*e)); + e->type =3D TCS_EXPR_ARG; + e->arg.num =3D num; + return e; +} + +static void +tcs_sub(tcscript_t *scr, char *name, tcs_stmt_t *st) +{ + tcscript_value_t *v =3D tcs_ns_create(scr->ns, name); + v->type =3D TCS_VAL_SUB; + v->value.sub =3D st; + free(name); + tcfree(v); } = static void diff -Nru a/src/script.c b/src/script.c --- a/src/script.c 2005-04-01 22:30:27 +02:00 +++ b/src/script.c 2005-04-01 22:30:27 +02:00 @@ -32,6 +32,8 @@ #include <tcscript.h> #include "tcs-internal.h" = +static int tcs_stmt_exec(tcscript_t *, tcs_stmt_t *, tcscript_value_t **); + static void tcs_value_free(void *p) { @@ -39,6 +41,8 @@ free(v->name); if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING || TCS_VAL_TYPE(v) =3D=3D TCS_VAL_DSTRING) free(v->value.s); + else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_SUB) + tcfree(v->value.sub); } = static tcscript_value_t * @@ -444,6 +448,8 @@ if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_STRING){ free(args[0]->value.s); args[0]->value.s =3D strdup(args[1]->value.s); + } else if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_SUB){ + args[0]->value.sub =3D tcref(args[1]->value.sub); } else { args[0]->value =3D args[1]->value; } @@ -460,11 +466,22 @@ tcs_op_funcall(tcscript_t *tcs, int n, tcscript_value_t **args) { tcscript_value_t *val; - if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_FUNCTION) + + if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_FUNCTION){ val =3D args[0]->value.fun(tcs, tcs->ns->data, args[0]->name, n - 1, args + 1); - else + } else if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_SUB){ + tcs_frame_t fr; + fr.nargs =3D n - 1; + fr.args =3D args + 1; + fr.up =3D tcs->fp; + tcs->fp =3D &fr; + tcs_stmt_exec(tcs, args[0]->value.sub, &val); + tcs->fp =3D fr.up; + } else { val =3D tcs_value_alloc(NULL, 0); + } + return val; } = @@ -529,7 +546,7 @@ static int tcs_type_convert(int n, tcscript_value_t **v, int type) { - int itg =3D 0, flt =3D 0, str =3D 0, ptr =3D 0, fun =3D 0; + int itg =3D 0, flt =3D 0, str =3D 0, ptr =3D 0, fun =3D 0, sub =3D 0; int temp =3D 0; int vtype =3D 0; int i; @@ -548,9 +565,11 @@ ptr++; else if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_FUNCTION) fun++; + else if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_SUB) + sub++; } = - if(ptr || fun) + if(ptr || fun || sub) return -1; = if(type =3D=3D TCS_TYPE_NUM){ @@ -674,6 +693,12 @@ break; case TCS_EXPR_OP: val =3D tcs_expr_op(tcs, expr); + break; + case TCS_EXPR_ARG: + if(tcs->fp && expr->arg.num < tcs->fp->nargs) + val =3D tcref(tcs->fp->args[expr->arg.num]); + else + val =3D tcs_value_alloc(NULL, 0); break; } = diff -Nru a/src/tcs-internal.h b/src/tcs-internal.h --- a/src/tcs-internal.h 2005-04-01 22:30:27 +02:00 +++ b/src/tcs-internal.h 2005-04-01 22:30:27 +02:00 @@ -39,6 +39,8 @@ void *data; }; = +typedef union tcs_stmt tcs_stmt_t; + struct tcscript_value { char *name; int type; @@ -48,6 +50,7 @@ char *s; void *p; tcscript_function_t fun; + tcs_stmt_t *sub; } value; }; = @@ -58,6 +61,7 @@ #define TCS_VAL_VARIABLE 2048 #define TCS_VAL_POINTER 2049 #define TCS_VAL_FUNCTION 2050 +#define TCS_VAL_SUB 2051 = #define TCS_VAL_EXTERN (1<<24) #define TCS_VAL_CONST (1<<25) @@ -83,16 +87,21 @@ tcscript_value_t *val; } tcs_value_expr_t; = +typedef struct tcs_arg_expr { + int type; + int num; +} tcs_arg_expr_t; + union tcs_expr { int type; tcs_value_expr_t val; tcs_op_expr_t op; + tcs_arg_expr_t arg; }; = #define TCS_EXPR_VAL 1 #define TCS_EXPR_OP 2 - -typedef union tcs_stmt tcs_stmt_t; +#define TCS_EXPR_ARG 3 = typedef struct tcs_expr_stmt { int type; @@ -139,10 +148,17 @@ #define TCS_STMT_BREAK BREAK #define TCS_STMT_RET RETURN = +typedef struct tcs_frame { + struct tcs_frame *up; + tcscript_value_t **args; + int nargs; +} tcs_frame_t; + struct tcscript { tcscript_namespace_t *ns; tcs_stmt_t **stmts; int nstmts; + tcs_frame_t *fp; }; = extern tcscript_value_t *tcs_ns_create(tcscript_namespace_t *, char *); |
From: <mr...@mr...> - 2005-04-01 15:00:32
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/01 16:59:45+02:00 mr...@fo... = # script: fail on syntax errors # = # src/tcs-internal.h # 2005/04/01 16:59:45+02:00 mr...@fo... +1 -0 # declare tcs_nerrs # = # src/script.c # 2005/04/01 16:59:45+02:00 mr...@fo... +8 -5 # fail on syntax errors # = # src/script-parse.y # 2005/04/01 16:59:45+02:00 mr...@fo... +4 -0 # deal with errors properly # = diff -Nru a/src/script-parse.y b/src/script-parse.y --- a/src/script-parse.y 2005-04-01 16:59:55 +02:00 +++ b/src/script-parse.y 2005-04-01 16:59:55 +02:00 @@ -118,6 +118,9 @@ %type <expr> op_expr %type <expr> args = +%destructor { tcfree($$); } statement expression +%destructor { free($$); } IDENTIFIER + %right '=3D' %left OR %left AND @@ -144,6 +147,7 @@ | break_stmt | return_stmt | ';' { $$ =3D NULL; } + | error ';' { $$ =3D NULL; yyerrok; } ; expression_stmt: expression ';' { $$ =3D tcs_stmt_expr($1); } ; diff -Nru a/src/script.c b/src/script.c --- a/src/script.c 2005-04-01 16:59:55 +02:00 +++ b/src/script.c 2005-04-01 16:59:55 +02:00 @@ -276,7 +276,7 @@ { static pthread_mutex_t lock =3D PTHREAD_MUTEX_INITIALIZER; tcscript_t *tcs; - int pr; + int pr, ne; = if(!ns){ ns =3D tcscript_ns_alloc(NULL, NULL, NULL); @@ -290,10 +290,12 @@ tcs->ns =3D ns; = pthread_mutex_lock(&lock); + tcs_nerrs =3D 0; pr =3D tcs_parse(data, iofn, tcs); + ne =3D tcs_nerrs; pthread_mutex_unlock(&lock); = - if(pr){ + if(pr || ne){ tcfree(tcs); tcs =3D NULL; } @@ -567,25 +569,26 @@ = for(i =3D 0; i < n; i++){ tcscript_value_t *tv =3D NULL; + int tmp =3D temp || v[i]->type & TCS_VAL_CONST; = if(TCS_VAL_TYPE(v[i]) =3D=3D vtype) continue; = if(vtype =3D=3D TCS_VAL_INT){ int64_t iv =3D tcscript_getint(v[i]); - if(temp) + if(tmp) tv =3D tcscript_mkint(iv); else tcscript_setint(v[i], iv); } else if(vtype =3D=3D TCS_VAL_FLOAT){ double d =3D tcscript_getfloat(v[i]); - if(temp) + if(tmp) tv =3D tcscript_mkfloat(d); else tcscript_setfloat(v[i], d); } else if(vtype =3D=3D TCS_VAL_STRING){ char *s =3D tcscript_getstring(v[i]); - if(temp) + if(tmp) tv =3D tcscript_mkstring(s, 0); else tcscript_setstring(v[i], s); diff -Nru a/src/tcs-internal.h b/src/tcs-internal.h --- a/src/tcs-internal.h 2005-04-01 16:59:55 +02:00 +++ b/src/tcs-internal.h 2005-04-01 16:59:55 +02:00 @@ -192,5 +192,6 @@ = extern int tcs_lex(void *, tcio_fn); extern int tcs_parse(void *, tcio_fn, tcscript_t *); +extern int tcs_nerrs; = #endif |
From: <mr...@mr...> - 2005-04-01 10:22:15
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/01 12:18:59+02:00 mr...@fo... = # script: fix empty statements, allow missing final ; compiling string # = # src/script.c # 2005/04/01 12:18:58+02:00 mr...@fo... +20 -7 # add a ; at end when compiling string # ignore null statements # = # src/script-parse.y # 2005/04/01 12:18:58+02:00 mr...@fo... +3 -2 # ignore empty statements # = diff -Nru a/src/script-parse.y b/src/script-parse.y --- a/src/script-parse.y 2005-04-01 12:21:53 +02:00 +++ b/src/script-parse.y 2005-04-01 12:21:53 +02:00 @@ -135,7 +135,7 @@ %% = script: /* empty */ - | script statement { tcs_add_stmt(scr, $2); } + | script statement { if($2) tcs_add_stmt(scr, $2); } ; statement: expression_stmt | compound_stmt @@ -143,6 +143,7 @@ | while_stmt | break_stmt | return_stmt + | ';' { $$ =3D NULL; } ; expression_stmt: expression ';' { $$ =3D tcs_stmt_expr($1); } ; @@ -151,7 +152,7 @@ cmp_stmt: { $$ =3D tcs_stmt_cmp(); } ; statements: /* empty */ { } - | statements statement { tcs_stmt_cmp_add($<stmt>0, $2); } + | statements statement { if($2) tcs_stmt_cmp_add($<stmt>0, $2); } ; if_stmt: IF '(' expression ')' statement else_stmt { $$ =3D tcs_stmt_if($3, $5, $6); } diff -Nru a/src/script.c b/src/script.c --- a/src/script.c 2005-04-01 12:21:53 +02:00 +++ b/src/script.c 2005-04-01 12:21:53 +02:00 @@ -317,8 +317,7 @@ = struct string_read { const char *d; - int s; - int p; + size_t s, p; }; = #define min(a, b) ((a)<(b)?(a):(b)) @@ -327,11 +326,20 @@ read_string(void *p, size_t s, size_t c, void *d) { struct string_read *sr =3D d; - int b =3D s * c; + size_t b =3D s * c; + char *t =3D p; = - b =3D min(b, sr->s - sr->p); - memcpy(p, sr->d + sr->p, b); - sr->p +=3D b; + if(sr->p < sr->s){ + b =3D min(b, sr->s - sr->p); + memcpy(t, sr->d + sr->p, b); + sr->p +=3D b; + } else if(sr->p =3D=3D sr->s){ + *t =3D ';'; + b =3D 1; + sr->p++; + } else { + b =3D 0; + } = return b / s; } @@ -674,7 +682,12 @@ { tcscript_value_t *val =3D NULL; tcscript_value_t *cv, *tv; - int r =3D stmt->type, i, rt; + int r, i, rt; + + if(!stmt) + return 0; + + r =3D stmt->type; = switch(stmt->type){ case TCS_STMT_EXPR: |
From: <mr...@mr...> - 2005-04-01 10:22:15
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/04/01 12:21:35+02:00 mr...@fo... = # ignore ylwrap # = # BitKeeper/etc/ignore # 2005/04/01 12:21:05+02:00 mr...@fo... +1 -0 # added ylwrap # = |
From: <mr...@mr...> - 2005-03-31 02:43:35
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/31 04:37:10+02:00 mr...@fo... = # script: optimize handling of constants, add compile_string() # = # src/tcs-internal.h # 2005/03/31 04:37:09+02:00 mr...@fo... +5 -1 # add constant related things # = # src/script.c # 2005/03/31 04:37:09+02:00 mr...@fo... +133 -52 # share constants # add tcscript_const() # add tcscript_compile_string() # fix some operators # warn on modification of constants # = # src/script-parse.y # 2005/03/31 04:37:09+02:00 mr...@fo... +4 -8 # add unary ! # share constants # = # include/tcscript.h # 2005/03/31 04:37:09+02:00 mr...@fo... +2 -0 # add tcscript_const() # = diff -Nru a/include/tcscript.h b/include/tcscript.h --- a/include/tcscript.h 2005-03-31 04:43:25 +02:00 +++ b/include/tcscript.h 2005-03-31 04:43:25 +02:00 @@ -64,4 +64,6 @@ extern void tcscript_setfun(tcscript_value_t *, tcscript_function_t); extern tcscript_value_t *tcscript_mkfun(tcscript_function_t); = +extern tcscript_value_t *tcscript_const(tcscript_value_t *); + #endif diff -Nru a/src/script-parse.y b/src/script-parse.y --- a/src/script-parse.y 2005-03-31 04:43:25 +02:00 +++ b/src/script-parse.y 2005-03-31 04:43:25 +02:00 @@ -195,6 +195,7 @@ | expression SHR expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } | '-' expression { $$ =3D tcs_expr_op(NEG, 1, $2); } | '~' expression { $$ =3D tcs_expr_op($1, 1, $2); } + | '!' expression { $$ =3D tcs_expr_op($1, 1, $2); } | INC expression { $$ =3D tcs_expr_op($1, 1, $2); } | DEC expression { $$ =3D tcs_expr_op($1, 1, $2); } | expression INC { $$ =3D tcs_expr_op(PINC, 1, $1); } @@ -383,20 +384,15 @@ va_start(args, type); e->type =3D TCS_EXPR_VAL; = - if(type =3D=3D INT){ - e->val.val =3D tcscript_mkint(va_arg(args, int64_t)); - } else if(type =3D=3D FLOAT){ - e->val.val =3D tcscript_mkfloat(va_arg(args, double)); - } else if(type =3D=3D STRING || type =3D=3D DSTRING){ - e->val.val =3D tcscript_mkstring(va_arg(args, char *), type =3D=3D DSTRING); - } else if(type =3D=3D TCS_VAL_VARIABLE){ + if(type =3D=3D TCS_VAL_VARIABLE){ char *n =3D va_arg(args, char *); e->val.val =3D tcs_ns_create(scr->ns, n); free(n); } else { - fprintf(stderr, "tcscript: impossible type %i\n", type); + e->val.val =3D tcs_ns_const(scr->ns, type, args); } = + va_end(args); return e; } = diff -Nru a/src/script.c b/src/script.c --- a/src/script.c 2005-03-31 04:43:25 +02:00 +++ b/src/script.c 2005-03-31 04:43:25 +02:00 @@ -24,6 +24,7 @@ = #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> #include <pthread.h> #include <tcstring.h> #include <tcalloc.h> @@ -163,11 +164,19 @@ return v; } = +extern tcscript_value_t * +tcscript_const(tcscript_value_t *v) +{ + v->type |=3D TCS_VAL_CONST; + return v; +} + static void tcs_ns_free(void *p) { tcscript_namespace_t *ns =3D p; tchash_destroy(ns->symbols, tcfree); + tchash_destroy(ns->constants, tcfree); } = extern tcscript_namespace_t * @@ -178,7 +187,8 @@ if(!ns) return NULL; = - ns->symbols =3D tchash_new(32, TC_LOCK_SLOPPY, 0); + ns->symbols =3D tchash_new(8, TC_LOCK_SLOPPY, 0); + ns->constants =3D tchash_new(8, TC_LOCK_SLOPPY, 0); ns->get =3D get; ns->set =3D set; ns->data =3D p; @@ -208,6 +218,47 @@ return tcref(v); } = +extern tcscript_value_t * +tcs_ns_const(tcscript_namespace_t *ns, int type, va_list args) +{ + tcscript_value_t *val; + union tcs_value v; + char *key; + void *kp; + int ks; + + if(type =3D=3D INT){ + v.i =3D va_arg(args, int64_t); + ks =3D sizeof(v.i); + kp =3D &v; + } else if(type =3D=3D FLOAT){ + v.f =3D va_arg(args, double); + ks =3D sizeof(v.f); + kp =3D &v; + } else if(type =3D=3D STRING || type =3D=3D DSTRING){ + v.s =3D strdup(va_arg(args, char *)); + ks =3D strlen(v.s); + kp =3D v.s; + } else { + fprintf(stderr, "tcscript: impossible type %i\n", type); + return NULL; + } + + key =3D malloc(ks + sizeof(type)); + memcpy(key, &type, sizeof(type)); + memcpy(key + sizeof(type), kp, ks); + ks +=3D sizeof(type); + + if(tchash_find(ns->constants, key, ks, &val)){ + val =3D tcs_value_alloc(NULL, type | TCS_VAL_CONST); + val->value =3D v; + tchash_replace(ns->constants, key, ks, val, NULL); + } + + free(key); + return tcref(val); +} + static void tcs_free(void *p) { @@ -264,6 +315,39 @@ return tcs; } = +struct string_read { + const char *d; + int s; + int p; +}; + +#define min(a, b) ((a)<(b)?(a):(b)) + +static size_t +read_string(void *p, size_t s, size_t c, void *d) +{ + struct string_read *sr =3D d; + int b =3D s * c; + + b =3D min(b, sr->s - sr->p); + memcpy(p, sr->d + sr->p, b); + sr->p +=3D b; + + return b / s; +} + +extern tcscript_t * +tcscript_compile_string(char *s, tcscript_namespace_t *ns) +{ + struct string_read sr; + + sr.d =3D s; + sr.s =3D strlen(s); + sr.p =3D 0; + + return tcscript_compile(&sr, read_string, ns); +} + #define op_int(op) \ case TCS_VAL_INT: \ v =3D tcscript_mkint(args[0]->value.i op args[1]->value.i); \ @@ -279,11 +363,6 @@ v =3D tcscript_mkint(strcmp(args[0]->value.s, args[1]->value.s) op 0); \ break; = -#define op_strbool(op) \ - case TCS_VAL_STRING: \ - v =3D tcscript_mkint(args[0]->value.s op args[1]->value.s); \ - break; - #define op_uint(op) \ case TCS_VAL_INT: \ v =3D tcscript_mkint(op args[0]->value.i); \ @@ -294,11 +373,6 @@ v =3D tcscript_mkfloat(op args[0]->value.f); \ break; = -#define op_ustrbool(op) \ - case TCS_VAL_STRING: \ - v =3D tcscript_mkint(op args[0]->value.s); \ - break; - #define op_puint(op) \ case TCS_VAL_INT: \ v =3D tcscript_mkint(args[0]->value.i op); \ @@ -315,7 +389,7 @@ { \ tcscript_value_t *v =3D NULL; \ (void) tcs; (void) n; \ - switch(TCS_VAL_TYPE(args[0])){ \ + switch(TCS_VAL_TYPE(args[0])){ \ ops(op) \ } \ return v; \ @@ -325,8 +399,6 @@ #define op_unum(op) op_uint(op) op_ufloat(op) #define op_punum(op) op_puint(op) op_pufloat(op) #define op_scalar(op) op_num(op) op_strcmp(op) -#define op_bool(op) op_num(op) op_strbool(op) -#define op_ubool(op) op_uint(op) op_ustrbool(op) = tcs_opdef(+, add, op_num) tcs_opdef(-, sub, op_num) @@ -343,9 +415,9 @@ tcs_opdef(|, or, op_int) tcs_opdef(^, xor, op_int) tcs_opdef(~, not, op_uint) -tcs_opdef(&&, land, op_bool) -tcs_opdef(||, lor, op_bool) -tcs_opdef(!, lnot, op_ubool) +tcs_opdef(&&, land, op_num) +tcs_opdef(||, lor, op_num) +tcs_opdef(!, lnot, op_unum) tcs_opdef(<, lt, op_scalar) tcs_opdef(>, gt, op_scalar) tcs_opdef(=3D=3D, eq, op_scalar) @@ -356,8 +428,8 @@ static tcscript_value_t * tcs_op_assign(tcscript_t *tcs, int n, tcscript_value_t **args) { - (void) n; - args[0]->type =3D args[1]->type; + (void) tcs; (void) n; + args[0]->type =3D args[1]->type & ~TCS_VAL_CONST; = if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_STRING){ free(args[0]->value.s); @@ -369,8 +441,6 @@ if(args[0]->type & TCS_VAL_EXTERN){ free(args[0]->name); args[0]->name =3D strdup(args[1]->name); - if(tcs->ns->set) - tcs->ns->set(tcs->ns->data, args[0]->name, args[0]); } = return tcref(args[0]); @@ -403,42 +473,43 @@ #define TCS_TYPE_BOOL 4 #define TCS_TYPE_SCALAR 5 = -#define tcs_op(op, name, type) \ - [op] =3D { tcs_op_##name, TCS_TYPE_##type } +#define tcs_op(op, name, type, mod) \ + [op] =3D { tcs_op_##name, TCS_TYPE_##type, mod } = typedef struct tcs_operator { tcscript_value_t *(*op)(tcscript_t *, int, tcscript_value_t **); int type; + int mod; } tcs_operator_t; = static tcs_operator_t tcs_operators[] =3D { - tcs_op('+', add, NUM), - tcs_op('-', sub, NUM), - tcs_op('*', mul, NUM), - tcs_op('/', div, NUM), - tcs_op(NEG, neg, NUM), - tcs_op(INC, inc, NUM), - tcs_op(DEC, dec, NUM), - tcs_op(PINC, pinc, NUM), - tcs_op(PDEC, pdec, NUM), - tcs_op(SHL, shl, INT), - tcs_op(SHR, shr, INT), - tcs_op('&', and, INT), - tcs_op('|', or, INT), - tcs_op('^', xor, INT), - tcs_op('~', not, INT), - tcs_op('<', lt, SCALAR), - tcs_op('>', gt, SCALAR), - tcs_op(LTE, lte, SCALAR), - tcs_op(GTE, gte, SCALAR), - tcs_op(EQ, eq, SCALAR), - tcs_op(NE, ne, SCALAR), - tcs_op(AND, land, BOOL), - tcs_op(OR, lor, BOOL), - tcs_op('!', lnot, BOOL), - tcs_op('=3D', assign, ANY), - tcs_op('[', array, ANY), - tcs_op('(', funcall, ANY), + tcs_op('+', add, NUM, 0), + tcs_op('-', sub, NUM, 0), + tcs_op('*', mul, NUM, 0), + tcs_op('/', div, NUM, 0), + tcs_op(NEG, neg, NUM, 0), + tcs_op(INC, inc, NUM, 1), + tcs_op(DEC, dec, NUM, 1), + tcs_op(PINC, pinc, NUM, 1), + tcs_op(PDEC, pdec, NUM, 1), + tcs_op(SHL, shl, INT, 0), + tcs_op(SHR, shr, INT, 0), + tcs_op('&', and, INT, 0), + tcs_op('|', or, INT, 0), + tcs_op('^', xor, INT, 0), + tcs_op('~', not, INT, 0), + tcs_op('<', lt, SCALAR, 0), + tcs_op('>', gt, SCALAR, 0), + tcs_op(LTE, lte, SCALAR, 0), + tcs_op(GTE, gte, SCALAR, 0), + tcs_op(EQ, eq, SCALAR, 0), + tcs_op(NE, ne, SCALAR, 0), + tcs_op(AND, land, BOOL, 0), + tcs_op(OR, lor, BOOL, 0), + tcs_op('!', lnot, BOOL, 0), + tcs_op('=3D', assign, ANY, 1), + tcs_op('[', array, ANY, 0), + tcs_op('(', funcall, ANY, 0), }; = #define NUM_OPS (sizeof(tcs_operators) / sizeof(tcs_operators[0])) @@ -540,13 +611,23 @@ for(i =3D 0; i < eop->nargs; i++) args[i] =3D tcs_expr_eval(tcs, eop->args[i]); = - if(tcs_type_convert(eop->nargs, args, op->type) >=3D 0) + if((args[0]->type & TCS_VAL_CONST) && op->mod){ + char *s =3D tcscript_getstring(args[0]); + fprintf(stderr, "tcscript: attempt to modify constant '%s'\n", s); + free(s); + } else if(tcs_type_convert(eop->nargs, args, op->type) >=3D 0){ val =3D op->op(tcs, eop->nargs, args); + } = for(i =3D 0; i < eop->nargs; i++) tcfree(args[i]); free(args); = + if(op->mod && val && (val->type & TCS_VAL_EXTERN)){ + if(tcs->ns->set) + tcs->ns->set(tcs->ns->data, val->name, val); + } + return val; } = @@ -556,7 +637,7 @@ tcscript_value_t *v =3D expr->val.val; tcscript_value_t *val =3D NULL; = - if(v->type & TCS_VAL_EXTERN){ + if((v->type & TCS_VAL_EXTERN) && !(v->type & TCS_VAL_CONST)){ val =3D tcs->ns->get(tcs->ns->data, v->name); val->type |=3D TCS_VAL_EXTERN; val->name =3D strdup(v->name); diff -Nru a/src/tcs-internal.h b/src/tcs-internal.h --- a/src/tcs-internal.h 2005-03-31 04:43:25 +02:00 +++ b/src/tcs-internal.h 2005-03-31 04:43:25 +02:00 @@ -25,6 +25,7 @@ #ifndef TCS_INTERNAL_H #define TCS_INTERNAL_H = +#include <stdarg.h> #include <tctypes.h> #include <tclist.h> #include <tchash.h> @@ -32,6 +33,7 @@ = struct tcscript_namespace { tchash_table_t *symbols; + tchash_table_t *constants; tcscript_get_t get; tcscript_set_t set; void *data; @@ -40,7 +42,7 @@ struct tcscript_value { char *name; int type; - union { + union tcs_value { uint64_t i; double f; char *s; @@ -58,6 +60,7 @@ #define TCS_VAL_FUNCTION 2050 = #define TCS_VAL_EXTERN (1<<24) +#define TCS_VAL_CONST (1<<25) = #define TCS_VAL_TYPEMASK ((1<<24)-1) = @@ -143,6 +146,7 @@ }; = extern tcscript_value_t *tcs_ns_create(tcscript_namespace_t *, char *); +extern tcscript_value_t *tcs_ns_const(tcscript_namespace_t *, int, va_list); = #define yymaxdepth tcs_maxdepth #define yyparse tcs_parse |
From: <mr...@mr...> - 2005-03-31 02:43:34
|
# This is a BitKeeper generated diff -Nru style patch. # # src/tcs-internal.h # 2005/03/31 02:22:52+02:00 mr...@fo... +192 -0 # = # src/script.c # 2005/03/31 02:22:52+02:00 mr...@fo... +666 -0 # = # src/script-parse.y # 2005/03/31 02:22:52+02:00 mr...@fo... +408 -0 # = # src/script-lex.l # 2005/03/31 02:22:52+02:00 mr...@fo... +82 -0 # = # include/tcscript.h # 2005/03/31 02:22:52+02:00 mr...@fo... +67 -0 # = # ChangeSet # 2005/03/31 02:22:52+02:00 mr...@fo... = # tcscript, a simple scripting engine # = # src/tcs-internal.h # 2005/03/31 02:22:52+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/tcs-internal.h # = # src/script.c # 2005/03/31 02:22:52+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/script.c # = # src/script-parse.y # 2005/03/31 02:22:52+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/script-parse.y # = # src/script-lex.l # 2005/03/31 02:22:52+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/script-lex.l # = # src/Makefile.am # 2005/03/31 02:22:52+02:00 mr...@fo... +15 -5 # add tcscript sources # fix lex/yacc building # = # include/tcscript.h # 2005/03/31 02:22:52+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/include/tcscript.h # = # include/Makefile.am # 2005/03/31 02:22:52+02:00 mr...@fo... +1 -1 # add tcscript.h # = diff -Nru a/include/Makefile.am b/include/Makefile.am --- a/include/Makefile.am 2005-03-31 04:43:22 +02:00 +++ b/include/Makefile.am 2005-03-31 04:43:22 +02:00 @@ -1,6 +1,6 @@ include_HEADERS =3D tc.h tclist.h tchash.h tcnet.h tctime.h tcconf.h \ tctree.h tcalloc.h tcprioq.h tcmath.h tcmempool.h \ - tcbyteswap.h tcfilter.h tcarg.h + tcbyteswap.h tcfilter.h tcarg.h tcscript.h nodist_include_HEADERS =3D tcstring.h tctypes.h tcdirent.h tcendian.h EXTRA_DIST =3D byteswap.yes byteswap.no snprintf.no \ strsep.yes strsep.no endian.little endian.big diff -Nru a/include/tcscript.h b/include/tcscript.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/tcscript.h 2005-03-31 04:43:22 +02:00 @@ -0,0 +1,67 @@ +/** + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#ifndef TCSCRIPT_H +#define TCSCRIPT_H + +#include <tctypes.h> + +typedef struct tcscript tcscript_t; +typedef struct tcscript_namespace tcscript_namespace_t; +typedef struct tcscript_value tcscript_value_t; +typedef tcscript_value_t *(*tcscript_function_t)(tcscript_t *, void *, char *, + int, tcscript_value_t **); +typedef tcscript_value_t *(*tcscript_get_t)(void *, char *); +typedef void (*tcscript_set_t)(void *, char *, tcscript_value_t *); + +extern tcscript_t *tcscript_compile(void *, tcio_fn, tcscript_namespace_t *); +extern tcscript_t *tcscript_compile_file(char *, tcscript_namespace_t *); +extern tcscript_t *tcscript_compile_string(char *, tcscript_namespace_t *); +extern tcscript_value_t *tcscript_run(tcscript_t *); + +extern tcscript_namespace_t *tcscript_ns_alloc(tcscript_get_t, tcscript_set_t, + void *); +extern tcscript_value_t *tcscript_ns_get(tcscript_namespace_t *, char *); + +extern int64_t tcscript_getint(tcscript_value_t *); +extern void tcscript_setint(tcscript_value_t *, int64_t); +extern tcscript_value_t *tcscript_mkint(int64_t); + +extern double tcscript_getfloat(tcscript_value_t *); +extern void tcscript_setfloat(tcscript_value_t *, double); +extern tcscript_value_t *tcscript_mkfloat(double); + +extern char *tcscript_getstring(tcscript_value_t *); +extern void tcscript_setstring(tcscript_value_t *, char *); +extern tcscript_value_t *tcscript_mkstring(char *, int); + +extern void *tcscript_getptr(tcscript_value_t *); +extern void tcscript_setptr(tcscript_value_t *, void *, tcfree_fn); +extern tcscript_value_t *tcscript_mkptr(void *, tcfree_fn); + +extern tcscript_function_t tcscript_getfun(tcscript_value_t *); +extern void tcscript_setfun(tcscript_value_t *, tcscript_function_t); +extern tcscript_value_t *tcscript_mkfun(tcscript_function_t); + +#endif diff -Nru a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am 2005-03-31 04:43:22 +02:00 +++ b/src/Makefile.am 2005-03-31 04:43:22 +02:00 @@ -22,22 +22,32 @@ LIBTOOL =3D case $@ in \ install*) echo " INSTALL $$p";; \ esac; true " >/dev/null " && @LIBTOOL@ --quiet -LEXCOMPILE =3D echo ' LEX $<' && $(LEX) $(LFLAGS) $(AM_LFLAGS) -YACCCOMPILE =3D echo ' YACC $<' && $(YACC) $(YFLAGS) $(AM_YFLAGS) = lib_LTLIBRARIES =3D libtc.la libtc_la_SOURCES =3D list.c hash.c gethostaddr.c gethostname.c pathfind.c \ strtotime.c conf.c conf-lex.l conf-parse.y tree.c alloc.c \ - prioq.c math.c string.c regex.c mkpath.c mpool.c filter.c + prioq.c math.c string.c regex.c mkpath.c mpool.c filter.c \ + script-lex.l script-parse.y script.c libtc_la_LDFLAGS =3D -version-info 16:0:0 libtc_la_LIBADD =3D @LTLIBOBJS@ INCLUDES =3D -I$(top_srcdir)/include -I$(top_builddir)/include -EXTRA_DIST =3D tcc-internal.h +EXTRA_DIST =3D tcc-internal.h tcs-internal.h AM_YFLAGS =3D -d -BUILT_SOURCES =3D conf-parse.h +BUILT_SOURCES =3D conf-parse.h script-parse.h = bin_PROGRAMS =3D tcconfdump tcconfdump_SOURCES =3D confdump.c tcconfdump_LDFLAGS =3D libtc.la + +TCLEXCOMPILE =3D echo ' LEX $<' && $(SHELL) $(YLWRAP) $< lex.$(<F:-lex.l=3D).c $@ -- $(LEXCOMPILE) + +conf-lex.c: conf-lex.l + $(TCLEXCOMPILE) -Pconf + +script-lex.c: script-lex.l + $(TCLEXCOMPILE) -Pscript + +.y.c: + echo ' YACC $<' && $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) = .SILENT: diff -Nru a/src/script-lex.l b/src/script-lex.l --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/script-lex.l 2005-03-31 04:43:22 +02:00 @@ -0,0 +1,82 @@ +/** -*- c -*- + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +%option noyywrap yylineno + +identifier [[:alpha:]_][[:alnum:]_]* + +%{ +#include <string.h> +#include "tcs-internal.h" +#include "script-parse.h" + +#define YY_DECL int tcs_lex(void *data, tcio_fn rfn) + +#define YY_INPUT(buf,res,size) do { \ + res =3D tcs_input.read(buf, 1, size, tcs_input.data); \ + res =3D res <=3D 0? YY_NULL: res; \ +} while(0) + +#define RET(v) tcs_lval.i =3D (v); return v + +static struct { + void *data; + tcio_fn read; +} tcs_input; +%} + +%% + tcs_input.data =3D data; + tcs_input.read =3D rfn; + +[[:space:]] /* skip blanks */ +"/*".*"*/" /* comments */ +"//".*\n +^[ \t]*\n /* skip blank lines */ + +return/[^[:alnum:]_] return RETURN; +if/[^[:alnum:]_] return IF; +else/[^[:alnum:]_] return ELSE; +while/[^[:alnum:]_] return WHILE; +break/[^[:alnum:]_] return BREAK; + +[+\-*/<>&|^=3D~!] | +[\(\){}\[\];,] RET(yytext[0]); +"<=3D" RET(LTE); +">=3D" RET(GTE); +"=3D=3D" RET(EQ); +"!=3D" RET(NE); +"&&" RET(AND); +"||" RET(OR); +"<<" RET(SHL); +">>" RET(SHR); +"++" RET(INC); +"--" RET(DEC); + +{identifier} { tcs_lval.s =3D strdup(yytext); return IDENTIFIER; } +0x[[:xdigit:]]+ | +[[:digit:]]+ { tcs_lval.i =3D strtoll(yytext, NULL, 0); return INT; } +[[:digit:]]+(\.[[:digit:]])*([eE][+\-]?[[:digit:]]+)? { tcs_lval.f =3D strtod(yytext, NULL); return FLOAT; } +\'[^\']*\' { yytext[yyleng-1]=3D0; tcs_lval.s =3D yytext + 1; return STRING; } +\"([^\"]*(\\\")?)*[^\\]\" { yytext[yyleng-1]=3D0; tcs_lval.s =3D yytext + 1; return DSTRING; } diff -Nru a/src/script-parse.y b/src/script-parse.y --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/script-parse.y 2005-03-31 04:43:22 +02:00 @@ -0,0 +1,408 @@ +/** + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +%{ +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <tcalloc.h> +#include "tcs-internal.h" + +#define yylex tcs_lex + +static void tcs_add_stmt(tcscript_t *scr, tcs_stmt_t *stmt); +static tcs_stmt_t *tcs_stmt_expr(tcs_expr_t *e); +static tcs_stmt_t *tcs_stmt_cmp(void); +static void tcs_stmt_cmp_add(tcs_stmt_t *stmt, tcs_stmt_t *s); +static tcs_stmt_t *tcs_stmt_if(tcs_expr_t *cond, tcs_stmt_t *, tcs_stmt_t *); +static tcs_stmt_t *tcs_stmt_while(tcs_expr_t *cond, tcs_stmt_t *body); +static tcs_stmt_t *tcs_stmt_break(void); +static tcs_stmt_t *tcs_stmt_ret(tcs_expr_t *val); +static tcs_expr_t *tcs_expr_op(int op, int n, ...); +static void tcs_expr_add(tcs_expr_t *e, tcs_expr_t *n); +static tcs_expr_t *tcs_expr_val(tcscript_t *scr, int type, ...); + +static void tcs_error(void *, tcio_fn, tcscript_t *, char *); +%} + +%parse-param {void *data} +%parse-param {tcio_fn rfn} +%parse-param {tcscript_t *scr} + +%lex-param {void *data} +%lex-param {tcio_fn rfn} + +%error-verbose + +%union { + int64_t i; + double f; + char *s; + tcs_expr_t *expr; + tcs_stmt_t *stmt; +} + +%token <i> INT +%token <f> FLOAT +%token <s> STRING +%token <s> DSTRING +%token <s> IDENTIFIER + +%token RETURN +%token IF +%token ELSE +%token WHILE +%token BREAK + +%token <i> '+' +%token <i> '-' +%token <i> '*' +%token <i> '/' +%token <i> '<' +%token <i> '>' +%token <i> '&' +%token <i> '|' +%token <i> '^' +%token <i> '=3D' +%token <i> '~' +%token <i> '!' +%token <i> '[' +%token <i> '(' +%token <i> LTE +%token <i> GTE +%token <i> EQ +%token <i> NE +%token <i> AND +%token <i> OR +%token <i> SHL +%token <i> SHR +%token <i> INC +%token <i> DEC +%token <i> NEG +%token <i> PINC +%token <i> PDEC + +%type <stmt> statement +%type <stmt> expression_stmt +%type <stmt> compound_stmt +%type <stmt> cmp_stmt +%type <stmt> if_stmt +%type <stmt> else_stmt +%type <stmt> while_stmt +%type <stmt> break_stmt +%type <stmt> return_stmt + +%type <expr> expression +%type <expr> value_expr +%type <expr> op_expr +%type <expr> args + +%right '=3D' +%left OR +%left AND +%left '|' +%left '^' +%left '&' +%left EQ NE +%left '<' LTE '>' GTE +%left SHL SHR +%left '+' '-' +%left '*' '/' +%left '!' '~' INC DEC NEG +%left '(' '[' + +%% + +script: /* empty */ + | script statement { tcs_add_stmt(scr, $2); } + ; +statement: expression_stmt + | compound_stmt + | if_stmt + | while_stmt + | break_stmt + | return_stmt + ; +expression_stmt: expression ';' { $$ =3D tcs_stmt_expr($1); } + ; +compound_stmt: '{' cmp_stmt statements '}' { $$ =3D $2; } + ; +cmp_stmt: { $$ =3D tcs_stmt_cmp(); } + ; +statements: /* empty */ { } + | statements statement { tcs_stmt_cmp_add($<stmt>0, $2); } + ; +if_stmt: IF '(' expression ')' statement else_stmt + { $$ =3D tcs_stmt_if($3, $5, $6); } + ; +else_stmt: /* empty */ { $$ =3D NULL; } + | ELSE statement { $$ =3D $2; } + ; +while_stmt: WHILE '(' expression ')' statement { $$ =3D tcs_stmt_while($3, $5); } + ; +break_stmt: BREAK ';' { $$ =3D tcs_stmt_break(); } + ; +return_stmt: RETURN expression ';' { $$ =3D tcs_stmt_ret($2); } + | RETURN ';' { $$ =3D tcs_stmt_ret(NULL); } + ; +expression: value_expr + | op_expr + ; +value_expr: INT { $$ =3D tcs_expr_val(scr, INT, $1); } + | FLOAT { $$ =3D tcs_expr_val(scr, FLOAT, $1); } + | STRING { $$ =3D tcs_expr_val(scr, STRING, $1); } + | DSTRING { $$ =3D tcs_expr_val(scr, DSTRING, $1); } + | IDENTIFIER { $$ =3D tcs_expr_val(scr, TCS_VAL_VARIABLE, $1); } + ; +op_expr: expression '+' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '-' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '*' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '/' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '<' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '>' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '&' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '|' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '^' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '=3D' expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression LTE expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression GTE expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression EQ expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression NE expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression AND expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression OR expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression SHL expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression SHR expression { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | '-' expression { $$ =3D tcs_expr_op(NEG, 1, $2); } + | '~' expression { $$ =3D tcs_expr_op($1, 1, $2); } + | INC expression { $$ =3D tcs_expr_op($1, 1, $2); } + | DEC expression { $$ =3D tcs_expr_op($1, 1, $2); } + | expression INC { $$ =3D tcs_expr_op(PINC, 1, $1); } + | expression DEC { $$ =3D tcs_expr_op(PDEC, 1, $1); } + | expression '[' expression ']' { $$ =3D tcs_expr_op($2, 2, $1, $3); } + | expression '(' args args1 ')' { $$ =3D $3; } + | '(' expression ')' { $$ =3D $2; } + ; +args: { $$ =3D tcs_expr_op('(', 1, $<expr>-1); } + ; +args1: /* empty */ { } + | expression { tcs_expr_add($<expr>0, $1); } + | args1 ',' expression { tcs_expr_add($<expr>0, $3); } + ; +%% + +static void +tcs_add_stmt(tcscript_t *scr, tcs_stmt_t *stmt) +{ + scr->stmts =3D realloc(scr->stmts, ++scr->nstmts * sizeof(*scr->stmts)); + scr->stmts[scr->nstmts - 1] =3D stmt; +} + +static void +tcs_stmt_expr_free(void *p) +{ + tcs_stmt_t *s =3D p; + tcfree(s->expr.expr); +} + +static tcs_stmt_t * +tcs_stmt_expr(tcs_expr_t *e) +{ + tcs_stmt_t *s =3D tcallocdz(sizeof(*s), NULL, tcs_stmt_expr_free); + s->type =3D TCS_STMT_EXPR; + s->expr.expr =3D e; + return s; +} + +static void +tcs_stmt_cmp_free(void *p) +{ + tcs_stmt_t *s =3D p; + int i; + + for(i =3D 0; i < s->comp.nstmts; i++) + tcfree(s->comp.stmts[i]); + free(s->comp.stmts); +} + +static tcs_stmt_t * +tcs_stmt_cmp(void) +{ + tcs_stmt_t *s =3D tcallocdz(sizeof(*s), NULL, tcs_stmt_cmp_free); + s->type =3D TCS_STMT_COMP; + return s; +} + +static void +tcs_stmt_cmp_add(tcs_stmt_t *stmt, tcs_stmt_t *s) +{ + stmt->comp.stmts =3D realloc(stmt->comp.stmts, ++stmt->comp.nstmts * + sizeof(*stmt->comp.stmts)); + stmt->comp.stmts[stmt->comp.nstmts - 1] =3D s; +} + +static void +tcs_stmt_if_free(void *p) +{ + tcs_if_stmt_t *s =3D p; + tcfree(s->cond); + tcfree(s->if_stmt); + tcfree(s->else_stmt); +} + +static tcs_stmt_t * +tcs_stmt_if(tcs_expr_t *cond, tcs_stmt_t *if_s, tcs_stmt_t *else_s) +{ + tcs_stmt_t *s =3D tcallocdz(sizeof(*s), NULL, tcs_stmt_if_free); + + s->type =3D TCS_STMT_IF; + s->if_stmt.cond =3D cond; + s->if_stmt.if_stmt =3D if_s; + s->if_stmt.else_stmt =3D else_s; + + return s; +} + +static void +tcs_stmt_while_free(void *p) +{ + tcs_while_stmt_t *s =3D p; + tcfree(s->cond); + tcfree(s->body); +} + +static tcs_stmt_t * +tcs_stmt_while(tcs_expr_t *cond, tcs_stmt_t *body) +{ + tcs_stmt_t *s =3D tcallocdz(sizeof(*s), NULL, tcs_stmt_while_free); + + s->type =3D TCS_STMT_WHILE; + s->while_stmt.cond =3D cond; + s->while_stmt.body =3D body; + + return s; +} + +static tcs_stmt_t * +tcs_stmt_break(void) +{ + tcs_stmt_t *s =3D tcallocz(sizeof(*s)); + s->type =3D TCS_STMT_BREAK; + return s; +} + +static void +tcs_stmt_ret_free(void *p) +{ + tcs_ret_stmt_t *s =3D p; + tcfree(s->val); +} + +static tcs_stmt_t * +tcs_stmt_ret(tcs_expr_t *val) +{ + tcs_stmt_t *s =3D tcallocdz(sizeof(*s), NULL, tcs_stmt_ret_free); + + s->type =3D TCS_STMT_RET; + s->ret.val =3D val; + + return s; +} + +static void +tcs_expr_op_free(void *p) +{ + tcs_expr_t *e =3D p; + u_int i; + + for(i =3D 0; i < e->op.nargs; i++) + tcfree(e->op.args[i]); + free(e->op.args); +} + +static tcs_expr_t * +tcs_expr_op(int op, int n, ...) +{ + tcs_expr_t *e =3D tcallocdz(sizeof(*e), NULL, tcs_expr_op_free); + va_list args; + int i; + + e->type =3D TCS_EXPR_OP; + e->op.op =3D op; + e->op.nargs =3D n; + e->op.args =3D malloc(n * sizeof(*e->op.args)); + + va_start(args, n); + for(i =3D 0; i < n; i++) + e->op.args[i] =3D va_arg(args, tcs_expr_t *); + va_end(args); + + return e; +} + +static void +tcs_expr_add(tcs_expr_t *e, tcs_expr_t *n) +{ + e->op.args =3D realloc(e->op.args, ++e->op.nargs * sizeof(*e->op.args)); + e->op.args[e->op.nargs - 1] =3D n; +} + +static void +tcs_expr_val_free(void *p) +{ + tcs_expr_t *e =3D p; + tcfree(e->val.val); +} + +static tcs_expr_t * +tcs_expr_val(tcscript_t *scr, int type, ...) +{ + tcs_expr_t *e =3D tcallocdz(sizeof(*e), NULL, tcs_expr_val_free); + va_list args; + + va_start(args, type); + e->type =3D TCS_EXPR_VAL; + + if(type =3D=3D INT){ + e->val.val =3D tcscript_mkint(va_arg(args, int64_t)); + } else if(type =3D=3D FLOAT){ + e->val.val =3D tcscript_mkfloat(va_arg(args, double)); + } else if(type =3D=3D STRING || type =3D=3D DSTRING){ + e->val.val =3D tcscript_mkstring(va_arg(args, char *), type =3D=3D DSTRING); + } else if(type =3D=3D TCS_VAL_VARIABLE){ + char *n =3D va_arg(args, char *); + e->val.val =3D tcs_ns_create(scr->ns, n); + free(n); + } else { + fprintf(stderr, "tcscript: impossible type %i\n", type); + } + + return e; +} + +static void +tcs_error(void *d, tcio_fn io, tcscript_t *s, char *msg) +{ + (void) d; (void) io; (void) s; + fprintf(stderr, "%s\n", msg); +} diff -Nru a/src/script.c b/src/script.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/script.c 2005-03-31 04:43:22 +02:00 @@ -0,0 +1,666 @@ +/** + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <tcstring.h> +#include <tcalloc.h> +#include <tchash.h> +#include <tcscript.h> +#include "tcs-internal.h" + +static void +tcs_value_free(void *p) +{ + tcscript_value_t *v =3D p; + free(v->name); + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING || TCS_VAL_TYPE(v) =3D=3D TCS_VAL_DSTRING) + free(v->value.s); +} + +static tcscript_value_t * +tcs_value_alloc(char *name, int type) +{ + tcscript_value_t *v =3D tcallocdz(sizeof(*v), NULL, tcs_value_free); + v->name =3D name? strdup(name): NULL; + v->type =3D type; + return v; +} + +extern tcscript_value_t * +tcscript_mkint(int64_t i) +{ + tcscript_value_t *v =3D tcs_value_alloc(NULL, TCS_VAL_INT); + v->value.i =3D i; + return v; +} + +extern int64_t +tcscript_getint(tcscript_value_t *v) +{ + int64_t i; + + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_INT) + i =3D v->value.i; + else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_FLOAT) + i =3D v->value.f; + else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING) + i =3D strtoll(v->value.s, NULL, 0); + else + i =3D 0; + + return i; +} + +extern void +tcscript_setint(tcscript_value_t *v, int64_t i) +{ + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING) + free(v->value.s); + v->type =3D TCS_VAL_INT; + v->value.i =3D i; +} + +extern tcscript_value_t * +tcscript_mkfloat(double f) +{ + tcscript_value_t *v =3D tcs_value_alloc(NULL, TCS_VAL_FLOAT); + v->value.f =3D f; + return v; +} + +extern double +tcscript_getfloat(tcscript_value_t *v) +{ + double f; + + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_INT) + f =3D v->value.i; + else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_FLOAT) + f =3D v->value.f; + else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING) + f =3D strtod(v->value.s, NULL); + else + f =3D 0; + + return f; +} + +extern void +tcscript_setfloat(tcscript_value_t *v, double d) +{ + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING) + free(v->value.s); + v->type =3D TCS_VAL_FLOAT; + v->value.f =3D d; +} + +extern tcscript_value_t * +tcscript_mkstring(char *s, int d) +{ + tcscript_value_t *v =3D + tcs_value_alloc(NULL, d? TCS_VAL_DSTRING: TCS_VAL_STRING); + v->value.s =3D strdup(s); + return v; +} + +extern char * +tcscript_getstring(tcscript_value_t *v) +{ + char *s; + + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_INT){ + s =3D malloc(32); + snprintf(s, 32, "%lli", v->value.i); + } else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_FLOAT){ + s =3D malloc(64); + snprintf(s, 64, "%.10g", v->value.f); + } else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING){ + s =3D strdup(v->value.s); + } else { + s =3D strdup(""); + } + + return s; +} + +extern void +tcscript_setstring(tcscript_value_t *v, char *s) +{ + if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_STRING) + free(v->value.s); + v->type =3D TCS_VAL_STRING; + v->value.s =3D strdup(s); +} + +extern tcscript_value_t * +tcscript_mkfun(tcscript_function_t fun) +{ + tcscript_value_t *v =3D tcs_value_alloc(NULL, TCS_VAL_FUNCTION); + v->value.fun =3D fun; + return v; +} + +static void +tcs_ns_free(void *p) +{ + tcscript_namespace_t *ns =3D p; + tchash_destroy(ns->symbols, tcfree); +} + +extern tcscript_namespace_t * +tcscript_ns_alloc(tcscript_get_t get, tcscript_set_t set, void *p) +{ + tcscript_namespace_t *ns =3D tcallocdz(sizeof(*ns), NULL, tcs_ns_free); + + if(!ns) + return NULL; + + ns->symbols =3D tchash_new(32, TC_LOCK_SLOPPY, 0); + ns->get =3D get; + ns->set =3D set; + ns->data =3D p; + + return ns; +} + +extern tcscript_value_t * +tcs_ns_create(tcscript_namespace_t *ns, char *name) +{ + tcscript_value_t *v =3D NULL; + + if(tchash_find(ns->symbols, name, -1, &v)){ + if(ns->get){ + v =3D ns->get(ns->data, name); + if(v){ + v->name =3D strdup(name); + v->type |=3D TCS_VAL_EXTERN; + } + } + if(!v){ + v =3D tcs_value_alloc(name, 0); + } + tchash_replace(ns->symbols, name, -1, v, NULL); + } + + return tcref(v); +} + +static void +tcs_free(void *p) +{ + tcscript_t *tcs =3D p; + int i; + + for(i =3D 0; i < tcs->nstmts; i++) + tcfree(tcs->stmts[i]); + free(tcs->stmts); + tcfree(tcs->ns); +} + +extern tcscript_t * +tcscript_compile(void *data, tcio_fn iofn, tcscript_namespace_t *ns) +{ + static pthread_mutex_t lock =3D PTHREAD_MUTEX_INITIALIZER; + tcscript_t *tcs; + int pr; + + if(!ns){ + ns =3D tcscript_ns_alloc(NULL, NULL, NULL); + if(!ns) + return NULL; + } else { + tcref(ns); + } + + tcs =3D tcallocdz(sizeof(*tcs), NULL, tcs_free); + tcs->ns =3D ns; + + pthread_mutex_lock(&lock); + pr =3D tcs_parse(data, iofn, tcs); + pthread_mutex_unlock(&lock); + + if(pr){ + tcfree(tcs); + tcs =3D NULL; + } + + return tcs; +} + +extern tcscript_t * +tcscript_compile_file(char *file, tcscript_namespace_t *ns) +{ + tcscript_t *tcs; + FILE *f; + + if((f =3D fopen(file, "r")) =3D=3D NULL) + return NULL; + tcs =3D tcscript_compile(f, (tcio_fn) fread, ns); + fclose(f); + + return tcs; +} + +#define op_int(op) \ + case TCS_VAL_INT: \ + v =3D tcscript_mkint(args[0]->value.i op args[1]->value.i); \ + break; + +#define op_float(op) \ + case TCS_VAL_FLOAT: \ + v =3D tcscript_mkfloat(args[0]->value.f op args[1]->value.f); \ + break; + +#define op_strcmp(op) \ + case TCS_VAL_STRING: \ + v =3D tcscript_mkint(strcmp(args[0]->value.s, args[1]->value.s) op 0); \ + break; + +#define op_strbool(op) \ + case TCS_VAL_STRING: \ + v =3D tcscript_mkint(args[0]->value.s op args[1]->value.s); \ + break; + +#define op_uint(op) \ + case TCS_VAL_INT: \ + v =3D tcscript_mkint(op args[0]->value.i); \ + break; + +#define op_ufloat(op) \ + case TCS_VAL_FLOAT: \ + v =3D tcscript_mkfloat(op args[0]->value.f); \ + break; + +#define op_ustrbool(op) \ + case TCS_VAL_STRING: \ + v =3D tcscript_mkint(op args[0]->value.s); \ + break; + +#define op_puint(op) \ + case TCS_VAL_INT: \ + v =3D tcscript_mkint(args[0]->value.i op); \ + break; + +#define op_pufloat(op) \ + case TCS_VAL_FLOAT: \ + v =3D tcscript_mkfloat(args[0]->value.f op); \ + break; + +#define tcs_opdef(op, name, ops) \ +static tcscript_value_t * \ +tcs_op_##name(tcscript_t *tcs, int n, tcscript_value_t **args) \ +{ \ + tcscript_value_t *v =3D NULL; \ + (void) tcs; (void) n; \ + switch(TCS_VAL_TYPE(args[0])){ \ + ops(op) \ + } \ + return v; \ +} + +#define op_num(op) op_int(op) op_float(op) +#define op_unum(op) op_uint(op) op_ufloat(op) +#define op_punum(op) op_puint(op) op_pufloat(op) +#define op_scalar(op) op_num(op) op_strcmp(op) +#define op_bool(op) op_num(op) op_strbool(op) +#define op_ubool(op) op_uint(op) op_ustrbool(op) + +tcs_opdef(+, add, op_num) +tcs_opdef(-, sub, op_num) +tcs_opdef(*, mul, op_num) +tcs_opdef(/, div, op_num) +tcs_opdef(-, neg, op_unum) +tcs_opdef(++, inc, op_unum) +tcs_opdef(--, dec, op_unum) +tcs_opdef(++, pinc, op_punum) +tcs_opdef(--, pdec, op_punum) +tcs_opdef(<<, shl, op_int) +tcs_opdef(>>, shr, op_int) +tcs_opdef(&, and, op_int) +tcs_opdef(|, or, op_int) +tcs_opdef(^, xor, op_int) +tcs_opdef(~, not, op_uint) +tcs_opdef(&&, land, op_bool) +tcs_opdef(||, lor, op_bool) +tcs_opdef(!, lnot, op_ubool) +tcs_opdef(<, lt, op_scalar) +tcs_opdef(>, gt, op_scalar) +tcs_opdef(=3D=3D, eq, op_scalar) +tcs_opdef(!=3D, ne, op_scalar) +tcs_opdef(<=3D, lte, op_scalar) +tcs_opdef(>=3D, gte, op_scalar) + +static tcscript_value_t * +tcs_op_assign(tcscript_t *tcs, int n, tcscript_value_t **args) +{ + (void) n; + args[0]->type =3D args[1]->type; + + if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_STRING){ + free(args[0]->value.s); + args[0]->value.s =3D strdup(args[1]->value.s); + } else { + args[0]->value =3D args[1]->value; + } + + if(args[0]->type & TCS_VAL_EXTERN){ + free(args[0]->name); + args[0]->name =3D strdup(args[1]->name); + if(tcs->ns->set) + tcs->ns->set(tcs->ns->data, args[0]->name, args[0]); + } + + return tcref(args[0]); +} + +static tcscript_value_t * +tcs_op_funcall(tcscript_t *tcs, int n, tcscript_value_t **args) +{ + tcscript_value_t *val; + if(TCS_VAL_TYPE(args[0]) =3D=3D TCS_VAL_FUNCTION) + val =3D args[0]->value.fun(tcs, tcs->ns->data, args[0]->name, + n - 1, args + 1); + else + val =3D tcs_value_alloc(NULL, 0); + return val; +} + +static tcscript_value_t * +tcs_op_array(tcscript_t *tcs, int n, tcscript_value_t **args) +{ + (void) tcs; (void) n; (void) args; + fprintf(stderr, "tcscript: arrays not implemented\n"); + return NULL; +} + +#define TCS_TYPE_ANY 0 +#define TCS_TYPE_NUM 1 +#define TCS_TYPE_INT 2 +#define TCS_TYPE_STRING 3 +#define TCS_TYPE_BOOL 4 +#define TCS_TYPE_SCALAR 5 + +#define tcs_op(op, name, type) \ + [op] =3D { tcs_op_##name, TCS_TYPE_##type } + +typedef struct tcs_operator { + tcscript_value_t *(*op)(tcscript_t *, int, tcscript_value_t **); + int type; +} tcs_operator_t; + +static tcs_operator_t tcs_operators[] =3D { + tcs_op('+', add, NUM), + tcs_op('-', sub, NUM), + tcs_op('*', mul, NUM), + tcs_op('/', div, NUM), + tcs_op(NEG, neg, NUM), + tcs_op(INC, inc, NUM), + tcs_op(DEC, dec, NUM), + tcs_op(PINC, pinc, NUM), + tcs_op(PDEC, pdec, NUM), + tcs_op(SHL, shl, INT), + tcs_op(SHR, shr, INT), + tcs_op('&', and, INT), + tcs_op('|', or, INT), + tcs_op('^', xor, INT), + tcs_op('~', not, INT), + tcs_op('<', lt, SCALAR), + tcs_op('>', gt, SCALAR), + tcs_op(LTE, lte, SCALAR), + tcs_op(GTE, gte, SCALAR), + tcs_op(EQ, eq, SCALAR), + tcs_op(NE, ne, SCALAR), + tcs_op(AND, land, BOOL), + tcs_op(OR, lor, BOOL), + tcs_op('!', lnot, BOOL), + tcs_op('=3D', assign, ANY), + tcs_op('[', array, ANY), + tcs_op('(', funcall, ANY), +}; + +#define NUM_OPS (sizeof(tcs_operators) / sizeof(tcs_operators[0])) + +static tcscript_value_t *tcs_expr_eval(tcscript_t *, tcs_expr_t *); + +static int +tcs_type_convert(int n, tcscript_value_t **v, int type) +{ + int itg =3D 0, flt =3D 0, str =3D 0, ptr =3D 0, fun =3D 0; + int temp =3D 0; + int vtype =3D 0; + int i; + + if(type =3D=3D TCS_TYPE_ANY) + return 0; + + for(i =3D 0; i < n; i++){ + if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_INT) + itg++; + else if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_FLOAT) + flt++; + else if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_STRING) + str++; + else if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_POINTER) + ptr++; + else if(TCS_VAL_TYPE(v[i]) =3D=3D TCS_VAL_FUNCTION) + fun++; + } + + if(ptr || fun) + return -1; + + if(type =3D=3D TCS_TYPE_NUM){ + vtype =3D flt? TCS_VAL_FLOAT: TCS_VAL_INT; + } else if(type =3D=3D TCS_TYPE_INT){ + vtype =3D TCS_VAL_INT; + } else if(type =3D=3D TCS_TYPE_STRING){ + vtype =3D TCS_VAL_STRING; + } else if(type =3D=3D TCS_TYPE_SCALAR){ + vtype =3D str? TCS_VAL_STRING: flt? TCS_VAL_FLOAT: TCS_VAL_INT; + temp =3D 1; + } else if(type =3D=3D TCS_TYPE_BOOL){ + vtype =3D TCS_VAL_INT; + temp =3D 1; + } + + for(i =3D 0; i < n; i++){ + tcscript_value_t *tv =3D NULL; + + if(TCS_VAL_TYPE(v[i]) =3D=3D vtype) + continue; + + if(vtype =3D=3D TCS_VAL_INT){ + int64_t iv =3D tcscript_getint(v[i]); + if(temp) + tv =3D tcscript_mkint(iv); + else + tcscript_setint(v[i], iv); + } else if(vtype =3D=3D TCS_VAL_FLOAT){ + double d =3D tcscript_getfloat(v[i]); + if(temp) + tv =3D tcscript_mkfloat(d); + else + tcscript_setfloat(v[i], d); + } else if(vtype =3D=3D TCS_VAL_STRING){ + char *s =3D tcscript_getstring(v[i]); + if(temp) + tv =3D tcscript_mkstring(s, 0); + else + tcscript_setstring(v[i], s); + free(s); + } + + if(tv){ + tcfree(v[i]); + v[i] =3D tv; + } + } + + return vtype; +} + +static tcscript_value_t * +tcs_expr_op(tcscript_t *tcs, tcs_expr_t *expr) +{ + tcs_op_expr_t *eop =3D &expr->op; + tcscript_value_t *val =3D NULL; + tcs_operator_t *op =3D tcs_operators + eop->op; + tcscript_value_t **args; + u_int i; + + if(eop->op >=3D NUM_OPS) + return NULL; + if(!op->op) + return NULL; + + args =3D calloc(eop->nargs, sizeof(*args)); + for(i =3D 0; i < eop->nargs; i++) + args[i] =3D tcs_expr_eval(tcs, eop->args[i]); + + if(tcs_type_convert(eop->nargs, args, op->type) >=3D 0) + val =3D op->op(tcs, eop->nargs, args); + + for(i =3D 0; i < eop->nargs; i++) + tcfree(args[i]); + free(args); + + return val; +} + +static tcscript_value_t * +tcs_expr_val(tcscript_t *tcs, tcs_expr_t *expr) +{ + tcscript_value_t *v =3D expr->val.val; + tcscript_value_t *val =3D NULL; + + if(v->type & TCS_VAL_EXTERN){ + val =3D tcs->ns->get(tcs->ns->data, v->name); + val->type |=3D TCS_VAL_EXTERN; + val->name =3D strdup(v->name); + } else if(TCS_VAL_TYPE(v) =3D=3D TCS_VAL_DSTRING){ + val =3D tcs_value_alloc(NULL, TCS_VAL_STRING); + val->value.s =3D malloc(strlen(v->value.s) + 1); + tcstresc(val->value.s, v->value.s); + } else { + val =3D tcref(expr->val.val); + } + + return val; +} + +static tcscript_value_t * +tcs_expr_eval(tcscript_t *tcs, tcs_expr_t *expr) +{ + tcscript_value_t *val =3D NULL; + + switch(expr->type){ + case TCS_EXPR_VAL: + val =3D tcs_expr_val(tcs, expr); + break; + case TCS_EXPR_OP: + val =3D tcs_expr_op(tcs, expr); + break; + } + + return val; +} + +static int +tcs_stmt_exec(tcscript_t *tcs, tcs_stmt_t *stmt, tcscript_value_t **ret) +{ + tcscript_value_t *val =3D NULL; + tcscript_value_t *cv, *tv; + int r =3D stmt->type, i, rt; + + switch(stmt->type){ + case TCS_STMT_EXPR: + val =3D tcs_expr_eval(tcs, stmt->expr.expr); + break; + case TCS_STMT_COMP: + for(i =3D 0; i < stmt->comp.nstmts; i++){ + r =3D tcs_stmt_exec(tcs, stmt->comp.stmts[i], &tv); + if(r !=3D TCS_STMT_BREAK && tv){ + tcfree(val); + val =3D tv; + } + if(r =3D=3D TCS_STMT_RET || r =3D=3D TCS_STMT_BREAK) + break; + } + break; + case TCS_STMT_IF: + cv =3D tcs_expr_eval(tcs, stmt->if_stmt.cond); + if(tcscript_getint(cv)){ + r =3D tcs_stmt_exec(tcs, stmt->if_stmt.if_stmt, &val); + } else if(stmt->if_stmt.else_stmt){ + r =3D tcs_stmt_exec(tcs, stmt->if_stmt.else_stmt, &val); + } + tcfree(cv); + break; + case TCS_STMT_WHILE: + while(tcscript_getint(cv =3D tcs_expr_eval(tcs, stmt->while_stmt.cond))){ + tcfree(val); + rt =3D tcs_stmt_exec(tcs, stmt->while_stmt.body, &val); + if(rt !=3D TCS_STMT_BREAK) + r =3D rt; + if(rt =3D=3D TCS_STMT_RET || rt =3D=3D TCS_STMT_BREAK) + break; + tcfree(cv); + } + tcfree(cv); + break; + case TCS_STMT_BREAK: + break; + case TCS_STMT_RET: + if(stmt->ret.val) + val =3D tcs_expr_eval(tcs, stmt->ret.val); + break; + default: + fprintf(stderr, "tcscript: invalid statement type %i\n", stmt->type); + break; + } + + if(ret) + *ret =3D val; + + return r; +} + +extern tcscript_value_t * +tcscript_run(tcscript_t *tcs) +{ + tcscript_value_t *val =3D NULL; + int i; + + for(i =3D 0; i < tcs->nstmts; i++){ + int r; + tcfree(val); + r =3D tcs_stmt_exec(tcs, tcs->stmts[i], &val); + if(r =3D=3D TCS_STMT_RET || r =3D=3D TCS_STMT_BREAK) + break; + } + + return val; +} diff -Nru a/src/tcs-internal.h b/src/tcs-internal.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/tcs-internal.h 2005-03-31 04:43:22 +02:00 @@ -0,0 +1,192 @@ +/** + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#ifndef TCS_INTERNAL_H +#define TCS_INTERNAL_H + +#include <tctypes.h> +#include <tclist.h> +#include <tchash.h> +#include <tcscript.h> + +struct tcscript_namespace { + tchash_table_t *symbols; + tcscript_get_t get; + tcscript_set_t set; + void *data; +}; + +struct tcscript_value { + char *name; + int type; + union { + uint64_t i; + double f; + char *s; + void *p; + tcscript_function_t fun; + } value; +}; + +#define TCS_VAL_INT INT +#define TCS_VAL_FLOAT FLOAT +#define TCS_VAL_STRING STRING +#define TCS_VAL_DSTRING DSTRING +#define TCS_VAL_VARIABLE 2048 +#define TCS_VAL_POINTER 2049 +#define TCS_VAL_FUNCTION 2050 + +#define TCS_VAL_EXTERN (1<<24) + +#define TCS_VAL_TYPEMASK ((1<<24)-1) + +#define TCS_VAL_TYPE(v) ((v)->type & TCS_VAL_TYPEMASK) + +typedef union tcs_expr tcs_expr_t; + +typedef struct tcs_op_expr { + int type; + u_int op; + u_int nargs; + tcs_expr_t **args; +} tcs_op_expr_t; + +#define TCS_OP_ARRAY '[' +#define TCS_OP_FUNCALL '(' + +typedef struct tcs_value_expr { + int type; + tcscript_value_t *val; +} tcs_value_expr_t; + +union tcs_expr { + int type; + tcs_value_expr_t val; + tcs_op_expr_t op; +}; + +#define TCS_EXPR_VAL 1 +#define TCS_EXPR_OP 2 + +typedef union tcs_stmt tcs_stmt_t; + +typedef struct tcs_expr_stmt { + int type; + tcs_expr_t *expr; +} tcs_expr_stmt_t; + +typedef struct tcs_compound_stmt { + int type; + int nstmts; + tcs_stmt_t **stmts; +} tcs_compound_stmt_t; + +typedef struct tcs_if_stmt { + int type; + tcs_expr_t *cond; + tcs_stmt_t *if_stmt; + tcs_stmt_t *else_stmt; +} tcs_if_stmt_t; + +typedef struct tcs_while_stmt { + int type; + tcs_expr_t *cond; + tcs_stmt_t *body; +} tcs_while_stmt_t; + +typedef struct tcs_ret_stmt { + int type; + tcs_expr_t *val; +} tcs_ret_stmt_t; + +union tcs_stmt { + int type; + tcs_expr_stmt_t expr; + tcs_compound_stmt_t comp; + tcs_if_stmt_t if_stmt; + tcs_while_stmt_t while_stmt; + tcs_ret_stmt_t ret; +}; + +#define TCS_STMT_EXPR 1024 +#define TCS_STMT_COMP 1025 +#define TCS_STMT_IF IF +#define TCS_STMT_WHILE WHILE +#define TCS_STMT_BREAK BREAK +#define TCS_STMT_RET RETURN + +struct tcscript { + tcscript_namespace_t *ns; + tcs_stmt_t **stmts; + int nstmts; +}; + +extern tcscript_value_t *tcs_ns_create(tcscript_namespace_t *, char *); + +#define yymaxdepth tcs_maxdepth +#define yyparse tcs_parse +#define yyerror tcs_error +#define yylval tcs_lval +#define yychar tcs_char +#define yydebug tcs_debug +#define yypact tcs_pact +#define yyr1 tcs_r1 +#define yyr2 tcs_r2 +#define yydef tcs_def +#define yychk tcs_chk +#define yypgo tcs_pgo +#define yyact tcs_act +#define yyexca tcs_exca +#define yyerrflag tcs_errflag +#define yynerrs tcs_nerrs +#define yyps tcs_ps +#define yypv tcs_pv +#define yys tcs_s +#define yy_yys tcs_yys +#define yystate tcs_state +#define yytmp tcs_tmp +#define yyv tcs_v +#define yy_yyv tcs_yyv +#define yyval tcs_val +#define yylloc tcs_lloc +#define yyreds tcs_reds +#define yytoks tcs_toks +#define yylhs tcs_lhs +#define yylen tcs_len +#define yydefred tcs_defred +#define yydgoto tcs_dgoto +#define yysindex tcs_sindex +#define yyrindex tcs_rindex +#define yygindex tcs_gindex +#define yytable tcs_table +#define yycheck tcs_check +#define yyname tcs_name +#define yyrule tcs_rule + +#include "script-parse.h" + +extern int tcs_lex(void *, tcio_fn); +extern int tcs_parse(void *, tcio_fn, tcscript_t *); + +#endif |
From: <mr...@mr...> - 2005-03-31 02:43:34
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/31 02:23:58+02:00 mr...@fo... = # conf: kill warning # = # src/tcc-internal.h # 2005/03/31 02:23:57+02:00 mr...@fo... +0 -1 # fix yylex redefinition warning # = # src/conf-parse.y # 2005/03/31 02:23:57+02:00 mr...@fo... +2 -0 # fix yylex redefinition warning # = diff -Nru a/src/conf-parse.y b/src/conf-parse.y --- a/src/conf-parse.y 2005-03-31 04:43:23 +02:00 +++ b/src/conf-parse.y 2005-03-31 04:43:23 +02:00 @@ -26,6 +26,8 @@ #include <string.h> #include "tcc-internal.h" = +#define yylex tcc_lex + static void tcc_error(void *, tcio_fn, conf_section *, tclist_t *, char *); = #define PREP_SEC() do { \ diff -Nru a/src/tcc-internal.h b/src/tcc-internal.h --- a/src/tcc-internal.h 2005-03-31 04:43:23 +02:00 +++ b/src/tcc-internal.h 2005-03-31 04:43:23 +02:00 @@ -89,7 +89,6 @@ = #define yymaxdepth tcc_maxdepth #define yyparse tcc_parse -#define yylex tcc_lex #define yyerror tcc_error #define yylval tcc_lval #define yychar tcc_char |
From: <mr...@mr...> - 2005-03-27 07:54:59
|
# This is a BitKeeper generated diff -Nru style patch. # # src/conf-parse.y # 2005/03/27 09:54:32+02:00 mr...@fo... +134 -0 # = # src/conf-lex.l # 2005/03/27 09:54:32+02:00 mr...@fo... +67 -0 # = # ChangeSet # 2005/03/27 09:54:32+02:00 mr...@fo... = # new yacc-based conf parser # = # src/tcc-internal.h # 2005/03/27 09:54:32+02:00 mr...@fo... +45 -2 # new parser # = # src/conf.c # 2005/03/27 09:54:32+02:00 mr...@fo... +16 -2 # use new conf parser # = # src/conf-parse.y # 2005/03/27 09:54:32+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/conf-parse.y # = # src/conf-lex.l # 2005/03/27 09:54:32+02:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/conf-lex.l # = # src/Makefile.am # 2005/03/27 09:54:32+02:00 mr...@fo... +4 -1 # add conf-lex.l and conf-parse.y, remove conf-parse.l # = # configure.in # 2005/03/27 09:54:32+02:00 mr...@fo... +1 -0 # check for yacc # = # BitKeeper/deleted/.del-conf-parse.l~b42e8b1d9e77abd2 # 2005/03/27 09:47:43+02:00 mr...@fo... +0 -0 # Delete: src/conf-parse.l # = diff -Nru a/configure.in b/configure.in --- a/configure.in 2005-03-27 09:54:46 +02:00 +++ b/configure.in 2005-03-27 09:54:46 +02:00 @@ -11,6 +11,7 @@ AC_PROG_CC AC_PROG_LIBTOOL AM_PROG_LEX +AC_PROG_YACC = dnl Check for pthread support SAVECFLAGS=3D"$CFLAGS" diff -Nru a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am 2005-03-27 09:54:46 +02:00 +++ b/src/Makefile.am 2005-03-27 09:54:46 +02:00 @@ -23,15 +23,18 @@ install*) echo " INSTALL $$p";; \ esac; true " >/dev/null " && @LIBTOOL@ --quiet LEXCOMPILE =3D echo ' LEX $<' && $(LEX) $(LFLAGS) $(AM_LFLAGS) +YACCCOMPILE =3D echo ' YACC $<' && $(YACC) $(YFLAGS) $(AM_YFLAGS) = lib_LTLIBRARIES =3D libtc.la libtc_la_SOURCES =3D list.c hash.c gethostaddr.c gethostname.c pathfind.c \ - strtotime.c conf.c conf-parse.l tree.c alloc.c \ + strtotime.c conf.c conf-lex.l conf-parse.y tree.c alloc.c \ prioq.c math.c string.c regex.c mkpath.c mpool.c filter.c libtc_la_LDFLAGS =3D -version-info 16:0:0 libtc_la_LIBADD =3D @LTLIBOBJS@ INCLUDES =3D -I$(top_srcdir)/include -I$(top_builddir)/include EXTRA_DIST =3D tcc-internal.h +AM_YFLAGS =3D -d +BUILT_SOURCES =3D conf-parse.h = bin_PROGRAMS =3D tcconfdump tcconfdump_SOURCES =3D confdump.c diff -Nru a/src/conf-lex.l b/src/conf-lex.l --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/conf-lex.l 2005-03-27 09:54:46 +02:00 @@ -0,0 +1,67 @@ +/** -*- c -*- + Copyright (C) 2001-2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +%option noyywrap yylineno + +keyword [[:alpha:]_][[:alnum:]_/-]* +keyref (\.\.\/)*{keyword} + +%{ +#include <string.h> +#include <tclist.h> +#include <tcalloc.h> +#include <tcconf.h> +#include "tcc-internal.h" +#include "conf-parse.h" + +#define YY_DECL int tcc_lex(void *data, tcio_fn rfn) + +#define YY_INPUT(buf,res,size) { \ + res =3D conf_file.read(buf, 1, size, conf_file.data); \ + res =3D res <=3D 0? YY_NULL: res; \ +} + +static struct { + void *data; + tcio_fn read; +} conf_file; +%} + +%% + conf_file.data =3D data; + conf_file.read =3D rfn; + +[ \t] /* skip blanks */ +#.*\n /* comment */ +^[ \t]*\n /* skip blank lines */ + +{keyword} { tcc_lval.s =3D strdup(yytext); return IDENT; } +{keyref} { tcc_lval.s =3D strdup(yytext); return IDENTD; } +[+\-]?0x[[:xdigit:]]+ | +[+\-]?[[:digit:]]+ { tcc_lval.i =3D strtoll(yytext, NULL, 0); return INT; } +[+\-]?[[:digit:]]+(\.[[:digit:]])*([eE][+\-]?[[:digit:]]+)? { tcc_lval.f =3D strtod(yytext, NULL); return FLOAT; } +\'[^\']*\' { yytext[yyleng-1]=3D0; tcc_lval.s =3D yytext + 1; return STRING; } +\"([^\"]*(\\\")?)*[^\\]\" { yytext[yyleng-1]=3D0; tcc_lval.s =3D yytext + 1; return DSTRING; } + +[{}\[\]:;\n] return (u_char) yytext[0]; diff -Nru a/src/conf-parse.l b/src/conf-parse.l --- a/src/conf-parse.l 2005-03-27 09:54:46 +02:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,182 +0,0 @@ -/** -*- c -*- - Copyright (C) 2001, 2002, 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, copy, - modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -**/ - -%option noyywrap - -%x sect -%x p_val -%x s_merge - -keyword [[:alnum:]_/-]+ -keyref (\.\.\/)*{keyword} - -%{ -#include <string.h> -#include <tclist.h> -#include <tcalloc.h> -#include "tcconf.h" -#include "tcc-internal.h" - -#define yyterminate() \ - if(section_stack) tclist_destroy(section_stack, tcfree); \ - YY_FLUSH_BUFFER; \ - BEGIN(INITIAL); \ - return NULL - -#define YY_DECL conf_section *tcc_lex(void *data, tcio_fn rfn, \ - conf_section *sec) - -#define YY_INPUT(buf,res,size) { \ - res =3D conf_file.read(buf, 1, size, conf_file.data); \ - res =3D res <=3D 0? YY_NULL: res; \ -} - -#define PUSH_SECTION(q, t) do { \ - tcc_entry *te; \ - char *n =3D yytext+q; \ - yytext[yyleng-q] =3D 0; \ - te =3D create_entry(cur_section, n, t); \ - tclist_push(section_stack, cur_section); \ - cur_section =3D te->section; \ -} while(0) - -static struct { - void *data; - tcio_fn read; -} conf_file; - -%} - -%% - tclist_t *section_stack =3D tclist_new(TC_LOCK_SLOPPY); - conf_section *cur_section; - tcc_entry *cur_entry =3D NULL; - int line_num =3D 1; - int secn =3D 0; - - if(!section_stack) - return NULL; - - if(sec){ - cur_section =3D sec; - } else { - cur_section =3D conf_new(NULL); - } - conf_file.data =3D data; - conf_file.read =3D rfn; - - YY_FLUSH_BUFFER; - BEGIN(INITIAL); - -<*>{ - [ \t] /* skip blanks */ - #.*$ /* comment */ -} - -<INITIAL>{ - section { - secn =3D 0; - BEGIN(sect); - } - {keyword}/([[:space:]]*:[[:space:]]*{keyref})*[[:space:]]*\{ { - PUSH_SECTION(0, TCC_SECTION); - secn =3D 1; - BEGIN(sect); - } - {keyword}/([[:space:]]*:[[:space:]]*{keyref})*[[:space:]]*\[ { - PUSH_SECTION(0, TCC_MSECTION); - secn =3D 1; - BEGIN(sect); - } - {keyword} { - cur_entry =3D create_entry(cur_section, yytext, TCC_VALUE); - BEGIN(p_val); - } - [\}\]] { conf_section *sec; - if((sec =3D tclist_pop(section_stack)) !=3D NULL){ - cur_section =3D sec; - } else { - fprintf(stderr, "line %d: Unexpected '%c'\n", line_num, yytext[0]); - yyterminate(); - } - } - <<EOF>> { - if(tclist_items(section_stack) =3D=3D 0){ - tclist_destroy(section_stack, NULL); - YY_FLUSH_BUFFER; - return cur_section; - } else { - fprintf(stderr, "Unexpected end of file.\n"); - yyterminate(); - } - } -} - -<p_val>{ - [+\-]?0x[[:xdigit:]]+ | - [+\-]?[[:digit:]]+ tcc_addint(cur_entry, strtoll(yytext, NULL, 0)); - [+\-]?[[:digit:]]+\.[[:digit:]]*([eE][+\-]?[[:digit:]]+)? tcc_addfloat(cur_entry, strtod(yytext, NULL)); - \'[^\']*\' yytext[yyleng-1]=3D0; tcc_addstring(cur_entry,strdup(yytext+1),0); - \"([^\"]*(\\\")?)*[^\\]\" yytext[yyleng-1]=3D0; tcc_addstring(cur_entry,strdup(yytext+1),1); - {keyref} tcc_addref(cur_entry, strdup(yytext)); - true tcc_addbool(cur_entry, 1); - false tcc_addbool(cur_entry, 0); - [[:space:]]*/[\]\}] | - [;\n] { - BEGIN(INITIAL); - if(yytext[0] =3D=3D '\n') - line_num++; - } - <<EOF>> fprintf(stderr, "Unexpected end of file.\n"); yyterminate(); -} - -<sect>{ - \"[^\"]*\" { - if(secn =3D=3D 0){ - PUSH_SECTION(1, TCC_SECTION); - secn =3D 1; - } else { - fprintf(stderr, "line %d: Expected '{', found %s.\n", - line_num, yytext); - yyterminate(); - } - } - [\{\[] { - if(secn){ - BEGIN(INITIAL); - } else { - fprintf(stderr, "line %d: Missing section name.\n", line_num); - yyterminate(); - } - } - : BEGIN(s_merge); -} - -<s_merge>[[:alnum:]_/.-]+ { - tclist_push(cur_section->merge, strdup(yytext)); - BEGIN(sect); -} - -<*>\n line_num++; -<*>[^ \t\n;]+ fprintf(stderr, "line %d: Syntax error near '%s'.\n", line_num, yytext); yyterminate(); diff -Nru a/src/conf-parse.y b/src/conf-parse.y --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/conf-parse.y 2005-03-27 09:54:46 +02:00 @@ -0,0 +1,134 @@ +/** + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +%{ +#include <string.h> +#include "tcc-internal.h" + +static void tcc_error(void *, tcio_fn, conf_section *, tclist_t *, char *); + +#define PREP_SEC() do { \ + merge =3D tclist_new(TC_LOCK_SLOPPY); \ +} while(0) + +#define PUSH_SEC(n, t) do { \ + tcc_entry *te =3D create_entry(cur_section, n, t); \ + tclist_push(section_stack, cur_section); \ + cur_section =3D te->section; \ + tclist_destroy(cur_section->merge, NULL); \ + cur_section->merge =3D merge; \ + merge =3D NULL; \ + free(n); \ +} while(0) + +#define POP_SEC() do { \ + cur_section =3D tclist_pop(section_stack); \ +} while(0) + +#define MERGE(n) tclist_push(merge, n) + +#define NEW_ENTRY(n) do { \ + cur_entry =3D create_entry(cur_section, n, TCC_VALUE); \ + free(n); \ +} while(0) + +static tclist_t *merge; +static tcc_entry *cur_entry; +%} + +%parse-param {void *data} +%parse-param {tcio_fn rfn} +%parse-param {conf_section *cur_section} +%parse-param {tclist_t *section_stack} + +%lex-param {void *data} +%lex-param {tcio_fn rfn} + +%error-verbose + +%union { + int64_t i; + double f; + char *s; +} + +%token <i> INT +%token <f> FLOAT +%token <s> STRING +%token <s> DSTRING +%token <s> IDENT +%token <s> IDENTD +%type <s> path + +%% + +configuration: /* empty */ + | configuration section_or_entry nl + ; +section_or_entry: section + | msection + | entry + ; +section: IDENT prep_sec merge '{' { PUSH_SEC($1, TCC_SECTION); } nl + configuration '}' nl { POP_SEC(); } + ; +msection: IDENT prep_sec merge '[' { PUSH_SEC($1, TCC_MSECTION); } nl + configuration ']' nl { POP_SEC(); } + ; +prep_sec: { PREP_SEC(); } + ; +merge: /* empty */ + | ':' mpaths + ; +mpaths: mpath + | mpaths mpath + ; +mpath: path { MERGE($1); } + ; +path: IDENT | IDENTD + ; +entry: IDENT { NEW_ENTRY($1); } values end + ; +values: /* empty */ + | values value + ; +value: INT { tcc_addint(cur_entry, $1); } + | FLOAT { tcc_addfloat(cur_entry, $1); } + | STRING { tcc_addstring(cur_entry, strdup($1), 0); } + | DSTRING { tcc_addstring(cur_entry, strdup($1), 1); } + | path { tcc_addref(cur_entry, $1); } + ; +nl: | '\n' + ; +end: nl | ';' + ; + +%% + +static void +tcc_error(void *d, tcio_fn io, conf_section *cs, tclist_t *ss, char *msg) +{ + (void) d; (void) io; (void) cs; (void) ss; + fprintf(stderr, "%s\n", msg); +} diff -Nru a/src/conf.c b/src/conf.c --- a/src/conf.c 2005-03-27 09:54:46 +02:00 +++ b/src/conf.c 2005-03-27 09:54:46 +02:00 @@ -77,10 +77,22 @@ tcconf_load(tcconf_section_t *ts, void *data, tcio_fn rfn) { conf_section *sec =3D ts? ts->sec: NULL; + tclist_t *sec_stack =3D tclist_new(TC_LOCK_NONE); + int ps; + + if(!sec) + sec =3D conf_new(NULL); + pthread_mutex_lock(&flex_mut); - sec =3D tcc_lex(data, rfn, sec); + ps =3D tcc_parse(data, rfn, sec, sec_stack); pthread_mutex_unlock(&flex_mut); = + tclist_destroy(sec_stack, NULL); + if(ps && !ts){ + tcfree(sec); + sec =3D NULL; + } + if(!ts && sec) ts =3D tcallocdz(sizeof(*ts), NULL, tcconf_free); if(ts && sec) @@ -1106,8 +1118,10 @@ = do_printf(file, ofn, "%*s%s", l, "", ts->name); = + if(tclist_items(ts->merge) > 0) + fprintf(file, " :"); while((m =3D tclist_next(ts->merge, &li))) - fprintf(file, " : %s", m); + fprintf(file, " %s", m); do_printf(file, ofn, " %c\n", d[0]); tcc_writelist(ts->entries, file, lv + 1, ofn); do_printf(file, ofn, "%*s%c\n", l, "", d[1]); diff -Nru a/src/tcc-internal.h b/src/tcc-internal.h --- a/src/tcc-internal.h 2005-03-27 09:54:46 +02:00 +++ b/src/tcc-internal.h 2005-03-27 09:54:46 +02:00 @@ -1,5 +1,5 @@ /** - Copyright (C) 2001 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2001-2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -27,6 +27,7 @@ = #include <tctypes.h> #include <tclist.h> +#include <tcconf.h> = #define TCC_INTEGER 1 #define TCC_FLOAT 2 @@ -82,7 +83,49 @@ extern int tcc_addstring(tcc_entry *, char *, int); extern int tcc_addbool(tcc_entry *, int); extern int tcc_addref(tcc_entry *te, char *ref); -extern conf_section *tcc_lex(void *, tcio_fn, conf_section *); +extern int tcc_parse(void *, tcio_fn, conf_section *, tclist_t *); extern tcc_entry *create_entry(conf_section *sec, char *name, int type); +extern int tcc_lex(void *, tcio_fn); + +#define yymaxdepth tcc_maxdepth +#define yyparse tcc_parse +#define yylex tcc_lex +#define yyerror tcc_error +#define yylval tcc_lval +#define yychar tcc_char +#define yydebug tcc_debug +#define yypact tcc_pact +#define yyr1 tcc_r1 +#define yyr2 tcc_r2 +#define yydef tcc_def +#define yychk tcc_chk +#define yypgo tcc_pgo +#define yyact tcc_act +#define yyexca tcc_exca +#define yyerrflag tcc_errflag +#define yynerrs tcc_nerrs +#define yyps tcc_ps +#define yypv tcc_pv +#define yys tcc_s +#define yy_yys tcc_yys +#define yystate tcc_state +#define yytmp tcc_tmp +#define yyv tcc_v +#define yy_yyv tcc_yyv +#define yyval tcc_val +#define yylloc tcc_lloc +#define yyreds tcc_reds +#define yytoks tcc_toks +#define yylhs tcc_lhs +#define yylen tcc_len +#define yydefred tcc_defred +#define yydgoto tcc_dgoto +#define yysindex tcc_sindex +#define yyrindex tcc_rindex +#define yygindex tcc_gindex +#define yytable tcc_table +#define yycheck tcc_check +#define yyname tcc_name +#define yyrule tcc_rule = #endif |
From: <mr...@mr...> - 2005-03-24 16:52:02
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/24 17:51:39+01:00 mr...@fo... = # new: tcarg, build va_lists at runtime # = # include/tcarg.h # 2005/03/24 17:51:38+01:00 mr...@fo... +120 -0 # = # include/tcarg.h # 2005/03/24 17:51:38+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/include/tcarg.h # = # include/Makefile.am # 2005/03/24 17:51:38+01:00 mr...@fo... +1 -1 # add tcarg.h # = diff -Nru a/include/Makefile.am b/include/Makefile.am --- a/include/Makefile.am 2005-03-24 17:51:51 +01:00 +++ b/include/Makefile.am 2005-03-24 17:51:51 +01:00 @@ -1,6 +1,6 @@ include_HEADERS =3D tc.h tclist.h tchash.h tcnet.h tctime.h tcconf.h \ tctree.h tcalloc.h tcprioq.h tcmath.h tcmempool.h \ - tcbyteswap.h tcfilter.h + tcbyteswap.h tcfilter.h tcarg.h nodist_include_HEADERS =3D tcstring.h tctypes.h tcdirent.h tcendian.h EXTRA_DIST =3D byteswap.yes byteswap.no snprintf.no \ strsep.yes strsep.no endian.little endian.big diff -Nru a/include/tcarg.h b/include/tcarg.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/tcarg.h 2005-03-24 17:51:51 +01:00 @@ -0,0 +1,120 @@ +/** + Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#ifndef TCARG_H +#define TCARG_H + +#include <stdarg.h> +#include <tcendian.h> + +#if defined __i386__ || defined __sparc__ || defined __ppc__ || \ + defined _POWER || defined __ia64__ + +typedef char *tcarg_sys_va_list_t; +#define tcarg_align sizeof(long) + +#define tcarg_sys_update(arg) do { \ + arg.list =3D arg.args; \ +} while(0) + +#define tcarg_sys_init(arg) tcarg_sys_update(arg) +#define tcarg_sys_free(arg) + +#define tcarg_sys_offset 0 + +#elif defined __alpha__ + +typedef struct { + char *base; + int offset; +} tcarg_sys_va_list_t; + +#define tcarg_align sizeof(long) +#define tcarg_sys_offset (6 * 8) + +#define tcarg_sys_init(arg) do { \ + tcarg_sys_update(arg); \ + arg.list.offset =3D 0; \ +} while(0) + +#define tcarg_sys_update(arg) do { \ + arg.list.base =3D arg.args + tcarg_sys_offset; \ +} while(0) + +#define tcarg_add_float(arg, type, v) do { \ + tcarg_doadd(arg, type, v, -(arg.pos < (6 * 8)? \ + 6 * 8 + 8: tcarg_size(type))); \ +} while(0) + +#define tcarg_sys_free(arg) + +#else +#error "Sorry, tcarg is not implemented on this architecture." +#endif + +typedef struct tcarg { + int pos; + tcarg_sys_va_list_t list; + char *args; +} tcarg_t; + +#define tcarg_doalign(s) (((s) + tcarg_align - 1) & ~(tcarg_align - 1)) +#define tcarg_size(t) tcarg_doalign(sizeof(t)) + +#if TCENDIAN =3D=3D TCENDIAN_LITTLE +#define tcarg_pad(t) 0 +#else +#define tcarg_pad(t) (tcarg_size(t) - sizeof(t)) +#endif + +#define tcarg_init(arg) do { \ + arg.args =3D malloc(tcarg_sys_offset); \ + arg.pos =3D 0; \ + tcarg_sys_init(arg); \ +} while(0) + +#define tcarg_doadd(arg, type, v, off) do { \ + arg.pos +=3D tcarg_size(type); \ + arg.args =3D realloc(arg.args, arg.pos + tcarg_sys_offset); \ + *(type *)(arg.args + arg.pos + tcarg_sys_offset + \ + off + tcarg_pad(type)) =3D (v); \ + tcarg_sys_update(arg); \ +} while(0) + +#define tcarg_add(arg, type, v) do { \ + tcarg_doadd(arg, type, v, -tcarg_size(type)); \ +} while(0) + +#ifndef tcarg_add_float +#define tcarg_add_float tcarg_add +#endif + +#define tcarg_va_list(arg) (*(va_list *) &arg.list) + +#define tcarg_free(arg) do { \ + tcarg_sys_free(arg); \ + free(arg.args); \ +} while(0) + +#endif |
From: <mr...@mr...> - 2005-03-24 01:32:43
|
# This is a BitKeeper generated diff -Nru style patch. # # doc/tree.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +5 -0 # = # doc/string.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +163 -0 # = # doc/refcount.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +44 -0 # = # doc/mempool.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +23 -0 # = # doc/list.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +122 -0 # = # doc/hash.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +121 -0 # = # doc/confsyn.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +71 -0 # = # doc/conffun.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +117 -0 # = # doc/confex.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +60 -0 # = # doc/attr.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +27 -0 # = # ChangeSet # 2005/03/24 02:32:11+01:00 mr...@fo... = # split texinfo into multiple files # = # doc/tree.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/tree.texi # = # doc/string.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/string.texi # = # doc/refcount.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/refcount.texi # = # doc/mempool.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/mempool.texi # = # doc/list.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/list.texi # = # doc/libtc.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +10 -758 # split texinfo into multiple files # = # doc/hash.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/hash.texi # = # doc/confsyn.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/confsyn.texi # = # doc/conffun.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/conffun.texi # = # doc/confex.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/confex.texi # = # doc/attr.texi # 2005/03/24 02:32:11+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/doc/attr.texi # = # doc/Makefile.am # 2005/03/24 02:32:10+01:00 mr...@fo... +2 -0 # split texinfo into multiple files # = diff -Nru a/doc/Makefile.am b/doc/Makefile.am --- a/doc/Makefile.am 2005-03-24 02:32:32 +01:00 +++ b/doc/Makefile.am 2005-03-24 02:32:32 +01:00 @@ -9,5 +9,7 @@ DVIPS =3D echo " PS $@" && dvips -q = info_TEXINFOS =3D libtc.texi +libtc_TEXINFOS =3D list.texi hash.texi tree.texi confsyn.texi conffun.texi \ + confex.texi string.texi refcount.texi attr.texi mempool.texi = .SILENT: diff -Nru a/doc/attr.texi b/doc/attr.texi --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/doc/attr.texi 2005-03-24 02:32:32 +01:00 @@ -0,0 +1,27 @@ +@node Attributes, Memory pools, Reference counting, Memory allocation +@section Attributes + +Blocks of memory allocated with the functions described in the previous +section can be assigned arbitrary attributes using the following +functions. They are declared in @file{tcalloc.h}. + +@deftypefun int tcattr_set (void *@var{p}, char * @var{name}, void * @var{val}, tcattr_ref_t @var{ref}, tcfree_fn @var{free}) +Set attribute @var{name} of @var{p} to @var{val}. If the attribute is +already set, it is replaced. All attributes are automatically deleted +when the memory is freed with @code{tcfree}. +@end deftypefun + +@deftypefun {void *} tcattr_get (void * @var{p}, char * @var{name}) +Get attribute @var{name} of @var{p}. If the attribute doesn't exist, +NULL is returned. +@end deftypefun + +@deftypefun int tcattr_getall (void * @var{p}, int @var{n}, tcattr_t * @var{attr}) +Get all attributes of @var{p} and store them in @var{attr}. Only the +@var{n} first attributes are returned. The number of attributes is +returned. +@end deftypefun + +@deftypefun int tcattr_del (void * @var{p}, char * @var{name}) +Delete attribute @var{name} from @var{p}. +@end deftypefun diff -Nru a/doc/confex.texi b/doc/confex.texi --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/doc/confex.texi 2005-03-24 02:32:33 +01:00 @@ -0,0 +1,60 @@ +@node Configuration file examples, , Configuration file functions, Configuration files +@section Configuration file examples + +@menu +* Sample configuration file:: +* Reading configuration file example:: +@end menu + +@node Sample configuration file, Reading configuration file example, Configuration file examples, Configuration file examples +@subsection Sample configuration file +@cindex configuration file, example of + +Here is a short example of a configuration file. + +@example +description "Meaning of life" +value 42 # ignore this +probability 1.46e-18 +mice @{ + names "Frodo" "Gandalf" + comment "Something is wrong" +@} +@end example + +@node Reading configuration file example, , Sample configuration file, Configuration file examples +@subsection Reading configuration file example + +This C program will read the file in the previous section and fetch some +of the values from it. + +@example +#include <stdio.h> +#include <tcconf.h> +#include <tcalloc.h> + +extern int +main(int argc, char **argv) +@{ + char *str; + int val; + tcconf_section_t *sec; + + if(!(sec =3D tcconf_load_file (NULL, "sample.conf")))@{ + fprintf(stderr, "Error loading file.\n"); + exit(1); + @} + + if(tcconf_getvalue(sec, "description", "%s", &str) =3D=3D 1)@{ + printf("Got description =3D \"%s\"\n", str); + free(str); + @} + + if(tcconf_getvalue(sec, "value", "%i", &val) =3D=3D 1) + printf("Got value =3D %i\n", val); + + tcfree(sec); + + return 0; +@} +@end example diff -Nru a/doc/conffun.texi b/doc/conffun.texi --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/doc/conffun.texi 2005-03-24 02:32:33 +01:00 @@ -0,0 +1,117 @@ +@node Configuration file functions, Configuration file examples, Configuration file syntax, Configuration files +@section Configuration file functions +@cindex configuration files, accessing + +This section describes the function used to manipulate configuration +files. They are all declared in @file{tcconf.h}. There is no explicit +function to free a conf section. Use @code{tcfree} for this. + +@deftypefun {tcconf_section_t *} tcconf_load (tcconf_section_t *@var{sec}, void *@var{data}, tcio_fn @var{fun}) +This function loads a configuration file from @var{data} using @var{fun} +to read bytes. If @var{sec} is not NULL, the new entries are merged +with the section referenced by @var{sec}. Otherwise a new section is +allocated. A pointer to the section containing the new entries is +returned, i.e. if @var{sec} is non-NULL it is also the return value. +@var{data} could be a @code{FILE *} and @var{fun} a pointer to +@code{fread}, though in this case the next function might be more +convenient. +@end deftypefun + +@deftypefun {tcconf_section_t *} tcconf_load_file (tcconf_section_t *@var{sec}, char *@var{file}) +This is the same as @code{tcconf_load}, except that the configuration is read +from the file named by @var{file}. +@end deftypefun + +@deftypefun {tcconf_section_t *} tcconf_load_string (tcconf_section_t *@var{sec}, char *@var{conf}, int @var{size}) +This is the same as @code{tcconf_load}, except that @var{size} bytes of +configuration is read from the memory location @var{conf}. If +@var{size} is less than 0, the @var{conf} is assumed to be +null-terminated. +@end deftypefun + +@deftypefun {tcconf_section_t *} tcconf_getsection (tcconf_section_t *@var{sec}, char *@var{name}) +This function returns the subsection @var{name} of section @var{sec}, or +NULL if the specified subsection does not exist. The returned section +must be freed with @code{tcfree}. +@end deftypefun + +@deftypefun int tcconf_getvalue (tcconf_section_t *@var{sec}, char *@var{name}, char *@var{format}, ...) +This function finds the entry with key @var{name} in section @var{sec}. +The values for this entry are stored in the locations addressed by the +arguments following @var{format}. @var{format} is a printf-style string +specifying the desired type of each value. If there is a mismatch +between @var{format} and the corresponding value in the configuration +entry, this and the remaining entries are ignored. The number of +matched entries is returned. If several entries with the same key +exist, the last one is used. + +The table below lists the recognized format specifiers and the +corresponding types. Note that it is not compatible with @code{printf}. + +@table @code +@item i +@itemx d +A pointer to an integer. Without modifiers, the target type is signed +32-bit. With the @samp{l} modifier, the target should be a 64-bit +integer type. With the @samp{u} modifier, the target is unsigned. Both +@samp{l} and @samp{u} may be used. + +@item f +A pointer to a @samp{float} or, with @samp{l} modifier, a @samp{double}. + +@item s +A pointer to @samp{char *}. The returned string is allocated with +@code{malloc}, and must be freed when no longer needed. +@end table + +All types can also have the @samp{z} modifier. When present, no value +will be written if the special token @samp{NULL} was used in the +configuration file. In all other cases the @samp{s} modifier is +ignored. +@end deftypefun + +@deftypefun int tcconf_nextvalue (tcconf_section_t *@var{sec}, char *@var{name}, void **@var{state}, char *@var{format}, ...) +This function is similar to @code{tcconf_getvalue}. Instead of returning +only the last entry, @code{tcconf_nextvalue} iterates over all entries +with key @var{name}. The current position is stored in @var{state}. +Initially, @var{state} must be NULL. When there are no more matching +entries, @var{state} is set to NULL. The remaining arguments and the +return value are the same as for @code{tcconf_getvalue}. +@end deftypefun + +@deftypefun int tcconf_nextvalue_g (tcconf_section_t *@var{sec}, char *@var{glob}, void **@var{state}, char **@var{name}, char *@var{format}, ...) +This function is similar to @code{tcconf_nextvalue}, with the difference +that all entries matching the shell glob @var{glob} are returned. Only +the final component of a path name may contain meta-characters. For +each matching entry, the actual name is returned in *@var{name}. +@end deftypefun + +@deftypefun {tcconf_section_t *} tcconf_nextsection (tcconf_section_t *@var{sec}, char *@var{name}, void **@var{state}) +This function returns, on successive calls, all subsections @var{name} +of @var{sec}. Both merged and non-merged sections are returned (but +don't use both). @var{state} is used as in @code{tcconf_nextvalue}. +The return value is a pointer to the selected subsection, or NULL if no +more subsections of that name exist. Each returned section must be freed +with @code{tcfree}. +@end deftypefun + +@deftypefun {tcconf_section_t *} tcconf_new (char *@var{name}) +This function allocates a new, empty section. The return value is a +pointer to the new section. This always succeeds, unless you are out of +memory. +@end deftypefun + +@deftypefun int tcconf_setvalue (tcconf_section_t *@var{sec}, char *@var{name}, char *@var{format}, ...) +This function adds a new entry with name @var{name} to section +@var{sec}. @var{format} is a text string describing the values of the +new entry. The remaining arguments are the actual values. The format +string uses the same specifiers as @code{tcconf_getvalue}. A new entry is +always added, even if there already exists one of the same name. To +replace an existing entry, it must first be removed with +@code{tcconf_clearvalue}. +@end deftypefun + +@deftypefun int tcconf_clearvalue (tcconf_section_t *@var{sec}, char *@var{name}) +This function removes all entries with name @var{name} in section +@var{sec}. Subsections of @var{sec} are not affected. +@end deftypefun diff -Nru a/doc/confsyn.texi b/doc/confsyn.texi --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/doc/confsyn.texi 2005-03-24 02:32:32 +01:00 @@ -0,0 +1,71 @@ +@node Configuration file syntax, Configuration file functions, Configuration files, Configuration files +@section Configuration file syntax +@cindex syntax, of configuration files +@cindex configuration file syntax + +A configuration file consists of multiple entries. Each entry begins +with a key followed by one or more values separated by any number of +spaces. Entries are separated by newline or semicolon. + +A value can be any of: +@itemize @bullet +@item +An integer. The prefixes 0x and 0 are treated the usual way indicating +hexadecimal and octal representation. The values are stored internally +using 64 bits. + +@item +A floating-point number in radix 10. The number is parsed with the +standard C library function @code{strtod}. +@ifinfo +@xref{Parsing of Floats,, strtod, libc}. +@end ifinfo + +@item +A text string enclosed in single or double quotes. When double quotes +are used, the string is subject to variable expansion and backslash +escaping by @code{tcstrexp}, using @samp{(} and @samp{)} as delimiters +and @samp{:} as flag separator. @xref{String utilities, tcstrexp}, for +detailed syntax. + +Briefly, any occurrence of @samp{$(foo)} is replaced with the value of +@samp{foo}. If @samp{foo} has several values, they are separated by a +single space. Non-string values are converted using @code{sprintf}. +Variable expansion is recursive, and loops are not detected, so beware. + +@item +A reference to another entry. Simply write the name of another entry, +relative to the section in which the reference is found. This is also +recursive. + +@item +The token @samp{NULL}. In this case 0 will be returned for the numeric +types, and NULL for strings, unless the @samp{z} modifier is specified +when accessing the value. +@end itemize + +Variable expansion and reference resolving is performed from +@code{tcconf_getvalue} and @code{tcconf_nextvalue}, so the order of +entries is not important from this aspect. + +An entry can also be a section grouping possibly related entries. A +section consists of the name of the section followed the section +contents within braces (@{@}). Sections can be nested to any reasonable +depth. If a section name occurs more than once, the contents of those +sections are merged. + +Sections can also be delimited by brackets ([]), in which case multiple +sections with the same name are not merged. If both types of section +with the same name exist, the results are possibly strange. Avoid this. + +If a section name is followed by a @samp{:} and another (relative) section +name, possibly repeated, the contents of these sections are virtually +included at the top of current section. This means that the @code{get} +and @code{next} functions will dynamically search these sections as +appropriate. Again, don't create loops. + +A comment is started by the @samp{#} character and lasts until the end +of line. + +There is an example of a configuration file elsewhere in this manual. +@xref{Sample configuration file}. diff -Nru a/doc/hash.texi b/doc/hash.texi --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/doc/hash.texi 2005-03-24 02:32:33 +01:00 @@ -0,0 +1,121 @@ +@node Hash table, Binary tree, Linked list, Data structures +@section Hash table +@cindex hash table +@cindex searching, in hash +@cindex replacing, in hash + +The libtc hash table maps arbitrary keys onto pointer values. The data +pointed to by these pointers is never examined directly. The hash table +uses separate chaining in case of collisions. This means that any hash +table can contain arbitrarily many entries, though performance decreases +for over-full tables. + +If the flag TCHASH_FROZEN is not set, adding or removing an element will +cause the size of the table to be adjusted to keep the load level within +reasonable bounds. + +The functions below are declared in @file{tchash.h} along with all types +and constants used by the hash table. As all libtc functions, the hash +table functions are thread safe. + +This manual describes version 1.1 of the API. The old API is selected +if the preprocessor macro @samp{TCHASH_OLDAPI} is defined before +including @file{tchash.h}. The old version will be removed in the +future. + +@deftypefun {tchash_table_t *} tchash_new (size_t @var{size}, int @var{lock}, uint32_t @var{flags}) +This function allocates and initializes a new hash table of initial size +@var{size} and with flags @var{flags}. If @var{lock} is nonzero, the +hash table will be protected against concurrent modification by multiple +threads. +@end deftypefun + +@deftypefun int tchash_find (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{ret}) +This function tries to locate the entry with key @var{key}. If it +exists, its data pointer is stored in *@var{ret}, if non-NULL, and 0 is +returned. If @var{key} does not exists in the table, 1 is returned. +The size of the key is @var{ks}. If @var{ks} is -1, the key is assumed +to be a null terminated string. +@end deftypefun + +@deftypefun int tchash_search (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{data}, void *@var{ret}) +This function is similar to @code{tchash_find}, the difference being +that if @var{key} is not found in the table it is added with data equal +to @var{data}, which is also stored in *@var{ret}. Return values are +the same as for @code{tchash_find}. The size of the key is @var{ks}. +If @var{ks} is -1, the key is assumed to be a null terminated string. +@end deftypefun + +@deftypefun int tchash_delete (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{ret}) +If @var{key} exists, it is deleted and the corresponding data is stored +in *@var{ret}. Otherwise nothing is done. The return value is 0 if +@var{key} was found, 1 otherwise. The size of the key is @var{ks}. If +@var{ks} is -1, the key is assumed to be a null terminated string. +@end deftypefun + +@deftypefun int tchash_replace (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{data}, void *@var{ret}) +This function adds @var{data} to the table @var{ht} with key @var{key}. +If @var{key} already exists, its data is replaced with @var{data}. The +return value is 0 if @var{key} already existed, 1 otherwise. The size +of the key is @var{ks}. If @var{ks} is -1, the key is assumed to be a +null terminated string. The old value, if any, is placed in *@var{ret}, +if @var{ret} is not NULL. +@end deftypefun + +@deftypefun int tchash_destroy (tchash_table_t *@var{ht}, tcfree_fn @var{hfree}) +This functions destroys the hash table @var{ht} and frees all resources +used by it. The function @var{hfree}, if non-NULL, is called for each +element in the table. +@end deftypefun + +@deftypefun int tchash_rehash (tchash_table_t *@var{ht}) +This function resizes the table @var{ht} to better fit the number of +elements currently in the table. This is done even if flag +TCHASH_FROZEN is set. +@end deftypefun + +@deftypefun {void **} tchash_keys (tchash_table_t *@var{ht}, int *@var{nk}, int @var{fast}) +This function returns an array of all keys in the table, in no +particular order. The number of keys is stored in *@var{nk}. If +@var{fast} is nonzero pointers to the actual keys are returned. +Otherwise, if @var{fast} is 0, copies of the keys are returned. In the +case of an empty table NULL is returned and *@var{nk} is set to 0. If +several threads are accessing the table, only the latter form should be +used since a key can be deleted at any time. For the same reason, it is +not certain that all returned keys will still be in the table when they +are used. +@end deftypefun + +@deftypefun int tchash_sethashfunction (tchash_table_t *@var{ht}, tchash_function_t @var{hf}) +This function sets the hash function used. The hash function is of type +@samp{tchash_function_t}, +@smallexample +u_int hash_func(void *@var{key}, size_t @var{size}); +@end smallexample +If @var{hf} is NULL, the default hash function is selected. The hash +function can only be changed when the table is empty. The return value +is 0 if the hash function was changed, nonzero if the table was not +empty. +@end deftypefun + +@deftypefun int tchash_setthresholds (tchash_table_t *@var{ht}, float @var{low}, float @var{high}) +This function sets the thresholds used for automatic rehashing of the +table. If either value is less than zero, the corresponding threshold +is left unchanged. On success, zero is returned. If the resulting +high threshold would be less than the low threshold, a nonzero value is +returned. +@end deftypefun + +@deftypefun int tchash_getflags (tchash_table_t *@var{ht}) +Get the current flags for hash table @var{ht}. +@end deftypefun + +@deftypefun int tchash_setflags (tchash_table_t *@var{ht}, int @var{flags}) +Set all flags of the table to @var{flags}. +@end deftypefun + +@deftypefun int tchash_setflag (tchash_table_t *@var{ht}, int @var{flags}) +@deftypefunx int tchash_clearflag (tchash_table_t *@var{ht}, int @var{flags}) +Set or clear all flags indicated in @var{flags}, leaving other flags +unchanged. +@end deftypefun diff -Nru a/doc/libtc.texi b/doc/libtc.texi --- a/doc/libtc.texi 2005-03-24 02:32:32 +01:00 +++ b/doc/libtc.texi 2005-03-24 02:32:32 +01:00 @@ -90,255 +90,9 @@ * Binary tree:: Fast access of ordered data @end menu = -@node Linked list, Hash table, Data structures, Data structures -@section Linked list -@cindex list -@cindex linked list -@cindex queue -@cindex stack -@cindex iterating, over list -@cindex searching, in list - -A linked list stores elements consisting of a single user-supplied -pointer. No meaning is attached to the target of the pointer. The -linked list has functions to add and remove elements at both ends of the -list. Thus, the list can be used as a stack or a queue. Other -functions find or remove elements anywhere in the list. Finally, -functions exist to iterate over all or selected elements in the list, -forwards or backwards. - -Linked lists support three locking levels: none, sloppy, and strict. -The first of these provides no locking. It is faster than the other -levels, but should be used only when it is known that no more than one -thread will be accessing the list at any time. With sloppy locking, the -list is locked for operations depending on the structure of the list -being constant, or when changes are made to the structure. Under strict -locking, all accesses to the list are serialized, even searches and -iterations. - -A list is represented by the opaque data type @code{tclist_t}. This and -all the following functions are declared in @file{tclist.h}. - -@deftypefun {tclist_t *} tclist_new (int @var{locking}) -This function allocates and initializes a new list. @var{locking} can -be one of @code{TC_LOCK_NONE}, @code{TC_LOCK_SLOPPY} or -@code{TC_LOCK_STRICT}. The meaning of these is described above. The -return value is a pointer to the new list, or @code{NULL} if something -went wrong. -@end deftypefun - -@deftypefun int tclist_destroy (tclist_t *@var{lst}, tcfree_fn @var{lfree}) -This functions destroys the list @var{lst} and frees any resources used -by it. The function @var{lfree}, if non-NULL, is called for each -element in the list. -@end deftypefun - -@deftypefun int tclist_push (tclist_t *@var{lst}, void *@var{p}) -@deftypefunx int tclist_unshift (tclist_t *@var{lst}, void *@var{p}) -These functions add the value @var{p} to the end or start of the list, -respectively. Their names match the equivalent functions in Perl. -@end deftypefun - -@deftypefun {void *} tclist_shift (tclist_t *@var{lst}) -@deftypefunx {void *} tclist_pop (tclist_t *@var{lst}) -These functions remove and return one element from the list @var{lst}. -@code{tclist_shift} removes at the start of the list and @code{tclist_pop} -at the end. These names were also taken from Perl. -@end deftypefun - -@deftypefun void tclist_remove (tclist_t *@var{lst}, tclist_item_t*@var{l}, tcfree_f @var{free}) -This function marks the list element @var{l} for removal as soon it can -safely be deleted from the list, i.e. when it is not in use by other -threads. The data in @var{l} is freed with @var{free}. -@end deftypefun - -@deftypefun int tclist_find (tclist_t *@var{lst}, void *@var{p}, void *@var{ret}, tccompare_fn @var{cmp}) -This function searches the list for the first element matching @var{p} -as determined by the comparison function @var{cmp}. @var{p} is always -passed as the first parameter to @var{cmp}, permitting dirty tricks. -If a match is found, it's data pointer is stored in the location pointed -to be @var{ret}, if @var{ret} is non-NULL, and 0 is returned. Otherwise -1 is returned and no other action is taken. -@end deftypefun - -@deftypefun int tclist_search (tclist_t *@var{lst}, void *@var{p}, void *@var{ret}, tccompare_fn @var{cmp}) -This function is similar to @code{tclist_find}. If no match is found the -value of @var{p} is appended to the list and also stored in *@var{ret}. -Return values are the same as for @code{tclist_find}. -@end deftypefun - -@deftypefun int tclist_delete (tclist_t *@var{lst}, void *@var{p}, tccompare_fn @var{cmp}, tcfree_fn fr) -This function searches the list like @code{tclist_find}. If a match is -found, that element is deleted from the list and the function @var{fr} -is called for the deleted elements data as soon as it is safe to do so. -Only the first match is deleted. If a match was found, 0 is returned. -Otherwise the return value is 1. -@end deftypefun - -@deftypefun int tclist_delete_matched (tclist_t *@var{lst}, void *@var{p}, tccompare_fn @var{cmp}, tcfree_fn @var{fr}) -This function searches the entire list for elements matching @var{p}. -All matches are deleted and @var{fr} is called for each deleted -element. The number of elements deleted is returned. -@end deftypefun - -@deftypefun {void *} tclist_next (tclist_t *@var{lst}, tclist_item_t **@var{l}) -@deftypefunx {void *} tclist_prev (tclist_t *@var{lst}, tclist_item_t **@var{l}) -These functions are used to iterate over the list @var{lst}. For each -call the position is advanced one step and the value pointed to by -@var{l} is updated. If @var{l} points to a value of NULL a new -iteration is started. When the end of the list is reached, NULL is -stored in *@var{l}. The return value from each call is the stored -pointer for the corresponding position in the list. @code{tclist_next} -iterates forwards and @code{tclist_prev} backwards. If an iteration is to -be aborted before the end of the list is reached @code{tclist_unlock} must -be called for the most recently returned element. -@end deftypefun - -@deftypefun {void *} tclist_next_matched (tclist_t *@var{lst}, tclist_item_t **@var{l}, void *@var{key}, tccompare_fn cmp) -@deftypefunx {void *} tclist_prev_matched (tclist_t *@var{lst}, tclist_item_t **@var{l}, void *@var{key}, tccompare_fn cmp) -These functions iterate over a list like @code{tclist_next} and -@code{tclist_prev}, except they only return elements matching @var{key} -using comparison function @var{cmp}. -@end deftypefun - -@deftypefun int tclist_unlock (tclist_t *@var{lst}, tclist_item_t *@var{l}) -This function unlocks an the element @var{l} in list @var{lst}. Since -this can trigger a pending removal of the element, @var{l} must not be -used after this call. -@end deftypefun - -@deftypefun {unsigned long} tclist_items (tclist_t *@var{lst}) -This function returns the number of elements in the list @var{lst}. The -count returned does not include elements marked as deleted but still in -use. -@end deftypefun - -@node Hash table, Binary tree, Linked list, Data structures -@section Hash table -@cindex hash table -@cindex searching, in hash -@cindex replacing, in hash - -The libtc hash table maps arbitrary keys onto pointer values. The data -pointed to by these pointers is never examined directly. The hash table -uses separate chaining in case of collisions. This means that any hash -table can contain arbitrarily many entries, though performance decreases -for over-full tables. - -If the flag TCHASH_FROZEN is not set, adding or removing an element will -cause the size of the table to be adjusted to keep the load level within -reasonable bounds. - -The functions below are declared in @file{tchash.h} along with all types -and constants used by the hash table. As all libtc functions, the hash -table functions are thread safe. - -This manual describes version 1.1 of the API. The old API is selected -if the preprocessor macro @samp{TCHASH_OLDAPI} is defined before -including @file{tchash.h}. The old version will be removed in the -future. - -@deftypefun {tchash_table_t *} tchash_new (size_t @var{size}, int @var{lock}, uint32_t @var{flags}) -This function allocates and initializes a new hash table of initial size -@var{size} and with flags @var{flags}. If @var{lock} is nonzero, the -hash table will be protected against concurrent modification by multiple -threads. -@end deftypefun - -@deftypefun int tchash_find (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{ret}) -This function tries to locate the entry with key @var{key}. If it -exists, its data pointer is stored in *@var{ret}, if non-NULL, and 0 is -returned. If @var{key} does not exists in the table, 1 is returned. -The size of the key is @var{ks}. If @var{ks} is -1, the key is assumed -to be a null terminated string. -@end deftypefun - -@deftypefun int tchash_search (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{data}, void *@var{ret}) -This function is similar to @code{tchash_find}, the difference being -that if @var{key} is not found in the table it is added with data equal -to @var{data}, which is also stored in *@var{ret}. Return values are -the same as for @code{tchash_find}. The size of the key is @var{ks}. -If @var{ks} is -1, the key is assumed to be a null terminated string. -@end deftypefun - -@deftypefun int tchash_delete (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{ret}) -If @var{key} exists, it is deleted and the corresponding data is stored -in *@var{ret}. Otherwise nothing is done. The return value is 0 if -@var{key} was found, 1 otherwise. The size of the key is @var{ks}. If -@var{ks} is -1, the key is assumed to be a null terminated string. -@end deftypefun - -@deftypefun int tchash_replace (tchash_table_t *@var{ht}, void *@var{key}, int @var{ks}, void *@var{data}, void *@var{ret}) -This function adds @var{data} to the table @var{ht} with key @var{key}. -If @var{key} already exists, its data is replaced with @var{data}. The -return value is 0 if @var{key} already existed, 1 otherwise. The size -of the key is @var{ks}. If @var{ks} is -1, the key is assumed to be a -null terminated string. The old value, if any, is placed in *@var{ret}, -if @var{ret} is not NULL. -@end deftypefun - -@deftypefun int tchash_destroy (tchash_table_t *@var{ht}, tcfree_fn @var{hfree}) -This functions destroys the hash table @var{ht} and frees all resources -used by it. The function @var{hfree}, if non-NULL, is called for each -element in the table. -@end deftypefun - -@deftypefun int tchash_rehash (tchash_table_t *@var{ht}) -This function resizes the table @var{ht} to better fit the number of -elements currently in the table. This is done even if flag -TCHASH_FROZEN is set. -@end deftypefun - -@deftypefun {void **} tchash_keys (tchash_table_t *@var{ht}, int *@var{nk}, int @var{fast}) -This function returns an array of all keys in the table, in no -particular order. The number of keys is stored in *@var{nk}. If -@var{fast} is nonzero pointers to the actual keys are returned. -Otherwise, if @var{fast} is 0, copies of the keys are returned. In the -case of an empty table NULL is returned and *@var{nk} is set to 0. If -several threads are accessing the table, only the latter form should be -used since a key can be deleted at any time. For the same reason, it is -not certain that all returned keys will still be in the table when they -are used. -@end deftypefun - -@deftypefun int tchash_sethashfunction (tchash_table_t *@var{ht}, tchash_function_t @var{hf}) -This function sets the hash function used. The hash function is of type -@samp{tchash_function_t}, -@smallexample -u_int hash_func(void *@var{key}, size_t @var{size}); -@end smallexample -If @var{hf} is NULL, the default hash function is selected. The hash -function can only be changed when the table is empty. The return value -is 0 if the hash function was changed, nonzero if the table was not -empty. -@end deftypefun - -@deftypefun int tchash_setthresholds (tchash_table_t *@var{ht}, float @var{low}, float @var{high}) -This function sets the thresholds used for automatic rehashing of the -table. If either value is less than zero, the corresponding threshold -is left unchanged. On success, zero is returned. If the resulting -high threshold would be less than the low threshold, a nonzero value is -returned. -@end deftypefun - -@deftypefun int tchash_getflags (tchash_table_t *@var{ht}) -Get the current flags for hash table @var{ht}. -@end deftypefun - -@deftypefun int tchash_setflags (tchash_table_t *@var{ht}, int @var{flags}) -Set all flags of the table to @var{flags}. -@end deftypefun - -@deftypefun int tchash_setflag (tchash_table_t *@var{ht}, int @var{flags}) -@deftypefunx int tchash_clearflag (tchash_table_t *@var{ht}, int @var{flags}) -Set or clear all flags indicated in @var{flags}, leaving other flags -unchanged. -@end deftypefun - -@node Binary tree, , Hash table, Data structures -@section Binary tree - -To be completed. +@include list.texi +@include hash.texi +@include tree.texi = @node Configuration files, String utilities, Data structures, Top @chapter Configuration files @@ -355,420 +109,11 @@ * Configuration file examples:: @end menu = -@node Configuration file syntax, Configuration file functions, Configuration files, Configuration files -@section Configuration file syntax -@cindex syntax, of configuration files -@cindex configuration file syntax - -A configuration file consists of multiple entries. Each entry begins -with a key followed by one or more values separated by any number of -spaces. Entries are separated by newline or semicolon. - -A value can be any of: -@itemize @bullet -@item -An integer. The prefixes 0x and 0 are treated the usual way indicating -hexadecimal and octal representation. The values are stored internally -using 64 bits. - -@item -A floating-point number in radix 10. The number is parsed with the -standard C library function @code{strtod}. -@ifinfo -@xref{Parsing of Floats,, strtod, libc}. -@end ifinfo - -@item -A text string enclosed in single or double quotes. When double quotes -are used, the string is subject to variable expansion and backslash -escaping by @code{tcstrexp}, using @samp{(} and @samp{)} as delimiters -and @samp{:} as flag separator. @xref{String utilities, tcstrexp}, for -detailed syntax. - -Briefly, any occurrence of @samp{$(foo)} is replaced with the value of -@samp{foo}. If @samp{foo} has several values, they are separated by a -single space. Non-string values are converted using @code{sprintf}. -Variable expansion is recursive, and loops are not detected, so beware. - -@item -A reference to another entry. Simply write the name of another entry, -relative to the section in which the reference is found. This is also -recursive. - -@item -The token @samp{NULL}. In this case 0 will be returned for the numeric -types, and NULL for strings, unless the @samp{z} modifier is specified -when accessing the value. -@end itemize - -Variable expansion and reference resolving is performed from -@code{tcconf_getvalue} and @code{tcconf_nextvalue}, so the order of -entries is not important from this aspect. - -An entry can also be a section grouping possibly related entries. A -section consists of the name of the section followed the section -contents within braces (@{@}). Sections can be nested to any reasonable -depth. If a section name occurs more than once, the contents of those -sections are merged. - -Sections can also be delimited by brackets ([]), in which case multiple -sections with the same name are not merged. If both types of section -with the same name exist, the results are possibly strange. Avoid this. - -If a section name is followed by a @samp{:} and another (relative) section -name, possibly repeated, the contents of these sections are virtually -included at the top of current section. This means that the @code{get} -and @code{next} functions will dynamically search these sections as -appropriate. Again, don't create loops. - -A comment is started by the @samp{#} character and lasts until the end -of line. - -There is an example of a configuration file elsewhere in this manual. -@xref{Sample configuration file}. - -@node Configuration file functions, Configuration file examples, Configuration file syntax, Configuration files -@section Configuration file functions -@cindex configuration files, accessing - -This section describes the function used to manipulate configuration -files. They are all declared in @file{tcconf.h}. There is no explicit -function to free a conf section. Use @code{tcfree} for this. - -@deftypefun {tcconf_section_t *} tcconf_load (tcconf_section_t *@var{sec}, void *@var{data}, tcio_fn @var{fun}) -This function loads a configuration file from @var{data} using @var{fun} -to read bytes. If @var{sec} is not NULL, the new entries are merged -with the section referenced by @var{sec}. Otherwise a new section is -allocated. A pointer to the section containing the new entries is -returned, i.e. if @var{sec} is non-NULL it is also the return value. -@var{data} could be a @code{FILE *} and @var{fun} a pointer to -@code{fread}, though in this case the next function might be more -convenient. -@end deftypefun - -@deftypefun {tcconf_section_t *} tcconf_load_file (tcconf_section_t *@var{sec}, char *@var{file}) -This is the same as @code{tcconf_load}, except that the configuration is read -from the file named by @var{file}. -@end deftypefun - -@deftypefun {tcconf_section_t *} tcconf_load_string (tcconf_section_t *@var{sec}, char *@var{conf}, int @var{size}) -This is the same as @code{tcconf_load}, except that @var{size} bytes of -configuration is read from the memory location @var{conf}. If -@var{size} is less than 0, the @var{conf} is assumed to be -null-terminated. -@end deftypefun - -@deftypefun {tcconf_section_t *} tcconf_getsection (tcconf_section_t *@var{sec}, char *@var{name}) -This function returns the subsection @var{name} of section @var{sec}, or -NULL if the specified subsection does not exist. The returned section -must be freed with @code{tcfree}. -@end deftypefun - -@deftypefun int tcconf_getvalue (tcconf_section_t *@var{sec}, char *@var{name}, char *@var{format}, ...) -This function finds the entry with key @var{name} in section @var{sec}. -The values for this entry are stored in the locations addressed by the -arguments following @var{format}. @var{format} is a printf-style string -specifying the desired type of each value. If there is a mismatch -between @var{format} and the corresponding value in the configuration -entry, this and the remaining entries are ignored. The number of -matched entries is returned. If several entries with the same key -exist, the last one is used. - -The table below lists the recognized format specifiers and the -corresponding types. Note that it is not compatible with @code{printf}. - -@table @code -@item i -@itemx d -A pointer to an integer. Without modifiers, the target type is signed -32-bit. With the @samp{l} modifier, the target should be a 64-bit -integer type. With the @samp{u} modifier, the target is unsigned. Both -@samp{l} and @samp{u} may be used. - -@item f -A pointer to a @samp{float} or, with @samp{l} modifier, a @samp{double}. - -@item s -A pointer to @samp{char *}. The returned string is allocated with -@code{malloc}, and must be freed when no longer needed. -@end table - -All types can also have the @samp{z} modifier. When present, no value -will be written if the special token @samp{NULL} was used in the -configuration file. In all other cases the @samp{s} modifier is -ignored. -@end deftypefun - -@deftypefun int tcconf_nextvalue (tcconf_section_t *@var{sec}, char *@var{name}, void **@var{state}, char *@var{format}, ...) -This function is similar to @code{tcconf_getvalue}. Instead of returning -only the last entry, @code{tcconf_nextvalue} iterates over all entries -with key @var{name}. The current position is stored in @var{state}. -Initially, @var{state} must be NULL. When there are no more matching -entries, @var{state} is set to NULL. The remaining arguments and the -return value are the same as for @code{tcconf_getvalue}. -@end deftypefun - -@deftypefun int tcconf_nextvalue_g (tcconf_section_t *@var{sec}, char *@var{glob}, void **@var{state}, char **@var{name}, char *@var{format}, ...) -This function is similar to @code{tcconf_nextvalue}, with the difference -that all entries matching the shell glob @var{glob} are returned. Only -the final component of a path name may contain meta-characters. For -each matching entry, the actual name is returned in *@var{name}. -@end deftypefun - -@deftypefun {tcconf_section_t *} tcconf_nextsection (tcconf_section_t *@var{sec}, char *@var{name}, void **@var{state}) -This function returns, on successive calls, all subsections @var{name} -of @var{sec}. Both merged and non-merged sections are returned (but -don't use both). @var{state} is used as in @code{tcconf_nextvalue}. -The return value is a pointer to the selected subsection, or NULL if no -more subsections of that name exist. Each returned section must be freed -with @code{tcfree}. -@end deftypefun - -@deftypefun {tcconf_section_t *} tcconf_new (char *@var{name}) -This function allocates a new, empty section. The return value is a -pointer to the new section. This always succeeds, unless you are out of -memory. -@end deftypefun - -@deftypefun int tcconf_setvalue (tcconf_section_t *@var{sec}, char *@var{name}, char *@var{format}, ...) -This function adds a new entry with name @var{name} to section -@var{sec}. @var{format} is a text string describing the values of the -new entry. The remaining arguments are the actual values. The format -string uses the same specifiers as @code{tcconf_getvalue}. A new entry is -always added, even if there already exists one of the same name. To -replace an existing entry, it must first be removed with -@code{tcconf_clearvalue}. -@end deftypefun - -@deftypefun int tcconf_clearvalue (tcconf_section_t *@var{sec}, char *@var{name}) -This function removes all entries with name @var{name} in section -@var{sec}. Subsections of @var{sec} are not affected. -@end deftypefun - -@node Configuration file examples, , Configuration file functions, Configuration files -@section Configuration file examples - -@menu -* Sample configuration file:: -* Reading configuration file example:: -@end menu - -@node Sample configuration file, Reading configuration file example, Configuration file examples, Configuration file examples -@subsection Sample configuration file -@cindex configuration file, example of - -Here is a short example of a configuration file. - -@example -description "Meaning of life" -value 42 # ignore this -probability 1.46e-18 -mice @{ - names "Frodo" "Gandalf" - comment "Something is wrong" -@} -@end example - -@node Reading configuration file example, , Sample configuration file, Configuration file examples -@subsection Reading configuration file example - -This C program will read the file in the previous section and fetch some -of the values from it. - -@example -#include <stdio.h> -#include <tcconf.h> -#include <tcalloc.h> - -extern int -main(int argc, char **argv) -@{ - char *str; - int val; - tcconf_section_t *sec; - - if(!(sec =3D tcconf_load_file (NULL, "sample.conf")))@{ - fprintf(stderr, "Error loading file.\n"); - exit(1); - @} - - if(tcconf_getvalue(sec, "description", "%s", &str) =3D=3D 1)@{ - printf("Got description =3D \"%s\"\n", str); - free(str); - @} - - if(tcconf_getvalue(sec, "value", "%i", &val) =3D=3D 1) - printf("Got value =3D %i\n", val); - - tcfree(sec); - - return 0; -@} -@end example - -@node String utilities, Memory allocation, Configuration files, Top -@chapter String utilities -@cindex backslash escape -@cindex escape, backslash -@cindex backslash substitution -@cindex substitution, backslash -@cindex variable expansion -@cindex variable substitution -@cindex expansion, variable -@cindex substitution, variable - -Libtc provides some string manipulation functions not present in the -standard C library. They are declared in @file{tcstring.h}. - -@deftypefun int tcstresc (char *@var{dst}, const char *@var{src}) -This function copies the null-terminated string @var{src} to @var{dst}, -performing backslash escape substitution. The resulting string is never -longer than the source string, @var{dst} need not have more space than -@var{src}. In fact, they can be equal. The return value is the length -of the resulting string. - -The following sequences are substituted. They are mostly the same as -the usual C escape sequences. - -@table @code -@item \t -tab -@item \n -newline -@item \r -return -@item \f -form feed -@item \b -backspace -@item \a -alarm -@item \e -escape -@item \<digits> -octal char (\033 =3D> escape) -@item \x<hex digits> -hex char (\x1b =3D> escape) -@item \c<char> -control char (\c[ =3D> escape) -@end table - -A backslash followed by any other character is replaced by that -character. -@end deftypefun +@include confsyn.texi +@include conffun.texi +@include confex.texi = -@deftypefun {char *} tcstrexp (const char *@var{src}, const char *@var{sd}, const char *@var{ed}, char @var{fs}, char *(*@var{lookup})(char *, void *), void *@var{ld}, int @var{flags}) -This function performs shell-like variable substitution and, optionally, -backslash escaping on the string @var{src}. A variable consists of a -@samp{$}, followed by the variable name between one character from -@var{sd} and the corresponding character from @var{ed}. If @var{fs} is -nonzero, it is the flag separator, meaning that if this character is -present between the delimiters, the variable name ends there, and the -remainder is processed as flags modifying the substitution, see below. -Each variable name is passed to the function @var{lookup}, along with -@var{ld}. This function should return the value of the variable, or -NULL if it is undefined. - -If a flag separator is specified in @var{fs}, and it is present between -the delimiters, the characters following it will modify the -substitution. The following character sequences are recognized in the -flags field: - -@table @code -@item u -The value is converted to uppercase. -@item l -The value is converted to lowercase. -@item sOFFSET:LENGTH -A substring from the value of length LENGTH starting at offset OFFSET is -substituted. If either of OFFSET or LENGTH is negative, it is counted -from the end of the string. If LENGTH is omitted, the rest of the -string is used. The @samp{s} is only necessary if OFFSET is negative, -to distinguish the - sign from the @samp{-} flag described below. -@item r/PATTERN/REPLACEMENT/ -Any match of the regular expression PATTERN in the value is replaced -with REPLACEMENT, as by @code{tcregsub}. The delimiter may be any -character not present in the pattern or the replacement. If the -delimiter is @samp{/}, the @samp{r} may be omitted. If this is the last -thing in the flags section, the trailing delimiter may also be omitted. -@item - -If the variable is undefined, the expansion of the remainder of the -flags section is substituted. Any previous flags are applied to the -final result. -@item + -If the variable is defined, the expansion of the remainder of the flags -section is substituted, any previous flags being applied to the result. -@end table - -These operations are performed in the following order: -@enumerate -@item -substring -@item -regex substitution -@item -case change -@end enumerate - -The argument @var{flags} should be a bitwise or combination of any of -the following flags: - -@table @code -@item TCSTREXP_ESCAPE -Perform backslash escape substitution as by @code{tcstresc}. This can -be used to inhibit variable expansion by escaping the @samp{$}. -@item TCSTREXP_FREE -Indicates that the strings returned by @var{lookup} must be freed with -@code{free}. If this flag is not set, nothing will be done to free the -variable values. -@item TCSTREXP_KEEPUNDEF -If this flag is set, any references to undefined variables will remain -in the output string. -@end table - -The returned string is allocated with @code{malloc}, and must be freed -when no longer needed. - -Some examples might better illustrate the use of this function. -Assuming @code{tcstrexp} is called as -@example -tcstrexp(string, "(", ")", ':', lookup, data, TCSTREXP_ESCAPE) -@end example -the following substitutions will be performed. - -@table @code -@item $(foo) -The value of @samp{foo}, if set, otherwise nothing. -@item $(foo:u) -The value of @samp{foo}, converted to uppercase. -@item $(foo:-bar) -The value of @samp{foo}, if set, otherwise the string @samp{bar}. -@item $(foo:-$(bar)) -The value of @samp{foo}, if set, otherwise the value of @samp{bar}. -@item $(foo:+bar) -If @samp{foo} is set, the string @samp{bar} is substituted, otherwise -nothing. -@item $(foo:0:5) -The first five characters of @samp{foo}. -@item $(foo:0:-5) -All but the last five characters of @samp{foo}. -@item $(foo:0:3-$(bar:s-5)) -The first 3 characters of @samp{foo}, if defined. Otherwise the first -three characters of the last five characters of @samp{bar} are used. -@end table -@end deftypefun - -@deftypefun {char *} tcregsub (const char *@var{str}, const char *@var{pat}, const char *@var{sub}, int @var{flags}) -This function matches the regular expression @var{pat} against the -string @var{str}. Each match is replaced by @var{sub}. In the -replacement, @samp{$@{1@}} is replaced with the text matched by the -first subexpression, and so on. The result is returned as a malloc()ed -string. If there is an error in the regular expression, NULL is -returned. - -The syntax of the regular expression is whatever the system -@code{regexec} uses, hopefully extended POSIX regular expressions. -@end deftypefun +@include string.texi = @node Memory allocation, Portability, String utilities, Top @chapter Memory allocation @@ -781,102 +126,9 @@ * Memory pools:: Efficient allocation of equal-sized blocks @end menu = -@node Reference counting, Attributes, Memory allocation, Memory allocation -@section Reference counting -@cindex reference counting - -When using dynamically allocated memory, it is important not to free any -blocks while they are still used somewhere. It is equally important to -free the blocks when they are no longer used. Keeping track of when it -is safe to free some memory can be difficult, particularly in -multi-threaded applications. Libtc aids in this task by providing a set -of functions for allocating memory blocks with attached reference -counters, and functions for manipulating the counters. Whenever a -counter reaches zero, the block is freed. - -All the functions below are declared in @file{tcalloc.h}. - -@deftypefun {void *} tcalloc (size_t @var{size}) -Allocate a reference counted block of size @var{size}. Returns a -pointer to the allocated block, or NULL if the allocation failed. -@end deftypefun - -@deftypefun {void *} tcallocz (size_t @var{size}) -Like @code{tcalloc}, but also fill the block with zeros. -@end deftypefun - -@deftypefun {void *} tcref (void * @var{p}) -Increase the reference counter for the block at address @var{p}. Return -@var{p}. -@end deftypefun - -@deftypefun void tcfree (void * @var{p}) -Decrease the reference counter for the block at address @var{p}. If -the counter reaches zero, the block is freed. -@end deftypefun - -@deftypefun {void *} tcallocd (size_t @var{size}, void (*@var{ref})(void *), void (*@var{free})) -Allocate a block like @code{tcalloc}. A pointer to the block is passed -to @var{ref} when @code{tcref} is called, and @var{free} just before the -block is freed. This is useful to ensure that complex data structures -are completely freed. -@end deftypefun - -@deftypefun {void *} tcallocdz (size_t @var{size}, void (*@var{ref})(void *), void (*@var{free})) -Same as @code{tcallocd}, but also fill the block with zeros. -@end deftypefun - -@node Attributes, Memory pools, Reference counting, Memory allocation -@section Attributes - -Blocks of memory allocated with the functions described in the previous -section can be assigned arbitrary attributes using the following -functions. They are declared in @file{tcalloc.h}. - -@deftypefun int tcattr_set (void *@var{p}, char * @var{name}, void * @var{val}, tcattr_ref_t @var{ref}, tcfree_fn @var{free}) -Set attribute @var{name} of @var{p} to @var{val}. If the attribute is -already set, it is replaced. All attributes are automatically deleted -when the memory is freed with @code{tcfree}. -@end deftypefun - -@deftypefun {void *} tcattr_get (void * @var{p}, char * @var{name}) -Get attribute @var{name} of @var{p}. If the attribute doesn't exist, -NULL is returned. -@end deftypefun - -@deftypefun int tcattr_getall (void * @var{p}, int @var{n}, tcattr_t * @var{attr}) -Get all attributes of @var{p} and store them in @var{attr}. Only the -@var{n} first attributes are returned. The number of attributes is -returned. -@end deftypefun - -@deftypefun int tcattr_del (void * @var{p}, char * @var{name}) -Delete attribute @var{name} from @var{p}. -@end deftypefun - -@node Memory pools, , Attributes, Memory allocation -@section Memory pools - -This section describes functions for allocating a large number of equal -sized blocks more efficiently, both in speed and overhead, than the -system malloc. They are declared in @file{tcmempool.h}. - -@deftypefun {tcmempool_t *} tcmempool_new (size_t @var{size}, int @var{lock}) -Create a new pool with chunks of size @var{size}. If @var{lock} is -nonzero, the pool is locked during access. If @var{size} is larger than -the system page size, NULL is returned. In this case, normal malloc is -good enough. When the pool is no longer needed, it can be freed with -@code{tcfree}. Don't do this if there are still chunks allocated from -the pool. -@end deftypefun - -@deftypefun {void *} tcmempool_get (tcmempool_t * @var{mp}) -Get a chunk from pool @var{mp}. -@end deftypefun - -@deftypefun void tcmempool_free (void * @var{p}) -Free a chunk obtained with @code{tcmempool_get}. -@end deftypefun +@include refcount.texi +@include attr.texi +@include mempool.texi = @node Portability, Concept index, Memory allocation, Top @chapter Portability diff -Nru a/doc/list.texi b/doc/list.texi --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/doc/list.texi 2005-03-24 02:32:32 +01:00 @@ -0,0 +1,122 @@ +@node Linked list, Hash table, Data structures, Data structures +@section Linked list +@cindex list +@cindex linked list +@cindex queue +@cindex stack +@cindex iterating, over list +@cindex searching, in list + +A linked list stores elements consisting of a single user-supplied +pointer. No meaning is attached to the target of the pointer. The +linked list has functions to add and remove elements at both ends of the +list. Thus, the list can be used as a stack or a queue. Other +functions find or remove elements anywhere in the list. Finally, +functions exist to iterate over all or selected elements in the list, +forwards or backwards. + +Linked lists support three locking levels: none, sloppy, and strict. +The first of these provides no locking. It is faster than the other +levels, but should be used only when it is known that no more than one +thread will be accessing the list at any time. With sloppy locking, the +list is locked for operations depending on the structure of the list +being constant, or when changes are made to the structure. Under strict +locking, all accesses to the list are serialized, even searches and +iterations. + +A list is represented by the opaque data type @code{tclist_t}. This and +all the following functions are declared in @file{tclist.h}. + +@deftypefun {tclist_t *} tclist_new (int @var{locking}) +This function allocates and initializes a new list. @var{locking} can +be one of @code{TC_LOCK_NONE}, @code{TC_LOCK_SLOPPY} or +@code{TC_LOCK_STRICT}. The meaning of these is described above. The +return value is a pointer to the new list, or @code{NULL} if something +went wrong. +@end deftypefun + +@deftypefun int tclist_destroy (tclist_t *@var{lst}, tcfree_fn @var{lfree}) +This functions destroys the list @var{lst} and frees any resources used +by it. The function @var{lfree}, if non-NULL, is called for each +element in the list. +@end deftypefun + +@deftypefun int tclist_push (tclist_t *@var{lst}, void *@var{p}) +@deftypefunx int tclist_unshift (tclist_t *@var{lst}, void *@var{p}) +These functions add the value @var{p} to the end or start of the list, +respectively. Their names match the equivalent functions in Perl. +@end deftypefun + +@deftypefun {void *} tclist_shift (tclist_t *@var{lst}) +@deftypefunx {void *} tclist_pop (tclist_t *@var{lst}) +These functions remove and return one element from the list @var{lst}. +@code{tclist_shift} removes at the start of the list and @code{tclist_pop} +at the end. These names were also taken from Perl. +@end deftypefun + +@deftypefun void tclist_remove (tclist_t *@var{lst}, tclist_item_t*@var{l}, tcfree_f @var{free}) +This function marks the list element @var{l} for removal as soon it can +safely be deleted from the list, i.e. when it is not in use by other +threads. The data in @var{l} is freed with @var{free}. +@end deftypefun + +@deftypefun int tclist_find (tclist_t *@var{lst}, void *@var{p}, void *@var{ret}, tccompare_fn @var{cmp}) +This function searches the list for the first element matching @var{p} +as determined by the comparison function @var{cmp}. @var{p} is always +passed as the first parameter to @var{cmp}, permitting dirty tricks. +If a match is found, it's data pointer is stored in the location pointed +to be @var{ret}, if @var{ret} is non-NULL, and 0 is returned. Otherwise +1 is returned and no other action is taken. +@end deftypefun + +@deftypefun int tclist_search (tclist_t *@var{lst}, void *@var{p}, void *@var{ret}, tccompare_fn @var{cmp}) +This function is similar to @code{tclist_find}. If no match is found the +value of @var{p} is appended to the list and also stored in *@var{ret}. +Return values are the same as for @code{tclist_find}. +@end deftypefun + +@deftypefun int tclist_delete (tclist_t *@var{lst}, void *@var{p}, tccompare_fn @var{cmp}, tcfree_fn fr) +This function searches the list like @code{tclist_find}. If a match is +found, that element is deleted from the list and the function @var{fr} +is called for the deleted elements data as soon as it is safe to do so. +Only the first match is deleted. If a match was found, 0 is returned. +Otherwise the return value is 1. +@end deftypefun + +@deftypefun int tclist_delete_matched (tclist_t *@var{lst}, void *@var{p}, tccompare_fn @var{cmp}, tcfree_fn @var{fr}) +This function searches the entire list for elements matching @var{p}. +All matches are deleted and @var{fr} is called for each deleted +element. The number of elements deleted is returned. +@end deftypefun + +@deftypefun {void *} tclist_next (tclist_t *@var{lst}, tclist_item_t **@var{l}) +@deftypefunx {void *} tclist_prev (tclist_t *@var{lst}, tclist_item_t **@var{l}) +These functions are used to iterate over the list @var{lst}. For each +call the position is advanced one step and the value pointed to by +@var{l} is updated. If @var{l} points to a value of NULL a new +iteration is started. When the end of the list is reached, NULL is +stored in *@var{l}. The return value from each call is the stored +pointer for the corresponding position in the list. @code{tclist_next} +iterates forwards and @code{tclist_prev} backwards. If an iteration is to +be aborted before the end of the list is reached @code{tclist_unlock} must +be c... [truncated message content] |
From: <mr...@mr...> - 2005-03-06 15:52:04
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/06 16:51:33+01:00 mr...@fo... = # more robust tcreduce() # = # src/math.c # 2005/03/06 16:51:33+01:00 mr...@fo... +5 -2 # nothing to do if numerator or denominator are zero # = diff -Nru a/src/math.c b/src/math.c --- a/src/math.c 2005-03-06 16:51:45 +01:00 +++ b/src/math.c 2005-03-06 16:51:45 +01:00 @@ -1,5 +1,5 @@ /** - Copyright (C) 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2003-2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -30,12 +30,15 @@ int n =3D f->num; int d =3D f->den; = + if(!n || !d) + return; + while(n){ int t =3D n; n =3D d % n; d =3D t; } - = + f->num /=3D d; f->den /=3D d; } |
From: <mr...@mr...> - 2004-11-22 17:04:17
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/22 18:03:45+01:00 mr...@fo... = # don't crash in tclist_head/tail on empty list # = # src/list.c # 2004/11/22 18:03:44+01:00 mr...@fo... +6 -4 # check that list is non-empty in tclist_head/tail # = diff -Nru a/src/list.c b/src/list.c --- a/src/list.c 2004-11-22 18:04:06 +01:00 +++ b/src/list.c 2004-11-22 18:04:06 +01:00 @@ -442,9 +442,10 @@ extern void * tclist_head(tclist_t *lst) { - void *h; + void *h =3D NULL; lock_list(lst); - h =3D lst->start->data; + if(lst->start) + h =3D lst->start->data; unlock_list(lst); return h; } @@ -452,9 +453,10 @@ extern void * tclist_tail(tclist_t *lst) { - void *t; + void *t =3D NULL; lock_list(lst); - t =3D lst->end->data; + if(lst->end) + t =3D lst->end->data; unlock_list(lst); return t; } |
From: <mr...@mr...> - 2004-11-15 10:36:41
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/15 11:36:11+01:00 mr...@fo... = # add filters # = # src/filter.c # 2004/11/15 11:36:10+01:00 mr...@fo... +196 -0 # = # include/tcfilter.h # 2004/11/15 11:36:10+01:00 mr...@fo... +65 -0 # = # src/filter.c # 2004/11/15 11:36:10+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/src/filter.c # = # src/Makefile.am # 2004/11/15 11:36:10+01:00 mr...@fo... +1 -1 # add filter.c # = # include/tcfilter.h # 2004/11/15 11:36:10+01:00 mr...@fo... +0 -0 # BitKeeper file /home/mru/src/libtc/include/tcfilter.h # = # include/Makefile.am # 2004/11/15 11:36:10+01:00 mr...@fo... +1 -1 # add tcfilter.h # = diff -Nru a/include/Makefile.am b/include/Makefile.am --- a/include/Makefile.am 2004-11-15 11:36:23 +01:00 +++ b/include/Makefile.am 2004-11-15 11:36:23 +01:00 @@ -1,6 +1,6 @@ include_HEADERS =3D tc.h tclist.h tchash.h tcnet.h tctime.h tcconf.h \ tctree.h tcalloc.h tcprioq.h tcmath.h tcmempool.h \ - tcbyteswap.h + tcbyteswap.h tcfilter.h nodist_include_HEADERS =3D tcstring.h tctypes.h tcdirent.h tcendian.h EXTRA_DIST =3D byteswap.yes byteswap.no snprintf.no \ strsep.yes strsep.no endian.little endian.big diff -Nru a/include/tcfilter.h b/include/tcfilter.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/tcfilter.h 2004-11-15 11:36:23 +01:00 @@ -0,0 +1,65 @@ +/** + Copyright (C) 2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#ifndef TCFILTER_H +#define TCFILTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct tcfilter tcfilter_t; +typedef struct tcfilter_matcher tcfilter_matcher_t; +typedef struct tcfilter_chain tcfilter_chain_t; + +typedef struct tcfilter_packet { + void *data; + void *matchdata; +} tcfilter_packet_t; + +struct tcfilter_matcher { + char *name; + int (*match)(tcfilter_matcher_t *, tcfilter_packet_t *); + void *private; +}; + +#define TCFILTER_REJECT 0 +#define TCFILTER_ACCEPT 1 +#define TCFILTER_MATCH_MASK 7 + +#define TCFILTER_CONTINUE 0 +#define TCFILTER_STOP 8 + +extern tcfilter_t *tcfilter_new(void); +extern tcfilter_chain_t *tcfilter_chain_new(tcfilter_t *, char *name); +extern int tcfilter_chain_append(tcfilter_chain_t *, tcfilter_matcher_t *, + char *target); + +extern int tcfilter_apply(tcfilter_t *, void *); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am 2004-11-15 11:36:23 +01:00 +++ b/src/Makefile.am 2004-11-15 11:36:23 +01:00 @@ -27,7 +27,7 @@ lib_LTLIBRARIES =3D libtc.la libtc_la_SOURCES =3D list.c hash.c gethostaddr.c gethostname.c pathfind.c \ strtotime.c conf.c conf-parse.l tree.c alloc.c \ - prioq.c math.c string.c regex.c mkpath.c mpool.c + prioq.c math.c string.c regex.c mkpath.c mpool.c filter.c libtc_la_LDFLAGS =3D -version-info 16:0:0 libtc_la_LIBADD =3D @LTLIBOBJS@ INCLUDES =3D -I$(top_srcdir)/include -I$(top_builddir)/include diff -Nru a/src/filter.c b/src/filter.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/src/filter.c 2004-11-15 11:36:23 +01:00 @@ -0,0 +1,196 @@ +/** + Copyright (C) 2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +**/ + +#include <stdlib.h> +#include <string.h> +#include <tcfilter.h> +#include <tclist.h> +#include <tchash.h> +#include <tcalloc.h> +#include <errno.h> + +#define TCFILTER_TARGET_ACCEPT ((void *)1) +#define TCFILTER_TARGET_REJECT ((void *)2) + +struct tcfilter { + tchash_table_t *chains; + tcfilter_chain_t *input; +}; + +struct tcfilter_chain { + char *name; + tclist_t *rules; + tcfilter_t *filter; +}; + +typedef struct tcfilter_rule { + tcfilter_matcher_t *matcher; + tcfilter_chain_t *target; +} tcfilter_rule_t; + +static void +tcfilter_free(void *p) +{ + tcfilter_t *tf =3D p; + if(tf->chains) + tchash_destroy(tf->chains, tcfree); +} + +extern tcfilter_t * +tcfilter_new(void) +{ + tcfilter_t *tf =3D tcallocdz(sizeof(*tf), NULL, tcfilter_free); + if(!tf) + return NULL; + tf->chains =3D tchash_new(8, TC_LOCK_SLOPPY, 0); + if(!tf->chains){ + tcfree(tf); + return NULL; + } + return tf; +} + +static void +tcfilter_chain_free(void *p) +{ + tcfilter_chain_t *tfc =3D p; + free(tfc->name); + if(tfc->rules) + tclist_destroy(tfc->rules, tcfree); +} + +extern tcfilter_chain_t * +tcfilter_chain_new(tcfilter_t *tf, char *name) +{ + tcfilter_chain_t *tfc =3D tcallocdz(sizeof(*tfc), NULL, tcfilter_chain_free); + tcfilter_chain_t *oc =3D NULL; + if(!tfc) + return NULL; + tfc->name =3D strdup(name); + if(!tfc->name) + goto err; + tfc->rules =3D tclist_new(TC_LOCK_SLOPPY); + if(!tfc->rules) + goto err; + tfc->filter =3D tf; + + if(tchash_replace(tf->chains, name, -1, tfc, &oc) < 0) + goto err; + + if(tf->input =3D=3D oc) + tf->input =3D tfc; + tcfree(oc); + + return tfc; +err: + tcfree(tfc); + return NULL; +} + +static void +tcfilter_rule_free(void *p) +{ + tcfilter_rule_t *r =3D p; + tcfree(r->matcher); +} + +extern int +tcfilter_chain_append(tcfilter_chain_t *tfc, tcfilter_matcher_t *tfm, + char *target) +{ + tcfilter_chain_t *mtg =3D NULL; + tcfilter_rule_t *rule; + + if(target){ + if(!strcmp(target, "ACCEPT")) + mtg =3D TCFILTER_TARGET_ACCEPT; + else if(!strcmp(target, "REJECT")) + mtg =3D TCFILTER_TARGET_REJECT; + else if(tchash_find(tfc->filter->chains, target, -1, &mtg)) + return -ENOENT; + } + + rule =3D tcallocdz(sizeof(*rule), NULL, tcfilter_rule_free); + if(!rule) + return -ENOMEM; + rule->matcher =3D tfm; + rule->target =3D mtg; + if(tclist_push(tfc->rules, rule) < 0){ + tcfree(rule); + return -1; + } + + return 0; +} + +static int +tcf_apply(tcfilter_chain_t *tfc, tcfilter_packet_t *fp) +{ + tcfilter_rule_t *rule; + tclist_item_t *ls =3D NULL; + int res =3D 0; + + while((rule =3D tclist_next(tfc->rules, &ls))){ + if(rule->matcher) + res =3D rule->matcher->match(rule->matcher, fp); + else + res =3D TCFILTER_ACCEPT | TCFILTER_CONTINUE; + if((res & TCFILTER_MATCH_MASK) =3D=3D TCFILTER_ACCEPT){ + if(rule->target =3D=3D TCFILTER_TARGET_ACCEPT){ + res =3D TCFILTER_ACCEPT | TCFILTER_STOP; + } else if(rule->target =3D=3D TCFILTER_TARGET_REJECT){ + res =3D TCFILTER_REJECT | TCFILTER_STOP; + } else { + res =3D tcf_apply(rule->target, fp); + } + } + if(res & TCFILTER_STOP) + break; + } + + if(ls) + tclist_unlock(tfc->rules, ls); + + return res; +} + +extern int +tcfilter_apply(tcfilter_t *tf, void *p) +{ + tcfilter_packet_t *fp; + int res; + + if(!tf->input) + return -EINVAL; + + fp =3D malloc(sizeof(*fp)); + if(!fp) + return -ENOMEM; + fp->data =3D p; + fp->matchdata =3D p; + + res =3D tcf_apply(tf->input, fp); + free(fp); + return res & TCFILTER_MATCH_MASK; +} |
From: <mr...@mr...> - 2004-11-15 10:36:41
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/15 11:35:33+01:00 mr...@fo... = # kill warning # = # src/conf.c # 2004/11/15 11:35:33+01:00 mr...@fo... +1 -1 # kill "uninitialized" variable # = diff -Nru a/src/conf.c b/src/conf.c --- a/src/conf.c 2004-11-15 11:36:22 +01:00 +++ b/src/conf.c 2004-11-15 11:36:22 +01:00 @@ -886,7 +886,7 @@ char *tmpf =3D tmp; char *s, *v; tcc_entry *te; - int crt; + int crt =3D 0; /* kill the warning */ tccompare_fn cmp =3D NULL; = if(!tmp) |
From: <mr...@mr...> - 2004-11-02 18:00:19
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/01 13:56:14+01:00 mr...@fo... = # improve pthread check # = # BitKeeper/etc/logging_ok # 2004/11/01 13:56:14+01:00 mr...@fo... +1 -0 # Logging to lo...@op... accepted # = # configure.in # 2004/11/01 13:56:01+01:00 mr...@fo... +2 -3 # improve pthread check # = diff -Nru a/configure.in b/configure.in --- a/configure.in 2004-11-02 19:00:02 +01:00 +++ b/configure.in 2004-11-02 19:00:02 +01:00 @@ -20,9 +20,8 @@ AC_CHECK_FUNC(pthread_mutex_init,, CFLAGS=3D"$SAVECFLAGS" LIBS=3D"$SAVELIBS" - AC_CHECK_LIB(pthread, pthread_mutex_init,, - AC_CHECK_LIB(pthreads, pthread_mutex_init,, - AC_MSG_ERROR([No pthreads support found.])))) + AC_SEARCH_LIBS(pthread_mutex_init, pthread pthreads,, + AC_MSG_ERROR([No pthreads support found.]))) = dnl Check byte order AC_CHECK_HEADERS(alloca.h stdarg.h) |
From: <mr...@mr...> - 2004-11-02 18:00:18
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/01 14:31:22+01:00 mr...@fo... = # conf: various error checks # = # src/conf.c # 2004/11/01 14:31:22+01:00 mr...@fo... +43 -14 # error checking # = # src/conf-parse.l # 2004/11/01 14:31:22+01:00 mr...@fo... +4 -0 # error checking # = diff -Nru a/src/conf-parse.l b/src/conf-parse.l --- a/src/conf-parse.l 2004-11-02 19:00:04 +01:00 +++ b/src/conf-parse.l 2004-11-02 19:00:04 +01:00 @@ -74,6 +74,10 @@ tcc_entry *cur_entry =3D NULL; int line_num =3D 1; int secn =3D 0; + + if(!section_stack) + return NULL; + if(sec){ cur_section =3D sec; } else { diff -Nru a/src/conf.c b/src/conf.c --- a/src/conf.c 2004-11-02 19:00:04 +01:00 +++ b/src/conf.c 2004-11-02 19:00:04 +01:00 @@ -1,5 +1,5 @@ /** - Copyright (C) 2001, 2002, 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2001-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -40,7 +40,7 @@ char *d, tcio_fn); static int tcc_writelist(tclist_t *l, void *file, int lv, tcio_fn); = -pthread_mutex_t flex_mut =3D PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t flex_mut =3D PTHREAD_MUTEX_INITIALIZER; = #define min(a, b) ((a)<(b)?(a):(b)) = @@ -796,8 +796,9 @@ tcc_entry *te =3D p; = switch(te->type){ - case TCC_VALUE: = - tclist_destroy(te->value.values, free_value); + case TCC_VALUE: + if(te->value.values) + tclist_destroy(te->value.values, free_value); free(te->value.key); break; = @@ -812,8 +813,10 @@ conf_free(void *p) { conf_section *sec =3D p; - tclist_destroy(sec->entries, tcfree); - tclist_destroy(sec->merge, free); + if(sec->entries) + tclist_destroy(sec->entries, tcfree); + if(sec->merge) + tclist_destroy(sec->merge, free); if(sec->name) free(sec->name); } @@ -822,18 +825,31 @@ conf_new(char *name) { conf_section *sec; - sec =3D tcallocdz(sizeof(*sec), NULL, conf_free); + if(!(sec =3D tcallocdz(sizeof(*sec), NULL, conf_free))) + return NULL; sec->name =3D name? strdup(name): NULL; - sec->entries =3D tclist_new(TC_LOCK_SLOPPY); - sec->merge =3D tclist_new(TC_LOCK_SLOPPY); + if(name && !sec->name) + goto err; + if(!(sec->entries =3D tclist_new(TC_LOCK_SLOPPY))) + goto err; + if(!(sec->merge =3D tclist_new(TC_LOCK_SLOPPY))) + goto err; return sec; +err: + tcfree(sec); + return NULL; } = extern tcconf_section_t * tcconf_new(char *name) { tcconf_section_t *ts =3D tcallocdz(sizeof(*ts), NULL, tcconf_free); - ts->sec =3D conf_new(name); + if(!ts) + return NULL; + if(!(ts->sec =3D conf_new(name))){ + tcfree(ts); + return NULL; + } return ts; } = @@ -841,19 +857,26 @@ alloc_entry(conf_section *sec, char *name, int type) { tcc_entry *te =3D NULL; - te =3D tcallocd(sizeof(*te), NULL, free_entry); + if(!(te =3D tcallocdz(sizeof(*te), NULL, free_entry))) + return NULL; switch((te->type =3D type)){ case TCC_SECTION: case TCC_MSECTION: - te->section =3D conf_new(name); + if(!(te->section =3D conf_new(name))) + goto err; te->section->parent =3D sec; break; case TCC_VALUE: - te->value.key =3D strdup(name); - te->value.values =3D tclist_new(TC_LOCK_SLOPPY); + if(!(te->value.key =3D strdup(name))) + goto err; + if(!(te->value.values =3D tclist_new(TC_LOCK_SLOPPY))) + goto err; break; } return te; +err: + tcfree(te); + return NULL; } = extern tcc_entry * @@ -866,6 +889,9 @@ int crt; tccompare_fn cmp =3D NULL; = + if(!tmp) + return NULL; + if((v =3D strrchr(tmp, '/'))){ *v++ =3D 0; } else { @@ -879,6 +905,8 @@ = if(tclist_find(sec->entries, s, &te, cmp_str_sec) !=3D 0){ te =3D alloc_entry(sec, s, TCC_SECTION); + if(!te) + goto out; tclist_unshift(sec->entries, te); } sec =3D te->section; @@ -906,6 +934,7 @@ tclist_unshift(sec->entries, te); } = +out: free(tmpf); return te; } |
From: <mr...@mr...> - 2004-05-15 22:48:07
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/05/15 12:51:17+02:00 mr...@fo... = # fix make pretty-printing with all compilers # = # src/Makefile.am # 2004/05/15 12:51:17+02:00 mr...@fo... +18 -10 # pretty-print when using depcomp # = # doc/Makefile.am # 2004/05/15 12:51:17+02:00 mr...@fo... +1 -1 # correct alignment of make output # = # configure.in # 2004/05/15 12:51:17+02:00 mr...@fo... +1 -1 # appropriate name for pretty-print conditional # = diff -Nru a/configure.in b/configure.in --- a/configure.in Sun May 16 00:47:56 2004 +++ b/configure.in Sun May 16 00:47:56 2004 @@ -110,7 +110,7 @@ AC_DEFINE([HAVE_STRDUPA], 1, [Define if strdupa exists.]) fi = -AM_CONDITIONAL(prettyprint, test x$AMDEP_TRUE$am__fastdepCC_FALSE !=3D x) +AM_CONDITIONAL(nodepcomp, test x$AMDEP_TRUE$am__fastdepCC_FALSE !=3D x) = INSTALL_SCRIPT=3D"echo \" INSTALL \$\$[]p\" && true \" >/dev/null \" && $INSTALL_SCRIPT" INSTALL_DATA=3D"echo \" INSTALL \$\$[]{p-\$\$[]file}\" && true \" >/dev/null \" && $INSTALL_DATA" diff -Nru a/doc/Makefile.am b/doc/Makefile.am --- a/doc/Makefile.am Sun May 16 00:47:56 2004 +++ b/doc/Makefile.am Sun May 16 00:47:56 2004 @@ -6,7 +6,7 @@ *.dvi) echo " DVI $@";; \ *.pdf) echo " PDF $@";; \ esac && texi2dvi --quiet -DVIPS =3D echo " PS $@" && dvips -q +DVIPS =3D echo " PS $@" && dvips -q = info_TEXINFOS =3D libtc.texi = diff -Nru a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am Sun May 16 00:47:56 2004 +++ b/src/Makefile.am Sun May 16 00:47:56 2004 @@ -1,21 +1,27 @@ -if prettyprint +if nodepcomp TCCOMPILE =3D echo ' CC $<' && $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -TCLIBTOOL =3D case $@ in \ - install*) echo " INSTALL $$p";; \ - *.lo) echo ' CC $<';; \ - *) echo ' LD $@';; \ - esac; true " >/dev/null " && @LIBTOOL@ --quiet -.SILENT: +TCLTCOMPILE =3D echo ' CC $<' && $(LIBTOOL) --mode=3Dcompile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +TCDEPCOMP =3D $(SHELL) $(top_srcdir)/depcomp else TCCOMPILE =3D $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -TCLIBTOOL =3D @LIBTOOL@ +TCLTCOMPILE =3D @LIBTOOL@ --quiet --mode=3Dcompile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +TCDEPCOMP =3D $(SHELL) -c 'echo " CC $<" && $(SHELL) $(top_srcdir)/depcomp "$$@"' depcomp endif = COMPILE =3D $(TCCOMPILE) -LIBTOOL =3D $(TCLIBTOOL) - +LTCOMPILE =3D $(TCLTCOMPILE) +depcomp =3D $(TCDEPCOMP) +LINK =3D echo ' LD $@' && $(LIBTOOL) --mode=3Dlink $(CCLD) $(AM_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +LIBTOOL =3D case $@ in \ + install*) echo " INSTALL $$p";; \ + esac; true " >/dev/null " && @LIBTOOL@ --quiet LEXCOMPILE =3D echo ' LEX $<' && $(LEX) $(LFLAGS) $(AM_LFLAGS) = lib_LTLIBRARIES =3D libtc.la @@ -30,3 +36,5 @@ bin_PROGRAMS =3D tcconfdump tcconfdump_SOURCES =3D confdump.c tcconfdump_LDFLAGS =3D libtc.la + +.SILENT: |
From: <mr...@mr...> - 2004-04-21 18:59:52
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/04/21 20:59:34+02:00 mr...@fo... = # remove tclist_free # tclist_destroy is the proper function # = # include/tclist.h # 2004/04/21 20:59:34+02:00 mr...@fo... +1 -4 # remove tclist_free, it's evil # = diff -Nru a/include/tclist.h b/include/tclist.h --- a/include/tclist.h Wed Apr 21 20:59:44 2004 +++ b/include/tclist.h Wed Apr 21 20:59:44 2004 @@ -1,5 +1,5 @@ /** - Copyright (C) 2001, 2002, 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2001-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -39,9 +39,6 @@ = /* Create new empty tclist_t */ extern tclist_t *tclist_new(int locking); - -/* Free resources used by list. */ -extern int tclist_free(tclist_t *); = /* Destroy list calling lfree with data in each item. */ extern int tclist_destroy(tclist_t *lst, tcfree_fn lfree); |
From: <mr...@mr...> - 2004-04-21 18:47:46
|
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/04/21 20:46:13+02:00 mr...@fo... = # check return values of malloc and friends # = # src/tree.c # 2004/04/21 20:46:13+02:00 mr...@fo... +17 -5 # check return values of malloc and friends # = # src/string.c # 2004/04/21 20:46:13+02:00 mr...@fo... +21 -3 # check return values of malloc and friends # = # src/regex.c # 2004/04/21 20:46:13+02:00 mr...@fo... +22 -9 # check return values of malloc and friends # = # src/prioq.c # 2004/04/21 20:46:13+02:00 mr...@fo... +18 -4 # check return values of malloc and friends # = # src/pathfind.c # 2004/04/21 20:46:13+02:00 mr...@fo... +5 -1 # check return values of malloc and friends # = # src/mpool.c # 2004/04/21 20:46:13+02:00 mr...@fo... +7 -4 # check return values of malloc and friends # = # src/list.c # 2004/04/21 20:46:13+02:00 mr...@fo... +15 -6 # check return values of malloc and friends # = # src/hash.c # 2004/04/21 20:46:13+02:00 mr...@fo... +41 -14 # check return values of malloc and friends # = # src/alloc.c # 2004/04/21 20:46:12+02:00 mr...@fo... +10 -2 # check return values of malloc and friends # = diff -Nru a/src/alloc.c b/src/alloc.c --- a/src/alloc.c Wed Apr 21 20:47:31 2004 +++ b/src/alloc.c Wed Apr 21 20:47:31 2004 @@ -26,6 +26,7 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> +#include <errno.h> = typedef struct tcattri { char *name; @@ -53,6 +54,8 @@ tcallocd(size_t size, tc_ref_fn r, tcfree_fn f) { tcalloc_t *tca =3D malloc(size + sizeof(tcalloc_t) - sizeof(tca->data)); + if(!tca) + return NULL; tca->rc =3D 1; tca->ref =3D r; tca->free =3D f; @@ -129,12 +132,17 @@ { tcalloc_t *tca =3D (tcalloc_t *)((char *) ptr - offsetof(tcalloc_t, data)); tcattri_t *a, *n, *p =3D NULL; + char *an; = for(a =3D tca->attr; a && a->next && strcmp(name, a->name); a =3D a->next) p =3D a; = - n =3D calloc(1, sizeof(*n)); - n->name =3D strdup(name); + if(!(an =3D strdup(name))) + return -ENOMEM; + + if(!(n =3D calloc(1, sizeof(*n)))) + return -ENOMEM; + n->name =3D an; n->value =3D val; n->ref =3D r; n->free =3D f; diff -Nru a/src/hash.c b/src/hash.c --- a/src/hash.c Wed Apr 21 20:47:31 2004 +++ b/src/hash.c Wed Apr 21 20:47:31 2004 @@ -1,5 +1,5 @@ /** - Copyright (C) 2001, 2002, 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2001-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -26,6 +26,7 @@ #include <string.h> #include <tctypes.h> #include <pthread.h> +#include <errno.h> #include <tchash.h> #include <tcmempool.h> #include <tcalloc.h> @@ -189,19 +190,25 @@ tchash_table_t *ht; = size =3D hash_size(size); - ht =3D malloc(sizeof(*ht)); + if(!(ht =3D malloc(sizeof(*ht)))) + return NULL; ht->size =3D size; ht->entries =3D 0; ht->flags =3D flags; - ht->buckets =3D calloc(size, sizeof(*ht->buckets)); + if(!(ht->buckets =3D calloc(size, sizeof(*ht->buckets)))) + goto err; ht->locking =3D lock; pthread_mutex_init(&ht->lock, NULL); ht->high_mark =3D 0.7; ht->low_mark =3D 0.3; ht->hash_func =3D hash_func; - ht->mp =3D tcmempool_new(sizeof(hash_entry), 0); + if(!(ht->mp =3D tcmempool_new(sizeof(hash_entry), 0))) + goto err; = return ht; +err: + free(ht); + return NULL; } = extern int @@ -241,6 +248,8 @@ hash_kdup(void *key, size_t ks) { void *nk =3D malloc(ks); + if(!nk) + return NULL; memcpy(nk, key, ks); return nk; } @@ -249,10 +258,18 @@ hash_addentry(tchash_table_t *ht, u_int hv, void *key, size_t ks, void *data) { hash_entry *he =3D tcmempool_get(ht->mp); + void *nk; + + if(!he) + return NULL; + if(ht->flags & TCHASH_NOCOPY) - he->key =3D key; + nk =3D key; else - he->key =3D hash_kdup(key, ks); + nk =3D hash_kdup(key, ks); + if(!nk) + return NULL; + he->key =3D nk; he->key_size =3D ks; he->data =3D data; he->next =3D ht->buckets[hv]; @@ -288,11 +305,13 @@ hf =3D 1; } = - if(ret !=3D NULL) + if(!hr) + hf =3D -ENOMEM; + else if(ret !=3D NULL) *ret =3D hr->data; = unlock_hash(ht); - if(hf && !(ht->flags & TCHASH_FROZEN)){ + if(hf > 0 && !(ht->flags & TCHASH_FROZEN)){ if((float) ht->entries / ht->size > ht->high_mark) tchash_rehash(ht); } @@ -349,12 +368,15 @@ *rt =3D hr->data; hr->data =3D data; } else { - hash_addentry(ht, hv, key, ks, data); + hr =3D hash_addentry(ht, hv, key, ks, data); ret =3D 1; } = + if(!hr) + ret =3D -ENOMEM; + unlock_hash(ht); - if(ret && !(ht->flags & TCHASH_FROZEN)){ + if(ret > 0 && !(ht->flags & TCHASH_FROZEN)){ if((float) ht->entries / ht->size > ht->high_mark) tchash_rehash(ht); } @@ -434,13 +456,17 @@ { hash_entry **nb =3D NULL; size_t ns, i; + int ret =3D 0; = lock_hash(ht); = ns =3D hash_size(ht->entries * 2 / (ht->high_mark + ht->low_mark)); if(ns =3D=3D ht->size) goto end; - nb =3D calloc(ns, sizeof(*nb)); + if(!(nb =3D calloc(ns, sizeof(*nb)))){ + ret =3D -ENOMEM; + goto end; + } = for(i =3D 0; i < ht->size; i++){ hash_entry *he =3D ht->buckets[i]; @@ -459,7 +485,7 @@ = end: unlock_hash(ht); - return 0; + return ret; } = extern void ** @@ -475,7 +501,8 @@ = lock_hash(ht); = - keys =3D malloc(ht->entries * sizeof(*keys)); + if(!(keys =3D malloc(ht->entries * sizeof(*keys)))) + goto out; = for(i =3D 0, j =3D 0; i < ht->size; i++){ hash_entry *he; @@ -485,8 +512,8 @@ = *n =3D ht->entries; = +out: unlock_hash(ht); - return keys; } = diff -Nru a/src/list.c b/src/list.c --- a/src/list.c Wed Apr 21 20:47:31 2004 +++ b/src/list.c Wed Apr 21 20:47:31 2004 @@ -1,5 +1,5 @@ /** - Copyright (C) 2001, 2002, 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2001-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -25,7 +25,8 @@ #include <stdio.h> #include <stdlib.h> #include <pthread.h> -#include "tclist.h" +#include <errno.h> +#include <tclist.h> = struct tclist_item { void *data; @@ -48,13 +49,15 @@ tclist_new(int locking) { tclist_t *l =3D calloc(1, sizeof(*l)); + if(!l) + return NULL; l->locking =3D locking; if(locking > TC_LOCK_NONE) pthread_mutex_init(&l->lock, NULL); return l; } = -extern int +static int tclist_free(tclist_t *lst) { if(lst->start !=3D NULL) @@ -156,6 +159,8 @@ new_item(void *p) { tclist_item_t *l =3D malloc(sizeof(tclist_item_t)); + if(!l) + return NULL; l->data =3D p; l->rc =3D 1; l->ic =3D 0; @@ -168,7 +173,8 @@ tclist_push(tclist_t *lst, void *p) { tclist_item_t *l =3D new_item(p); - + if(!l) + return -ENOMEM; lock_list(lst); if(lst->start =3D=3D NULL){ lst->start =3D l; @@ -190,7 +196,8 @@ tclist_unshift(tclist_t *lst, void *p) { tclist_item_t *l =3D new_item(p); - + if(!l) + return -ENOMEM; lock_list(lst); if(lst->start =3D=3D NULL){ lst->start =3D l; @@ -282,7 +289,9 @@ tclist_unlock(lst, l); return 0; } else { - tclist_push(lst, p); + int pr =3D tclist_push(lst, p); + if(pr) + return pr; if(r !=3D NULL) *r =3D p; return 1; diff -Nru a/src/mpool.c b/src/mpool.c --- a/src/mpool.c Wed Apr 21 20:47:31 2004 +++ b/src/mpool.c Wed Apr 21 20:47:31 2004 @@ -1,5 +1,5 @@ /** - Copyright (C) 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2003-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -94,7 +94,8 @@ if(size > pagesize - offsetof(tcmempool_page_t, data)) return NULL; = - mp =3D tcallocdz(sizeof(*mp), NULL, mp_free); + if(!(mp =3D tcallocdz(sizeof(*mp), NULL, mp_free))) + return NULL; mp->size =3D size; mp->cpp =3D (pagesize - offsetof(tcmempool_page_t, data)) / size; mp->locking =3D lock; @@ -107,7 +108,7 @@ tcmempool_get(tcmempool_t *mp) { tcmempool_page_t *mpp; - void *chunk; + void *chunk =3D NULL; = mp_lock(mp); = @@ -116,6 +117,8 @@ if(!mpp){ mpp =3D mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if(!mpp) + goto out; mpp->pool =3D mp; mp->pages =3D mpp; } @@ -134,8 +137,8 @@ mpp->prev =3D NULL; } = +out: mp_unlock(mp); - return chunk; } = diff -Nru a/src/pathfind.c b/src/pathfind.c --- a/src/pathfind.c Wed Apr 21 20:47:31 2004 +++ b/src/pathfind.c Wed Apr 21 20:47:31 2004 @@ -36,7 +36,10 @@ return strdup(name); = p =3D dp =3D strdup(path); - fn =3D malloc(strlen(path) + strlen(name) + 2); + if(!p) + return NULL; + if(!(fn =3D malloc(strlen(path) + strlen(name) + 2))) + goto end; while((pc =3D strsep(&p, ":"))){ sprintf(fn, "%s/%s", pc, name); if(!access(fn, how)) @@ -48,6 +51,7 @@ fn =3D NULL; } = +end: free(dp); return fn; } diff -Nru a/src/prioq.c b/src/prioq.c --- a/src/prioq.c Wed Apr 21 20:47:31 2004 +++ b/src/prioq.c Wed Apr 21 20:47:31 2004 @@ -1,5 +1,5 @@ /** - Copyright (C) 2003 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd + Copyright (C) 2003-2004 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd = Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -27,6 +27,7 @@ #include <string.h> #include <tctypes.h> #include <pthread.h> +#include <errno.h> #include <tcprioq.h> = struct tcprioq { @@ -57,7 +58,11 @@ { tcprioq_t *pq =3D malloc(sizeof(*pq)); = - pq->qt =3D malloc(size * sizeof(*pq->qt)); + if(!pq) + return NULL; + + if(!(pq->qt =3D malloc(size * sizeof(*pq->qt)))) + goto err; pq->size =3D size; pq->count =3D 1; pq->cmp =3D cmp; @@ -66,17 +71,25 @@ pthread_mutex_init(&pq->lock, NULL); = return pq; +err: + free(pq); + return NULL; } = extern int tcprioq_add(tcprioq_t *pq, void *data) { - int i; + int i, r =3D 0; = tcp_lock(pq); = if(pq->count =3D=3D pq->size){ - pq->qt =3D realloc(pq->qt, (pq->size *=3D 2) * sizeof(*pq->qt)); + void **nqt =3D realloc(pq->qt, (pq->size *=3D 2) * sizeof(*pq->qt)); + if(!nqt){ + r =3D -ENOMEM; + goto end; + } + pq->qt =3D nqt; } = i =3D pq->count; @@ -91,6 +104,7 @@ = pq->count++; = +end: tcp_unlock(pq); return 0; } diff -Nru a/src/regex.c b/src/regex.c --- a/src/regex.c Wed Apr 21 20:47:31 2004 +++ b/src/regex.c Wed Apr 21 20:47:31 2004 @@ -50,7 +50,8 @@ return strdup(""); = ml =3D rs->m[m].rm_eo - rs->m[m].rm_so; - t =3D malloc(ml + 1); + if(!(t =3D malloc(ml + 1))) + return NULL; strncpy(t, rs->s + rs->m[m].rm_so, ml); t[ml] =3D 0; = @@ -62,7 +63,7 @@ { regsub_t rs; const char *s; - char *ss, *p; + char *ss =3D NULL, *p; int r, l; = (void) flags; /* unused, kill warning */ @@ -74,9 +75,11 @@ return NULL; } = - rs.m =3D calloc(rs.rx.re_nsub + 1, sizeof(*rs.m)); + if(!(rs.m =3D calloc(rs.rx.re_nsub + 1, sizeof(*rs.m)))) + goto end; l =3D strlen(str); - ss =3D malloc(l + 1); + if(!(ss =3D malloc(l + 1))) + goto end; p =3D ss; s =3D str; = @@ -89,28 +92,38 @@ p +=3D rs.m[0].rm_so; ml =3D rs.m[0].rm_eo - rs.m[0].rm_so; if(ml > 0){ - char *ms =3D malloc(ml + 1); - char *rp; + char *rp, *nss; int sl, o; = rs.s =3D s; rp =3D tcstrexp(sub, "{", "}", 0, rs_lookup, &rs, TCSTREXP_KEEPUNDEF | TCSTREXP_FREE); + if(!rp) + goto err; sl =3D strlen(rp); o =3D p - ss; - ss =3D realloc(ss, l +=3D sl); + nss =3D realloc(ss, l +=3D sl); + if(!nss){ + free(rp); + goto err; + } + ss =3D nss; p =3D ss + o; - strcpy(p, rp); p +=3D sl; free(rp); - free(ms); } s +=3D rs.m[0].rm_eo; } = strcpy(p, s); + +end: free(rs.m); regfree(&rs.rx); return ss; +err: + free(ss); + ss =3D NULL; + goto end; } diff -Nru a/src/string.c b/src/string.c --- a/src/string.c Wed Apr 21 20:47:31 2004 +++ b/src/string.c Wed Apr 21 20:47:31 2004 @@ -88,13 +88,20 @@ char *exp =3D malloc(l); char *p =3D exp; char *d, *f; + char *vn =3D NULL, *vo =3D NULL; = #define ext(n) do { \ int o =3D p - exp; \ - exp =3D realloc(exp, l +=3D n); \ + char *nx =3D realloc(exp, l +=3D n); \ + if(!nx) \ + goto err; \ + exp =3D nx; \ p =3D exp + o; \ } while(0) = + if(!exp) + return NULL; + while(*s){ switch(*s){ case '\\': @@ -126,13 +133,15 @@ = if(*e){ int vl =3D e - s; - char *vn =3D malloc(vl + 1); char *v; char *def =3D NULL, *alt =3D NULL; int upcase =3D 0, downcase =3D 0; int sss =3D 0, ssl =3D INT_MAX; char *rx =3D NULL, *rsub =3D NULL, rd; = + if(!(vn =3D malloc(vl + 1))) + goto err; + strncpy(vn, s, vl); vn[vl] =3D 0; if(fs && (f =3D strchr(vn, fs))){ @@ -206,7 +215,7 @@ } if(v){ int sl =3D strlen(v); - char *vo =3D v; + vo =3D v; = if(sss < 0){ if(-sss < sl){ @@ -259,6 +268,7 @@ } } free(vo); + vo =3D NULL; } else if(flags & TCSTREXP_KEEPUNDEF){ int n =3D e - s + 3; ext(n); @@ -267,6 +277,7 @@ } s =3D e + 1; free(vn); + vn =3D NULL; } } else { *p++ =3D '$'; @@ -282,6 +293,13 @@ = #undef ext return exp; +err: + if(vn) + free(vn); + if(vo) + free(vo); + free(exp); + return NULL; } = extern int diff -Nru a/src/tree.c b/src/tree.c --- a/src/tree.c Wed Apr 21 20:47:31 2004 +++ b/src/tree.c Wed Apr 21 20:47:31 2004 @@ -27,6 +27,7 @@ #include <pthread.h> #include <tctree.h> #include <assert.h> +#include <errno.h> = typedef enum { dnode_red, dnode_black } dnode_color_t; = @@ -127,6 +128,9 @@ { tctree_t *t =3D calloc(1, sizeof(*t)); = + if(!t) + return NULL; + t->nilnode.left =3D &t->nilnode; t->nilnode.right =3D &t->nilnode; t->nilnode.parent =3D &t->nilnode; @@ -225,6 +229,7 @@ dnode_t *node; void **ret =3D r; int result =3D -1; + int rv; = tree_lock(dict); = @@ -239,15 +244,19 @@ *ret =3D where->key; if(replace) where->key =3D key; - tree_unlock(dict); - return 0; + rv =3D 0; = + goto end; } } = if(ret) *ret =3D key; = - node =3D malloc(sizeof(*node)); + if(!(node =3D malloc(sizeof(*node)))){ + rv =3D -ENOMEM; + goto end; + } + node->key =3D key; = if (result < 0) @@ -311,8 +320,10 @@ = dict_root(dict)->color =3D dnode_black; = + rv =3D 1; +end: tree_unlock(dict); - return 1; + return rv; } = extern int @@ -334,7 +345,8 @@ * the nil node. */ = -dnode_t *dict_next(tctree_t *dict, dnode_t *curr) +static dnode_t * +dict_next(tctree_t *dict, dnode_t *curr) { dnode_t *nil =3D dict_nil(dict), *parent, *left; = |