165 lines
4.2 KiB
C
165 lines
4.2 KiB
C
|
#include "emacs-module.h"
|
|||
|
#include <stdbool.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <stdarg.h>
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#ifndef EMACS_MODULE_PRELUDE_H
|
|||
|
#define EMACS_MODULE_PRELUDE_H
|
|||
|
|
|||
|
#define EMP_MAJOR_VERSION 1
|
|||
|
#define EMP_MINOR_VERSION 0
|
|||
|
#define EMP_PATCH_VERSION 0
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
Copy a Lisp string VALUE into BUFFER, and store the string size in
|
|||
|
SIZE. A user doesn’t need to allocate BUFFER, but it is the user’s
|
|||
|
responsibility to free it. If failed, return false, and the buffer
|
|||
|
doesn’t need to be freed.
|
|||
|
*/
|
|||
|
bool
|
|||
|
emp_copy_string_contents
|
|||
|
(emacs_env *env, emacs_value value, char **buffer, size_t *size)
|
|||
|
/* Copied from Pillipp’s document. I commented out assertions. */
|
|||
|
{
|
|||
|
ptrdiff_t buffer_size;
|
|||
|
if (!env->copy_string_contents (env, value, NULL, &buffer_size))
|
|||
|
return false;
|
|||
|
/* assert (env->non_local_exit_check (env) == emacs_funcall_exit_return); */
|
|||
|
/* assert (buffer_size > 0); */
|
|||
|
*buffer = (char*) malloc ((size_t) buffer_size);
|
|||
|
if (*buffer == NULL)
|
|||
|
{
|
|||
|
env->non_local_exit_signal (env, env->intern (env, "memory-full"),
|
|||
|
env->intern (env, "nil"));
|
|||
|
return false;
|
|||
|
}
|
|||
|
ptrdiff_t old_buffer_size = buffer_size;
|
|||
|
if (!env->copy_string_contents (env, value, *buffer, &buffer_size))
|
|||
|
{
|
|||
|
free (*buffer);
|
|||
|
*buffer = NULL;
|
|||
|
return false;
|
|||
|
}
|
|||
|
/* assert (env->non_local_exit_check (env) == emacs_funcall_exit_return); */
|
|||
|
/* assert (buffer_size == old_buffer_size); */
|
|||
|
*size = (size_t) (buffer_size - 1);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Return a Lisp string. This is basically env->make_string except that
|
|||
|
it calls strlen for you.
|
|||
|
*/
|
|||
|
emacs_value
|
|||
|
emp_build_string (emacs_env *env, const char *string)
|
|||
|
{
|
|||
|
return env->make_string (env, string, strlen (string));
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Intern NAME to a symbol. NAME has to be all-ASCII.
|
|||
|
*/
|
|||
|
emacs_value
|
|||
|
emp_intern (emacs_env *env, const char *name)
|
|||
|
{
|
|||
|
return env->intern (env, name);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Call a function named FN which takes NARGS number of arguments.
|
|||
|
Example: funcall (env, "cons", 2, car, cdr);
|
|||
|
*/
|
|||
|
emacs_value
|
|||
|
emp_funcall (emacs_env *env, const char* fn, ptrdiff_t nargs, ...)
|
|||
|
{
|
|||
|
va_list argv;
|
|||
|
va_start (argv, nargs);
|
|||
|
emacs_value *args = (emacs_value *) malloc(nargs * sizeof(emacs_value));
|
|||
|
for (int idx = 0; idx < nargs; idx++)
|
|||
|
{
|
|||
|
args[idx] = va_arg (argv, emacs_value);
|
|||
|
}
|
|||
|
va_end (argv);
|
|||
|
emacs_value val = env->funcall (env, emp_intern (env, fn), nargs, args);
|
|||
|
free (args);
|
|||
|
return val;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Provide FEATURE like ‘provide’ in Lisp.
|
|||
|
*/
|
|||
|
void
|
|||
|
emp_provide (emacs_env *env, const char *feature)
|
|||
|
{
|
|||
|
emp_funcall (env, "provide", 1, emp_intern (env, feature));
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Raise a signal where NAME is the signal name and MESSAGE is the
|
|||
|
error message.
|
|||
|
*/
|
|||
|
void
|
|||
|
emp_signal_message1
|
|||
|
(emacs_env *env, const char *name, const char *message)
|
|||
|
{
|
|||
|
env->non_local_exit_signal
|
|||
|
(env, env->intern (env, name),
|
|||
|
emp_funcall (env, "cons", 2,
|
|||
|
env->make_string (env, message, strlen (message)),
|
|||
|
emp_intern (env, "nil")));
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Define an error like ‘define-error’.
|
|||
|
*/
|
|||
|
void
|
|||
|
emp_define_error
|
|||
|
(emacs_env *env, const char *name,
|
|||
|
const char *description, const char *parent)
|
|||
|
{
|
|||
|
emp_funcall (env, "define-error", 3,
|
|||
|
emp_intern (env, name),
|
|||
|
env->make_string (env, description, strlen (description)),
|
|||
|
emp_intern (env, parent));
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Return true if VAL is symbol nil.
|
|||
|
*/
|
|||
|
bool
|
|||
|
emp_nilp (emacs_env *env, emacs_value val)
|
|||
|
{
|
|||
|
return !env->is_not_nil (env, val);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Define a function NAME. The number of arguments that the function
|
|||
|
takes is between MIN_ARITY and MAX_ARITY. FUNCTION is a function
|
|||
|
with signature
|
|||
|
|
|||
|
static emacs_value
|
|||
|
function
|
|||
|
(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
|
|||
|
EMACS_NOEXCEPT
|
|||
|
|
|||
|
DOCUMENTATION is the docstring for FUNCTION.
|
|||
|
*/
|
|||
|
void
|
|||
|
emp_define_function
|
|||
|
(emacs_env *env, const char *name, ptrdiff_t min_arity,
|
|||
|
ptrdiff_t max_arity,
|
|||
|
emacs_value (*function) (emacs_env *env,
|
|||
|
ptrdiff_t nargs,
|
|||
|
emacs_value* args,
|
|||
|
void *data) EMACS_NOEXCEPT,
|
|||
|
const char *documentation)
|
|||
|
{
|
|||
|
emacs_value fn = env->make_function
|
|||
|
(env, min_arity, max_arity, function, documentation, NULL);
|
|||
|
emp_funcall (env, "fset", 2, emp_intern (env, name), fn);
|
|||
|
}
|
|||
|
|
|||
|
#endif /* EMACS_MODULE_PRELUDE_H */
|