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