From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stephen Leake Newsgroups: gmane.emacs.devel Subject: dynamic modules progress Date: Fri, 15 May 2015 09:36:51 -0500 Message-ID: <85wq09q54s.fsf@stephe-leake.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1431700701 32454 80.91.229.3 (15 May 2015 14:38:21 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Fri, 15 May 2015 14:38:21 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri May 15 16:38:13 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1YtGke-0002wu-DR for ged-emacs-devel@m.gmane.org; Fri, 15 May 2015 16:38:12 +0200 Original-Received: from localhost ([::1]:59916 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtGkd-0002Xn-Vf for ged-emacs-devel@m.gmane.org; Fri, 15 May 2015 10:38:11 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51003) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YtGk2-00026J-Qz for emacs-devel@gnu.org; Fri, 15 May 2015 10:37:36 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YtGjx-0000iH-IY for emacs-devel@gnu.org; Fri, 15 May 2015 10:37:34 -0400 Original-Received: from gproxy9-pub.mail.unifiedlayer.com ([69.89.20.122]:36546) by eggs.gnu.org with smtp (Exim 4.71) (envelope-from ) id 1YtGjx-0000cB-9V for emacs-devel@gnu.org; Fri, 15 May 2015 10:37:29 -0400 Original-Received: (qmail 2557 invoked by uid 0); 15 May 2015 14:36:20 -0000 Original-Received: from unknown (HELO cmgw3) (10.0.90.84) by gproxy9.mail.unifiedlayer.com with SMTP; 15 May 2015 14:36:20 -0000 Original-Received: from host114.hostmonster.com ([74.220.207.114]) by cmgw3 with id ULWP1q00b2UdiVW01LWShf; Fri, 15 May 2015 14:30:30 -0600 X-Authority-Analysis: v=2.1 cv=d9Vml3TE c=1 sm=1 tr=0 a=CQdxDb2CKd3SRg4I0/XZPQ==:117 a=CQdxDb2CKd3SRg4I0/XZPQ==:17 a=DsvgjBjRAAAA:8 a=f5113yIGAAAA:8 a=2wGvvwaKUHMA:10 a=9i_RQKNPAAAA:8 a=hEr_IkYJT6EA:10 a=x_XPkuGwIRMA:10 a=h1PgugrvaO0A:10 a=mDV3o1hIAAAA:8 a=R-IlhjFrEnSakyKQ8j8A:9 a=inoG4m36AAAA:8 a=kOhZ_UguO_oswccUsdEA:9 a=jCqg-KcJ7bHC1YT9:21 a=Odrlg0Ntx1tdaumZ:21 Original-Received: from [76.218.37.33] (port=49446 helo=TAKVER) by host114.hostmonster.com with esmtpa (Exim 4.84) (envelope-from ) id 1YtGjj-0001rC-D0 for emacs-devel@gnu.org; Fri, 15 May 2015 08:37:15 -0600 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (windows-nt) X-Identified-User: {2442:host114.hostmonster.com:stephele:stephe-leake.org} {sentby:smtp auth 76.218.37.33 authed with stephen_leake@stephe-leake.org} X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 69.89.20.122 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:186514 Archived-At: --=-=-= Content-Type: text/plain I've got parsers for several symbol test grammars working as Emacs modules. In doing so, I've added a few things to emacs_modules.h and modules.c; patch below. I also added FIXMEs for any issues I could identify from the discussion on emacs-devel. Next step is to get this working with the full Ada grammar, and then address the FIXMEs in the below patch. Can we get this branch hosted on git.sv.gnu.org? That would make it easier to update from current master, and to merge to master when we agree it's ready. Aurelian, do you need write privs there? -- -- Stephe --=-=-= Content-Type: text/css Content-Disposition: inline; filename=modules.patch diff --git a/ChangeLog b/ChangeLog index 0bfdfbb..681b58e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2015-05-15 Stephen Leake + + add FIXMEs for remaining module issues + + * src/emacs_module.h: emacs_value type/size + + * src/module.c: several fixmes + +2015-05-14 Stephen Leake + + implement some missing module functions, add new ones + + * src/emacs_module.h: add buffer_byte_length, copy_buffer_substring + + * src/module.c: add buffer_byte_length, copy_buffer_substring + +2015-05-13 Stephen Leake + + * src/emacs_module.h: add Qt_value, Qnil_value change signal_error + to take 'const char*' instead of emacs_value for string add + intern_soft, bind_function, message, symbol_value + + * src/module.c: change declaration order to match emacs_module.h, + doc missing features, add new implement module_signal_error, + module_intern_soft, module_bind_function, module_message, + module_symbol_value + + * src/module.c: (Fmodule_load): improve error message + 2015-02-27 Paul Eggert Don't require GNU putenv diff --git a/src/emacs_module.h b/src/emacs_module.h index 072ee46..d903eae 100644 --- a/src/emacs_module.h +++ b/src/emacs_module.h @@ -27,6 +27,9 @@ /* Current environement */ typedef struct emacs_env_25 emacs_env; + +/* FIXME: size mismatch on 32 bit system with --with-wide-int. Have + Emacs pass env var to makefile to specify this type. */ typedef void* emacs_value; /* Struct passed to a module init function (emacs_module_init) */ @@ -51,6 +54,12 @@ struct emacs_env_25 { size_t size; /* + * Constants + */ + emacs_value Qt_value; + emacs_value Qnil_value; + + /* * Memory management */ @@ -73,7 +82,7 @@ struct emacs_env_25 { emacs_value *error_data_out); void (*signal_error)(emacs_env *env, - emacs_value error_symbol, + const char* msg, emacs_value error_data); /* @@ -93,6 +102,13 @@ struct emacs_env_25 { emacs_value (*intern)(emacs_env *env, const char *symbol_name); + emacs_value (*intern_soft)(emacs_env *env, + const char *symbol_name); + + void (*bind_function) (emacs_env *env, + const char *name, + emacs_value definition); + /* * Type conversion */ @@ -117,8 +133,38 @@ struct emacs_env_25 { char *buffer, size_t* length_inout); + size_t (*buffer_byte_length)(emacs_env *env, + emacs_value start, + emacs_value end); + /* Return the size in bytes of the buffer substring in the current + buffer from START to END */ + + void (*copy_buffer_substring)(emacs_env *env, + emacs_value start, + emacs_value end, + char *buffer, + size_t* length_inout); + /* Copy buffer string from current buffer, BEG to END (integers or + markers), to BUFFER. On call, LENGTH_INOUT is the size in bytes + of BUFFER; on return, it is the size in bytes of the copied + string. + + If BUFFER is too small, signals an error. Use buffer_byte_length + to ensure BUFFER is not too small. */ + emacs_value (*make_string)(emacs_env *env, const char *contents); + + /* + * miscellaneous + */ + + void (*message)(emacs_env *env, + emacs_value msg); + /* msg must be already formatted */ + + emacs_value (*symbol_value)(emacs_env *env, + emacs_value symbol); }; #endif /* EMACS_MODULE_H */ diff --git a/src/module.c b/src/module.c index a4fc13c..bfbaab6 100644 --- a/src/module.c +++ b/src/module.c @@ -20,15 +20,25 @@ #include #include "lisp.h" +#include "character.h" +#include "buffer.h" #include "emacs_module.h" #include +/* internal functions */ void syms_of_module (void); static struct emacs_runtime* module_get_runtime (void); static emacs_env* module_get_environment (struct emacs_runtime *ert); -static emacs_value module_make_fixnum (emacs_env *env, int64_t n); -static int64_t module_fixnum_to_int (emacs_env *env, emacs_value n); -static emacs_value module_intern (emacs_env *env, const char *name); + +/* emacs_module.h emacs_env_* functions; same order as there */ +/* FIXME: make_global_reference */ +/* FIXME: free_global_reference */ +/* FIXME: error_check */ +/* FIXME: clear_error */ +/* FIXME: get_error */ +static void module_signal_error (emacs_env *env, + const char* msg, + emacs_value error_data); static emacs_value module_make_function (emacs_env *env, int min_arity, int max_arity, @@ -37,9 +47,41 @@ static emacs_value module_funcall (emacs_env *env, emacs_value fun, int nargs, emacs_value args[]); +static emacs_value module_intern (emacs_env *env, + const char *name); +static emacs_value module_intern_soft (emacs_env *env, + const char *name); +static void module_bind_function (emacs_env *env, + const char *name, + emacs_value definition); +/* FIXME: type_of */ +static int64_t module_fixnum_to_int (emacs_env *env, + emacs_value n); +static emacs_value module_make_fixnum (emacs_env *env, + int64_t n); +/* FIXME: float_to_c_double */ +/* FIXME: make_float */ +/* FIXME: copy_string_contents */ +static size_t module_buffer_byte_length (emacs_env *env, + emacs_value start, + emacs_value end); + +static void module_copy_buffer_substring (emacs_env *env, + emacs_value start, + emacs_value end, + char *buffer, + size_t *length_inout); +static emacs_value module_make_string (emacs_env *env, + const char *contents); +static void module_message (emacs_env *env, + emacs_value msg); +static emacs_value module_symbol_value (emacs_env *env, + emacs_value symbol); + static struct emacs_runtime* module_get_runtime (void) { + /* FIXME: why do we need module_get_runtime, as opposed to just module_get_environment? */ struct emacs_runtime *ert = xzalloc (sizeof *ert); ert->size = sizeof *ert; @@ -50,14 +92,32 @@ static struct emacs_runtime* module_get_runtime (void) static emacs_env* module_get_environment (struct emacs_runtime *ert) { + /* FIXME: error if not on main emacs thread? */ + emacs_env *env = xzalloc (sizeof *env); - env->size = sizeof *env; - env->make_fixnum = module_make_fixnum; - env->fixnum_to_int = module_fixnum_to_int; - env->intern = module_intern; - env->make_function = module_make_function; - env->funcall = module_funcall; + env->size = sizeof *env; + env->Qt_value = (emacs_value) Qt; + env->Qnil_value = (emacs_value) Qnil; + /* FIXME: make_global_reference */ + /* FIXME: free_global_reference */ + /* FIXME: error_check */ + /* FIXME: clear_error */ + /* FIXME: get_error */ + env->signal_error = module_signal_error; + env->make_function = module_make_function; + env->funcall = module_funcall; + env->intern = module_intern; + env->intern_soft = module_intern_soft; + env->bind_function = module_bind_function; + env->fixnum_to_int = module_fixnum_to_int; + env->make_fixnum = module_make_fixnum; + /* FIXME: copy_string_contents */ + env->buffer_byte_length = module_buffer_byte_length; + env->copy_buffer_substring = module_copy_buffer_substring; + env->make_string = module_make_string; + env->message = module_message; + env->symbol_value = module_symbol_value; return env; } @@ -77,6 +137,32 @@ static emacs_value module_intern (emacs_env *env, const char *name) return (emacs_value) intern (name); } +static emacs_value module_intern_soft (emacs_env *env, const char *name) +{ + register ptrdiff_t len = strlen (name); + register Lisp_Object tem = oblookup (Vobarray, name, len, len); + + if (INTEGERP (tem)) + return (emacs_value) Qnil; + else + return (emacs_value) tem; +} + +static void module_bind_function (emacs_env *env, + const char *name, + emacs_value definition) +{ + Lisp_Object symbol = intern (name); + set_symbol_function (symbol, (Lisp_Object) definition); +} + +static void module_signal_error (emacs_env *env, + const char* msg, + emacs_value error_data) +{ + signal_error (msg, (Lisp_Object) (error_data)); +} + static emacs_value module_make_function (emacs_env *env, int min_arity, int max_arity, @@ -91,6 +177,7 @@ static emacs_value module_make_function (emacs_env *env, subrptr arglist))) */ + /* FIXME: allow for doc string and interactive */ Lisp_Object Qrest = intern ("&rest"); Lisp_Object Qarglist = intern ("arglist"); Lisp_Object Qmodule_call = intern ("module-call"); @@ -138,6 +225,100 @@ static emacs_value module_funcall (emacs_env *env, return (emacs_value) ret; } +static size_t module_buffer_byte_length (emacs_env *env, + emacs_value start, + emacs_value end) +{ + Lisp_Object start_1 = (Lisp_Object)start; + Lisp_Object end_1 = (Lisp_Object)end; + + validate_region (&start_1, &end_1); + + { + ptrdiff_t start_byte = CHAR_TO_BYTE (XINT (start_1)); + ptrdiff_t end_byte = CHAR_TO_BYTE (XINT (end_1)); + + return (size_t) end_byte - start_byte; + } +} + +static void module_copy_buffer_substring (emacs_env *env, + emacs_value start, + emacs_value end, + char *buffer, + size_t *length_inout) +{ + /* Copied from editfns.c "buffer-substring-no-properties" and make_buffer_string_both */ + Lisp_Object start_1 = (Lisp_Object)start; + Lisp_Object end_1 = (Lisp_Object)end; + + validate_region (&start_1, &end_1); + + { + ptrdiff_t start = XINT (start_1); + ptrdiff_t start_byte = CHAR_TO_BYTE (start); + ptrdiff_t end = XINT (end_1); + ptrdiff_t end_byte = CHAR_TO_BYTE (end); + ptrdiff_t beg0, end0, beg1, end1; + size_t size; + + if (end_byte - start_byte > *length_inout) + { + /* buffer too small */ + /* FIXME: could copy less than requested, but that's + complicated for multi-byte characters */ + signal_error ("module_copy_buffer_substring: buffer too small", Qnil); + } + + if (start_byte < GPT_BYTE && GPT_BYTE < end_byte) + { + /* Two regions, before and after the gap. */ + beg0 = start_byte; + end0 = GPT_BYTE; + beg1 = GPT_BYTE + GAP_SIZE - BEG_BYTE; + end1 = end_byte + GAP_SIZE - BEG_BYTE; + } + else + { + /* One region, before the gap. */ + beg0 = start_byte; + end0 = end_byte; + beg1 = -1; + end1 = -1; + } + + size = end0 - beg0; + + /* FIXME: need to decode? See external process stuff. */ + + /* BYTE_POS_ADDR handles one region after the gap */ + memcpy (buffer, BYTE_POS_ADDR (beg0), size); + if (beg1 != -1) + memcpy (buffer + size, BEG_ADDR + beg1, end1 - beg1); + } +} + +static emacs_value module_make_string (emacs_env *env, const char *contents) +{ + return (emacs_value) make_string (contents, strlen (contents)); +} + +static void module_message (emacs_env *env, + emacs_value msg) +{ + message3 ((Lisp_Object) msg); +} + +static emacs_value module_symbol_value (emacs_env *env, + emacs_value symbol) +{ + Lisp_Object val= find_symbol_value ((Lisp_Object) symbol); + if (!EQ (val, Qunbound)) + return (emacs_value) val; + + xsignal1 (Qvoid_variable, (Lisp_Object) symbol); +} + DEFUN ("module-call", Fmodule_call, Smodule_call, 3, 3, 0, doc: "Call a module function") (Lisp_Object envptr, Lisp_Object subrptr, Lisp_Object arglist) @@ -181,10 +362,13 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0, lt_init_done = 1; } + /* FIXME: check for libltdl, load it if available; don't require + --with-ltdl at configure time. See image.c for example. */ + CHECK_STRING (file); handle = lt_dlopen (SDATA (file)); if (!handle) - error ("Cannot load file %s", SDATA (file)); + error ("Cannot load file %s : %s", SDATA (file), lt_dlerror()); gpl_sym = lt_dlsym (handle, "plugin_is_GPL_compatible"); if (!gpl_sym) @@ -197,6 +381,7 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0, int r = module_init (module_get_runtime ()); + /* Errors are reported by calling env->signal_error. FIXME: so why does module_init return anything? */ return Qt; } --=-=-=--