~ubuntu-branches/ubuntu/maverick/uim/maverick

« back to all changes in this revision

Viewing changes to uim/uim-custom.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2008-06-25 19:56:33 UTC
  • mfrom: (3.1.18 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080625195633-8jljph4rfq00l8o7
Tags: 1:1.5.1-2
* uim-tcode: provide tutcode-custom.scm, tutcode-bushudic.scm
  and tutcode-rule.scm (Closes: #482659)
* Fix FTBFS: segv during compile (Closes: #483078).
  I personally think this bug is not specific for uim but is a optimization
  problem on gcc-4.3.1. (https://bugs.freedesktop.org/show_bug.cgi?id=16477)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 
3
 
  Copyright (c) 2003-2006 uim Project http://uim.freedesktop.org/
 
3
  Copyright (c) 2003-2008 uim Project http://code.google.com/p/uim/
4
4
 
5
5
  All rights reserved.
6
6
 
49
49
#include <stdlib.h>
50
50
#include <stdio.h>
51
51
#include <string.h>
 
52
#include <stdarg.h>
 
53
#include "gettext.h"
 
54
 
52
55
#include "uim-scm.h"
53
 
#include "uim-compat-scm.h"
54
56
#include "uim-custom.h"
55
57
#include "uim-internal.h"
56
58
#include "uim-helper.h"
75
77
#define UIM_CUSTOM_EXPERIMENTAL_MTIME_SENSING
76
78
#endif
77
79
 
 
80
#define MAX_LENGTH_OF_INT_AS_STR (((sizeof(int) == 4) ? sizeof("-2147483648") : sizeof("-9223372036854775808")) - sizeof((char)'\0'))
 
81
 
 
82
#define UGETTEXT(str) (dgettext(GETTEXT_PACKAGE, (str)))
 
83
 
 
84
/* we cannot use the variadic macro (i.e. __VA_ARGS__) because we
 
85
   should also support C89 compilers
 
86
*/
 
87
#define UIM_EVAL_STRING_INTERNAL(uc, sexp_str) \
 
88
  (uim_scm_last_val = uim_scm_eval_c_string(sexp_str))
 
89
 
 
90
#define UIM_EVAL_STRING(uc, sexp_str) \
 
91
  { \
 
92
    UIM_EVAL_STRING_INTERNAL(uc, sexp_str); \
 
93
  }
 
94
 
 
95
#define UIM_EVAL_FSTRING1(uc, sexp_tmpl, arg1) \
 
96
  { \
 
97
    int form_size; \
 
98
    char *buf; \
 
99
    form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1); \
 
100
    if (form_size != -1) { \
 
101
      buf = malloc(form_size); \
 
102
      snprintf(buf, form_size, sexp_tmpl, arg1); \
 
103
      UIM_EVAL_STRING_INTERNAL(uc, buf); \
 
104
      free(buf); \
 
105
    } \
 
106
  }
 
107
 
 
108
#define UIM_EVAL_FSTRING2(uc, sexp_tmpl, arg1, arg2) \
 
109
  { \
 
110
    int form_size; \
 
111
    char *buf; \
 
112
    form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2); \
 
113
    if (form_size != -1) { \
 
114
      buf = malloc(form_size); \
 
115
      snprintf(buf, form_size, sexp_tmpl, arg1, arg2); \
 
116
      UIM_EVAL_STRING_INTERNAL(uc, buf); \
 
117
      free(buf); \
 
118
    } \
 
119
  }
 
120
 
 
121
#define UIM_EVAL_FSTRING3(uc, sexp_tmpl, arg1, arg2, arg3) \
 
122
  { \
 
123
    int form_size; \
 
124
    char *buf; \
 
125
    form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2, arg3); \
 
126
    if (form_size != -1) { \
 
127
      buf = malloc(form_size); \
 
128
      snprintf(buf, form_size, sexp_tmpl, arg1, arg2, arg3); \
 
129
      UIM_EVAL_STRING_INTERNAL(uc, buf); \
 
130
      free(buf); \
 
131
    } \
 
132
  }
 
133
 
 
134
#define UIM_EVAL_FSTRING4(uc, sexp_tmpl, arg1, arg2, arg3, arg4) \
 
135
  { \
 
136
    int form_size; \
 
137
    char *buf; \
 
138
    form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2, arg3, arg4); \
 
139
    if (form_size != -1) { \
 
140
      buf = malloc(form_size); \
 
141
      snprintf(buf, form_size, sexp_tmpl, arg1, arg2, arg3, arg4); \
 
142
      UIM_EVAL_STRING_INTERNAL(uc, buf); \
 
143
      free(buf); \
 
144
    } \
 
145
  }
 
146
 
 
147
#define UIM_EVAL_FSTRING5(uc, sexp_tmpl, arg1, arg2, arg3, arg4, arg5) \
 
148
  { \
 
149
    int form_size; \
 
150
    char *buf; \
 
151
    form_size = uim_sizeof_sexp_str(sexp_tmpl, arg1, arg2, arg3, arg4, arg5); \
 
152
    if (form_size != -1) { \
 
153
      buf = malloc(form_size); \
 
154
      snprintf(buf, form_size, sexp_tmpl, arg1, arg2, arg3, arg4, arg5); \
 
155
      UIM_EVAL_STRING_INTERNAL(uc, buf); \
 
156
      free(buf); \
 
157
    } \
 
158
  }
 
159
 
78
160
typedef void (*uim_custom_cb_update_cb_t)(void *ptr, const char *custom_sym);
79
161
typedef void (*uim_custom_global_cb_update_cb_t)(void *ptr);
80
162
 
 
163
typedef void *(*uim_scm_c_list_conv_func)(uim_lisp elem);
 
164
typedef void (*uim_scm_c_list_free_func)(void *elem);
 
165
 
81
166
/* exported for internal use */
82
167
uim_bool uim_custom_init(void);
83
168
uim_bool uim_custom_quit(void);
84
169
 
 
170
/* uim_scm_return_value() can only be used to retrieve result of
 
171
 * UIM_EVAL_FSTRINGn() or UIM_EVAL_STRING(). */
 
172
static uim_lisp uim_scm_return_value(void);
 
173
static int uim_sizeof_sexp_str(const char *tmpl, ...);
 
174
 
 
175
static void **uim_scm_c_list(const char *list_repl, const char *mapper_proc,
 
176
                             uim_scm_c_list_conv_func conv_func);
 
177
static char *uim_scm_c_str_failsafe(uim_lisp str);
 
178
static char **uim_scm_c_str_list(const char *list_repl,
 
179
                                 const char *mapper_proc);
 
180
static void uim_scm_c_list_free(void **list,
 
181
                                uim_scm_c_list_free_func free_func);
 
182
 
85
183
static char *literalize_string(const char *str);
 
184
static char *literalize_string_internal(const char *str);
86
185
 
87
186
static char *c_list_to_str(const void *const *list, char *(*mapper)(const void *elem), const char *sep);
88
187
 
89
188
static int uim_custom_type_eq(const char *custom_sym, const char *custom_type);
90
189
static int uim_custom_type(const char *custom_sym);
91
190
static int uim_custom_is_active(const char *custom_sym);
92
 
static char *uim_custom_get_str(const char *custom_sym, const char *proc);
 
191
static const char *uim_custom_get_str(const char *custom_sym,
 
192
                                      const char *proc);
93
193
static char *uim_custom_label(const char *custom_sym);
94
194
static char *uim_custom_desc(const char *custom_sym);
95
195
 
120
220
static void uim_custom_range_free(int custom_type, union uim_custom_range *custom_range);
121
221
static uim_lisp uim_custom_cb_update_cb_gate(uim_lisp cb, uim_lisp ptr, uim_lisp custom_sym);
122
222
static uim_lisp uim_custom_global_cb_update_cb_gate(uim_lisp cb, uim_lisp ptr);
 
223
static uim_bool custom_cb_remove(const char *key_sym, const char *hook);
123
224
static uim_bool custom_cb_add(const char *hook, const char *validator,
124
225
                              const char *custom_sym, void *ptr,
125
226
                              const char *gate_func, void (*cb)(void));
126
 
static uim_bool custom_cb_remove(const char *key_sym, const char *hook);
 
227
struct custom_cb_add_args {
 
228
  const char *hook;
 
229
  const char *validator;
 
230
  const char *custom_sym;
 
231
  void *ptr;
 
232
  const char *gate_func;
 
233
  void (*cb)(void);
 
234
};
 
235
static void *custom_cb_add_internal(struct custom_cb_add_args *args);
127
236
 
128
237
static void helper_disconnect_cb(void);
129
238
static char *uim_conf_path(const char *subpath);
134
243
static uim_bool uim_custom_load_group(const char *group);
135
244
static uim_bool uim_custom_save_group(const char *group);
136
245
 
137
 
#if UIM_SCM_GCC4_READY_GC
138
 
static char *literalize_string_internal(const char *str);
139
 
static uim_bool custom_cb_add_internal(const char *hook, const char *validator,
140
 
                                       const char *custom_sym, void *ptr,
141
 
                                       const char *gate_func, void (*cb)(void));
142
 
#endif
143
 
 
144
246
static const char str_list_arg[] = "uim-custom-c-str-list-arg";
145
247
static const char custom_subdir[] = "customs";
146
248
static const char custom_msg_tmpl[] = "prop_update_custom\n%s\n%s\n";
147
249
static int helper_fd = -1;
148
250
static uim_lisp return_val;
149
 
 
 
251
static uim_lisp uim_scm_last_val;
 
252
 
 
253
 
 
254
static uim_lisp
 
255
uim_scm_return_value(void)
 
256
{
 
257
  return uim_scm_last_val;
 
258
}
 
259
 
 
260
/** Calculate actual sexp string size from printf-style args.
 
261
 * This function calculates actual sexp string size from printf-style
 
262
 * args. Format string \a sexp_tmpl only accepts %d and %s.
 
263
 */
 
264
int
 
265
uim_sizeof_sexp_str(const char *sexp_tmpl, ...)
 
266
{
 
267
  va_list ap;
 
268
  int len, size;
 
269
  int tmp;
 
270
  const char *sexp_tmpl_end, *escp = sexp_tmpl, *strarg;
 
271
  char fmtchr;
 
272
 
 
273
  va_start(ap, sexp_tmpl);
 
274
  len = strlen(sexp_tmpl);
 
275
  sexp_tmpl_end = sexp_tmpl + len - 1;
 
276
  while ((escp = strchr(escp, '%'))) {
 
277
    if (escp < sexp_tmpl_end) {
 
278
      escp += sizeof((char)'%');
 
279
      fmtchr = *escp++;
 
280
      switch (fmtchr) {
 
281
      case 'd':
 
282
        tmp = va_arg(ap, int);
 
283
        len += MAX_LENGTH_OF_INT_AS_STR;
 
284
        break;
 
285
      case 's':
 
286
        strarg = va_arg(ap, const char *);
 
287
        len += strlen(strarg);
 
288
        break;
 
289
      default:
 
290
        /* unexpected format string */
 
291
        size = -1;
 
292
        goto end;
 
293
      }
 
294
    } else {
 
295
      /* invalid format string */
 
296
      size = -1;
 
297
      goto end;
 
298
    }
 
299
  }
 
300
  size = len + sizeof((char)'\0');
 
301
 
 
302
 end:
 
303
  va_end(ap);
 
304
 
 
305
  return size;
 
306
}
 
307
 
 
308
/*
 
309
  - list_repl must always returns same list for each evaluation
 
310
  - returns NULL terminated array. NULL will not appeared except terminator
 
311
  - non-string element such as #f is converted to ""
 
312
 */
 
313
static void **
 
314
uim_scm_c_list(const char *list_repl, const char *mapper_proc,
 
315
               uim_scm_c_list_conv_func conv_func)
 
316
{
 
317
  int list_len, i;
 
318
  void **result;
 
319
 
 
320
  UIM_EVAL_FSTRING1(NULL, "(length %s)", list_repl);
 
321
  list_len = uim_scm_c_int(uim_scm_return_value());
 
322
 
 
323
  result = (void **)malloc(sizeof(void *) * (list_len + 1));
 
324
  if (!result)
 
325
    return NULL;
 
326
 
 
327
  result[list_len] = NULL;
 
328
  for (i = 0; i < list_len; i++) {
 
329
    UIM_EVAL_FSTRING3(NULL, "(%s (nth %d %s))", mapper_proc, i, list_repl);
 
330
    result[i] = (*conv_func)(uim_scm_return_value());
 
331
  }
 
332
 
 
333
  return result;
 
334
}
 
335
 
 
336
static char *
 
337
uim_scm_c_str_failsafe(uim_lisp str)
 
338
{
 
339
  return (uim_scm_truep(str)) ? uim_scm_c_str(str) : strdup("");
 
340
}
 
341
 
 
342
static char **
 
343
uim_scm_c_str_list(const char *list_repl, const char *mapper_proc)
 
344
{
 
345
  void **list;
 
346
  
 
347
  list = uim_scm_c_list(list_repl, mapper_proc,
 
348
                        (uim_scm_c_list_conv_func)uim_scm_c_str_failsafe);
 
349
 
 
350
  return (char **)list;
 
351
}
 
352
 
 
353
static void
 
354
uim_scm_c_list_free(void **list, uim_scm_c_list_free_func free_func)
 
355
{
 
356
  void *elem;
 
357
  void **p;
 
358
 
 
359
  if (!list)
 
360
    return;
 
361
 
 
362
  for (p = list; *p; p++) {
 
363
    elem = *p;
 
364
    free_func(elem);
 
365
  }
 
366
  free(list);
 
367
}
150
368
 
151
369
static char *
152
370
literalize_string(const char *str)
153
 
#if UIM_SCM_GCC4_READY_GC
154
371
{
155
 
  char *ret;
156
 
 
157
 
  UIM_SCM_GC_PROTECTED_CALL(ret, char *, literalize_string_internal, (str));
158
 
 
159
 
  return ret;
 
372
  return uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)literalize_string_internal, (void *)str);
160
373
}
161
374
 
162
375
static char *
163
376
literalize_string_internal(const char *str)
164
 
#endif
165
377
{
166
 
#if !UIM_SCM_GCC4_READY_GC
167
 
  uim_lisp stack_start;
168
 
#endif
169
378
  uim_lisp form;
170
379
  char *escaped;
171
380
 
172
 
#if !UIM_SCM_GCC4_READY_GC
173
 
  uim_scm_gc_protect_stack(&stack_start);
174
 
#endif
175
 
 
176
381
  form = uim_scm_list2(uim_scm_make_symbol("string-escape"),
177
382
                       uim_scm_make_str(str));
178
383
  escaped = uim_scm_c_str(uim_scm_eval(form));
179
384
 
180
 
#if !UIM_SCM_GCC4_READY_GC
181
 
  uim_scm_gc_unprotect_stack(&stack_start);
182
 
#endif
183
 
 
184
385
  return escaped;
185
386
}
186
387
 
256
457
  return uim_scm_c_bool(return_val);
257
458
}
258
459
 
259
 
static char *
 
460
static const char *
260
461
uim_custom_get_str(const char *custom_sym, const char *proc)
261
462
{
262
463
  UIM_EVAL_FSTRING2(NULL, "(%s '%s)", proc, custom_sym);
263
464
  return_val = uim_scm_return_value();
264
465
 
265
 
  /*
266
 
    The arg must be assigned to return_val to be proteced from GC
267
 
    while evaluation
268
 
  */
269
 
  return uim_scm_c_str(return_val);
 
466
  return uim_scm_refer_c_str(return_val);
270
467
}
271
468
 
272
469
static char *
273
470
uim_custom_label(const char *custom_sym)
274
471
{
275
 
  return uim_custom_get_str(custom_sym, "custom-label");
 
472
  const char *str;
 
473
 
 
474
  str = uim_custom_get_str(custom_sym, "custom-label");
 
475
  return strdup(UGETTEXT(str));
276
476
}
277
477
 
278
478
static char *
279
479
uim_custom_desc(const char *custom_sym)
280
480
{
281
 
  return uim_custom_get_str(custom_sym, "custom-desc");
 
481
  const char *str;
 
482
 
 
483
  str = uim_custom_get_str(custom_sym, "custom-desc");
 
484
  return strdup(UGETTEXT(str));
282
485
}
283
486
 
284
487
/* pathname */
348
551
  UIM_EVAL_FSTRING2(NULL, "(custom-choice-label '%s '%s)",
349
552
                    custom_sym, choice_sym);
350
553
  return_val = uim_scm_return_value();
351
 
  c_choice->label = uim_scm_c_str(return_val);
 
554
  c_choice->label = strdup(UGETTEXT(uim_scm_refer_c_str(return_val)));
352
555
 
353
556
  UIM_EVAL_FSTRING2(NULL, "(custom-choice-desc '%s '%s)",
354
557
                    custom_sym, choice_sym);
355
558
  return_val = uim_scm_return_value();
356
 
  c_choice->desc = uim_scm_c_str(return_val);
 
559
  c_choice->desc = strdup(UGETTEXT(uim_scm_refer_c_str(return_val)));
357
560
 
358
561
  return c_choice;
359
562
}
781
984
uim_bool
782
985
uim_custom_init(void)
783
986
{
 
987
  const char *client_codeset;
 
988
 
784
989
  return_val = uim_scm_f();
785
 
 
 
990
  uim_scm_last_val = uim_scm_f();
786
991
  uim_scm_gc_protect(&return_val);
 
992
  uim_scm_gc_protect(&uim_scm_last_val);
787
993
 
788
 
  uim_scm_init_subr_3("custom-update-cb-gate", uim_custom_cb_update_cb_gate);
789
 
  uim_scm_init_subr_2("custom-global-update-cb-gate",
790
 
                      uim_custom_global_cb_update_cb_gate);
 
994
  uim_scm_init_proc3("custom-update-cb-gate", uim_custom_cb_update_cb_gate);
 
995
  uim_scm_init_proc2("custom-global-update-cb-gate",
 
996
                     uim_custom_global_cb_update_cb_gate);
791
997
 
792
998
  uim_scm_require_file("custom.scm");
793
999
 
794
1000
  /* temporary solution to control key definition expantion */
795
1001
  UIM_EVAL_STRING(NULL, "(define uim-custom-expand-key? #t)");
796
1002
 
 
1003
  /* Assumes that bind_textdomain_codeset() is already called in client
 
1004
   * program. */
 
1005
  client_codeset = bind_textdomain_codeset(textdomain(NULL), NULL);
 
1006
  bind_textdomain_codeset(GETTEXT_PACKAGE, client_codeset);
 
1007
 
797
1008
  return UIM_TRUE;
798
1009
}
799
1010
 
821
1032
{
822
1033
  char *dir;
823
1034
 
824
 
  UIM_EVAL_STRING(NULL, "(string-append (getenv \"HOME\") \"/.uim.d\")");
 
1035
  UIM_EVAL_STRING(NULL, "(string-append (or (home-directory (user-name)) \"\") \"/.uim.d\")");
825
1036
  dir = uim_scm_c_str(uim_scm_return_value());
826
1037
  if (subpath) {
827
1038
    UIM_EVAL_FSTRING2(NULL, "\"%s/%s\"", dir, subpath);
1097
1308
        uim_custom_symbol_list_free(custom_syms);
1098
1309
        return UIM_FALSE;
1099
1310
      }
1100
 
      sprintf(msg, custom_msg_tmpl, *sym, value);
 
1311
      snprintf(msg, msg_size, custom_msg_tmpl, *sym, value);
1101
1312
      uim_helper_send_message(helper_fd, msg);
1102
1313
      free(msg);
1103
1314
      free(value);
1273
1484
char *
1274
1485
uim_custom_value_as_literal(const char *custom_sym)
1275
1486
{
1276
 
  return uim_custom_get_str(custom_sym, "custom-value-as-literal");
 
1487
  return strdup(uim_custom_get_str(custom_sym, "custom-value-as-literal"));
1277
1488
}
1278
1489
 
1279
1490
/**
1286
1497
char *
1287
1498
uim_custom_definition_as_literal(const char *custom_sym)
1288
1499
{
1289
 
  return uim_custom_get_str(custom_sym, "custom-definition-as-literal");
 
1500
  return strdup(uim_custom_get_str(custom_sym, "custom-definition-as-literal"));
1290
1501
}
1291
1502
 
1292
1503
/**
1301
1512
uim_custom_group_get(const char *group_sym)
1302
1513
{
1303
1514
  struct uim_custom_group *custom_group;
 
1515
  const char *label, *desc;
1304
1516
 
1305
1517
  custom_group = (struct uim_custom_group *)malloc(sizeof(struct uim_custom_group));
1306
1518
  if (!custom_group)
1307
1519
    return NULL;
1308
1520
 
 
1521
  label = uim_custom_get_str(group_sym, "custom-group-label");
 
1522
  desc = uim_custom_get_str(group_sym, "custom-group-desc");
 
1523
 
1309
1524
  custom_group->symbol = strdup(group_sym);
1310
 
  custom_group->label = uim_custom_get_str(group_sym, "custom-group-label");
1311
 
  custom_group->desc = uim_custom_get_str(group_sym, "custom-group-desc");
 
1525
  custom_group->label = strdup(UGETTEXT(label));
 
1526
  custom_group->desc = strdup(UGETTEXT(desc));
1312
1527
 
1313
1528
  return custom_group;
1314
1529
}
1461
1676
custom_cb_add(const char *hook, const char *validator,
1462
1677
              const char *custom_sym, void *ptr,
1463
1678
              const char *gate_func, void (*cb)(void))
1464
 
#if UIM_SCM_GCC4_READY_GC
1465
1679
{
1466
 
  uim_bool ret;
1467
 
 
1468
 
  UIM_SCM_GC_PROTECTED_CALL(ret, uim_bool, custom_cb_add_internal,
1469
 
                            (hook, validator, custom_sym, ptr, gate_func, cb));
1470
 
 
1471
 
  return ret;
 
1680
  struct custom_cb_add_args args;
 
1681
 
 
1682
  args.hook = hook;
 
1683
  args.validator = validator;
 
1684
  args.custom_sym = custom_sym;
 
1685
  args.ptr = ptr;
 
1686
  args.gate_func = gate_func;
 
1687
  args.cb = cb;
 
1688
  return (uim_bool)(uintptr_t)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)custom_cb_add_internal, &args);
1472
1689
}
1473
1690
 
1474
 
static uim_bool
1475
 
custom_cb_add_internal(const char *hook, const char *validator,
1476
 
                       const char *custom_sym, void *ptr,
1477
 
                       const char *gate_func, void (*cb)(void))
1478
 
#endif
 
1691
static void *
 
1692
custom_cb_add_internal(struct custom_cb_add_args *args)
1479
1693
{
1480
1694
  uim_bool succeeded;
1481
 
#if !UIM_SCM_GCC4_READY_GC
1482
 
  uim_lisp stack_start;
1483
 
#endif
 
1695
  const char *hook;
 
1696
  const char *validator;
 
1697
  const char *custom_sym;
 
1698
  void *ptr;
 
1699
  const char *gate_func;
 
1700
  void (*cb)(void);
1484
1701
  uim_lisp form;
1485
1702
 
1486
 
#if !UIM_SCM_GCC4_READY_GC
1487
 
  uim_scm_gc_protect_stack(&stack_start);
1488
 
#endif
 
1703
  hook = args->hook;
 
1704
  validator = args->validator;
 
1705
  custom_sym = args->custom_sym;
 
1706
  ptr = args->ptr;
 
1707
  gate_func = args->gate_func;
 
1708
  cb = args->cb;
1489
1709
 
1490
1710
  form = uim_scm_list5(uim_scm_make_symbol(validator),
1491
1711
                       uim_scm_quote(uim_scm_make_symbol(custom_sym)),
1496
1716
  form = uim_scm_cons(uim_scm_make_symbol("custom-register-cb"), form);
1497
1717
  succeeded = uim_scm_c_bool(uim_scm_eval(form));
1498
1718
 
1499
 
#if !UIM_SCM_GCC4_READY_GC
1500
 
  uim_scm_gc_unprotect_stack(&stack_start);
1501
 
#endif
1502
 
 
1503
 
  return succeeded;
 
1719
  return (void *)(uintptr_t)succeeded;
1504
1720
}
1505
1721
 
1506
1722
static uim_bool