summaryrefslogtreecommitdiff
path: root/src/bin/solve_calc.c
blob: be769863279b61d12800d62ecaf5cd7fd044d0e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <Elementary.h>

#include "solve_calc.h"

/* Start of BC */
static void (*_bc_res_cb)(void *data, const char *result);
static Ecore_Exe *bc_exe;
static Ecore_Event_Handler *ee_data_handle;
static Ecore_Event_Handler *ee_error_handle;

static const char _bc_allowed_chars[] = "0123456789.()+-*/ \t";

/* FIXME: Instead of blindly stripping, we should strip if doesn't look
 * like a number. */
static char *
_bc_prepare_expression(const char *expression)
{
   char *ret = calloc(1, strlen(expression) + 2); /* \n + \0 */
   char *tmp = ret;

   for ( ; *expression ; expression++)
     {
        if (strchr(_bc_allowed_chars, *expression))
          {
             *(tmp++) = *expression;
          }
     }

   *tmp = '\n';

   return ret;
}

/* Got the result. */
static Eina_Bool
_bc_msg_from_child_handler(void *data, int type EINA_UNUSED, void *event)
{
   Ecore_Exe_Event_Data *dataFromProcess = (Ecore_Exe_Event_Data *)event;
   char msg[1024];

   if (dataFromProcess->size >= (int) (sizeof(msg) - 1))
     {
        fprintf(stdout, "Data too big for buffer. error\n");
        return ECORE_CALLBACK_DONE;
     }

   strncpy(msg, dataFromProcess->data, dataFromProcess->size);
   msg[dataFromProcess->size] = 0;

   if (_bc_res_cb)
      _bc_res_cb(data, msg);

   return ECORE_CALLBACK_DONE;
}

void
solve_calc_callback_set(void (*cb)(void *data, const char *result), const void *data)
{
   ee_data_handle = ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _bc_msg_from_child_handler, data);
   ee_error_handle = ecore_event_handler_add(ECORE_EXE_EVENT_ERROR, _bc_msg_from_child_handler, data);

   _bc_res_cb = cb;
}

void
solve_calc_calc(const char *_expression)
{
   char *expression = _bc_prepare_expression(_expression);
   if (EINA_TRUE != ecore_exe_send(bc_exe, expression, strlen(expression)))
     {
        printf("Can't send expression to bc.\n");
     }
   free(expression);
}

/* We assume we init once. */
void
solve_calc_init(void)
{
   bc_exe = ecore_exe_pipe_run("bc -l",
         ECORE_EXE_PIPE_ERROR |
         ECORE_EXE_PIPE_READ |
         ECORE_EXE_PIPE_WRITE, NULL);
}

void
solve_calc_shutdown(void)
{
   if (ee_data_handle)
      ecore_event_handler_del(ee_data_handle);
   if (ee_error_handle)
      ecore_event_handler_del(ee_error_handle);
   ecore_exe_free(bc_exe);
}
/* End of BC */