GNU Emacs as a LISP interpreter

 

After applying the following patch, you can run GNU Emacs as a standalone LISP interpreter for batch usage. It basically disables the command loop and non-essential symbols in batch mode.  

temacs is Emacs sans any bootstrap elisp code. It is the first artifact generated during the Emacs build process. So you might not find it in your package installation. You can use the emacs binary too for the same effect - just understand that underneath they are not the same.

 

modified   src/keyboard.c
@@ -1067,6 +1067,7 @@ command_loop (void)
     while (1)
       {
     internal_catch (Qtop_level, top_level_1, Qnil);
+    if (!noninteractive)
     internal_catch (Qtop_level, command_loop_2, Qnil);
     executing_kbd_macro = Qnil;
 
@@ -2631,9 +2632,9 @@ read_char (int commandflag, Lisp_Object map,
   if (minibuf_level == 0
       && !end_time
       && !current_kboard->immediate_echo
+      && ! noninteractive
       && (this_command_key_count > 0
       || !NILP (call0 (Qinternal_echo_keystrokes_prefix)))
-      && ! noninteractive
       && echo_keystrokes_p ()
       && (/* No message.  */
       NILP (echo_area_buffer[0])
@@ -4166,6 +4167,7 @@ timer_start_idle (void)
   timer_last_idleness_start_time = timer_idleness_start_time;
 
   /* Mark all idle-time timers as once again candidates for running.  */
+  if (INTERACTIVE)
   call0 (intern ("internal-timer-start-idle"));
 }
 
modified   src/lread.c
@@ -1030,7 +1030,9 @@ load_error_handler (Lisp_Object data)
 static void
 load_warn_unescaped_character_literals (Lisp_Object file)
 {
-  Lisp_Object warning = call0 (Qbyte_run_unescaped_character_literals_warning);
+ Lisp_Object warning = Qnil;
+ if (INTERACTIVE)
+   call0 (Qbyte_run_unescaped_character_literals_warning);
   if (!NILP (warning))
     {
       AUTO_STRING (format, "Loading `%s': %s");

 

Threads

Here's a thread example in lisp. Create a file a.el with following content. Some points to remember:
  • Note that you need to use load and not require for loading a file.
  • When the parent process exits, all children threads are killed. Hence you need to use thread-join at the end to avoid that.
  • Emacs Lisp mutexes are of a type called recursive, which means that a thread can re-acquire a mutex it owns any number of times. A mutex keeps a count of how many times it has been acquired, and each acquisition of a mutex must be paired with a release.
  • systhread.c (and not thread.c) has the wrapper implementation around pthreads.

;; For defun
(load "emacs-lisp/byte-run")
;; For with-mutex
(load "subr")

;; Unset global-var
(setq global-var nil)

;; Create a mutex and an associated condition variable
(setq mutex (make-mutex "mutex"))
(setq cond-var (make-condition-variable mutex "cond-var"))

;; Read and set functions used by read and set threads
(defun read-global-var ()
  (message "read: global-var = %s ... reading" global-var)
  (with-mutex mutex
    (while (not global-var)
      ;; condition-wait is a blocking function. The thread will block here.
      (condition-wait cond-var))
    (message "read: global-var = %-3s ... exiting" global-var)))

(defun set-global-var ()
  (with-mutex mutex
    (progn
      (message "set: Sleeping for 5s before setting global-var")
      (sleep-for 5)
      (message "set: Setting global-var")
      (setq global-var "1")
      (condition-notify cond-var))))

;; Create and start set thread
(make-thread 'set-global-var)

;; Create, start and wait for read to finish
(thread-join (make-thread 'read-global-var))
 
 
 
When you execute the script you should see following output.
 
anand@PureBook:~/work/emacs/src$ ./temacs -batch -nl -l $PWD/a.el
Loading /home/anand/work/emacs/src/a.el (source)...
Loading emacs-lisp/byte-run...
Loading subr...
set: Sleeping for 5s before setting global-var
read: global-var = nil ... reading
set: Setting global-var
read: global-var = 1   ... exiting 
  
 

Minix


 
For running this on Minix, following is one tested configuration of Emacs (fork of Emacs - minix branch).
 
configure --without-all --without-x --without-makeinfo --with-mailutils
 
 
 

References

 

 

 

  

 

Comments

Popular posts from this blog

GNU Emacs as a Comic Book Reader

Data Visualization with GNU Emacs

Tinylisp and Multi-threaded Emacs