// ---------------------------------------------------------------------------- // https://dataswamp.org/~incal/peval/peval.c // ----------------------------------------------------------------------------- #include "peval.h" #include // ----------------------------------------------------------------------------- #include #include #include #include #include #include // ----------------------------------------------------------------------------- int plugin_is_GPL_compatible; // ----------------------------------------------------------------------------- const int PIPES_R = 0; const int PIPES_W = 1; const int MAX_LEN = 256; // ----------------------------------------------------------------------------- int emacs_module_init (struct emacs_runtime* rnt) { /* check for incompatible Emacs binary */ if (rnt->size < (long int)sizeof(*rnt)) { return 1; } /* check for incompatible module API */ emacs_env* env = rnt->get_environment(rnt); if (env->size < (long int)sizeof(*env)) { return 2; } /* check for too old Emacs */ int __attribute__((unused)) emacs_ver; if ((long int)sizeof(struct emacs_env_31) <= env->size) { emacs_ver = 31; } else if ((long int)sizeof(struct emacs_env_30) <= env->size) { emacs_ver = 30; } else if ((long int)sizeof(struct emacs_env_29) <= env->size) { emacs_ver = 29; } else { return 3; } /* init module */ emacs_value peval_func = env->make_function(env, 0, 8, peval, "`eval' in parallel.", NULL); emacs_value peval_symb = env->intern(env, "peval"); emacs_value peval_args[] = {peval_symb, peval_func}; env->funcall(env, env->intern(env, "defalias"), 2, peval_args); /* done */ return 0; } // ----------------------------------------------------------------------------- emacs_value peval (emacs_env* env, ptrdiff_t nargs, emacs_value* args, void* data __attribute__((unused))) { pid_t wpid; pid_t p; int status = 0; int (*pipes)[2] = malloc(nargs * sizeof(int[2])); if (!pipes) { perror("[malloc] error\n"); exit(1); } for (int i = 0; i < nargs; i++) { if (pipe(pipes[i]) == -1) { perror("[pipe] error\n"); exit(1); } } for (ptrdiff_t i = 0; i < nargs; i++) { p = fork(); if (p == -1) { perror("[fork] error\n"); exit(1); } else if (p == 0) { close(pipes[i][PIPES_R]); emacs_value es = env->funcall(env, env->intern(env, "peval--eform"), 1, &(args[i])); char str[MAX_LEN]; ptrdiff_t l = 0; env->copy_string_contents(env, es, NULL, &l); env->copy_string_contents(env, es, str, &l); write(pipes[i][PIPES_W], str, strlen(str)); close(pipes[i][PIPES_W]); exit(0); } } for (int i = 0; i < nargs; i++) { close(pipes[i][PIPES_W]); } while ((wpid = wait(&status)) > 0); emacs_value evals[nargs]; char str[nargs][MAX_LEN]; for (int i = 0; i < nargs; i++) { read(pipes[i][PIPES_R], str[i], MAX_LEN); close(pipes[i][PIPES_R]); evals[i] = env->make_unibyte_string(env, str[i], strlen(str[i])); } free(pipes); emacs_value lst = env->funcall(env, env->intern(env, "list"), nargs, evals); return lst; } // -----------------------------------------------------------------------------