/* emacs-module.h - GNU Emacs module API.

Copyright (C) 2015-2019 Free Software Foundation, Inc.

This file is part of GNU Emacs.

GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */

#ifndef EMACS_MODULE_H
#define EMACS_MODULE_H

#include <stdint.h>
#include <stddef.h>
#include <time.h>

#ifndef __cplusplus
#include <stdbool.h>
#endif

#if defined EMACS_MODULE_GMP && !defined EMACS_MODULE_HAVE_MPZ_T
#include <gmp.h>
#endif

#define EMACS_MAJOR_VERSION @emacs_major_version@

#if defined __cplusplus && __cplusplus >= 201103L
# define EMACS_NOEXCEPT noexcept
#else
# define EMACS_NOEXCEPT
#endif

#ifdef __has_attribute
#if __has_attribute(__nonnull__)
# define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
#endif
#endif
#ifndef EMACS_ATTRIBUTE_NONNULL
# define EMACS_ATTRIBUTE_NONNULL(...)
#endif

#ifdef __cplusplus
extern "C" {
#endif

/* Current environment.  */
typedef struct emacs_env_27 emacs_env;

/* Opaque pointer representing an Emacs Lisp value.
   BEWARE: Do not assume NULL is a valid value!  */
typedef struct emacs_value_tag *emacs_value;

enum { emacs_variadic_function = -2 };

/* Struct passed to a module init function (emacs_module_init).  */
struct emacs_runtime
{
  /* Structure size (for version checking).  */
  ptrdiff_t size;

  /* Private data; users should not touch this.  */
  struct emacs_runtime_private *private_members;

  /* Return an environment pointer.  */
  emacs_env *(*get_environment) (struct emacs_runtime *ert)
    EMACS_ATTRIBUTE_NONNULL(1);
};


/* Possible Emacs function call outcomes.  */
enum emacs_funcall_exit
{
  /* Function has returned normally.  */
  emacs_funcall_exit_return = 0,

  /* Function has signaled an error using `signal'.  */
  emacs_funcall_exit_signal = 1,

  /* Function has exit using `throw'.  */
  emacs_funcall_exit_throw = 2
};

/* Possible return values for emacs_env.process_input.  */
enum emacs_process_input_result
{
  /* Module code may continue  */
  emacs_process_input_continue = 0,

  /* Module code should return control to Emacs as soon as possible.  */
  emacs_process_input_quit = 1
};

#ifdef EMACS_MODULE_GMP
struct emacs_mpz { mpz_t value; };
#else
struct emacs_mpz;  /* no definition */
#endif

struct emacs_env_25
{
@module_env_snippet_25@
};

struct emacs_env_26
{
@module_env_snippet_25@

@module_env_snippet_26@
};

struct emacs_env_27
{
@module_env_snippet_25@

@module_env_snippet_26@

@module_env_snippet_27@
};

/* Every module should define a function as follows.  */
extern int emacs_module_init (struct emacs_runtime *ert)
  EMACS_NOEXCEPT
  EMACS_ATTRIBUTE_NONNULL(1);

#ifdef __cplusplus
}
#endif

#endif /* EMACS_MODULE_H */