*** empty log message ***
[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   else if (mplist_key (arg) == Mplist
181            && mplist_key ((MPlist *) mplist_value (arg)) == Mnil)
182     arg = (MPlist *) mplist_value (arg);
183   if (func (lang, name, target, arg) < 0)
184     ERROR (error_command_fail);
185   return NULL;
186 }
187
188 MPlist *
189 eval_config_command (MPlist *arg)
190 {
191   return call_config_common (minput_config_command, arg);
192 }
193
194 MPlist *
195 eval_config_variable (MPlist *arg)
196 {
197   return call_config_common (minput_config_variable, arg);
198 }
199
200 MPlist *
201 eval_save_config (MPlist *arg)
202 {
203   int ret = minput_save_config ();
204
205   if (ret < 0)
206     ERROR (error_command_fail);
207   if (ret == 0)
208     ERROR (error_lock_fail);
209   return NULL;
210 }
211
212 struct EvalFunc {
213   MPlist *(*eval_func) (MPlist *arg);
214   char *form;
215 } eval_functions[] =
216   { {eval_help, "help"},
217     {eval_set, "set SYMBOL FORM"},
218     {eval_open, "open LANG NAME"},
219     {eval_close, "close SYMBOL"},
220     {eval_get_description, "get-description LANG NAME"},
221     {eval_get_command, "get-command [LANG NAME [COMMAND]]"},
222     {eval_config_command, "config-command LANG NAME [COMMAND [(KEY ...) ...]]"},
223     {eval_get_variable, "get-variable [LANG NAME [VARIABLE]]"},
224     {eval_config_variable, "config-variable LANG NAME [VARIABLE [VALUE]]"},
225     {eval_save_config, "save-config"} };
226
227 MPlist *
228 eval_help (MPlist *arg)
229 {
230   int i;
231
232   printf ("Valid FORMs are:\n");
233   for (i = 0; i < (sizeof eval_functions) / (sizeof eval_functions[0]); i++)
234     printf ("  %s\n", eval_functions[i].form);
235   printf ("  SYMBOL -- print the value of SYMBOL\n");
236   return NULL;
237 }
238
239 MPlist *
240 eval (MPlist *plist)
241 {
242   MSymbol cmd;
243   struct EvalFunc *eval_func;
244
245   if (! SYMBOLP (plist))
246     ERROR (error_invalid_format);
247   cmd = mplist_value (plist);
248   eval_func = msymbol_get (cmd, Meval_function);
249   if (! eval_func)
250     {
251       if (mplist_key (mplist_next (plist)) == Mnil)
252         {
253           MPlist *value = msymbol_get (cmd, Mvalue);
254
255           if (value)
256             return value;
257         }
258       ERROR (error_unknown_command);
259     }
260
261   return eval_func->eval_func (mplist_next (plist));
262 }
263
264 void
265 init (void)
266 {
267   int n;
268
269   M17N_INIT ();
270
271   Merror = msymbol ("error");
272   Mvalue = msymbol ("value");
273
274   Meval_function = msymbol ("eval-function");
275   n = 0;
276   msymbol_put (msymbol ("help"), Meval_function, eval_functions + n), n++;
277   msymbol_put (msymbol ("set"), Meval_function, eval_functions + n), n++;
278   msymbol_put (msymbol ("open"), Meval_function, eval_functions + n), n++;
279   msymbol_put (msymbol ("close"), Meval_function, eval_functions + n), n++;
280   msymbol_put (msymbol ("get-description"), Meval_function, eval_functions + n), n++;
281   msymbol_put (msymbol ("get-command"), Meval_function, eval_functions + n), n++;
282   msymbol_put (msymbol ("config-command"), Meval_function, eval_functions + n), n++;
283   msymbol_put (msymbol ("get-variable"), Meval_function, eval_functions + n), n++;
284   msymbol_put (msymbol ("config-variable"), Meval_function, eval_functions + n), n++;
285   msymbol_put (msymbol ("save-config"), Meval_function, eval_functions + n);
286
287   error_invalid_format = mplist ();
288   mplist_add (error_invalid_format, Msymbol, Merror);
289   mplist_add (error_invalid_format, Msymbol, msymbol ("invalid-format"));
290
291   error_unknown_command = mplist ();
292   mplist_add (error_unknown_command, Msymbol, Merror);
293   mplist_add (error_unknown_command, Msymbol, msymbol ("unknwon-command"));
294
295   error_invalid_arg = mplist ();
296   mplist_add (error_invalid_arg, Msymbol, Merror);
297   mplist_add (error_invalid_arg, Msymbol, msymbol ("invalid-argument"));
298
299   error_command_fail = mplist ();
300   mplist_add (error_command_fail, Msymbol, Merror);
301   mplist_add (error_command_fail, Msymbol, msymbol ("command-fail"));
302
303   error_lock_fail = mplist ();
304   mplist_add (error_lock_fail, Msymbol, Merror);
305   mplist_add (error_lock_fail, Msymbol, msymbol ("lock-fail"));
306 }
307
308 void
309 fini (void)
310 {
311   m17n_object_unref (error_invalid_format);
312   m17n_object_unref (error_unknown_command);
313   m17n_object_unref (error_invalid_arg);
314   m17n_object_unref (error_command_fail);
315   m17n_object_unref (error_lock_fail);
316
317   M17N_FINI ();
318 }
319
320 int
321 main ()
322 {
323   char line[256];
324
325   setlocale (LC_ALL, "");
326
327   init ();
328
329   while (printf ("> ") && fgets (line, 256, stdin) != NULL)
330     {
331       MText *mt;
332       MPlist *plist, *val;
333       int len = strlen (line);
334
335       if (line[len - 1] == '\n')
336         line[--len] = '\0';
337       if (len == 0)
338         continue;
339
340       mt = mtext_from_data (line, len, MTEXT_FORMAT_US_ASCII);
341       plist = mplist_deserialize (mt);
342       val = eval (plist);
343
344       if (val)
345         {
346           mdebug_dump_plist (val, 0);
347           putc ('\n', stderr);
348           fflush (stderr);
349           m17n_object_unref (val);
350         }
351       m17n_object_unref (plist);
352       m17n_object_unref (mt);
353     }
354
355   fini ();
356   exit (0);
357 }