static char rcsid[] = "@(#)$Id: rc_delay.c,v 1.5 2006/04/09 07:37:08 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.5 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* or Kari Hurtta <elm@elmme-mailer.org>
*****************************************************************************/
#include "headers.h"
#include "rc_imp.h"
#include "save_opts.h"
DEBUG_VAR(Debug,__FILE__,"config");
enum xx { line_normal, line_negate, line_continue };
struct rec1 {
int lcl;
char *value;
int lineno;
char *filename;
enum xx negate_continue;
};
static void replay_rec P_((struct rec1 *rec,
struct rc_save_info_rec * real));
static void replay_rec(rec,real)
struct rec1 *rec;
struct rc_save_info_rec * real;
{
switch (rec->negate_continue) {
case line_normal:
rc_eval_tail(real,rec->lcl,rec->value,rec->lineno,rec->filename,0);
break;
case line_negate:
rc_eval_tail(real,rec->lcl,rec->value,rec->lineno,rec->filename,1);
break;
case line_continue:
if (RCTYPE_magic != real->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"replay_rec",
"Bad config item type",0);
real->dt_type->parse_cline(real,rec->lcl,rec->value,rec->lineno,
rec->filename);
break;
}
}
static struct rc_save {
struct rc_save_info_rec * real;
struct rc_save_info_rec * delayed;
struct rec1 * lines;
int line_count;
struct rc_save * next;
} * root = NULL;
void mark_delayed_changed(A)
void *A;
{
struct rc_save *x;
for (x = root; x; x = x->next) {
if (x->real && x->real->val.dummy == A) {
DPRINT(Debug,10,(&Debug,
"mark_delayed_changed: %p: %p\n",
x,A));
mark_XX(x->real);
if (x->delayed)
mark_XX(x->delayed);
else {
DPRINT(Debug,10,(&Debug,
"mark_delayed_changed: %p: %p -- no delayed registered\n",
x,A));
}
}
}
}
void mark_fdelayed_changed(A)
option_func *A;
{
struct rc_save *x;
for (x = root; x; x = x->next) {
if (x->real && x->real->func_val == A) {
DPRINT(Debug,10,(&Debug,
"mark_fdelayed_changed: %p: %p\n",
x,A));
mark_XX(x->real);
if (x->delayed)
mark_XX(x->delayed);
else {
DPRINT(Debug,10,(&Debug,
"mark_fdelayed_changed: %p: %p -- no delayed registered\n",
x,A));
}
}
}
}
static struct rc_save * new_record P_((void));
static struct rc_save * new_record()
{
struct rc_save * x = safe_malloc(sizeof (*x));
bzero((void *)x,sizeof (*x));
x->real = NULL;
x->delayed = NULL;
x->next = root;
root = x;
return x;
}
static void replay_saved P_((struct rc_save *p));
static void replay_saved(p)
struct rc_save *p;
{
int i;
for (i = 0; i < p->line_count; i++) {
replay_rec(& (p->lines[i]), p->real);
}
for (i = 0; i < p->line_count; i++) {
if (p->lines[i].value)
free(p->lines[i].value);
p->lines[i].value = NULL;
if (p->lines[i].filename)
free(p->lines[i].filename);
p->lines[i].filename = NULL;
}
if (p->lines)
free(p->lines);
p->lines = NULL;
p->line_count = 0;
}
static void add_delayed P_((struct rc_save *p));
static void add_delayed(p)
struct rc_save *p;
{
int x;
for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
if (0 == strcmp(save_info[x].name,p->real->name)) {
if (save_info[x].dt_type != &rc_DT_DELAY)
panic("RC PANIC",__FILE__,__LINE__,"add_delayed",
"Option is not delayed",0);
p->delayed = & (save_info[x]);
return;
}
}
panic("RC PANIC",__FILE__,__LINE__,"add_delayed",
"Deleayed option not found",0);
}
static void register_delayed1 P_((struct rc_save_info_rec *option_real));
static void register_delayed1(option_real)
struct rc_save_info_rec *option_real;
{
struct rc_save *p;
for (p = root; p; p = p->next) {
if (option_real == p->real)
panic("RC PANIC",__FILE__,__LINE__,"register_delayed1",
"Duplicate registeration",0);
if (p->delayed &&
0 == strcmp(option_real->name,p->delayed->name)) {
if (p->real)
panic("RC PANIC",__FILE__,__LINE__,"register_delayed1",
"Duplicate name",0);
p->real = option_real;
replay_saved(p);
return;
}
}
p = new_record();
p->real = option_real;
add_delayed(p);
}
void register_delayed(rc_options,rc_option_count)
struct rc_save_info_rec * rc_options;
int rc_option_count;
{
int i;
for (i = 0; i < rc_option_count; i++) {
register_delayed1(& (rc_options[i]) );
}
}
static struct rc_save * register_delayed2 P_((struct rc_save_info_rec *option_proxy));
static struct rc_save * register_delayed2(option_proxy)
struct rc_save_info_rec *option_proxy;
{
struct rc_save *p;
for (p = root; p; p = p->next) {
if (option_proxy == p->delayed)
return p;
if (p->real &&
0 == strcmp(option_proxy->name,p->real->name)) {
if (p->delayed)
panic("RC PANIC",__FILE__,__LINE__,"register_delayed2",
"Duplicate name",0);
p->delayed = option_proxy;
return p;
}
}
p = new_record();
p->delayed = option_proxy;
return p;
}
#ifdef ANSI_C
static rc_parse_line dt_DELAY_parse_line;
#endif
static int dt_DELAY_parse_line(r,lcl,value,lineno,filename, negate)
struct rc_save_info_rec *r;
int lcl;
char *value;
int lineno;
char *filename;
int negate;
{
int ret = 1;
struct rc_save *p = register_delayed2(r);
if (p->real && p->line_count)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_parse_line",
"Bad state",0);
if (p->real) {
ret = rc_eval_tail(p->real,lcl,value,lineno,filename,negate);
} else {
p->lines = safe_realloc(p->lines,
(p->line_count + 1) * sizeof (p->lines[0]));
bzero((void *)& (p->lines[p->line_count]),
sizeof (p->lines[p->line_count]) );
p->lines[p->line_count].lcl = lcl;
p->lines[p->line_count].value = safe_strdup(value);
p->lines[p->line_count].lineno = lineno;
p->lines[p->line_count].filename = safe_strdup(filename);
p->lines[p->line_count].negate_continue = negate ?
line_negate : line_normal;
p->line_count++;
ret = 1;
}
return ret;
}
#ifdef ANSI_C
static rc_parse_cline dt_DELAY_parse_cline;
#endif
static int dt_DELAY_parse_cline(r,lcl,value,lineno,filename)
struct rc_save_info_rec *r;
int lcl;
char *value;
int lineno;
char *filename;
{
int ret = 1;
struct rc_save *p = register_delayed2(r);
if (p->real && p->line_count)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_parse_cline",
"Bad state",0);
if (p->real) {
if (RCTYPE_magic != p->real->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_parse_cline",
"Bad config item type",0);
ret = p->real->dt_type->parse_cline(p->real,lcl,value,lineno,
filename);
} else {
if (!p->line_count)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_parse_cline",
"Bad state",0);
p->lines = safe_realloc(p->lines,
(p->line_count + 1) * sizeof (p->lines[0]));
bzero((void *)& (p->lines[p->line_count]),
sizeof (p->lines[p->line_count]) );
p->lines[p->line_count].lcl = lcl;
p->lines[p->line_count].value = safe_strdup(value);
p->lines[p->line_count].lineno = lineno;
p->lines[p->line_count].filename = safe_strdup(filename);
p->lines[p->line_count].negate_continue = line_continue;
p->line_count++;
ret = 1;
}
return ret;
}
#if ANSI_C
static rc_print_value dt_DELAY_print_value;
#endif
static void dt_DELAY_print_value(F,r,comment)
FILE *F;
struct rc_save_info_rec *r;
int comment;
{
struct rc_save *p = register_delayed2(r);
if (p->real && p->line_count)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_print_value",
"Bad state",0);
if (p->real) {
if (RCTYPE_magic != p->real->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_print_value",
"Bad config item type",0);
p->real->dt_type->print_value(F,p->real,comment);
} else if (p->line_count) {
int i,start = 0;
for (i = 0; i < p->line_count; i++) {
if (line_normal == p->lines[i].negate_continue)
start = i;
}
for (i = start; i < p->line_count; i++) {
if (comment)
fprintf(F, "### ");
switch (p->lines[i].negate_continue) {
case line_normal:
fprintf(F, "%s = %s\n", r->name, p->lines[i].value);
break;
case line_continue:
if (0 == i)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_print_value",
"Bad state",0);
fprintf(F, "\t%s\n", p->lines[i].value);
break;
case line_negate:
/* unsupported */
fprintf(F, "# !%s = %s\n", r->name, p->lines[i].value);
break;
}
}
}
}
#if ANSI_C
static rc_get_value dt_DELAY_get_value;
#endif
static char * dt_DELAY_get_value(r)
struct rc_save_info_rec *r;
{
struct rc_save *p = register_delayed2(r);
if (p->real && p->line_count)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_get_value",
"Bad state",0);
if (p->real) {
if (RCTYPE_magic != p->real->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"dt_DELAY_get_value",
"Bad config item type",0);
return p->real->dt_type->get_value(p->real);
} else if (p->line_count) {
int i,start = 0;
for (i = 0; i < p->line_count; i++) {
if (line_normal == p->lines[i].negate_continue)
start = i;
}
if (start == p->line_count-1 &&
line_normal == p->lines[start].negate_continue)
return p->lines[start].value;
}
return "*bad*";
}
struct rc_type rc_DT_DELAY = { RCTYPE_magic,
dt_DELAY_parse_line, dt_DELAY_parse_cline,
dt_DELAY_print_value, dt_DELAY_get_value };
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1