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