Commit 22a87d3de511be4e24d415761f8197e9598cc33a

Thomas de Grivel 2020-04-10T18:28:28

#.(include "adams/file") includes #P"adams/file.adams"

diff --git a/adams.asd b/adams.asd
index 557350d..d6590f8 100644
--- a/adams.asd
+++ b/adams.asd
@@ -50,6 +50,7 @@
              (:file "helpers")
              (:file "host"       :depends-on ("defs" "os" "resource-container"
                                                      "syntaxes"))
+             (:file "include")
              (:file "operation"  :depends-on ("defs" "host" "properties"))
 	     (:file "os")
 	     (:file "probe"      :depends-on ("defs" "host" "properties"))
diff --git a/core/include.lisp b/core/include.lisp
new file mode 100644
index 0000000..0b1ae78
--- /dev/null
+++ b/core/include.lisp
@@ -0,0 +1,44 @@
+;;
+;;  adams - system administrator written in Common Lisp
+;;
+;;  Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+;;
+;;  Permission to use, copy, modify, and distribute this software for any
+;;  purpose with or without fee is hereby granted, provided that the above
+;;  copyright notice and this permission notice appear in all copies.
+;;
+;;  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+;;  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+;;  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+;;  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+;;  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+;;  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+;;  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+;;
+
+(in-package :adams)
+
+(defun include/resolve-filename (spec)
+  (flet ((try (&rest parts)
+           (let ((path (str parts)))
+             (when (probe-file path)
+               (return-from include/resolve-filename path)))))
+    (try spec)
+    (try spec ".adams")))
+
+(defun include (&rest sources)
+  (let* ((head (cons 'list nil))
+         (tail head)
+         (eof (gensym "EOF")))
+    (dolist (source sources)
+      (let ((path (include/resolve-filename source)))
+        (with-open-file (in path
+                            :element-type 'character
+                            :external-format :utf-8)
+          (loop
+             (let ((form (read in nil eof)))
+               (when (eq form eof)
+                 (return))
+               (setf (rest tail) (cons form nil)
+                     tail (rest tail)))))))
+    head))
diff --git a/core/spec.lisp b/core/spec.lisp
index 4d063c4..891eef9 100644
--- a/core/spec.lisp
+++ b/core/spec.lisp
@@ -37,10 +37,12 @@
 ;;  Parse specifications
 
 (defmethod parse-next-specification ((res resource) spec)
-  (let ((property (pop spec))
-	(value (pop spec)))
-    (setf (get-specified res property) value)
-    spec))
+  (when (and (symbolp (first spec))
+             (consp (rest spec)))
+    (let ((property (pop spec))
+          (value (pop spec)))
+      (setf (get-specified res property) value)
+      spec)))
 
 (defmethod parse-next-specification ((res resource-container) spec)
   (cond ((typep (first spec) 'resource)
@@ -56,10 +58,14 @@
   (loop
      (when (endp spec)
        (return))
-     (let ((next-spec (parse-next-specification res spec)))
-       (when (eq spec next-spec)
-         (error "Invalid specification : ~S" spec))
-       (setq spec next-spec)))
+     (if (consp (first spec))
+         (progn
+           (parse-specification res (first spec))
+           (setq spec (rest spec)))
+         (let ((next-spec (parse-next-specification res spec)))
+           (when (eq spec next-spec)
+             (error "Invalid specification : ~S" spec))
+           (setq spec next-spec))))
   res)
 
 #+nil
diff --git a/package.lisp b/package.lisp
index 05a307f..5c61e4a 100644
--- a/package.lisp
+++ b/package.lisp
@@ -151,6 +151,7 @@
    ;; OpenBSD
    #:openbsd-pkg
    ;; helpers
+   #:include
    #:read-file
    ))