-
Notifications
You must be signed in to change notification settings - Fork 2
/
emacs-module-prelude.h
163 lines (148 loc) · 4.16 KB
/
emacs-module-prelude.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#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.
*/
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 */