/*
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 <stdlib.h>
#include <string.h>
#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
*
****************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1