diff options
Diffstat (limited to 'lib/erl_interface/include')
-rw-r--r-- | lib/erl_interface/include/ei.h | 785 | ||||
-rw-r--r-- | lib/erl_interface/include/ei_connect.h | 26 | ||||
-rw-r--r-- | lib/erl_interface/include/eicode.h | 26 | ||||
-rw-r--r-- | lib/erl_interface/include/erl_interface.h | 449 |
4 files changed, 1286 insertions, 0 deletions
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h new file mode 100644 index 0000000000..01272244e1 --- /dev/null +++ b/lib/erl_interface/include/ei.h @@ -0,0 +1,785 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#ifndef EI_H +#define EI_H + +#define EI_HAVE_TIMEOUT 1 /* Flag to user code that we have them */ +#define USE_EI_UNDOCUMENTED /* Want declarations for undocumented */ + +/************************************************************************/ +/* This file defines the complete interface to ei */ +/************************************************************************/ + +/* -------------------------------------------------------------------- */ +/* Include types needed below */ +/* -------------------------------------------------------------------- */ + +#if defined(__WIN32__) +#include <winsock2.h> +#include <windows.h> +#include <winbase.h> +#endif + +#include <stdio.h> /* Need type FILE */ +#include <errno.h> /* Need EHOSTUNREACH, ENOMEM, ... */ + +#if !defined(__WIN32__) && !defined(VXWORKS) || (defined(VXWORKS) && defined(HAVE_SENS)) +# include <netdb.h> +#endif + + +/* -------------------------------------------------------------------- */ +/* Defines part of API */ +/* -------------------------------------------------------------------- */ + +/* + * Some error codes might be missing, so here's a backstop definitions + * of the ones we use with `erl_errno': + */ + +#ifndef EMSGSIZE /* Message too long */ +#define EMSGSIZE EIO +#endif + +#ifndef ETIMEDOUT /* Connection timed out */ +#define ETIMEDOUT EIO +#endif + +#ifndef EHOSTUNREACH /* No route to host */ +#define EHOSTUNREACH EIO +#endif + +/* FIXME just a few are documented, does it mean they can't be returned? */ + +#define ERL_ERROR -1 /* Error of some kind */ +#define ERL_NO_DAEMON -2 /* No contact with EPMD */ +#define ERL_NO_PORT -3 /* No port received from EPMD */ +#define ERL_CONNECT_FAIL -4 /* Connect to Erlang Node failed */ +#define ERL_TIMEOUT -5 /* A timeout has expired */ +#define ERL_NO_REMOTE -6 /* Cannot execute rsh */ + +#define ERL_TICK 0 +#define ERL_MSG 1 + +#define ERL_NO_TIMEOUT -1 + +/* these are the control message types */ +#define ERL_LINK 1 +#define ERL_SEND 2 +#define ERL_EXIT 3 +#define ERL_UNLINK 4 +#define ERL_NODE_LINK 5 +#define ERL_REG_SEND 6 +#define ERL_GROUP_LEADER 7 +#define ERL_EXIT2 8 +#define ERL_PASS_THROUGH 'p' + +/* new ones for tracing, from Kenneth */ +#define ERL_SEND_TT 12 +#define ERL_EXIT_TT 13 +#define ERL_REG_SEND_TT 16 +#define ERL_EXIT2_TT 18 + + +/* -------------------------------------------------------------------- */ +/* Defines used for ei_get_type_internal() output */ +/* -------------------------------------------------------------------- */ +/* + * these are the term type indicators used in + * the external (distribution) format + */ + +/* FIXME we don't want to export these..... */ + +#define ERL_SMALL_INTEGER_EXT 'a' +#define ERL_INTEGER_EXT 'b' +#define ERL_FLOAT_EXT 'c' +#define ERL_ATOM_EXT 'd' +#define ERL_REFERENCE_EXT 'e' +#define ERL_NEW_REFERENCE_EXT 'r' +#define ERL_PORT_EXT 'f' +#define ERL_PID_EXT 'g' +#define ERL_SMALL_TUPLE_EXT 'h' +#define ERL_LARGE_TUPLE_EXT 'i' +#define ERL_NIL_EXT 'j' +#define ERL_STRING_EXT 'k' +#define ERL_LIST_EXT 'l' +#define ERL_BINARY_EXT 'm' +#define ERL_SMALL_BIG_EXT 'n' +#define ERL_LARGE_BIG_EXT 'o' +#define ERL_NEW_FUN_EXT 'p' +#define ERL_FUN_EXT 'u' + +#define ERL_NEW_CACHE 'N' /* c nodes don't know these two */ +#define ERL_CACHED_ATOM 'C' + + +/* -------------------------------------------------------------------- */ +/* Define the erl_errno macro */ +/* -------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * GCC's attributes are too useful to not use. Other compilers + * just lose opportunities to optimize and warn. + */ +#if !defined(__GNUC__) || __GNUC__ < 2 +# define __attribute__(foo) /* nothing */ +#endif + +/* + * Define the 'erl_errno' facility. Unfortunately this lives on in + * the 'ei' interface as well.... :-( + */ + +#if defined(_REENTRANT) || defined(VXWORKS) || defined(__WIN32__) + +/* 'erl_errno' as a function return value */ +volatile int* __erl_errno_place(void) __attribute__ ((__const__)); + +#define erl_errno (*__erl_errno_place ()) + +#else /* !_REENTRANT && !VXWORKS && !__WIN32__ */ + +extern volatile int __erl_errno; + +#define erl_errno __erl_errno + +#endif /* !_REENTRANT && !VXWORKS && !__WIN32__ */ + + +/* -------------------------------------------------------------------- */ +/* Type definitions */ +/* -------------------------------------------------------------------- */ + +/* + * To avoid confusion about the MAXHOSTNAMELEN when compiling the + * library and when using the library we set a value that we use + */ + +#define EI_MAXHOSTNAMELEN 64 +#define EI_MAXALIVELEN 63 +#define EI_MAX_COOKIE_SIZE 512 +#define MAXATOMLEN 255 +#define MAXNODELEN EI_MAXALIVELEN+1+EI_MAXHOSTNAMELEN + +/* a pid */ +typedef struct { + char node[MAXATOMLEN+1]; + unsigned int num; + unsigned int serial; + unsigned int creation; +} erlang_pid; + +/* a port */ +typedef struct { + char node[MAXATOMLEN+1]; + unsigned int id; + unsigned int creation; +} erlang_port; + +/* a ref */ +typedef struct { + char node[MAXATOMLEN+1]; + int len; + unsigned int n[3]; + unsigned int creation; +} erlang_ref; + +/* a trace token */ +typedef struct { + long serial; + long prev; + erlang_pid from; + long label; + long flags; +} erlang_trace; + +/* a message */ +typedef struct { + long msgtype; + erlang_pid from; + erlang_pid to; + char toname[MAXATOMLEN+1]; + char cookie[MAXATOMLEN+1]; + erlang_trace token; +} erlang_msg; + +/* a fun */ +typedef struct { + long arity; + char module[MAXATOMLEN+1]; + char md5[16]; + long index; + long old_index; + long uniq; + long n_free_vars; + erlang_pid pid; + long free_var_len; + char* free_vars; +} erlang_fun; + +/* a big */ +typedef struct { + unsigned int arity; + int is_neg; + void *digits; +} erlang_big; + +typedef struct { + char ei_type; + int arity; + int size; + union { + long i_val; + double d_val; + char atom_name[MAXATOMLEN+1]; + erlang_pid pid; + erlang_port port; + erlang_ref ref; + } value; +} ei_term; + +/* XXX */ + +typedef struct { + char ipadr[4]; /* stored in network byte order */ + char nodename[MAXNODELEN+1]; +} ErlConnect; + +typedef struct ei_cnode_s { + char thishostname[EI_MAXHOSTNAMELEN+1]; + char thisnodename[MAXNODELEN+1]; + char thisalivename[EI_MAXALIVELEN+1]; +/* Currently this_ipaddr isn't used */ +/* struct in_addr this_ipaddr; */ + char ei_connect_cookie[EI_MAX_COOKIE_SIZE+1]; + short creation; + erlang_pid self; +} ei_cnode; + +typedef struct in_addr *Erl_IpAddr; + + +/* A dynamic version of ei XX */ + +typedef struct ei_x_buff_TAG { + char* buff; + int buffsz; + int index; +} ei_x_buff; + + +/* -------------------------------------------------------------------- */ +/* Function definitions (listed in same order as documentation) */ +/* -------------------------------------------------------------------- */ + +/* Handle the connection */ + +int ei_connect_init(ei_cnode* ec, const char* this_node_name, + const char *cookie, short creation); +int ei_connect_xinit (ei_cnode* ec, const char *thishostname, + const char *thisalivename, const char *thisnodename, + Erl_IpAddr thisipaddr, const char *cookie, + const short creation); + +int ei_connect(ei_cnode* ec, char *nodename); +int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms); +int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename); +int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned ms); + +int ei_receive(int fd, unsigned char *bufp, int bufsize); +int ei_receive_tmo(int fd, unsigned char *bufp, int bufsize, unsigned ms); +int ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x); +int ei_receive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned ms); +int ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x); +int ei_xreceive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned ms); + +int ei_send(int fd, erlang_pid* to, char* buf, int len); +int ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned ms); +int ei_reg_send(ei_cnode* ec, int fd, char *server_name, char* buf, int len); +int ei_reg_send_tmo(ei_cnode* ec, int fd, char *server_name, char* buf, int len, unsigned ms); + +int ei_rpc(ei_cnode* ec, int fd, char *mod, char *fun, + const char* inbuf, int inbuflen, ei_x_buff* x); +int ei_rpc_to(ei_cnode* ec, int fd, char *mod, char *fun, + const char* buf, int len); +int ei_rpc_from(ei_cnode* ec, int fd, int timeout, erlang_msg* msg, + ei_x_buff* x); + +int ei_publish(ei_cnode* ec, int port); +int ei_publish_tmo(ei_cnode* ec, int port, unsigned ms); +int ei_accept(ei_cnode* ec, int lfd, ErlConnect *conp); +int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms); +int ei_unpublish(ei_cnode* ec); +int ei_unpublish_tmo(const char *alive, unsigned ms); + +const char *ei_thisnodename(const ei_cnode* ec); +const char *ei_thishostname(const ei_cnode* ec); +const char *ei_thisalivename(const ei_cnode* ec); + +erlang_pid *ei_self(ei_cnode* ec); + +void ei_set_compat_rel(unsigned rel); + +/* + * We have erl_gethost*() so we include ei versions as well. + */ + +#if defined(VXWORKS) + +extern int h_errno; + +/* + * We need these definitions - if the user has SENS then he gets them + * from netdb.h, otherwise we define them ourselves. + * + * If you are getting "multiple definition" errors here, + * make sure you have included <netdb.h> BEFORE "erl_interface.h" + * or define HAVE_SENS in your CFLAGS. + */ + +#if !defined(HAVE_SENS) && !defined(HOST_NOT_FOUND) /* just in case */ + +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +#define h_addr h_addr_list[0] /* address, for backward compatiblity */ + unsigned int unused; /* SENS defines this as ttl */ +}; + +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +#endif /* !HAVE_SENS && !HOST_NOT_FOUND */ +#endif /* VXWORKS */ + + +struct hostent *ei_gethostbyname(const char *name); +struct hostent *ei_gethostbyaddr(const char *addr, int len, int type); +struct hostent *ei_gethostbyname_r(const char *name, + struct hostent *hostp, + char *buffer, + int buflen, + int *h_errnop); +struct hostent *ei_gethostbyaddr_r(const char *addr, + int length, + int type, + struct hostent *hostp, + char *buffer, + int buflen, + int *h_errnop); + + +/* Encode/decode functions */ + +int ei_encode_version(char *buf, int *index); +int ei_x_encode_version(ei_x_buff* x); +int ei_encode_long(char *buf, int *index, long p); +int ei_x_encode_long(ei_x_buff* x, long n); +int ei_encode_ulong(char *buf, int *index, unsigned long p); +int ei_x_encode_ulong(ei_x_buff* x, unsigned long n); +int ei_encode_double(char *buf, int *index, double p); +int ei_x_encode_double(ei_x_buff* x, double dbl); +int ei_encode_boolean(char *buf, int *index, int p); +int ei_x_encode_boolean(ei_x_buff* x, int p); +int ei_encode_char(char *buf, int *index, char p); +int ei_x_encode_char(ei_x_buff* x, char p); +int ei_encode_string(char *buf, int *index, const char *p); +int ei_encode_string_len(char *buf, int *index, const char *p, int len); +int ei_x_encode_string(ei_x_buff* x, const char* s); +int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len); +int ei_encode_atom(char *buf, int *index, const char *p); +int ei_encode_atom_len(char *buf, int *index, const char *p, int len); +int ei_x_encode_atom(ei_x_buff* x, const char* s); +int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len); +int ei_encode_binary(char *buf, int *index, const void *p, long len); +int ei_x_encode_binary(ei_x_buff* x, const void* s, int len); +int ei_encode_pid(char *buf, int *index, const erlang_pid *p); +int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid); +int ei_encode_fun(char* buf, int* index, const erlang_fun* p); +int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun); +int ei_encode_port(char *buf, int *index, const erlang_port *p); +int ei_x_encode_port(ei_x_buff* x, const erlang_port *p); +int ei_encode_ref(char *buf, int *index, const erlang_ref *p); +int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p); +int ei_encode_term(char *buf, int *index, void *t); /* ETERM* actually */ +int ei_x_encode_term(ei_x_buff* x, void* t); +int ei_encode_trace(char *buf, int *index, const erlang_trace *p); +int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p); +int ei_encode_tuple_header(char *buf, int *index, int arity); +int ei_x_encode_tuple_header(ei_x_buff* x, long n); +int ei_encode_list_header(char *buf, int *index, int arity); +int ei_x_encode_list_header(ei_x_buff* x, long n); +#define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0) +int ei_x_encode_empty_list(ei_x_buff* x); + +/* + * ei_get_type() returns the type and "size" of the item at + * buf[index]. For strings and atoms, size is the number of characters + * not including the terminating 0. For binaries, size is the number + * of bytes. For lists and tuples, size is the arity of the + * object. For other types, size is 0. In all cases, index is left + * unchanged. + */ + +int ei_get_type(const char *buf, const int *index, int *type, int *size); +int ei_get_type_internal(const char *buf, const int *index, int *type, + int *size); + +/* Step through buffer, decoding the given type into the buffer + * provided. On success, 0 is returned and index is updated to point + * to the start of the next item in the buffer. If the type of item at + * buf[index] is not the requested type, -1 is returned and index is + * not updated. The buffer provided by the caller must be sufficiently + * large to contain the decoded object. + */ +int ei_decode_version(const char *buf, int *index, int *version); +int ei_decode_long(const char *buf, int *index, long *p); +int ei_decode_ulong(const char *buf, int *index, unsigned long *p); +int ei_decode_double(const char *buf, int *index, double *p); +int ei_decode_boolean(const char *buf, int *index, int *p); +int ei_decode_char(const char *buf, int *index, char *p); +int ei_decode_string(const char *buf, int *index, char *p); +int ei_decode_atom(const char *buf, int *index, char *p); +int ei_decode_binary(const char *buf, int *index, void *p, long *len); +int ei_decode_fun(const char* buf, int* index, erlang_fun* p); +void free_fun(erlang_fun* f); +int ei_decode_pid(const char *buf, int *index, erlang_pid *p); +int ei_decode_port(const char *buf, int *index, erlang_port *p); +int ei_decode_ref(const char *buf, int *index, erlang_ref *p); +int ei_decode_term(const char *buf, int *index, void *t); /* ETERM** actually */ +int ei_decode_trace(const char *buf, int *index, erlang_trace *p); +int ei_decode_tuple_header(const char *buf, int *index, int *arity); +int ei_decode_list_header(const char *buf, int *index, int *arity); + +/* + * ei_decode_ei_term() returns 1 if term is decoded, 0 if term is OK, + * but not decoded here and -1 if something is wrong. ONLY changes + * index if term is decoded (return value 1)! + */ + +int ei_decode_ei_term(const char* buf, int* index, ei_term* term); + + +/* + * ei_print_term to print out a binary coded term + */ + +int ei_print_term(FILE *fp, const char* buf, int* index); +int ei_s_print_term(char** s, const char* buf, int* index); + +/* + * format to build binary format terms a bit like printf + */ + +int ei_x_format(ei_x_buff* x, const char* fmt, ...); +int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ...); + +int ei_x_new(ei_x_buff* x); +int ei_x_new_with_version(ei_x_buff* x); +int ei_x_free(ei_x_buff* x); +int ei_x_append(ei_x_buff* x, const ei_x_buff* x2); +int ei_x_append_buf(ei_x_buff* x, const char* buf, int len); +int ei_skip_term(const char* buf, int* index); + +/*************************************************************************** + * + * Hash types needed by registry types + * + ***************************************************************************/ + +#define EI_SMALLKEY 32 + +typedef struct bucket_s { + int rawhash; + const char *key; + char keybuf[EI_SMALLKEY]; + const void *value; + struct bucket_s *next; +} ei_bucket; + +/* users of the package declare variables as pointers to this. */ +typedef struct { + ei_bucket **tab; + int (*hash)(const char *); /* hash function for this table */ + int size; /* size of table */ + int nelem; /* nr elements */ + int npos; /* nr occupied positions */ + ei_bucket *freelist; /* reuseable freed buckets */ +} ei_hash; + + +/*************************************************************************** + * + * Registry defines, types, functions + * + ***************************************************************************/ + +/* -------------------------------------------------------------------- */ +/* XXXXXXXXXXX */ +/* -------------------------------------------------------------------- */ + +/* registry object attributes */ +#define EI_DIRTY 0x01 /* dirty bit (object value differs from backup) */ +#define EI_DELET 0x02 /* object is deleted */ +#define EI_INT 0x10 /* object is an integer */ +#define EI_FLT 0x20 /* object is a float */ +#define EI_STR 0x40 /* object is a string */ +#define EI_BIN 0x80 /* object is a binary, i.e. pointer to arbitrary type */ + + +/* -------------------------------------------------------------------- */ +/* XXXXXXXXXXX */ +/* -------------------------------------------------------------------- */ + +typedef struct ei_reg_inode { + int attr; + int size; + union { + long i; + double f; + char *s; + void *p; + } val; + struct ei_reg_inode *next; +} ei_reg_obj; + +typedef struct { + ei_reg_obj *freelist; + ei_hash *tab; +} ei_reg; + +struct ei_reg_stat { + int attr; /* object attributes (see above) */ + int size; /* size in bytes (for STR and BIN) 0 for others */ +}; + +struct ei_reg_tabstat { + int size; /* size of table */ + int nelem; /* number of stored elements */ + int npos; /* number of occupied positions */ + int collisions; /* number of positions with more than one element */ +}; + + +/* -------------------------------------------------------------------- */ +/* XXXXXXXXXXX */ +/* -------------------------------------------------------------------- */ + +/* FIXME move comments to source */ + +/* open / close registry. On open, a descriptor is returned that must + * be specified in all subsequent calls to registry functions. You can + * open as many registries as you like. + */ +ei_reg *ei_reg_open(int size); +int ei_reg_resize(ei_reg *oldreg, int newsize); +int ei_reg_close(ei_reg *reg); + +/* set values... these routines assign values to keys. If the key + * exists, the previous value is discarded and the new one replaces + * it. + * + * BIN objects require an additional argument indicating the size in + * bytes of the stored object. This will be used when the object is + * backed up, since it will need to be copied at that time. Remember + * also that pointers are process-space specific and it is not + * meaningful to back them up for later recall. If you are storing + * binary objects for backup, make sure that they are self-contained + * (without references to other objects). + * + * On success the function returns 0, otherwise a value + * indicating the reason for failure will be returned. + */ +int ei_reg_setival(ei_reg *reg, const char *key, long i); +int ei_reg_setfval(ei_reg *reg, const char *key, double f); +int ei_reg_setsval(ei_reg *reg, const char *key, const char *s); +int ei_reg_setpval(ei_reg *reg, const char *key, const void *p, int size); + +/* general set function (specifiy type via flags) + * optional arguments are as for equivalent type-specific function, + * i.e.: + * ei_reg_setval(fd, path, EI_INT, int i); + * ei_reg_setval(fd, path, EI_FLT, float f); + * ei_reg_setval(fd, path, EI_STR, const char *s); + * ei_reg_setval(fd, path, EI_BIN, const void *p, int size); + */ +int ei_reg_setval(ei_reg *reg, const char *key, int flags, ...); + +/* get value of specific type object */ +/* warning: it may be difficult to detect errors when using these + * functions, since the error values are returned "in band" + */ +long ei_reg_getival(ei_reg *reg, const char *key); +double ei_reg_getfval(ei_reg *reg, const char *key); +const char *ei_reg_getsval(ei_reg *reg, const char *key); +const void *ei_reg_getpval(ei_reg *reg, const char *key, int *size); + +/* get value of any type object (must specify) + * Retrieve a value from an object. The type of value expected and a + * pointer to a large enough buffer must be provided. flags must be + * set to the appropriate type (see type constants above) and the + * object type must match. If (flags == 0) the pointer is *assumed* to + * be of the correct type for the object. In any case, the actual + * object type is always returned on success. + * + * The argument following flags must be one of int*, double*, const + * char** and const void**. + * + * for BIN objects an int* is needed to return the size of the object, i.e. + * int ei_reg_getval(ei_reg *reg, const char *path, int flags, void **p, int *size); + */ +int ei_reg_getval(ei_reg *reg, const char *key, int flags, ...); + +/* mark the object as dirty. Normally this operation will not be + * necessary, as it is done automatically by all of the above 'set' + * functions. However, if you modify the contents of an object pointed + * to by a STR or BIN object, then the registry will not be aware of + * the change. As a result, the object may be missed on a subsequent + * backup operation. Use this function to set the dirty bit on the + * object. + */ +int ei_reg_markdirty(ei_reg *reg, const char *key); + +/* remove objects. The value, if any, is discarded. For STR and BIN + * objects, the object itself is removed using free(). */ +int ei_reg_delete(ei_reg *reg, const char *key); + +/* get information about an object */ +int ei_reg_stat(ei_reg *reg, const char *key, struct ei_reg_stat *obuf); + +/* get information about table */ +int ei_reg_tabstat(ei_reg *reg, struct ei_reg_tabstat *obuf); + +/* dump to / restore from backup */ +/* fd is open descriptor to Erlang, mntab is Mnesia table name */ +/* flags here: */ +#define EI_FORCE 0x1 /* dump all records (not just dirty ones) */ +#define EI_NOPURGE 0x2 /* don't purge deleted records */ +int ei_reg_dump(int fd, ei_reg *reg, const char *mntab, int flags); +int ei_reg_restore(int fd, ei_reg *reg, const char *mntab); +int ei_reg_purge(ei_reg *reg); + + +/* -------------------------------------------------------------------- */ +/* Encoding/decoding bugnums to GNU MP format */ +/* -------------------------------------------------------------------- */ + +/* If the user included <gmp.h> we supply some more functions */ + +#if defined(__GNU_MP_VERSION) \ + && __GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR >= 1 + +int ei_decode_bignum(const char *buf, int *index, mpz_t obj); +int ei_encode_bignum(char *buf, int *index, mpz_t obj); +int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj); + +#endif /* __GNU_MP_VERSION */ + +/* -------------------------------------------------------------------- */ +/* Function definitions not documented FIXME */ +/* -------------------------------------------------------------------- */ + +/* FIXME replace this primitive type size code */ + +#ifdef __WIN32__ +#define EI_LONGLONG __int64 +#define EI_ULONGLONG unsigned __int64 +#else +#ifndef VXWORKS +#define EI_LONGLONG long long +#define EI_ULONGLONG unsigned long long +#endif +#endif + +#ifndef VXWORKS +int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p); +int ei_decode_ulonglong(const char *buf, int *index, EI_ULONGLONG *p); +int ei_encode_longlong(char *buf, int *index, EI_LONGLONG p); +int ei_encode_ulonglong(char *buf, int *index, EI_ULONGLONG p); +int ei_x_encode_longlong(ei_x_buff* x, EI_LONGLONG n); +int ei_x_encode_ulonglong(ei_x_buff* x, EI_ULONGLONG n); +#endif + +#ifdef USE_EI_UNDOCUMENTED + +/* + * Decode a list of integers into an integer array (i.e. even if it is + * encoded as a string). count gets number of items in array. + * See "decode_intlist.c". + */ + +int ei_decode_intlist(const char *buf, int *index, long *a, int *count); + +/* + * FIXME: used in IC, document? + * bufp = address of pointer to dynamically allocated buffer - may be reallocated by + * this function if it is too small for the message + * bufsz = in/out value: in=user buffer size, out=new buffer size + * msglen = nr bytes in received message + */ +int ei_receive_encoded(int fd, char **bufp, int *bufsz, erlang_msg *to, + int *msglen); +int ei_receive_encoded_tmo(int fd, char **bufp, int *bufsz, erlang_msg *to, + int *msglen, unsigned ms); +int ei_send_encoded(int fd, const erlang_pid *to, char *msg, int msglen); +int ei_send_encoded_tmo(int fd, const erlang_pid *to, char *msg, int msglen, + unsigned ms); +int ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to, + char *msg, int msglen); +int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, + char *msg, int msglen, unsigned ms); + +/* + * Bacward compatibility with old undocumented but used interface... + * FIXME use wrapper function instead?! + */ +#define ei_send_encoded_timeout(Fd,To,Msg,MsgLen,Ms) \ + ei_send_encoded_tmo((Fd),(To),(Msg),(MsgLen),(Ms)) +#define ei_send_reg_encoded_timeout(Fd,From,To,Msg,MsgLen,Ms) \ + ei_send_reg_encoded_tmo((Fd),(From),(To),(Msg),(MsgLen),(Ms)) + + +/* FIXME: is this really the best way to handle bignums? */ +int ei_encode_big(char *buf, int *index, erlang_big* big); +int ei_x_encode_big(ei_x_buff* x, erlang_big* big); +int ei_decode_big(const char *buf, int *index, erlang_big* p); +int ei_big_comp(erlang_big *x, erlang_big *y); +int ei_big_to_double(erlang_big *b, double *resp); +int ei_small_to_big(int s, erlang_big *b); +erlang_big *ei_alloc_big(unsigned int arity); +void ei_free_big(erlang_big *b); + +#endif /* USE_EI_UNDOCUMENTED */ + +#ifdef __cplusplus +} +#endif + +#endif /* EI_H */ diff --git a/lib/erl_interface/include/ei_connect.h b/lib/erl_interface/include/ei_connect.h new file mode 100644 index 0000000000..02880e197c --- /dev/null +++ b/lib/erl_interface/include/ei_connect.h @@ -0,0 +1,26 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2003-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#ifndef EI_CONNECT_H +#define EI_CONNECT_H + +/* Dummy for now.... */ + +#include "ei.h" + +#endif /* EI_CONNECT_H */ diff --git a/lib/erl_interface/include/eicode.h b/lib/erl_interface/include/eicode.h new file mode 100644 index 0000000000..c35489e890 --- /dev/null +++ b/lib/erl_interface/include/eicode.h @@ -0,0 +1,26 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2003-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#ifndef EICODE_H +#define EICODE_H + +/* Dummy for now.... */ + +#include "ei.h" + +#endif /* EICODE_H */ diff --git a/lib/erl_interface/include/erl_interface.h b/lib/erl_interface/include/erl_interface.h new file mode 100644 index 0000000000..1c4a94700d --- /dev/null +++ b/lib/erl_interface/include/erl_interface.h @@ -0,0 +1,449 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1996-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#ifndef _ERL_INTERFACE_H +#define _ERL_INTERFACE_H + +/************************************************************************/ +/* This file defines the complete interface to erl_interface */ +/* Note: the 'ei' interface is the prefered C API. */ +/************************************************************************/ + +/* FIXME only include if needed? */ + +#include "ei.h" /* ei is the base */ + +/* -------------------------------------------------------------------- */ +/* Public defines */ +/* -------------------------------------------------------------------- */ + +#define ERL_COMPOUND (1 << 7) + +#define ERL_UNDEF 0 +#define ERL_INTEGER 1 +#define ERL_U_INTEGER 2 /* unsigned int */ +#define ERL_ATOM 3 +#define ERL_PID 4 +#define ERL_PORT 5 +#define ERL_REF 6 +#define ERL_CONS (7 | ERL_COMPOUND) +#define ERL_LIST ERL_CONS +#define ERL_NIL 8 +#define ERL_EMPTY_LIST ERL_NIL +#define ERL_TUPLE (9 | ERL_COMPOUND) +#define ERL_BINARY 10 +#define ERL_FLOAT 11 +#define ERL_VARIABLE (12 | ERL_COMPOUND) /* used in patterns */ +#define ERL_SMALL_BIG 13 +#define ERL_U_SMALL_BIG 14 +#define ERL_FUNCTION (15 | ERL_COMPOUND) +#define ERL_BIG 16 +#define ERL_LONGLONG 17 +#define ERL_U_LONGLONG 18 + + +#define ERL_TYPE(x) (ERL_HEADER(x)->type) + +/* FIXME some macros left in erl_eterm.h should probably be documented */ + +#define ERL_IS_INTEGER(x) (ERL_TYPE(x) == ERL_INTEGER) +#define ERL_IS_UNSIGNED_INTEGER(x) (ERL_TYPE(x) == ERL_U_INTEGER) +#define ERL_IS_LONGLONG(x) (ERL_TYPE(x) == ERL_LONGLONG) +#define ERL_IS_UNSIGNED_LONGLONG(x) (ERL_TYPE(x) == ERL_U_LONGLONG) +#define ERL_IS_FLOAT(x) (ERL_TYPE(x) == ERL_FLOAT) +#define ERL_IS_ATOM(x) (ERL_TYPE(x) == ERL_ATOM) +#define ERL_IS_PID(x) (ERL_TYPE(x) == ERL_PID) +#define ERL_IS_PORT(x) (ERL_TYPE(x) == ERL_PORT) +#define ERL_IS_REF(x) (ERL_TYPE(x) == ERL_REF) +#define ERL_IS_TUPLE(x) (ERL_TYPE(x) == ERL_TUPLE) +#define ERL_IS_BINARY(x) (ERL_TYPE(x) == ERL_BINARY) +#define ERL_IS_NIL(x) (ERL_TYPE(x) == ERL_NIL) +#define ERL_IS_EMPTY_LIST(x) ERL_IS_NIL(x) +#define ERL_IS_CONS(x) (ERL_TYPE(x) == ERL_CONS) +#define ERL_IS_LIST(x) (ERL_IS_CONS(x) || ERL_IS_EMPTY_LIST(x)) + +/* + * Macros used for XXXX + */ + +#define ERL_HEADER(x) ((Erl_Header *)x) +#define ERL_COUNT(x) (ERL_HEADER(x)->count) + +/* + * Macros used for retrieving values from Erlang terms. + */ + +#define ERL_INT_VALUE(x) ((x)->uval.ival.i) +#define ERL_INT_UVALUE(x) ((x)->uval.uival.u) +#define ERL_LL_VALUE(x) ((x)->uval.llval.i) +#define ERL_LL_UVALUE(x) ((x)->uval.ullval.u) + +#define ERL_FLOAT_VALUE(x) ((x)->uval.fval.f) + +#define ERL_ATOM_PTR(x) ((x)->uval.aval.a) +#define ERL_ATOM_SIZE(x) ((x)->uval.aval.len) + +#define ERL_PID_NODE(x) ((x)->uval.pidval.node) +#define ERL_PID_NUMBER(x) ((x)->uval.pidval.number) +#define ERL_PID_SERIAL(x) ((x)->uval.pidval.serial) +#define ERL_PID_CREATION(x) ((x)->uval.pidval.creation) + +#define ERL_PORT_NODE(x) ((x)->uval.portval.node) +#define ERL_PORT_NUMBER(x) ((x)->uval.portval.number) +#define ERL_PORT_CREATION(x) ((x)->uval.portval.creation) + +#define ERL_REF_NODE(x) ((x)->uval.refval.node) +#define ERL_REF_NUMBER(x) ((x)->uval.refval.n[0]) +#define ERL_REF_NUMBERS(x) ((x)->uval.refval.n) +#define ERL_REF_LEN(x) ((x)->uval.refval.len) +#define ERL_REF_CREATION(x) ((x)->uval.refval.creation) + +#define ERL_TUPLE_SIZE(x) ((x)->uval.tval.size) + +/* NOTE!!! This is 0-based!! (first item is number 0) + * Note too that element/2 (in Erlang) and + * erl_element() are both 1-based. + */ +#define ERL_TUPLE_ELEMS(x) ((x)->uval.tval.elems) +#define ERL_TUPLE_ELEMENT(x, i) (ERL_TUPLE_ELEMS(x)[(i)]) + +#define ERL_BIN_SIZE(x) ((x)->uval.bval.size) +#define ERL_BIN_PTR(x) ((x)->uval.bval.b) + +#define ERL_CONS_HEAD(x) ((x)->uval.lval.head) +#define ERL_CONS_TAIL(x) ((x)->uval.lval.tail) + +#define ERL_VAR_LEN(x) ((x)->uval.vval.len) +#define ERL_VAR_NAME(x) ((x)->uval.vval.name) +#define ERL_VAR_VALUE(x) ((x)->uval.vval.v) + +#define ERL_CLOSURE_SIZE(x) ((x)->uval.funcval.size) +#define ERL_FUN_CREATOR(x) ((x)->uval.funcval.creator) +#define ERL_FUN_MODULE(x) ((x)->uval.funcval.module) +#define ERL_FUN_UNIQ(x) ((x)->uval.funcval.uniq) +#define ERL_FUN_INDEX(x) ((x)->uval.funcval.index) +#define ERL_FUN_ARITY(x) ((x)->uval.funcval.arity) +#define ERL_FUN_NEW_INDEX(x) ((x)->uval.funcval.new_index) +#define ERL_FUN_MD5(x) ((x)->uval.funcval.md5) +#define ERL_CLOSURE(x) ((x)->uval.funcval.closure) +#define ERL_CLOSURE_ELEMENT(x,i) (ERL_CLOSURE(x)[(i)]) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------------------------------------------------- */ +/* Type definitions of Erlang terms in C */ +/* -------------------------------------------------------------------- */ + +typedef struct { + unsigned int count:24; /* reference counter */ + unsigned int type:8; /* type of Erlang term */ +} Erl_Header; + +typedef struct { + Erl_Header h; + int i; +} Erl_Integer; + +typedef struct { + Erl_Header h; + unsigned int u; +} Erl_Uinteger; + +typedef struct { + Erl_Header h; + long long i; +} Erl_LLInteger; + +typedef struct { + Erl_Header h; + unsigned long long u; +} Erl_ULLInteger; + +typedef struct { + Erl_Header h; + double f; +} Erl_Float; + +typedef struct { + Erl_Header h; + int len; + char *a; +} Erl_Atom; + +typedef struct { + Erl_Header h; + char * node; + unsigned int number; + unsigned int serial; + unsigned char creation; +} Erl_Pid; + +typedef struct { + Erl_Header h; + char * node; + unsigned int number; + unsigned char creation; +} Erl_Port; + +typedef struct { + Erl_Header h; + char * node; + int len; + unsigned int n[3]; + unsigned char creation; +} Erl_Ref; + +typedef struct { + Erl_Header h; + int arity; + int is_neg; + unsigned short *digits; +} Erl_Big; + +struct _eterm; /* forward */ + +typedef struct { + Erl_Header h; + struct _eterm *head; + struct _eterm *tail; +} Erl_List; + +typedef struct { + Erl_Header h; +} Erl_EmptyList; + +typedef struct { + Erl_Header h; + int size; + struct _eterm **elems; +} Erl_Tuple; + +typedef struct { + Erl_Header h; + int size; + unsigned char *b; +} Erl_Binary; + +/* Variables may only exist in patterns. + * Note: identical variable names in a pattern + * denotes the same value. + */ +typedef struct { + Erl_Header h; + int len; + char *name; + struct _eterm *v; +} Erl_Variable; + + +typedef struct { + Erl_Header h; + int size; /* size of closure */ + int arity; /* arity for new (post R7) external funs */ + unsigned char md5[16]; /* md5 for new funs */ + int new_index; /* new funs */ + struct _eterm* creator; /* pid */ + struct _eterm* module; /* module */ + struct _eterm* index; + struct _eterm* uniq; + struct _eterm** closure; +} Erl_Function; + +typedef struct _eterm { + union { + Erl_Integer ival; + Erl_Uinteger uival; + Erl_LLInteger llval; + Erl_ULLInteger ullval; + Erl_Float fval; + Erl_Atom aval; + Erl_Pid pidval; + Erl_Port portval; + Erl_Ref refval; + Erl_List lval; + Erl_EmptyList nval; + Erl_Tuple tval; + Erl_Binary bval; + Erl_Variable vval; + Erl_Function funcval; + Erl_Big bigval; + } uval; +} ETERM; + + +#define MAXREGLEN 255 /* max length of registered (atom) name */ + +typedef struct { + int type; /* one of the message type constants in eiext.h */ + ETERM *msg; /* the actual message */ + ETERM *from; + ETERM *to; + char to_name[MAXREGLEN+1]; +} ErlMessage; + +typedef unsigned char Erl_Heap; + + +/* -------------------------------------------------------------------- */ +/* The functions */ +/* -------------------------------------------------------------------- */ + +void erl_init(void *x, long y); +void erl_set_compat_rel(unsigned); +int erl_connect_init(int, char*,short); +int erl_connect_xinit(char*,char*,char*,struct in_addr*,char*,short); +int erl_connect(char*); +int erl_xconnect(struct in_addr*,char *); +int erl_close_connection(int); +int erl_receive(int, unsigned char*, int); +int erl_receive_msg(int, unsigned char*, int, ErlMessage*); +int erl_xreceive_msg(int, unsigned char**, int*, ErlMessage*); +int erl_send(int, ETERM*, ETERM*); +int erl_reg_send(int, char*, ETERM*); +ETERM *erl_rpc(int,char*,char*,ETERM*); +int erl_rpc_to(int,char*,char*,ETERM*); +int erl_rpc_from(int,int,ErlMessage*); + +/* erl_publish returns open descriptor on success, or -1 */ +int erl_publish(int port); +int erl_accept(int,ErlConnect*); + +const char *erl_thiscookie(void); +const char *erl_thisnodename(void); +const char *erl_thishostname(void); +const char *erl_thisalivename(void); +short erl_thiscreation(void); + +/* returns 0 on success, -1 if node not known to epmd or epmd not reached */ +int erl_unpublish(const char *alive); + +/* Report generic error to stderr. */ +void erl_err_msg(const char * __template, ...) + __attribute__ ((__format__ (printf, 1, 2))); +/* Report generic error to stderr and die. */ +void erl_err_quit(const char * __template, ...) + __attribute__ ((__format__ (printf, 1, 2), __noreturn__)); +/* Report system/libc error to stderr. */ +void erl_err_ret(const char * __template, ...) + __attribute__ ((__format__ (printf, 1, 2))); +/* Report system/libc error to stderr and die. */ +void erl_err_sys(const char * __template, ...) + __attribute__ ((__format__ (printf, 1, 2), __noreturn__)); + +ETERM *erl_cons(ETERM*,ETERM*); +ETERM *erl_copy_term(const ETERM*); +ETERM *erl_element(int,const ETERM*); + +ETERM *erl_hd(const ETERM*); +ETERM* erl_iolist_to_binary(const ETERM* term); +char* erl_iolist_to_string(const ETERM* term); +int erl_iolist_length(const ETERM*); +int erl_length(const ETERM*); +ETERM *erl_mk_atom(const char*); +ETERM *erl_mk_binary(const char*,int); +ETERM *erl_mk_empty_list(void); +ETERM *erl_mk_estring(const char*, int); +ETERM *erl_mk_float(double); +ETERM *erl_mk_int(int); +ETERM *erl_mk_longlong(long long); +ETERM *erl_mk_list(ETERM**,int); +ETERM *erl_mk_pid(const char*,unsigned int,unsigned int,unsigned char); +ETERM *erl_mk_port(const char*,unsigned int,unsigned char); +ETERM *erl_mk_ref(const char*,unsigned int,unsigned char); +ETERM *erl_mk_long_ref(const char*,unsigned int,unsigned int, + unsigned int,unsigned char); +ETERM *erl_mk_string(const char*); +ETERM *erl_mk_tuple(ETERM**,int); +ETERM *erl_mk_uint(unsigned int); +ETERM *erl_mk_ulonglong(unsigned long long); +ETERM *erl_mk_var(const char*); +int erl_print_term(FILE*,const ETERM*); +/* int erl_sprint_term(char*,const ETERM*); */ +int erl_size(const ETERM*); +ETERM *erl_tl(const ETERM*); +ETERM *erl_var_content(const ETERM*, const char*); + +ETERM *erl_format(char*, ... ); +int erl_match(ETERM*, ETERM*); + +char **erl_global_names(int fd, int *count); +int erl_global_register(int fd, const char *name, ETERM *pid); +int erl_global_unregister(int fd, const char *name); +ETERM *erl_global_whereis(int fd, const char *name, char *node); + +void erl_init_malloc(Erl_Heap*,long); +ETERM *erl_alloc_eterm(unsigned char); +void erl_eterm_release(void); +void erl_eterm_statistics(unsigned long*,unsigned long*); +void erl_free_array(ETERM**,int); +void erl_free_term(ETERM*); +void erl_free_compound(ETERM*); +void *erl_malloc(long); +void erl_free(void*); + +int erl_compare_ext(unsigned char*, unsigned char*); +ETERM *erl_decode(unsigned char*); +ETERM *erl_decode_buf(unsigned char**); +int erl_encode(ETERM*,unsigned char*t); +int erl_encode_buf(ETERM*,unsigned char**); +int erl_ext_size(unsigned char*); +unsigned char erl_ext_type(unsigned char*); /* Note: returned 'char' before R9C */ +unsigned char *erl_peek_ext(unsigned char*,int); +int erl_term_len(ETERM*); + + +/* -------------------------------------------------------------------- */ +/* Wrappers around ei functions */ +/* -------------------------------------------------------------------- */ + +/* + * Undocumented before R9C, included for compatibility with old code + */ + +struct hostent *erl_gethostbyname(const char *name); +struct hostent *erl_gethostbyaddr(const char *addr, int len, int type); +struct hostent *erl_gethostbyname_r(const char *name, + struct hostent *hostp, + char *buffer, + int buflen, + int *h_errnop); +struct hostent *erl_gethostbyaddr_r(const char *addr, + int length, + int type, + struct hostent *hostp, + char *buffer, + int buflen, + int *h_errnop); + +/* + * Undocumented, included for compatibility with old code + */ + +void erl_init_resolve(void); +int erl_distversion(int fd); +int erl_epmd_connect(struct in_addr *inaddr); +int erl_epmd_port(struct in_addr *inaddr, const char *alive, int *dist); + +#ifdef __cplusplus +} +#endif + +#endif |