230c1bb6d545a62feab3a99b31117e6c11936b23
[m17n/m17n-test.git] / run-im.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <m17n.h>
5 #include <m17n-misc.h>
6
7 MPlist *error_invalid_format;
8 MPlist *error_unknown_command;
9 MPlist *error_invalid_arg;
10 MPlist *error_command_fail;
11 MPlist *error_lock_fail;
12
13 MSymbol Merror, Mvalue;
14 MSymbol Meval_function;
15
16 #define ERROR(msg)              \
17   do {                          \
18     m17n_object_ref (msg);      \
19     return msg;                 \
20   } while (0)
21
22 MPlist *eval (MPlist *);
23
24 #define INTEGERP(plist) (mplist_key (plist) == Minteger)
25 #define SYMBOLP(plist) (mplist_key (plist) == Msymbol)
26 #define MTEXTP(plist) (mplist_key (plist) == Mtext)
27 #define PLISTP(plist) (mplist_key (plist) == Mplist)
28 #define TAILP(plist) (mplist_key (plist) == Mnil)
29
30 MPlist *
31 eval_set (MPlist *arg)
32 {
33   MSymbol var;
34
35   if (! SYMBOLP (arg))
36     ERROR (error_invalid_arg);
37   var = mplist_value (arg);
38   arg = mplist_next (arg);
39   if (TAILP (arg))
40     msymbol_put (var, Mvalue, NULL);
41   else if (PLISTP (arg))
42     msymbol_put (var, Mvalue, eval (mplist_value (arg)));
43   else
44     {
45       m17n_object_ref (arg);
46       msymbol_put (var, Mvalue, arg);
47     }
48   return NULL;
49 }
50
51 MPlist *
52 eval_open (MPlist *arg)
53 {
54   MSymbol lang, name;
55   MInputMethod *im;;
56
57   if (! SYMBOLP (arg))
58     ERROR (error_invalid_arg);
59   lang = mplist_value (arg);
60   arg = mplist_next (arg);
61   if (! SYMBOLP (arg))
62     ERROR (error_invalid_arg);
63   name = mplist_value (arg);
64   im = minput_open_im (lang, name, Mnil);
65   arg = mplist ();
66   mplist_add (arg, Mt, im);
67   return arg;
68 }
69
70 MPlist *
71 eval_close (MPlist *arg)
72 {
73   MPlist *value;
74
75   if (! SYMBOLP (arg))
76     ERROR (error_invalid_arg);
77   value = msymbol_get (mplist_value (arg), Mvalue);
78   if (! value)
79     ERROR (error_invalid_arg);
80   minput_close_im (mplist_value (value));
81   return NULL;
82 }
83
84 MPlist *
85 eval_get_command (MPlist *arg)
86 {
87   MSymbol lang, name, command;
88
89   if (! SYMBOLP (arg))
90     ERROR (error_invalid_arg);
91   lang = mplist_value (arg);
92   arg = mplist_next (arg);
93   if (! SYMBOLP (arg))
94     ERROR (error_invalid_arg);
95   name = mplist_value (arg);
96   arg = mplist_next (arg);
97   if (SYMBOLP (arg))
98     command = mplist_value (arg);
99   else if (TAILP (arg))
100     command = Mnil;
101   else
102     ERROR (error_invalid_arg);
103   arg = minput_get_command (lang, name, command);
104   if (arg)
105     m17n_object_ref (arg);
106   return arg;
107 }
108
109 MPlist *
110 eval_config_command (MPlist *arg)
111 {
112   MSymbol lang, name, command;
113   MPlist *keyseq;
114
115   if (! SYMBOLP (arg))
116     ERROR (error_invalid_arg);
117   lang = mplist_value (arg);
118   arg = mplist_next (arg);
119   if (! SYMBOLP (arg))
120     ERROR (error_invalid_arg);
121   name = mplist_value (arg);
122   arg = mplist_next (arg);
123   if (SYMBOLP (arg))
124     {
125       command = mplist_value (arg);
126       arg = mplist_next (arg);
127     }
128   else if (TAILP (arg))
129     command = Mnil;
130   else
131     ERROR (error_invalid_arg);
132   if (PLISTP (arg))
133     keyseq = arg;
134   else
135     keyseq = NULL;
136   if (minput_config_command (lang, name, command, keyseq) < 0)
137     ERROR (error_command_fail);
138   return NULL;
139 }
140
141 MPlist *
142 eval_get_variable (MPlist *arg)
143 {
144   MSymbol lang, name, variable;
145
146   if (! SYMBOLP (arg))
147     ERROR (error_invalid_arg);
148   lang = mplist_value (arg);
149   arg = mplist_next (arg);
150   if (! SYMBOLP (arg))
151     ERROR (error_invalid_arg);
152   name = mplist_value (arg);
153   arg = mplist_next (arg);
154   if (SYMBOLP (arg))
155     variable = mplist_value (arg);
156   else if (TAILP (arg))
157     variable = Mnil;
158   else
159     ERROR (error_invalid_arg);
160   arg = minput_get_variable (lang, name, variable);
161   if (arg)
162     m17n_object_ref (arg);
163   return arg;
164 }
165
166 MPlist *
167 eval_config_variable (MPlist *arg)
168 {
169   MSymbol lang, name, variable;
170
171   if (! SYMBOLP (arg))
172     ERROR (error_invalid_arg);
173   lang = mplist_value (arg);
174   arg = mplist_next (arg);
175   if (! SYMBOLP (arg))
176     ERROR (error_invalid_arg);
177   name = mplist_value (arg);
178   arg = mplist_next (arg);
179   if (SYMBOLP (arg))
180     {
181       variable = mplist_value (arg);
182       arg = mplist_next (arg);
183     }
184   else if (TAILP (arg))
185     variable = Mnil;
186   else
187     ERROR (error_invalid_arg);
188   if (TAILP (arg))
189     arg = NULL;
190   if (minput_config_variable (lang, name, variable, arg) < 0)
191     ERROR (error_command_fail);
192   return NULL;
193 }
194
195 MPlist *
196 eval_save_config (MPlist *arg)
197 {
198   int ret = minput_save_config ();
199
200   if (ret < 0)
201     ERROR (error_command_fail);
202   if (ret == 0)
203     ERROR (error_lock_fail);
204   return NULL;
205 }
206
207 struct EvalFunc {
208   MPlist *(*eval_func) (MPlist *arg);
209 } eval_functions[] =
210   { {eval_set}, {eval_open}, {eval_close}, {eval_get_command},
211     {eval_config_command}, {eval_get_variable}, {eval_config_variable},
212     {eval_save_config} };
213
214 MPlist *
215 eval (MPlist *plist)
216 {
217   MSymbol cmd;
218   struct EvalFunc *eval_func;
219
220   if (! SYMBOLP (plist))
221     ERROR (error_invalid_format);
222   cmd = mplist_value (plist);
223   eval_func = msymbol_get (cmd, Meval_function);
224   if (! eval_func)
225     {
226       if (mplist_key (mplist_next (plist)) == Mnil)
227         {
228           MPlist *value = msymbol_get (cmd, Mvalue);
229
230           if (value)
231             return value;
232         }
233       ERROR (error_unknown_command);
234     }
235
236   return eval_func->eval_func (mplist_next (plist));
237 }
238
239 void
240 init (void)
241 {
242   Merror = msymbol ("error");
243   Mvalue = msymbol ("value");
244
245   Meval_function = msymbol ("eval-function");
246   msymbol_put (msymbol ("set"), Meval_function, eval_functions + 0);
247   msymbol_put (msymbol ("open"), Meval_function, eval_functions + 1);
248   msymbol_put (msymbol ("close"), Meval_function, eval_functions + 2);
249   msymbol_put (msymbol ("get-command"), Meval_function, eval_functions + 3);
250   msymbol_put (msymbol ("config-command"), Meval_function, eval_functions + 4);
251   msymbol_put (msymbol ("get-variable"), Meval_function, eval_functions + 5);
252   msymbol_put (msymbol ("config-variable"), Meval_function, eval_functions + 6);
253   msymbol_put (msymbol ("save-config"), Meval_function, eval_functions + 7);
254
255   error_invalid_format = mplist ();
256   mplist_add (error_invalid_format, Msymbol, Merror);
257   mplist_add (error_invalid_format, Msymbol, msymbol ("invalid-format"));
258
259   error_unknown_command = mplist ();
260   mplist_add (error_unknown_command, Msymbol, Merror);
261   mplist_add (error_unknown_command, Msymbol, msymbol ("unknwon-command"));
262
263   error_invalid_arg = mplist ();
264   mplist_add (error_invalid_arg, Msymbol, Merror);
265   mplist_add (error_invalid_arg, Msymbol, msymbol ("invalid-argument"));
266
267   error_command_fail = mplist ();
268   mplist_add (error_command_fail, Msymbol, Merror);
269   mplist_add (error_command_fail, Msymbol, msymbol ("command-fail"));
270
271   error_lock_fail = mplist ();
272   mplist_add (error_lock_fail, Msymbol, Merror);
273   mplist_add (error_lock_fail, Msymbol, msymbol ("lock-fail"));
274 }
275
276 void
277 fini (void)
278 {
279   m17n_object_unref (error_invalid_format);
280   m17n_object_unref (error_unknown_command);
281   m17n_object_unref (error_invalid_arg);
282   m17n_object_unref (error_command_fail);
283 }
284
285 int
286 main ()
287 {
288   char line[256];
289
290   M17N_INIT ();
291   init ();
292
293   while (printf ("> ") && fgets (line, 256, stdin) != NULL)
294     {
295       MText *mt;
296       MPlist *plist, *val;
297
298       if (line[strlen (line) - 1] == '\n')
299         line[strlen (line) - 1] = '\0';
300       mt = mtext_from_data (line, strlen (line), MTEXT_FORMAT_US_ASCII);
301       plist = mplist_deserialize (mt);
302       val = eval (plist);
303
304       if (val)
305         {
306           mdebug_dump_plist (val, 0);
307           putc ('\n', stderr);
308           fflush (stderr);
309           m17n_object_unref (val);
310         }
311       m17n_object_unref (plist);
312       m17n_object_unref (mt);
313     }
314
315   fini ();
316   M17N_FINI ();
317   exit (0);
318 }