PageRenderTime 23ms CodeModel.GetById 14ms app.highlight 7ms RepoModel.GetById 0ms app.codeStats 0ms

/foreign/parser.lisp

https://bitbucket.org/raghu/libxml-clisp
Lisp | 125 lines | 76 code | 15 blank | 34 comment | 8 complexity | cfe89e13b9c7e558e2af442bfb76f287 MD5 | raw file
  1;;;; parser.lisp --- FFI definitions for libxml-clisp
  2
  3;;; Copyright (C) 2009 N. Raghavendra.  All rights reserved.
  4;;; 
  5;;; Redistribution and use in source and binary forms, with or without
  6;;; modification, are permitted provided that the following conditions
  7;;; are met:
  8;;; 1. Redistributions of source code must retain the above copyright
  9;;;    notice, this list of conditions and the following disclaimer.
 10;;; 2. Redistributions in binary form must reproduce the above
 11;;;    copyright notice, this list of conditions and the following
 12;;;    disclaimer in the documentation and/or other materials provided
 13;;;    with the distribution.
 14;;; 
 15;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 16;;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 17;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 18;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 19;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 20;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 21;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 22;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 23;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 24;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26
 27;;; N. Raghavendra <raghu@retrotexts.net>
 28;;; 
 29;;; Created: 2009-07-08
 30;;; 
 31;;; $Hg$
 32
 33(in-package "NET.RETROTEXTS.LIBXML-CLISP")
 34
 35
 36
 37(defun cleanup-parser ()
 38  "Clean up the memory allocated by libxml2.
 39Tries to reclaim all related global memory allocated for libxml
 40processing.  Does not deallocate any document-related memory.  This
 41function should be called only when the process has finished using the
 42libxml2 library, and all documents built with it."
 43  ($xml-cleanup-parser))
 44
 45(defvar *parser-options*
 46  (loop for i from 0 to 16
 47     collect (enum-from-value '$xml-parser-option (ash 1 i)))
 48  "List of XML parser options.")
 49
 50(defun combine-options (options)
 51  "Return an integer denoting the union of all the parser options OPTIONS.
 52OPTIONS must be symbol or a list of symbols from `*parser-options*'."
 53  (flet ((option-value (option)
 54           (enum-to-value '$xml-parser-option option)))
 55    (if (listp options)
 56      (loop for result = 0 then (logior result (option-value option))
 57         for option in options
 58         finally (return result))
 59      (option-value options))))
 60
 61(defun parse-file (filename &key encoding options)
 62  "Return the Document obtained by parsing FILENAME.
 63FILENAME must be a pathname designator for an XML file.  If ENCODING
 64is non-nil, it is assumed to be the encoding of FILENAME.  If ENCODING
 65is nil, then the encoding of FILENAME is taken from the XML
 66declaration, if any, in FILENAME.  If the encoding of FILENAME cannot
 67be obtained from its XML declaration, then the encoding of FILENAME is
 68assumed to be UTF-8.  OPTIONS must be symbol or a list of symbols from
 69`*parser-options*'."
 70  (let* ((encoding-name (encoding-name encoding))
 71         (doc-address ($xml-read-file (namestring filename) encoding-name
 72                                      (combine-options options))))
 73    (if doc-address
 74      (make-document doc-address)
 75      (restart-case (error 'file-parse-error
 76                           :pathname (pathname filename))
 77        (parse-new-file (new-filename)
 78          :report "Parse another file."
 79          :interactive read-new-value
 80          (parse-file new-filename :encoding encoding :options options))))))
 81
 82(defmacro with-xml-file ((document filename &key encoding options) &body body)
 83  "Evaluate BODY using the Document parsed from FILENAME.
 84FILENAME must be a pathname designator for an XML file.  During the
 85evaluation, the variable DOCUMENT and the special variable *DOCUMENT*
 86are both bound to the Document parsed from FILENAME.  That Document
 87has dynamic extent, which ends when the form is exited.
 88
 89If ENCODING is non-nil, it is assumed to be the encoding of FILENAME.
 90If ENCODING is nil, then the encoding of FILENAME is taken from the
 91XML declaration, if any, in FILENAME.  If the encoding of FILENAME
 92cannot be obtained from its XML declaration, then the encoding of
 93FILENAME is assumed to be UTF-8.  OPTIONS must be symbol or a list of
 94symbols from `*parser-options*'."
 95  (let ((created (gensym)))
 96    `(let* ((,created nil)
 97            (,document (parse-file ,filename :encoding ,encoding
 98                                   :options ,options))
 99            (*document* ,document))
100       (unwind-protect (progn (setf ,created t)
101                              (init-library)
102                              ,@body)
103         (when ,created
104           (free-item ,document)
105           (cleanup-parser))))))
106
107(defun initialize-catalog ()
108  "Initialize XML catalogs."
109  ($xml-initialize-catalog))
110
111(defun load-catalog (filename)
112  "Load the XML catalog FILENAME.
113FILENAME must be pathname designator."
114  (let ((status ($xml-load-catalog (namestring filename))))
115    (or (zerop status)
116        (error "Unable to load catalog ~A." filename))))
117
118
119
120;;; Local Variables:
121;;; mode: lisp
122;;; comment-column: 32
123;;; End:
124
125;;;; parser.lisp ends here