+(defmacro cast-and-free (value &key (type 'system-string)
+ (free-function 'free-alien))
+ `(prog1 (cast ,value ,type)
+ (,free-function ,value)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defmacro with-funcname ((name description) &body body)
+ `(let
+ ((,name (etypecase ,description
+ (string ,description)
+ (cons (destructuring-bind (s &optional (l 0) c) ,description
+ (format nil "~A~A~A" s
+ (if c #!-sb-unicode "A@" #!+sb-unicode "W@" "@")
+ l))))))
+ ,@body)))
+
+(defmacro make-system-buffer (x)
+ `(make-alien char #!+sb-unicode (ash ,x 1) #!-sb-unicode ,x))
+
+;;; FIXME: The various FOO-SYSCALL-BAR macros, and perhaps some other
+;;; macros in this file, are only used in this file, and could be
+;;; implemented using SB!XC:DEFMACRO wrapped in EVAL-WHEN.
+
+(defmacro syscall ((name ret-type &rest arg-types) success-form &rest args)
+ (with-funcname (sname name)
+ `(locally
+ (declare (optimize (sb!c::float-accuracy 0)))
+ (let ((result (alien-funcall
+ (extern-alien ,sname
+ (function ,ret-type ,@arg-types))
+ ,@args)))
+ (declare (ignorable result))
+ ,success-form))))
+
+;;; This is like SYSCALL, but if it fails, signal an error instead of
+;;; returning error codes. Should only be used for syscalls that will
+;;; never really get an error.
+(defmacro syscall* ((name &rest arg-types) success-form &rest args)
+ (with-funcname (sname name)
+ `(locally
+ (declare (optimize (sb!c::float-accuracy 0)))
+ (let ((result (alien-funcall
+ (extern-alien ,sname (function bool ,@arg-types))
+ ,@args)))
+ (when (zerop result)
+ (win32-error ,sname))
+ ,success-form))))
+
+(defmacro with-sysfun ((func name ret-type &rest arg-types) &body body)
+ (with-funcname (sname name)
+ `(with-alien ((,func (function ,ret-type ,@arg-types)
+ :extern ,sname))
+ ,@body)))
+
+(defmacro void-syscall* ((name &rest arg-types) &rest args)
+ `(syscall* (,name ,@arg-types) (values t 0) ,@args))
+