****************************************************************************** General ****************************************************************************** There are two different interfaces, the old 'erl_interface' and 'ei'. The old interface is to depend on the new one, not the other way arount. Erl_interface should be "thread safe", i.e. you should be able to handle connections, convert data etc from different threads. Ei should be "reentrant" or "async safe", i.e. no locks should be set so that if an ei function is called inside an signal handler there could be a deadlock. VxWorks call the operating processes "tasks". These are to be handled the same way as Unix threads, i.e. there can only be one C node for all tasks using the old interface. Try to keep the documented functions, variables and symbols in sync between * Documentation * ei.h and erl_interface.h * prog/ei_fake_prog.c and prog/erl_fake_prog.c From time to time do a % (cd src; gmake check) (FIXME this check should be rewritten to a test case) ****************************************************************************** Directories ****************************************************************************** * src/aux/ Support files for configure described in the next section * src/legacy/ Old erl_interface stuff FIXME what about thread support etc....? * src/connect/ Create nodes, connections, communication with the other node etc * src/decode/ Simple decode functions * src/encode/ Simple encode functions * src/epmd/ Handle communication with epmd * src/registry/ Key/value database with optional mnesia back up * src/misc/ The rest of the library * src/prog/ erl_call and some test programs for compiling and linking * src/not_used/ Strange, some files are not used.... ****************************************************************************** Configuration support files ****************************************************************************** The build uses GNU configure and libtool. The libtool and autoconf package don't need to be installed to configure and build the sources. But in "maintainer mode" you need them to update some files in the source distribution. * configure.in Used in maintainer mode together with "aclocal.m4" to create "configure". "configure.in" is hand written and only need to be updated when you change the sources to use new header files or C compiler features. You may get some hints about what to update using a recent autoconf package and do % cd erl_inteface % autoscan src The result to compare with the current "configure.in" will be stored in "src/configure.scan". * aclocal.m4 This file contains macros generated by ??? appended with the content of "libtool.m4" in the installed libtool package. (FIXME don't know when this is to be updated and why it contains so much). * src/aux/config.guess * src/aux/config.sub Used by "configure" to form the subdirectory name "cpu-vendor-os". * src/aux/install-sh* Used if no other BSD compatible install script is found. * src/aux/config.h.in Used by "configure" as a template for the resulting "src/config.h". The file "config.h.in" should be updated when "configure.in" is updated because the new macros used in your source and this is the file where they are listed. You can find out what to update using % autoheader * ltmain.sh This is XXX (FIXME what?) The base for the configure.in script was created with 'autoscan'. The base for the config.h.in file was created with 'autoheader'. ****************************************************************************** Writing source ****************************************************************************** C files in "registry" are considered users of 'ei' and should not include "eidef.h" or "config.h", only "ei.h". C files in "prog" could include "config.h" directly. Other C files should include "eidef.h" as the first line of source. "eidef.h" contains some common constants and macros and also includes config.h. In general avoid including other header files from header files. The exception is to make the protoypes complete to the user of this library, i.e. to include to defined FILE or to include "ei_x_encode" to define the type ei_x_buff. The function ei_decode_term() (FIXME encode_term?) work on ETERM, i.e. it converts between the old erl_interface format and ei. Because of this it is really part of the erl_interface library, not the ei library. Use uint8, uint16, uint32, int8, int16, and int32 for types where size matters ;-) Use uint8 for buffers where we construct messages. NOTE!!!! Sending a "char" to macros like isupper(), isalpha() where the character is > 127 will cause serios problems on some machines/OS. The reason is that 'char' may be unsigned, i.e. the Swedish char 'ä' will as a number be negativ. The implementation of isupper() and others will on some machines use an array that is indexed with the incoming character code. The Swedish 'ä' will then create an access on memory outside the array! This may give a random value as a result or a segmentation violation error. ****************************************************************************** Global variables ****************************************************************************** There are two reasons we avoid global variables: - It is much easier to support threads without them - On operating systems like VxWorks the global variable is global to all operating system processes. There are a few global variables that are ok ei_x_extra This is set to 100 in "ei_x_encode.c" but can be changed for debugging the memory allocation. ei_trace_distribution Enable verbose tracing on stderr. errno In the non threaded version of the lib this is a global variable. __erl_errno This is a global handled by "ei_pthreads.c" You can check for globals using something like % nm -g ei_fake_prog | fgrep OBJT Global variables but with local scope erl_if_ec Global state, is ok ****************************************************************************** The "long long" story ****************************************************************************** There are some functions in the 'ei' library that uses the GCC and VC++ "long long" type. Unfortunately this can lead to some trouble. When user code is linked with the "libei.a" the linker will extract all objects files needed for resolving all symbol references found. This means that you want to follow the rule that * To reduce executable code size we use resonably small C source files. One C file is one object file. * We try to avoid unessesary dependency. For example currently almost all ei_x_encode*() functions are in the same object file. Because they all use the corresponding ei_encode*() function this means using one ei_x function we will link in "ei_x_encode.o" object file but also all the "ei_encode*.o" object files even if they are not used. But the above is not the real trouble, memory and disk is cheap these days. The real trouble is if we compile the 'ei' library using one compiler, usually GNU cc, and link with another linker than GNU ld or miss some runtime libraries that the GNU cc generated object files assume is on the target. For example currently on Solaris some "long long" operations will create a dependency to a "hidden" library "libgcc.a". For example in a library not released got references to "libgcc.a" '__ashldi3' % nm -A libei.a | grep '__ashldi3' libei.a[decode_longlong.o]: [6] | 0| 0|NOTY |GLOB |0 |UNDEF |__ashldi3 libei.a[decode_ulonglong.o]: [5] | 0| 0|NOTY |GLOB |0 |UNDEF |__ashldi3 We can accept that a dependecy is created for code linked with "libei.a" that actually use 'ei' long long functions. But if we arrange the 'ei' source badly using a non "long long" functions from 'ei' will still link in an object file that need "libgcc.a". One example is that in plain R9C the ei_x_encode_longlong() function is located in the file "ei_x_encode.c". So if any "long long" ei_x function is used we have an unessesary dependency on "ei_encode_longlong.o" and then need to link with GNU ld on with the user code or explicitly link with "libgcc.a". The situation can be visible in in plain R9C using % nm -A erl_interface-3.4/lib/libei.a | \ grep 'longlong' | fgrep -v 'longlong.o' As an possibly alternative to the current solution we may include the object files inside the "libgcc.a" archive in the "libei.a" archive. The "libgcc.a" that is assumed to be used when linking can be found using % gcc -print-libgcc-file-name Some links about problems and solutions using "libgcc.a" http://www.gnu.org/software/gcc/gcc-3.0/libgcc.html http://www.gnu.org/software/libc/FAQ.html The license for "libgcc.a" is a bit special and not located on the official sites. You have to look in the source file for the "libgcc.a" you use. The file is named "libgcc.c". If you don't know what gcc that was used for the build of for example 'r9c' you can use % otp_build_env -o r9c | perl -ne '/(gcc-[\d\.]+)/ and print "$1\n"' Then to view the lincense do % less `find /usr/local/share/src/gcc-REL/ -name "libgcc*.c"` ********************************* EOF ****************************************