1 #include <stdarg.h> 2 #include <string.h> 3 4 #include "emacs-module.h" 5 #include "symbols.h" 6 7 #ifndef INTERFACE_H 8 #define INTERFACE_H 9 10 // Assert that VAL is a cons cell, signal an error and return otherwise. 11 #define EM_ASSERT_CONS(val) \ 12 do { if (!em_assert(env, esym_consp, (val))) return esym_nil; } while (0) 13 14 // Assert that VAL is a function, signal an error and return otherwise. 15 #define EM_ASSERT_FUNCTION(val) \ 16 do { if (!em_assert(env, esym_functionp, (val))) return esym_nil; } while (0) 17 18 // Assert that VAL is a string, signal an error and return otherwise. 19 #define EM_ASSERT_STRING(val) \ 20 do { if (!em_assert(env, esym_stringp, (val))) return esym_nil; } while (0) 21 22 // Assert that VAL is a string or nil, signal an error and return otherwise. 23 #define EM_ASSERT_STRING_OR_NIL(val) \ 24 do { if (EM_EXTRACT_BOOLEAN(val)) EM_ASSERT_STRING(val); } while (0) 25 26 // Assert that VAL is an integer, signal an error and return otherwise. 27 #define EM_ASSERT_INTEGER(val) \ 28 do { if (!em_assert(env, esym_integerp, (val))) return esym_nil; } while (0) 29 30 // Assert that VAL is an integer or nil, signal an error and return otherwise. 31 #define EM_ASSERT_INTEGER_OR_NIL(val) \ 32 do { if (EM_EXTRACT_BOOLEAN(val)) EM_ASSERT_INTEGER(val); } while (0) 33 34 // Assert that VAL is an user-ptr, signal an error and return otherwise. 35 #define EM_ASSERT_USER_PTR(val) \ 36 do { if (!em_assert(env, esym_user_ptrp, (val))) return esym_nil; } while (0) 37 38 // Normalize an emacs_value string path. This macro may return. 39 #define EM_NORMALIZE_PATH(val) \ 40 do { \ 41 (val) = em_expand_file_name(env, val); \ 42 EM_RETURN_NIL_IF_NLE(); \ 43 } while (0) 44 45 // Extract a boolean from an emacs_value. 46 #define EM_EXTRACT_BOOLEAN(val) (env->is_not_nil(env, (val)) ? 1 : 0) 47 48 // Extract a string from an emacs_value. 49 // Caller is responsible for ensuring that the emacs_value represents a string. 50 #define EM_EXTRACT_STRING(val) em_get_string(env, (val)); 51 52 // Extract an integer from an emacs_value. 53 // Caller is responsible for ensuring that the emacs_value represents an integer. 54 #define EM_EXTRACT_INTEGER(val) env->extract_integer(env, (val)) 55 56 // Extract an integer from an emacs_value with a default. 57 // Caller is responsible for ensuring that the emacs_value represents an integer or nil. 58 #define EM_EXTRACT_INTEGER_OR_DEFAULT(val, default) \ 59 (EM_EXTRACT_BOOLEAN(val) ? EM_EXTRACT_INTEGER(val) : (default)) 60 61 // Extract a string from an emacs_value, or NULL. 62 // Caller is responsible for ensuring that the emacs_value represents a string or nil. 63 #define EM_EXTRACT_STRING_OR_NULL(val) \ 64 (EM_EXTRACT_BOOLEAN(val) ? em_get_string(env, (val)) : NULL) 65 66 // Extract a user pointer from an emacs_value. 67 // Caller is responsible for ensuring that the emacs_value represents a user pointer. 68 #define EM_EXTRACT_USER_PTR(val) env->get_user_ptr(env, (val)) 69 70 // Call (eq a b) in Emacs 71 #define EM_EQ(a,b) (env->eq(env, (a), (b))) 72 73 // Create an Emacs integer 74 #define EM_INTEGER(val) (env->make_integer(env, (val))) 75 76 // Create an Emacs string from a null-terminated char* 77 #define EM_STRING(val) (env->make_string(env, (val), strlen(val))) 78 79 // Create an Emacs user pointer 80 #define EM_USER_PTR(val, fin) (env->make_user_ptr(env, (fin), (val))) 81 82 // Return if a non-local exit is set 83 #define EM_RETURN_IF_NLE(val) \ 84 do { \ 85 if (env->non_local_exit_check(env)) \ 86 return (val); \ 87 } while (0) 88 89 #define EM_RETURN_NIL_IF_NLE() EM_RETURN_IF_NLE(esym_nil) 90 91 /** 92 * Initiate a loop over an Emacs list. 93 * If any element is not a cons cell or nil, it WILL signal an error and return nil. 94 * @param var Variable bound to each car. 95 * @param listvar List to loop over. 96 * @param name Unique name identifying the loop. 97 */ 98 #define EM_DOLIST(var, listvar, name) \ 99 emacs_value __cell##name = (listvar); \ 100 __loop##name: \ 101 if (!EM_EXTRACT_BOOLEAN(__cell##name)) goto __end##name; \ 102 if (!em_assert(env, esym_consp, __cell##name)) return esym_nil; \ 103 emacs_value (var) = em_car(env, __cell##name) 104 105 /** 106 * Close a loop over an Emacs lisp. 107 * @param name: Unique name identifying the loop. 108 */ 109 #define EM_DOLIST_END(name) \ 110 __cell##name = em_cdr(env, __cell##name); \ 111 goto __loop##name; \ 112 __end##name: 113 114 /** 115 * Initialize the libegit2-emacs interface. 116 * This function should only be called once. 117 */ 118 void em_init(emacs_env *env); 119 120 /** 121 * Signal a wrong-type-argument error if PREDICATE does not apply to ARG. 122 * @param env The active Emacs environment. 123 * @param predicate The predicate. 124 * @param arg The argument. 125 * @return True iff an error was signaled. 126 */ 127 bool em_assert(emacs_env *env, emacs_value predicate, emacs_value arg); 128 129 /** 130 * Signal a wrong-type-argument error if ARG is not a proper list, every 131 * element of which satisfies PREDICATE. PREDICATE may be nil, in which 132 * case only the list-ness is checked. 133 * @param env The active Emacs environment. 134 * @param predicate The predicate. 135 * @param arg The list. 136 * @return The number of elements in the list, or negative if error. 137 */ 138 ptrdiff_t em_assert_list(emacs_env *env, emacs_value predicate, emacs_value arg); 139 140 /** 141 * Signal an error with string message. 142 * @param env The active Emacs environment. 143 * @param error The error symbol. 144 * @param _msg The error message. 145 */ 146 void em_signal(emacs_env *env, emacs_value error, const char* _msg); 147 148 /** 149 * Signal a wrong-type-argument error. 150 * @param env The active Emacs environment. 151 * @param expected Symbol describing the expected type. 152 * @param actual Emacs value that does not have the expected type. 153 */ 154 void em_signal_wrong_type(emacs_env *env, emacs_value expected, emacs_value actual); 155 156 /** 157 * Signal a wrong-value-argument error. 158 * @param env The active Emacs environment. 159 * @param actual Emacs value that does not have the expected value. 160 */ 161 void em_signal_wrong_value(emacs_env *env, emacs_value actual); 162 163 /** 164 * Signal an args-out-of-range error. 165 * @param env The active Emacs environment. 166 * @param index The erroneous index. 167 */ 168 void em_signal_args_out_of_range(emacs_env *env, intmax_t index); 169 170 /** 171 * Return a string with size from an emacs_value. 172 * Caller is responsible for ensuring that the value is a string, and to free the returned pointer. 173 * @param env The active Emacs environment. 174 * @param arg Emacs value representing a string. 175 * @param size Where the size will be stored. 176 * @return The string (owned pointer). 177 */ 178 char *em_get_string_with_size(emacs_env *env, emacs_value arg, ptrdiff_t *size); 179 180 /** 181 * Return a string from an emacs_value. 182 * Caller is responsible for ensuring that the value is a string, and to free the returned pointer. 183 * @param env The active Emacs environment. 184 * @param arg Emacs value representing a string. 185 * @return The string (owned pointer). 186 */ 187 char *em_get_string(emacs_env *env, emacs_value arg); 188 189 /** 190 * Call (cons car cdr) in Emacs. 191 * @param env The active Emacs environment. 192 * @param car The car. 193 * @param cdr The cdr. 194 * @return The cons cell. 195 */ 196 emacs_value em_cons(emacs_env *env, emacs_value car, emacs_value cdr); 197 198 /** 199 * Call (consp cell) in Emacs. 200 * @param env The active Emacs environment. 201 * @param cell The cell you're testing. 202 * @return True if cell is a cons cell, false otherwise. 203 */ 204 bool em_consp(emacs_env *env, emacs_value cell); 205 206 /** 207 * Call (car cell) in Emacs. 208 * @param env The active Emacs environment. 209 * @param cell the cell to get the car of. 210 * @return the car of the cell or nil. 211 */ 212 emacs_value em_car(emacs_env *env, emacs_value cell); 213 214 /** 215 * Call (cdr cell) in Emacs. 216 * @param env The active Emacs environment. 217 * @param cell the cell to get the cdr of. 218 * @return the cdr of the cell or nil. 219 */ 220 emacs_value em_cdr(emacs_env *env, emacs_value cell); 221 222 /** 223 * Call (list OBJECTS...) in Emacs. 224 * @param env The active Emacs environment. 225 * @param objects Array of objects. 226 * @param nobjects Number of \p objects. 227 */ 228 emacs_value em_list(emacs_env *env, emacs_value *objects, ptrdiff_t nobjects); 229 230 /** 231 * Call (listp OBJECT) in Emacs. 232 * @param env The active Emacs environment. 233 * @param object An emacs value. 234 */ 235 bool em_listp(emacs_env *env, emacs_value object); 236 237 /** 238 * Call (length SEQUENCE) in Emacs. 239 * @param env The active Emacs environment. 240 * @param object An emacs sequence. 241 * @return Length of the sequence, or -1 on error. 242 */ 243 ptrdiff_t em_length(emacs_env *env, emacs_value sequence); 244 245 /** 246 * Call (assq key list) in Emacs. 247 * @param env The active Emacs environment. 248 * @param key The key to lookup. 249 * @param list The associated list (alist). 250 * @return The first cons cell whose car is \p key. 251 */ 252 emacs_value em_assq(emacs_env *env, emacs_value key, emacs_value list); 253 254 /** 255 * Call (define-error SYMBOL MSG) in Emacs. 256 * @param env The active Emacs environment. 257 * @param symbol The error symbol. 258 * @param msg The error description. 259 * @param parent The parent error. 260 */ 261 void em_define_error(emacs_env *env, emacs_value symbol, const char *msg, emacs_value parent); 262 263 /** 264 * Define a function in Emacs, using defalias. 265 * @param env The active Emacs environment. 266 * @param name Symbol name of the desired function. 267 * @param func Function to bind. 268 */ 269 void em_defun(emacs_env *env, const char *name, emacs_value func); 270 271 /** 272 * Call (expand-file-name PATH) in Emacs. 273 * @param env The active Emacs environment. 274 * @param path The path to expand. 275 */ 276 emacs_value em_expand_file_name(emacs_env *env, emacs_value path); 277 278 /** 279 * Provide a feature to Emacs. 280 * @param env The active Emacs environment. 281 * @param name Symbol name of the feature to provide. 282 */ 283 void em_provide(emacs_env *env, const char *feature); 284 285 /** 286 * Check if a value is a user pointer. 287 * @param env The active Emacs environment. 288 * @param val Value to check. 289 * @return True iff val is a user pointer. 290 */ 291 bool em_user_ptrp(emacs_env *env, emacs_value val); 292 293 /** 294 * Return the value of default-directory in Emacs. 295 */ 296 char *em_default_directory(emacs_env *env); 297 298 /** 299 * Run (decode-time TIMESTAMP OFFSET) in Emacs. 300 */ 301 emacs_value em_decode_time(emacs_env *env, intmax_t timestamp, intmax_t offset); 302 303 /** 304 * Run (encode-time ...) in Emacs. 305 */ 306 bool em_encode_time(emacs_env *env, emacs_value time, intmax_t *timestamp, intmax_t *offset); 307 308 /** 309 * Run (insert ...) in Emacs. 310 */ 311 void em_insert(emacs_env *env, const char *ptr, size_t length); 312 313 /** 314 * Convert an emacs string to unibyte. 315 */ 316 emacs_value em_string_as_unibyte(emacs_env *env, emacs_value str); 317 318 319 // ============================================================================= 320 // Symbol <-> enum map functions 321 322 bool em_findsym_branch(git_branch_t *out, emacs_env *env, emacs_value value, bool required); 323 bool em_findsym_checkout_strategy(git_checkout_strategy_t *out, emacs_env *env, emacs_value value, bool required); 324 bool em_findsym_config_level(git_config_level_t *out, emacs_env *env, emacs_value value, bool required); 325 bool em_findsym_delta(git_delta_t *out, emacs_env *env, emacs_value value, bool required); 326 bool em_findsym_diff_format(git_diff_format_t *out, emacs_env *env, emacs_value value, bool required); 327 bool em_findsym_diff_find(git_diff_find_t *out, emacs_env *env, emacs_value value, bool required); 328 bool em_findsym_describe_strategy(git_describe_strategy_t *out, emacs_env *env, emacs_value value, bool required); 329 bool em_findsym_fetch_prune(git_fetch_prune_t *out, emacs_env *env, emacs_value value, bool required); 330 bool em_findsym_filemode(git_filemode_t *out, emacs_env *env, emacs_value value, bool required); 331 bool em_findsym_merge_file_favor(git_merge_file_favor_t *out, emacs_env *env, emacs_value value, bool required); 332 bool em_findsym_otype(git_otype *out, emacs_env *env, emacs_value value, bool required); 333 bool em_findsym_pathspec_flag(git_pathspec_flag_t *out, emacs_env *env, emacs_value value, bool required); 334 bool em_findsym_proxy(git_proxy_t *out, emacs_env *env, emacs_value value, bool required); 335 bool em_findsym_remote_autotag_option(git_remote_autotag_option_t *out, emacs_env *env, emacs_value value, bool required); 336 bool em_findsym_reset(git_reset_t *out, emacs_env *env, emacs_value value, bool required); 337 bool em_findsym_submodule_ignore(git_submodule_ignore_t *out, emacs_env *env, emacs_value value, bool required); 338 bool em_findsym_submodule_recurse(git_submodule_recurse_t *out, emacs_env *env, emacs_value value, bool required); 339 bool em_findsym_submodule_update(git_submodule_update_t *out, emacs_env *env, emacs_value value, bool required); 340 bool em_findsym_stage(int *out, emacs_env *env, emacs_value value, bool required); 341 bool em_findsym_status_show(git_status_show_t *out, emacs_env *env, emacs_value value, bool required); 342 343 emacs_value em_findenum_checkout_notify(git_checkout_notify_t value); 344 emacs_value em_findenum_delta(git_delta_t value); 345 emacs_value em_findenum_direction(git_direction value); 346 emacs_value em_findenum_error(git_error_t value); 347 emacs_value em_findenum_filemode(git_filemode_t value); 348 emacs_value em_findenum_merge_preference(git_merge_preference_t value); 349 emacs_value em_findenum_otype(git_otype value); 350 emacs_value em_findenum_submodule_ignore(git_submodule_ignore_t value); 351 emacs_value em_findenum_submodule_update(git_submodule_update_t value); 352 emacs_value em_findenum_submodule_recurse(git_submodule_recurse_t value); 353 emacs_value em_findenum_remote_autotag_option(git_remote_autotag_option_t value); 354 emacs_value em_findenum_repository_state(git_repository_state_t value); 355 emacs_value em_findenum_stage(int value); 356 357 typedef bool setter(void *out, emacs_env *env, emacs_value value, bool on, bool required); 358 359 setter em_setflag_checkout_notify; 360 setter em_setflag_diff_option; 361 setter em_setflag_index_add_option; 362 setter em_setflag_merge_file_flag; 363 setter em_setflag_merge_flag; 364 setter em_setflag_sort; 365 setter em_setflag_status_opt; 366 367 bool em_setflags_list(void *out, emacs_env *env, emacs_value list, bool required, setter *setter); 368 bool em_setflags_alist(void *out, emacs_env *env, emacs_value alist, bool required, setter *setter); 369 370 emacs_value em_getlist_credtype(emacs_env *env, git_credtype_t value); 371 emacs_value em_getlist_indexcap(emacs_env *env, int value); 372 emacs_value em_getlist_merge_analysis(emacs_env *env, git_merge_analysis_t value); 373 emacs_value em_getlist_status(emacs_env *env, git_status_t value); 374 emacs_value em_getlist_submodule_status(emacs_env *env, git_submodule_status_t value); 375 376 bool em_checkflag_feature(emacs_value *out, emacs_env *env, emacs_value symbol, git_feature_t value, bool required); 377 bool em_checkflag_submodule_status(emacs_value *out, emacs_env *env, emacs_value symbol, 378 git_submodule_status_t value, bool required); 379 380 #endif /* INTERFACE_H */ 381