/* mod.c: loadable nawm modules */ /* Copyright (C) 1999 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */ #include "nawm.h" #include "lang.h" #include "parser.h" #include #include #include #include #include #include #ifdef NEED_UNDERSCORES #define SYMNAME(x) ("_" x) #else #define SYMNAME #endif static char **nawm_libpath; extern long eventmask; extern event_handler *eventhandlers; void initmodules(void) { char *libpath, *p; int i; libpath = getenv("NAWM_LIBRARY_PATH"); if (!libpath) libpath = NAWM_DEFAULT_LIBPATH; for (i = 0, p = libpath; *p; p++) { if (*p == ':') i++; } nawm_libpath = xmalloc((i + 2) * sizeof(char *)); /* split libpath into components, recognizing an empty component * as NAWM_DEFAULT_LIBPATH */ for (i = 0, p = libpath; *libpath; p++) { if (*p == ':' || *p == '\0') { if (p == libpath) nawm_libpath[i] = NAWM_DEFAULT_LIBPATH; else { int len = p - libpath; while (libpath[len] == '/') len--; nawm_libpath[i] = xmalloc(len + 1); memcpy(nawm_libpath[i], libpath, len); nawm_libpath[i][len] = '\0'; } libpath = *p ? p + 1 : p; i++; } } nawm_libpath[i] = NULL; } void load_module(char *name) { int i, len = strlen(name), *modrev, found = 0, opened = 0; void *dlconfig = NULL; void (*modinit)(); for (i = 0; nawm_libpath[i]; i++) { char *path = xmalloc(strlen(nawm_libpath[i]) + len + 5); sprintf(path, "%s/%s.so", nawm_libpath[i], name); if (!access(path, R_OK)) { found = 1; dlconfig = dlopen(path, RTLD_NOW); free(path); if (!dlconfig) continue; opened = 1; modrev = dlsym(dlconfig, SYMNAME("nawm_modrev")); if (!modrev || *modrev != 1) continue; modinit = dlsym(dlconfig, SYMNAME("modinit")); if (!modinit) continue; modinit(); return; } } if (opened) { if (modrev) die("No symbol \"modinit\" in module \"%s\".", name); else die("No symbol \"nawm_modrev\" in module \"%s\".", name); } else if (found) die("Couldn't open module \"%s\":\n%s", name, dlerror()); else die("Couldn't find module \"%s\"", name); } void module_define_procedure(char *name, dtype rtype, void (*body)(), int numargs, ...) { function *f; va_list ap; int i, nargs; nargs = (numargs < 0) ? -numargs : numargs; f = xmalloc(sizeof(function) + (nargs - 3) * sizeof(dtype)); f->body = body; f->type = rtype; f->numvars = -1; f->numargs = numargs; if (numargs < 0) numargs = -numargs; va_start(ap, numargs); for (i = 0; i < numargs; i++) f->vartype[i] = va_arg(ap, dtype); va_end(ap); define(rtype ? FUN : CMD, name, f); } void module_define_variable(char *name, dtype type, nawmval data) { variable *v = mkvar(type); v->data = data; define(VAR, name, v); } int module_define_type(char *name) { return newtype(name); } int module_lookup_type(char *name) { int kind; int type = (nawmval)lookup(name, &kind, 0); if (kind != DTYPE || type == 0) return -1; else return type; } void module_define_event_handler(void (*handler)(XEvent *), long mask) { event_handler *h; eventmask |= mask; h = xmalloc(sizeof(event_handler)); h->handler = handler; h->next = eventhandlers; eventhandlers = h; }