chiark / gitweb /
Work in progress. Mostly bug fixing.
[sod] / src / c-types-test.lisp
index f1e432495b7c2c0dc36fdfbfd1164fa9161e9f3f..16e41ce6be6f6264ceafd774f9789d32fe910ab6 100644 (file)
@@ -42,11 +42,25 @@ (defun assert-not-cteqp (a b)
   (when (c-type-equal-p a b)
     (failure "Assert unequal C types: ~A ~_and ~A" a b)))
 
+(defun expand-tabs (string)
+  (with-output-to-string (out)
+    (do ((i 0 (1+ i))
+        (char (char string 0) (char string i))
+        (pos 0))
+       ((>= i (length string)))
+      (case char
+       (#\newline (write-char char out)
+                  (setf pos 0))
+       (#\tab (write-string "        " out :end (- 8 (mod pos 8)))
+              (setf pos (logandc2 (+ pos 8) 7)))
+       (t (write-char char out)
+          (incf pos))))))
+
 (defun assert-pp-ctype (type kernel string)
   (let* ((*print-right-margin* 77)
         (print (with-output-to-string (out)
                  (pprint-c-type type out kernel))))
-    (assert-equal print string
+    (assert-equal (expand-tabs print) (expand-tabs string)
                  (format nil "Type ~S with kernel ~S ~_prints as `~A' ~_~
                               rather than `~A'."
                          type kernel print string))))
@@ -232,4 +246,43 @@ (def-test-method commentify-non-recursive ((test c-types-test) :run nil)
                      int typeflag),
        int /*nopenfd*/)")))
 
+;;;--------------------------------------------------------------------------
+;;; Parsing.
+
+(def-test-method parse-c-type ((test c-types-test) :run nil)
+  (flet ((check (string c-type name)
+          (let* ((char-scanner (make-string-scanner string))
+                 (scanner (make-instance 'sod-token-scanner
+                                         :char-scanner char-scanner
+                                         :filename "<none>")))
+            (with-parser-context (token-scanner-context :scanner scanner)
+              (define-module ("<temporary>" :truename nil :location scanner)
+                (multiple-value-bind (result winp consumedp)
+                    (parse (seq ((ds (parse-c-type scanner))
+                                 (dc (parse-declarator scanner ds))
+                                 :eof)
+                             dc))
+                  (declare (ignore consumedp))
+                  (cond ((null c-type)
+                         (assert-false winp))
+                        (t
+                         (assert-true winp)
+                         (unless (eq c-type t)
+                           (assert-cteqp (car result) c-type))
+                         (unless (eq name t)
+                           (assert-equal (cdr result) name))))))))))
+
+    (check "int x" (c-type int) "x")
+    (check "int long unsigned long y" (c-type unsigned-long-long) "y")
+    (check "int long int x" nil nil)
+    (check "float v[69][42]" (c-type ([] float "69" "42")) "v")
+    (check "const char *const tab[]"
+          (c-type ([] (* (char :const) :const) ""))
+          "tab")
+    (check "void (*signal(int, void (*)(int)))(int)"
+          (c-type (func (* (func void (nil int)))
+                        (nil int)
+                        (nil (* (func void (nil int))))))
+          "signal")))
+
 ;;;----- That's all, folks --------------------------------------------------