1 /* Test GNU Emacs modules.
3 Copyright 2015-2016 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23 #include <emacs-module.h>
25 int plugin_is_GPL_compatible
;
27 /* Always return symbol 't'. */
29 Fmod_test_return_t (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
32 return env
->intern (env
, "t");
35 /* Expose simple sum function. */
37 sum (intmax_t a
, intmax_t b
)
43 Fmod_test_sum (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[], void *data
)
47 intmax_t a
= env
->extract_integer (env
, args
[0]);
48 intmax_t b
= env
->extract_integer (env
, args
[1]);
50 intmax_t r
= sum (a
, b
);
52 return env
->make_integer (env
, r
);
56 /* Signal '(error 56). */
58 Fmod_test_signal (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
61 assert (env
->non_local_exit_check (env
) == emacs_funcall_exit_return
);
62 env
->non_local_exit_signal (env
, env
->intern (env
, "error"),
63 env
->make_integer (env
, 56));
64 return env
->intern (env
, "nil");
68 /* Throw '(tag 65). */
70 Fmod_test_throw (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
73 assert (env
->non_local_exit_check (env
) == emacs_funcall_exit_return
);
74 env
->non_local_exit_throw (env
, env
->intern (env
, "tag"),
75 env
->make_integer (env
, 65));
76 return env
->intern (env
, "nil");
80 /* Call argument function, catch all non-local exists and return
81 either normal result or a list describing the non-local exit. */
83 Fmod_test_non_local_exit_funcall (emacs_env
*env
, ptrdiff_t nargs
,
84 emacs_value args
[], void *data
)
87 emacs_value result
= env
->funcall (env
, args
[0], 0, NULL
);
88 emacs_value non_local_exit_symbol
, non_local_exit_data
;
89 enum emacs_funcall_exit code
90 = env
->non_local_exit_get (env
, &non_local_exit_symbol
,
91 &non_local_exit_data
);
94 case emacs_funcall_exit_return
:
96 case emacs_funcall_exit_signal
:
98 env
->non_local_exit_clear (env
);
99 emacs_value Flist
= env
->intern (env
, "list");
100 emacs_value list_args
[] = {env
->intern (env
, "signal"),
101 non_local_exit_symbol
, non_local_exit_data
};
102 return env
->funcall (env
, Flist
, 3, list_args
);
104 case emacs_funcall_exit_throw
:
106 env
->non_local_exit_clear (env
);
107 emacs_value Flist
= env
->intern (env
, "list");
108 emacs_value list_args
[] = {env
->intern (env
, "throw"),
109 non_local_exit_symbol
, non_local_exit_data
};
110 return env
->funcall (env
, Flist
, 3, list_args
);
115 return env
->intern (env
, "nil");;
119 /* Return a global reference. */
121 Fmod_test_globref_make (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
124 /* Make a big string and make it global. */
126 for (int i
= 0; i
< sizeof str
; i
++)
127 str
[i
] = 'a' + (i
% 26);
129 /* We don't need to null-terminate str. */
130 emacs_value lisp_str
= env
->make_string (env
, str
, sizeof str
);
131 return env
->make_global_ref (env
, lisp_str
);
135 /* Return a copy of the argument string where every 'a' is replaced
138 Fmod_test_string_a_to_b (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
141 emacs_value lisp_str
= args
[0];
145 env
->copy_string_contents (env
, lisp_str
, buf
, &size
);
147 env
->copy_string_contents (env
, lisp_str
, buf
, &size
);
149 for (ptrdiff_t i
= 0; i
+ 1 < size
; i
++)
153 return env
->make_string (env
, buf
, size
- 1);
157 /* Embedded pointers in lisp objects. */
159 /* C struct (pointer to) that will be embedded. */
163 char large_unused_buffer
[512];
166 /* Return a new user-pointer to a super_struct, with amazing_int set
167 to the passed parameter. */
169 Fmod_test_userptr_make (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
172 struct super_struct
*p
= calloc (1, sizeof *p
);
173 p
->amazing_int
= env
->extract_integer (env
, args
[0]);
174 return env
->make_user_ptr (env
, free
, p
);
177 /* Return the amazing_int of a passed 'user-pointer to a super_struct'. */
179 Fmod_test_userptr_get (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
182 struct super_struct
*p
= env
->get_user_ptr (env
, args
[0]);
183 return env
->make_integer (env
, p
->amazing_int
);
187 /* Fill vector in args[0] with value in args[1]. */
189 Fmod_test_vector_fill (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
192 emacs_value vec
= args
[0];
193 emacs_value val
= args
[1];
194 ptrdiff_t size
= env
->vec_size (env
, vec
);
195 for (ptrdiff_t i
= 0; i
< size
; i
++)
196 env
->vec_set (env
, vec
, i
, val
);
197 return env
->intern (env
, "t");
201 /* Return whether all elements of vector in args[0] are 'eq' to value
204 Fmod_test_vector_eq (emacs_env
*env
, ptrdiff_t nargs
, emacs_value args
[],
207 emacs_value vec
= args
[0];
208 emacs_value val
= args
[1];
209 ptrdiff_t size
= env
->vec_size (env
, vec
);
210 for (ptrdiff_t i
= 0; i
< size
; i
++)
211 if (!env
->eq (env
, env
->vec_get (env
, vec
, i
), val
))
212 return env
->intern (env
, "nil");
213 return env
->intern (env
, "t");
217 /* Lisp utilities for easier readability (simple wrappers). */
219 /* Provide FEATURE to Emacs. */
221 provide (emacs_env
*env
, const char *feature
)
223 emacs_value Qfeat
= env
->intern (env
, feature
);
224 emacs_value Qprovide
= env
->intern (env
, "provide");
225 emacs_value args
[] = { Qfeat
};
227 env
->funcall (env
, Qprovide
, 1, args
);
230 /* Bind NAME to FUN. */
232 bind_function (emacs_env
*env
, const char *name
, emacs_value Sfun
)
234 emacs_value Qfset
= env
->intern (env
, "fset");
235 emacs_value Qsym
= env
->intern (env
, name
);
236 emacs_value args
[] = { Qsym
, Sfun
};
238 env
->funcall (env
, Qfset
, 2, args
);
241 /* Module init function. */
243 emacs_module_init (struct emacs_runtime
*ert
)
245 emacs_env
*env
= ert
->get_environment (ert
);
247 #define DEFUN(lsym, csym, amin, amax, doc, data) \
248 bind_function (env, lsym, \
249 env->make_function (env, amin, amax, csym, doc, data))
251 DEFUN ("mod-test-return-t", Fmod_test_return_t
, 1, 1, NULL
, NULL
);
252 DEFUN ("mod-test-sum", Fmod_test_sum
, 2, 2, "Return A + B", NULL
);
253 DEFUN ("mod-test-signal", Fmod_test_signal
, 0, 0, NULL
, NULL
);
254 DEFUN ("mod-test-throw", Fmod_test_throw
, 0, 0, NULL
, NULL
);
255 DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall
,
257 DEFUN ("mod-test-globref-make", Fmod_test_globref_make
, 0, 0, NULL
, NULL
);
258 DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b
, 1, 1, NULL
, NULL
);
259 DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make
, 1, 1, NULL
, NULL
);
260 DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get
, 1, 1, NULL
, NULL
);
261 DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill
, 2, 2, NULL
, NULL
);
262 DEFUN ("mod-test-vector-eq", Fmod_test_vector_eq
, 2, 2, NULL
, NULL
);
266 provide (env
, "mod-test");