/* elmo - ELectronic Mail Operator Copyright (C) 2003, 2004 rzyjontko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------- User-invoked functions are kept in exec_table.t file. This module contains routines used to execute them. */ /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include "exec.h" #include "abook.h" #include "attach.h" #include "bayes.h" #include "box_selection.h" #include "cmd.h" #include "choose.h" #include "error.h" #include "fetch.h" #include "folder.h" #include "mailreader.h" #include "sender.h" #include "xmalloc.h" #include "help.h" #include "gettext.h" #include "mybox.h" #include "wrapbox.h" #include "read.h" #include "interface.h" #include "debug.h" #include "smtp.h" #include "stats.h" #include "pgp.h" #include "select.h" #include "rarray.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ #define FUN_COUNT (sizeof (fun_table) / sizeof (exec_t)) /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ static exec_t fun_table[] = { #include "exec_table.t" }; static rarray_t *macros = NULL; static exec_t *macro = NULL; static int size = 0; static int count = 0; static exec_t **table = NULL; static char *default_description = NULL; /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ static int exec_cmp (const void *a, const void *b) { exec_t *aa = (exec_t *) a; exec_t *bb = (exec_t *) b; return strcmp (aa->name, bb->name); } static void execute (exec_t *exec) { if (exec->fun) exec->fun (); hook_execute (exec->hook); } static void destroy_exec (exec_t *exec) { if (exec->hook){ hook_destroy (exec->hook); xfree (exec->hook); } } static void table_resize (void) { if (count < size) return; size *= 2; table = xrealloc (table, size * sizeof (exec_t *)); } static void table_add (void) { int lbound = 0; int rbound = count; int index; int ret; while (rbound > lbound){ index = (rbound + lbound) / 2; ret = strcmp (macro->name, table[index]->name); if (ret == 0){ error_ (0, _("function or macro %s already exists"), macro->name); return; } if (ret < 0) rbound = ((index == rbound) ? rbound - 1 : index); else lbound = ((index == lbound) ? lbound + 1 : index); } memmove (table + lbound + 1, table + lbound, (count - lbound) * sizeof (exec_t *)); table[lbound] = macro; count++; } static void destroy_macros (void) { int i; exec_t *macro; if (macros == NULL) return; for (i = 0; i < macros->count; i++){ macro = (exec_t *) macros->array[i]; if (macro->desc != default_description) xfree (macro->desc); xfree (macro->name); destroy_exec (macro); xfree (macro); } rarray_destroy (macros); macros = NULL; } /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ void exec_init (void) { int i; qsort (fun_table, FUN_COUNT, sizeof (exec_t), exec_cmp); size = FUN_COUNT * 3 / 2; count = FUN_COUNT; table = xmalloc (size * sizeof (exec_t *)); for (i = 0; i < FUN_COUNT; i++){ table[i] = fun_table + i; } default_description = _("user defined macro"); } exec_t * exec_lookup (const char *name) { int lbound = 0; int rbound = count; int index; int ret; if (name == NULL) return NULL; while (rbound > lbound){ index = (rbound + lbound) / 2; ret = strcmp (name, table[index]->name); if (ret == 0){ return table[index]; } if (ret < 0) rbound = ((index == rbound) ? rbound - 1 : index); if (ret > 0) lbound = ((index == lbound) ? lbound + 1 : index); } return NULL; } exec_t * exec_lookup_fun (void (*fun)(void)) { int i; for (i = 0; i < count; i++){ if (table[i]->fun == fun) break; } if (i < count) return table[i]; return NULL; } void exec_run (exec_t *exec) { if (exec) execute (exec); } void exec_run_name (char *name) { exec_t *exec; if (name == NULL || *name == '\0' || *name == '\n') return; exec = exec_lookup (name); if (exec) execute (exec); else error_ (0, _("undefined function %s"), name); } void exec_free_resources (void) { int i; for (i = 0; i < FUN_COUNT; i++){ destroy_exec (fun_table + i); } if (table) xfree (table); table = NULL; destroy_macros (); } rstring_t * exec_get_functions (const char *prefix) { int off = 0; int i = 0; rstring_t *result; while (prefix[off]){ while (i < count && prefix[off] > table[i]->name[off]) i++; if (i == count) return NULL; if (prefix[off] != table[i]->name[off]) return NULL; off++; } off--; result = rstring_create (); while (i < count && strstr (table[i]->name, prefix) == table[i]->name){ rstring_add (result, table[i]->name); i++; } return result; } void exec_new_macro (const char *name) { macro = xmalloc (sizeof (exec_t)); macro->name = xstrdup (name); macro->fun = NULL; macro->hook = NULL; macro->desc = default_description; } void exec_macro_comment (char *comment) { macro->desc = comment; } void exec_macro_add_hook (const char *fun) { exec_t *exec; exec = exec_lookup (fun); if (exec == NULL){ error_ (0, _("undefined function %s"), fun); return; } if (exec->fun){ if (macro->hook) hook_add (macro->hook, exec->fun); else macro->hook = hook_create (exec->fun); } else { error_ (0, _("macros (%s) cannot be used as parts of " "other macros"), fun); } } void exec_macro_commit (void) { if (macros == NULL) macros = rarray_create (); rarray_add (macros, macro); table_resize (); table_add (); macro = NULL; } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE exec.c * ****************************************************************************/