Browse Source

Merge branch 'master' of git+ssh://repo.or.cz/srv/git/org-mode

Carsten Dominik 7 years ago
parent
commit
6b8632e2c3
2 changed files with 174 additions and 2 deletions
  1. 169 0
      contrib/babel/lisp/langs/org-babel-C.el
  2. 5 2
      contrib/babel/lisp/org-babel.el

+ 169 - 0
contrib/babel/lisp/langs/org-babel-C.el

@@ -0,0 +1,169 @@
+;;; org-babel-C.el --- org-babel functions for C and similar languages
+
+;; Copyright (C) 2010 Eric Schulte
+
+;; Author: Eric Schulte
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program 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, or (at your option)
+;; any later version.
+;;
+;; This program 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; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Org-Babel support for evaluating C code.
+;;
+;; very limited implementation:
+;; - currently only support :results output
+;; - not much in the way of error feedback
+
+;;; Code:
+(require 'org-babel)
+(require 'cc-mode)
+
+(org-babel-add-interpreter "C")
+(add-to-list 'org-babel-tangle-langs '("C" "c" nil))
+
+(org-babel-add-interpreter "c++")
+(add-to-list 'org-babel-tangle-langs '("c++" "cpp" nil))
+
+(defvar org-babel-C-compiler "gcc"
+  "Command used to compile a C source code file into an
+  executable.")
+
+(defvar org-babel-c++-compiler "g++"
+  "Command used to compile a c++ source code file into an
+  executable.")
+
+(defun org-babel-execute:cpp (body params)
+  (org-babel-execute:C body params))
+
+(defun org-babel-execute:c++ (body params)
+    "Execute a block of C++ code with org-babel.  This function is
+called by `org-babel-execute-src-block'."
+  (let ((c-variant 'cpp)) (org-babel-C-execute body params)))
+
+(defun org-babel-execute:C (body params)
+  "Execute a block of C code with org-babel.  This function is
+called by `org-babel-execute-src-block'."
+  (let ((c-variant 'c)) (org-babel-C-execute body params)))
+
+(defun org-babel-C-execute (body params)
+  "This should only be called by `org-babel-execute:C' or
+`org-babel-execute:c++'."
+  (message "executing C source code block")
+  (let* ((processed-params (org-babel-process-params params))
+         (tmp-src-file (make-temp-file "org-babel-C-src" nil
+                                       (case c-variant
+                                         ('c ".c")
+                                         ('cpp ".cpp"))))
+         (tmp-bin-file (make-temp-file "org-babel-C-bin"))
+         (tmp-out-file (make-temp-file "org-babel-C-out"))
+         (flags (cdr (assoc :flags params)))
+         (vars (second processed-params))
+         (includes (org-babel-read
+                    (or (cdr (assoc :includes params))
+                        (org-entry-get nil "includes" t))))
+         (defines (org-babel-read
+                   (or (cdr (assoc :includes params))
+                       (org-entry-get nil "defines" t))))
+         (full-body (mapconcat 'identity
+                     (list
+                      ;; includes
+                      (mapconcat
+                       (lambda (inc) (format "#include %s" inc))
+                       (if (listp includes) includes (list includes)) "\n")
+                      ;; defines
+                      (mapconcat
+                       (lambda (inc) (format "#define %s" inc))
+                       (if (listp defines) defines (list defines)) "\n")
+                      ;; variables
+                      (mapconcat 'org-babel-C-var-to-C vars "\n")
+                      ;; body
+                      "\n" (org-babel-C-ensure-main-wrap body) "\n") "\n"))
+         (error-buf (get-buffer-create "*Org-Babel Error Output*"))
+         (compile
+          (progn
+            (with-temp-file tmp-src-file (insert full-body))
+            (with-temp-buffer
+              (org-babel-shell-command-on-region
+               (point-min) (point-max)
+               (format "%s -o %s %s %s"
+                       (case c-variant
+                         ('c org-babel-C-compiler)
+                         ('cpp org-babel-c++-compiler))
+                       tmp-bin-file
+                       (mapconcat 'identity
+                                  (if (listp flags) flags (list flags)) " ")
+                       tmp-src-file)
+               (current-buffer) 'replace error-buf)))))
+    (if (= compile 0)
+        (org-babel-read
+         (org-babel-trim
+          (with-temp-buffer
+            (org-babel-shell-command-on-region
+             (point-min) (point-max) tmp-bin-file (current-buffer) 'replace)
+            (buffer-string))))
+      (progn
+        (with-current-buffer error-buf
+          (goto-char (point-max))
+          (insert (concat "\n\n--body--\n" full-body))
+          (goto-char (point-min)))
+        (display-buffer error-buf) nil))))
+
+(defun org-babel-C-ensure-main-wrap (body)
+  "Wrap body in a \"main\" function call if none exists."
+  (if (string-match "^[ \t]*[intvod]+[ \t]*main[ \t]*(.*)" body)
+      body
+    (format "int main() {\n%s\n}\n" body)))
+
+(defun org-babel-prep-session:C (session params)
+  "C is a compiled languages -- no support for sessions"
+  (error "C is a compiled languages -- no support for sessions"))
+
+(defun org-babel-load-session:C (session body params)
+  "C is a compiled languages -- no support for sessions"
+  (error "C is a compiled languages -- no support for sessions"))
+
+;; helper functions
+
+(defun org-babel-C-var-to-C (pair)
+  "Convert an elisp val into a string of C code specifying a var
+of the same value.  TODO list support."
+  (let ((var (car pair))
+        (val (cdr pair)))
+    (when (symbolp val)
+      (setq val (symbol-name val))
+      (when (= (length val) 1)
+        (setq val (string-to-char val))))
+    (cond
+     ((integerp val)
+      (format "int %S = %S;" var val))
+     ((floatp val)
+      (format "double %S = %S;" var val))
+     ((or (characterp val))
+      (format "char %S = '%S';" var val))
+     ((stringp val)
+      (format "char %S[%d] = \"%s\";"
+              var (+ 1 (length val)) val))
+     (t
+      (format "u32 %S = %S;" var val)))))
+
+
+(provide 'org-babel-C)
+;;; org-babel-C.el ends here

+ 5 - 2
contrib/babel/lisp/org-babel.el

@@ -153,7 +153,10 @@ can not be resolved.")
   "Add INTERPRETER to `org-babel-interpreters' and update
 `org-babel-src-block-regexp' appropriately."
   (unless (member interpreter org-babel-interpreters)
-    (setq org-babel-interpreters (cons interpreter org-babel-interpreters))
+    (setq org-babel-interpreters
+          (sort (cons interpreter org-babel-interpreters)
+		(lambda (left right)
+		  (> (length left) (length right)))))
     (org-babel-set-interpreters 'org-babel-interpreters org-babel-interpreters)))
 
 (defcustom org-babel-interpreters '()
@@ -1090,7 +1093,7 @@ the table is trivial, then return it as a scalar."
 	result))))
 
 (defun org-babel-string-read (cell)
-  "Strip nested \"s from around strings in exported R values."
+  "Strip nested \"s from around strings."
   (org-babel-read (or (and (stringp cell)
                            (string-match "\\\"\\(.+\\)\\\"" cell)
                            (match-string 1 cell))