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 * or Kari Hurtta *****************************************************************************/ #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: */