SVN EFL Migration SVN-54790
[framework/uifw/evas.git] / src / lib / file / evas_module.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <string.h>
6
7 #include <evas_common.h>
8 #include <evas_private.h>
9 #include <evas_module.h>
10
11 #ifdef _WIN32
12 # ifdef open
13 #  undef open
14 # endif
15 # ifdef close
16 #  undef close
17 # endif
18 #endif
19
20
21 static Eina_Hash *evas_modules[4] = {
22   NULL,
23   NULL,
24   NULL,
25   NULL
26 };
27
28 static Eina_List *eina_evas_modules = NULL;
29 static Eina_List *evas_module_paths = NULL;
30 static Eina_Array *evas_engines = NULL;
31
32 static Eina_List *
33 _evas_module_append(Eina_List *list, char *path)
34 {
35    if (path)
36      {
37         if (evas_file_path_exists(path))
38           list = eina_list_append(list, path);
39         else
40           free(path);
41      }
42    return list;
43 }
44
45 /* this will alloc a list of paths to search for the modules */
46 /* by now these are:  */
47 /* 1. ~/.evas/modules/ */
48 /* 2. $(EVAS_MODULE_DIR)/evas/modules/ */
49 /* 3. dladdr/evas/modules/ */
50 /* 4. PREFIX/evas/modules/ */
51 void
52 evas_module_paths_init(void)
53 {
54    char *path, *path2;
55 #ifndef _MSC_VER
56    const char *path3;
57 #endif
58
59    /* 1. ~/.evas/modules/ */
60    path = eina_module_environment_path_get("HOME", "/.evas/modules");
61    evas_module_paths = _evas_module_append(evas_module_paths, path);
62
63    /* 2. $(EVAS_MODULE_DIR)/evas/modules/ */
64    path = eina_module_environment_path_get("EVAS_MODULES_DIR", "/evas/modules");
65    evas_module_paths = _evas_module_append(evas_module_paths, path);
66
67    /* 3. libevas.so/../evas/modules/ */
68    path2 = eina_module_symbol_path_get(evas_module_paths_init, "/evas/modules");
69    if (path2 && path && (strcmp(path, path2) == 0))
70      free(path2);
71    else
72      evas_module_paths = _evas_module_append(evas_module_paths, path2);
73
74    /* 4. PREFIX/evas/modules/ */
75 #ifndef _MSC_VER
76    path3 = PACKAGE_LIB_DIR "/evas/modules";
77    if ((path && (strcmp(path, path3) != 0)) ||
78        (path2 && (strcmp(path2, path3) != 0)) ||
79        (!path && !path2))
80      {
81         path = strdup(path3);
82         if (path)
83           evas_module_paths = _evas_module_append(evas_module_paths, path);
84      }
85 #endif
86 }
87
88 #define EVAS_EINA_STATIC_MODULE_DEFINE(Tn, Name)        \
89   Eina_Bool evas_##Tn##_##Name##_init(void);            \
90   void evas_##Tn##_##Name##_shutdown(void);
91
92 #define EVAS_EINA_STATIC_MODULE_USE(Tn, Name)   \
93   { evas_##Tn##_##Name##_init, evas_##Tn##_##Name##_shutdown }
94
95 EVAS_EINA_STATIC_MODULE_DEFINE(engine, buffer);
96 EVAS_EINA_STATIC_MODULE_DEFINE(engine, cairo_x11);
97 EVAS_EINA_STATIC_MODULE_DEFINE(engine, direct3d);
98 EVAS_EINA_STATIC_MODULE_DEFINE(engine, directfb);
99 EVAS_EINA_STATIC_MODULE_DEFINE(engine, fb);
100 EVAS_EINA_STATIC_MODULE_DEFINE(engine, gl_glew);
101 EVAS_EINA_STATIC_MODULE_DEFINE(engine, gl_x11);
102 EVAS_EINA_STATIC_MODULE_DEFINE(engine, gl_sdl);
103 EVAS_EINA_STATIC_MODULE_DEFINE(engine, quartz);
104 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16);
105 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_ddraw);
106 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_sdl);
107 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_wince);
108 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_x11);
109 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_8);
110 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_8_x11);
111 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_ddraw);
112 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_gdi);
113 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_generic);
114 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_qtopia);
115 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_sdl);
116 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_x11);
117 EVAS_EINA_STATIC_MODULE_DEFINE(engine, xrender_x11);
118 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, xpm);
119 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp);
120 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tiff);
121 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, svg);
122 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, png);
123 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, pmaps);
124 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jpeg);
125 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, gif);
126 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet);
127 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, edb);
128 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga);
129 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, wbmp);
130 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, edb);
131 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet);
132 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg);
133 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, png);
134 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, tiff);
135
136 static const struct {
137    Eina_Bool (*init)(void);
138    void (*shutdown)(void);
139 } evas_static_module[] = {
140 #ifdef EVAS_STATIC_BUILD_BUFFER
141   EVAS_EINA_STATIC_MODULE_USE(engine, buffer),
142 #endif
143 #ifdef EVAS_STATIC_BUILD_CAIRO_X11
144   EVAS_EINA_STATIC_MODULE_USE(engine, cairo_x11),
145 #endif
146 #ifdef EVAS_STATIC_BUILD_DIRECT3D
147   EVAS_EINA_STATIC_MODULE_USE(engine, direct3d),
148 #endif
149 #ifdef EVAS_STATIC_BUILD_DIRECTFB
150   EVAS_EINA_STATIC_MODULE_USE(engine, directfb),
151 #endif
152 #ifdef EVAS_STATIC_BUILD_FB
153   EVAS_EINA_STATIC_MODULE_USE(engine, fb),
154 #endif
155 #ifdef EVAS_STATIC_BUILD_GL_GLEW
156   EVAS_EINA_STATIC_MODULE_USE(engine, gl_glew),
157 #endif
158 #ifdef EVAS_STATIC_BUILD_GL_X11
159   EVAS_EINA_STATIC_MODULE_USE(engine, gl_x11),
160 #endif
161 #ifdef EVAS_STATIC_BUILD_GL_SDL
162   EVAS_EINA_STATIC_MODULE_USE(engine, gl_sdl),
163 #endif
164 #ifdef EVAS_STATIC_BUILD_QUARTZ
165   EVAS_EINA_STATIC_MODULE_USE(engine, quartz),
166 #endif
167 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16
168   EVAS_EINA_STATIC_MODULE_USE(engine, software_16),
169 #endif
170 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_DDRAW
171   EVAS_EINA_STATIC_MODULE_USE(engine, software_16_ddraw),
172 #endif
173 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_SDL
174   EVAS_EINA_STATIC_MODULE_USE(engine, software_16_sdl),
175 #endif
176 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_WINCE
177   EVAS_EINA_STATIC_MODULE_USE(engine, software_16_wince),
178 #endif
179 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_X11
180   EVAS_EINA_STATIC_MODULE_USE(engine, software_16_x11),
181 #endif
182 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_DDRAW
183   EVAS_EINA_STATIC_MODULE_USE(engine, software_ddraw),
184 #endif
185 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_GDI
186   EVAS_EINA_STATIC_MODULE_USE(engine, software_gdi),
187 #endif
188 #ifdef EVAS_STATIC_BUILD_SOFTWARE_8
189   EVAS_EINA_STATIC_MODULE_USE(engine, software_8),
190 #endif
191 #ifdef EVAS_STATIC_BUILD_SOFTWARE_8_X11
192   EVAS_EINA_STATIC_MODULE_USE(engine, software_8_x11),
193 #endif
194 #ifdef EVAS_STATIC_BUILD_SOFTWARE_GENERIC
195   EVAS_EINA_STATIC_MODULE_USE(engine, software_generic),
196 #endif
197 #ifdef EVAS_STATIC_BUILD_SOFTWARE_QTOPIA
198   EVAS_EINA_STATIC_MODULE_USE(engine, software_qtopia),
199 #endif
200 #ifdef EVAS_STATIC_BUILD_SOFTWARE_SDL
201   EVAS_EINA_STATIC_MODULE_USE(engine, software_sdl),
202 #endif
203 #ifdef EVAS_STATIC_BUILD_SOFTWARE_X11
204   EVAS_EINA_STATIC_MODULE_USE(engine, software_x11),
205 #endif
206 #ifdef EVAS_STATIC_BUILD_XRENDER_X11
207   EVAS_EINA_STATIC_MODULE_USE(engine, xrender_x11),
208 #endif
209 #ifdef EVAS_STATIC_BUILD_XPM
210   EVAS_EINA_STATIC_MODULE_USE(image_loader, xpm),
211 #endif
212 #ifdef EVAS_STATIC_BUILD_BMP
213   EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp),
214 #endif
215 #ifdef EVAS_STATIC_BUILD_TIFF
216   EVAS_EINA_STATIC_MODULE_USE(image_loader, tiff),
217 #endif
218 #ifdef EVAS_STATIC_BUILD_SVG
219   EVAS_EINA_STATIC_MODULE_USE(image_loader, svg),
220 #endif
221 #ifdef EVAS_STATIC_BUILD_PNG
222   EVAS_EINA_STATIC_MODULE_USE(image_loader, png),
223 #endif
224 #ifdef EVAS_STATIC_BUILD_PMAPS
225   EVAS_EINA_STATIC_MODULE_USE(image_loader, pmaps),
226 #endif
227 #ifdef EVAS_STATIC_BUILD_JPEG
228   EVAS_EINA_STATIC_MODULE_USE(image_loader, jpeg),
229 #endif
230 #ifdef EVAS_STATIC_BUILD_GIF
231   EVAS_EINA_STATIC_MODULE_USE(image_loader, gif),
232 #endif
233 #ifdef EVAS_STATIC_BUILD_EET
234   EVAS_EINA_STATIC_MODULE_USE(image_loader, eet),
235 #endif
236 #ifdef EVAS_STATIC_BUILD_EDB
237   EVAS_EINA_STATIC_MODULE_USE(image_loader, edb),
238 #endif
239 #ifdef EVAS_STATIC_BUILD_TGA
240   EVAS_EINA_STATIC_MODULE_USE(image_loader, tga),
241 #endif
242 #ifdef EVAS_STATIC_BUILD_WBMP
243   EVAS_EINA_STATIC_MODULE_USE(image_loader, wbmp),
244 #endif
245 #ifdef EVAS_STATIC_BUILD_EDB
246   EVAS_EINA_STATIC_MODULE_USE(image_saver, edb),
247 #endif
248 #ifdef EVAS_STATIC_BUILD_EET
249   EVAS_EINA_STATIC_MODULE_USE(image_saver, eet),
250 #endif
251 #ifdef EVAS_STATIC_BUILD_JPEG
252   EVAS_EINA_STATIC_MODULE_USE(image_saver, jpeg),
253 #endif
254 #ifdef EVAS_STATIC_BUILD_PNG
255   EVAS_EINA_STATIC_MODULE_USE(image_saver, png),
256 #endif
257 #ifdef EVAS_STATIC_BUILD_TIFF
258   EVAS_EINA_STATIC_MODULE_USE(image_saver, tiff),
259 #endif
260   { NULL, NULL }
261 };
262
263 /* this will alloc an Evas_Module struct for each module
264  * it finds on the paths */
265 void
266 evas_module_init(void)
267 {
268    int i;
269
270    evas_module_paths_init();
271
272    evas_modules[EVAS_MODULE_TYPE_ENGINE] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
273    evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
274    evas_modules[EVAS_MODULE_TYPE_IMAGE_SAVER] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
275    evas_modules[EVAS_MODULE_TYPE_OBJECT] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
276
277    evas_engines = eina_array_new(4);
278
279    for (i = 0; evas_static_module[i].init; ++i)
280      evas_static_module[i].init();
281 }
282
283 Eina_Bool
284 evas_module_register(const Evas_Module_Api *module, Evas_Module_Type type)
285 {
286    Evas_Module *em;
287
288    if ((unsigned int)type > 3) return EINA_FALSE;
289    if (!module) return EINA_FALSE;
290    if (module->version != EVAS_MODULE_API_VERSION) return EINA_FALSE;
291
292    em = eina_hash_find(evas_modules[type], module->name);
293    if (em) return EINA_FALSE;
294
295    em = calloc(1, sizeof (Evas_Module));
296    if (!em) return EINA_FALSE;
297
298    em->definition = module;
299
300    if (type == EVAS_MODULE_TYPE_ENGINE)
301      {
302         eina_array_push(evas_engines, em);
303         em->id_engine = eina_array_count_get(evas_engines);
304      }
305
306    eina_hash_direct_add(evas_modules[type], module->name, em);
307
308    return EINA_TRUE;
309 }
310
311 Eina_Bool
312 evas_module_unregister(const Evas_Module_Api *module, Evas_Module_Type type)
313 {
314    Evas_Module *em;
315
316    if ((unsigned int)type > 3) return EINA_FALSE;
317    if (!module) return EINA_FALSE;
318
319    em = eina_hash_find(evas_modules[type], module->name);
320    if (!em || em->definition != module) return EINA_FALSE;
321
322    if (type == EVAS_MODULE_TYPE_ENGINE)
323      eina_array_data_set(evas_engines, em->id_engine, NULL);
324
325    eina_hash_del(evas_modules[type], module->name, em);
326    free(em);
327
328    return EINA_TRUE;
329 }
330
331 #if defined(__CEGCC__) || defined(__MINGW32CE__)
332 # define EVAS_MODULE_NAME_IMAGE_SAVER "saver_%s.dll"
333 # define EVAS_MODULE_NAME_IMAGE_LOADER "loader_%s.dll"
334 # define EVAS_MODULE_NAME_ENGINE "engine_%s.dll"
335 # define EVAS_MODULE_NAME_OBJECT "object_%s.dll"
336 #elif _WIN32
337 # define EVAS_MODULE_NAME_IMAGE_SAVER "module.dll"
338 # define EVAS_MODULE_NAME_IMAGE_LOADER "module.dll"
339 # define EVAS_MODULE_NAME_ENGINE "module.dll"
340 # define EVAS_MODULE_NAME_OBJECT "module.dll"
341 #else
342 # define EVAS_MODULE_NAME_IMAGE_SAVER "module.so"
343 # define EVAS_MODULE_NAME_IMAGE_LOADER "module.so"
344 # define EVAS_MODULE_NAME_ENGINE "module.so"
345 # define EVAS_MODULE_NAME_OBJECT "module.so"
346 #endif
347
348 Evas_Module *
349 evas_module_find_type(Evas_Module_Type type, const char *name)
350 {
351    const char *path;
352    const char *format = NULL;
353    char buffer[4096];
354    Evas_Module *em;
355    Eina_Module *en;
356    Eina_List *l;
357
358    if ((unsigned int)type > 3) return NULL;
359
360    em = eina_hash_find(evas_modules[type], name);
361    if (em) return em;
362
363    EINA_LIST_FOREACH(evas_module_paths, l, path)
364      {
365         switch (type)
366           {
367            case EVAS_MODULE_TYPE_ENGINE: format = "%s/engines/%s/%s/" EVAS_MODULE_NAME_ENGINE; break;
368            case EVAS_MODULE_TYPE_IMAGE_LOADER: format = "%s/loaders/%s/%s/" EVAS_MODULE_NAME_IMAGE_LOADER; break;
369            case EVAS_MODULE_TYPE_IMAGE_SAVER: format = "%s/savers/%s/%s/" EVAS_MODULE_NAME_IMAGE_SAVER; break;
370            case EVAS_MODULE_TYPE_OBJECT: format = "%s/object/%s/%s/" EVAS_MODULE_NAME_OBJECT; break;
371           }
372
373         snprintf(buffer, sizeof (buffer), format, path, name, MODULE_ARCH, name);
374         if (!evas_file_path_is_file(buffer)) continue;
375
376         en = eina_module_new(buffer);
377         if (!en) continue;
378
379         if (!eina_module_load(en))
380           {
381              eina_module_free(en);
382              continue;
383           }
384
385         em = eina_hash_find(evas_modules[type], name);
386         if (em)
387           {
388              eina_evas_modules = eina_list_append(eina_evas_modules, en);
389              return em;
390           }
391
392         eina_module_free(en);
393      }
394
395    return NULL;
396 }
397
398 Evas_Module *
399 evas_module_engine_get(int render_method)
400 {
401    if ((render_method <= 0) ||
402        ((unsigned int)render_method > eina_array_count_get(evas_engines)))
403      return NULL;
404    return eina_array_data_get(evas_engines, render_method - 1);
405 }
406
407 void
408 evas_module_foreach_image_loader(Eina_Hash_Foreach cb, const void *fdata)
409 {
410    eina_hash_foreach(evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER], cb, fdata);
411 }
412
413 int
414 evas_module_load(Evas_Module *em)
415 {
416    if (em->loaded) return 1;
417    if (!em->definition) return 0;
418
419    if (!em->definition->func.open(em)) return 0;
420    em->loaded = 1;
421
422 #ifdef BUILD_ASYNC_PRELOAD
423    LKI(em->lock);
424 #endif
425    return 1;
426 }
427
428 void
429 evas_module_unload(Evas_Module *em)
430 {
431    if (!em->loaded)
432      return;
433    if (!em->definition)
434      return ;
435
436 // for now lets not unload modules - they may still be in use.   
437 //   em->definition->func.close(em);
438 //   em->loaded = 0;
439
440 #ifdef BUILD_ASYNC_PRELOAD
441    LKD(em->lock);
442 #endif
443 }
444
445 void
446 evas_module_ref(Evas_Module *em)
447 {
448 #ifdef BUILD_ASYNC_PRELOAD
449    LKL(em->lock);
450 #endif
451    em->ref++;
452 #ifdef BUILD_ASYNC_PRELOAD
453    LKU(em->lock);
454 #endif
455 }
456
457 void
458 evas_module_unref(Evas_Module *em)
459 {
460 #ifdef BUILD_ASYNC_PRELOAD
461    LKL(em->lock);
462 #endif
463    em->ref--;
464 #ifdef BUILD_ASYNC_PRELOAD
465    LKU(em->lock);
466 #endif
467 }
468
469 static int use_count = 0;
470
471 void
472 evas_module_use(Evas_Module *em)
473 {
474    em->last_used = use_count;
475 }
476
477 void
478 evas_module_clean(void)
479 {
480    static int call_count = 0;
481 /*    int ago; */
482    int noclean = -1;
483 /*    Eina_List *l; */
484 /*    Evas_Module *em; */
485
486    /* only clean modules every 256 calls */
487    call_count++;
488    if (call_count <= 256) return;
489    call_count = 0;
490
491    if (noclean == -1)
492      {
493         if (getenv("EVAS_NOCLEAN"))
494           noclean = 1;
495         else 
496           noclean = 0;
497      }
498    if (noclean == 1) return;
499
500    /* disable module cleaning for now - may cause instability with some modules */
501    return;
502
503    /* FIXME: Don't know what it is supposed to do. */
504 /*    /\* incriment use counter = 28bits *\/ */
505 /*    use_count++; */
506 /*    if (use_count > 0x0fffffff) use_count = 0; */
507
508 /*    /\* printf("CLEAN!\n"); *\/ */
509 /*    /\* go through all modules *\/ */
510 /*    EINA_LIST_FOREACH(evas_modules, l, em) */
511 /*      { */
512 /*         /\* printf("M %s %i %i\n", em->name, em->ref, em->loaded); *\/ */
513 /*      /\* if the module is refernced - skip *\/ */
514 /*      if ((em->ref > 0) || (!em->loaded)) continue; */
515 /*      /\* how many clean cycles ago was this module last used *\/ */
516 /*      ago = use_count - em->last_used; */
517 /*      if (em->last_used > use_count) ago += 0x10000000; */
518 /*      /\* if it was used last more than N clean cycles ago - unload *\/ */
519 /*      if (ago > 5) */
520 /*        { */
521 /*             /\* printf("  UNLOAD %s\n", em->name); *\/ */
522 /*           evas_module_unload(em); */
523 /*        } */
524 /*      } */
525 }
526
527 /* will dlclose all the modules loaded and free all the structs */
528 void
529 evas_module_shutdown(void)
530 {
531    Eina_Module *en;
532    char *path;
533    int i;
534
535    for (i = 0; evas_static_module[i].shutdown; ++i)
536      evas_static_module[i].shutdown();
537
538    EINA_LIST_FREE(eina_evas_modules, en)
539      eina_module_free(en);
540
541    eina_hash_free(evas_modules[EVAS_MODULE_TYPE_ENGINE]);
542    evas_modules[EVAS_MODULE_TYPE_ENGINE] = NULL;
543    eina_hash_free(evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER]);
544    evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER] = NULL;
545    eina_hash_free(evas_modules[EVAS_MODULE_TYPE_IMAGE_SAVER]);
546    evas_modules[EVAS_MODULE_TYPE_IMAGE_SAVER] = NULL;
547    eina_hash_free(evas_modules[EVAS_MODULE_TYPE_OBJECT]);
548    evas_modules[EVAS_MODULE_TYPE_OBJECT] = NULL;
549
550    EINA_LIST_FREE(evas_module_paths, path)
551      free(path);
552
553    eina_array_free(evas_engines);
554    evas_engines = NULL;
555 }
556
557 EAPI int
558 _evas_module_engine_inherit(Evas_Func *funcs, char *name)
559 {
560    Evas_Module *em;
561
562    em = evas_module_find_type(EVAS_MODULE_TYPE_ENGINE, name);
563    if (em)
564      {
565         if (evas_module_load(em))
566           {
567              /* FIXME: no way to unref */
568              evas_module_ref(em);
569              evas_module_use(em);
570              *funcs = *((Evas_Func *)(em->functions));
571              return 1;
572           }
573      }
574    return 0;
575 }