/[slime]/slime/swank-clisp.lisp
ViewVC logotype

Contents of /slime/swank-clisp.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.50 - (hide annotations)
Sun Jul 3 15:53:33 2005 UTC (8 years, 9 months ago) by heller
Branch: MAIN
Changes since 1.49: +18 -2 lines
(describe-symbol-for-emacs): Report :setf and :type where appropriate.

(getpid): Explicitly define it as foreign function on WIN32.
1 heller 1.1 ;;;; SWANK support for CLISP.
2    
3 vsedach 1.3 ;;;; Copyright (C) 2003, 2004 W. Jenkner, V. Sedach
4 heller 1.1
5     ;;;; swank-clisp.lisp is free software; you can redistribute it and/or
6     ;;;; modify it under the terms of the GNU General Public License as
7     ;;;; published by the Free Software Foundation; either version 2, or
8     ;;;; (at your option) any later version.
9    
10     ;;; This is work in progress, but it's already usable. Many things
11     ;;; are adapted from other swank-*.lisp, in particular from
12     ;;; swank-allegro (I don't use allegro at all, but it's the shortest
13     ;;; one and I found Helmut Eller's code there enlightening).
14    
15 vsedach 1.3 ;;; This code is developed using the current CVS version of CLISP and
16     ;;; CLISP 2.32 on Linux. Older versions may not work (2.29 and below
17     ;;; are confirmed non-working; please upgrade). You need an image
18 wjenkner 1.16 ;;; containing the "SOCKET", "REGEXP", and "LINUX" packages. The
19     ;;; portable xref from the CMU AI repository and metering.lisp from
20 heller 1.20 ;;; CLOCC [1] are also required (alternatively, you have to manually
21     ;;; comment out some code below).
22     ;;;
23     ;;; [1] http://cvs.sourceforge.net/viewcvs.py/clocc/clocc/src/tools/metering/
24 heller 1.1
25 heller 1.25 (in-package :swank-backend)
26 heller 1.1
27     (eval-when (:compile-toplevel :load-toplevel :execute)
28 heller 1.33 ;;(use-package "SOCKET")
29 heller 1.1 (use-package "GRAY"))
30    
31 wjenkner 1.10 (eval-when (:compile-toplevel :execute)
32     (when (find-package "LINUX")
33     (pushnew :linux *features*)))
34 heller 1.1
35 heller 1.49 ;;;; if this lisp has the complete CLOS then we use it, otherwise we
36     ;;;; build up a "fake" swank-mop and then override the methods in the
37 mbaringer 1.36 ;;;; inspector.
38    
39     (eval-when (:compile-toplevel :load-toplevel :execute)
40     (defvar *have-mop*
41 mbaringer 1.37 (and (find-package :clos)
42     (eql :external
43 heller 1.44 (nth-value 1 (find-symbol (string ':standard-slot-definition)
44     :clos))))
45 heller 1.49 "True in those CLISP images which have a complete MOP implementation."))
46 mbaringer 1.37
47     #+#.(cl:if swank-backend::*have-mop* '(cl:and) '(cl:or))
48     (progn
49 heller 1.44 (import-swank-mop-symbols :clos '(:slot-definition-documentation))
50 mbaringer 1.37
51     (defun swank-mop:slot-definition-documentation (slot)
52     (clos::slot-definition-documentation slot)))
53 mbaringer 1.35
54 mbaringer 1.37 #-#.(cl:if swank-backend::*have-mop* '(and) '(or))
55 mbaringer 1.36 (defclass swank-mop:standard-slot-definition ()
56     ()
57 heller 1.44 (:documentation
58     "Dummy class created so that swank.lisp will compile and load."))
59 mbaringer 1.36
60 vsedach 1.3 #+linux
61 wjenkner 1.10 (defmacro with-blocked-signals ((&rest signals) &body body)
62     (ext:with-gensyms ("SIGPROCMASK" ret mask)
63     `(multiple-value-bind (,ret ,mask)
64     (linux:sigprocmask-set-n-save
65     ,linux:SIG_BLOCK
66     ,(do ((sigset (linux:sigset-empty)
67     (linux:sigset-add sigset (the fixnum (pop signals)))))
68     ((null signals) sigset)))
69     (linux:check-res ,ret 'linux:sigprocmask-set-n-save)
70     (unwind-protect
71     (progn ,@body)
72     (linux:sigprocmask-set ,linux:SIG_SETMASK ,mask nil)))))
73 heller 1.25
74     ;; XXX currently only works in CVS version. 2.32 breaks.
75 heller 1.15 ;; #+linux
76 heller 1.27 ;; (defimplementation call-without-interrupts (fn)
77 heller 1.15 ;; (with-blocked-signals (#.linux:SIGINT) (funcall fn)))
78     ;;
79     ;; #-linux
80 heller 1.27 (defimplementation call-without-interrupts (fn)
81 heller 1.12 (funcall fn))
82 vsedach 1.3
83 heller 1.50 #+unix
84     (ffi:def-call-out getpid (:return-type ffi:int))
85    
86     #+win32
87     (ffi:def-call-out getpid (:name "GetCurrentProcessId")
88     (:library "kernel32.dll")
89     (:return-type ffi:uint32))
90    
91     #+(or)
92 heller 1.49 (let ((getpid (or (find-symbol "PROCESS-ID" :system)
93     ;; old name prior to 2005-03-01, clisp <= 2.33.2
94     (find-symbol "PROGRAM-ID" :system)
95     #+win32 ; integrated into the above since 2005-02-24
96     (and (find-package :win32) ; optional modules/win32
97     (find-symbol "GetCurrentProcessId" :win32)))))
98     (defimplementation getpid () ; a required interface
99     (cond
100     (getpid (funcall getpid))
101     #+win32 ((ext:getenv "PID")) ; where does that come from?
102     (t -1))))
103 heller 1.1
104 heller 1.21 (defimplementation lisp-implementation-type-name ()
105     "clisp")
106    
107 heller 1.28 (defimplementation set-default-directory (directory)
108     (setf (ext:default-directory) directory)
109     (namestring (setf *default-pathname-defaults* (ext:default-directory))))
110    
111 wjenkner 1.4
112 heller 1.1 ;;; TCP Server
113    
114 heller 1.17 (defimplementation create-socket (host port)
115     (declare (ignore host))
116 heller 1.8 (socket:socket-server port))
117 lgorrie 1.7
118 wjenkner 1.14 (defimplementation local-port (socket)
119 heller 1.8 (socket:socket-server-port socket))
120 vsedach 1.5
121 wjenkner 1.14 (defimplementation close-socket (socket)
122 heller 1.8 (socket:socket-server-close socket))
123 vsedach 1.5
124 heller 1.42 (defun find-encoding (external-format)
125     (ecase external-format
126     (:iso-latin-1-unix (ext:make-encoding :charset 'charset:iso-8859-1
127     :line-terminator :unix))
128     (:utf-8-unix (ext:make-encoding :charset 'charset:utf-8
129     :line-terminator :unix))))
130    
131 heller 1.43 (defimplementation accept-connection (socket
132     &key (external-format :iso-latin-1-unix))
133 heller 1.8 (socket:socket-accept socket
134     :buffered nil ;; XXX should be t
135     :element-type 'character
136 heller 1.42 :external-format (find-encoding external-format)))
137 vsedach 1.3
138     ;;; Swank functions
139 heller 1.1
140 heller 1.25 (defimplementation arglist (fname)
141 heller 1.30 (block nil
142     (or (ignore-errors (return (ext:arglist fname)))
143     :not-available)))
144 heller 1.1
145 wjenkner 1.14 (defimplementation macroexpand-all (form)
146 heller 1.1 (ext:expand-form form))
147    
148 wjenkner 1.14 (defimplementation describe-symbol-for-emacs (symbol)
149 heller 1.1 "Return a plist describing SYMBOL.
150     Return NIL if the symbol is unbound."
151     (let ((result ()))
152 heller 1.47 (flet ((doc (kind)
153     (or (documentation symbol kind) :not-documented))
154     (maybe-push (property value)
155     (when value
156     (setf result (list* property value result)))))
157     (maybe-push :variable (when (boundp symbol) (doc 'variable)))
158 heller 1.1 (when (fboundp symbol)
159 heller 1.47 (maybe-push
160     ;; Report WHEN etc. as macros, even though they may be
161     ;; implemented as special operators.
162     (if (macro-function symbol) :macro
163     (typecase (fdefinition symbol)
164     (generic-function :generic-function)
165     (function :function)
166     ;; (type-of 'progn) -> ext:special-operator
167     (t :special-operator)))
168     (doc 'function)))
169 heller 1.50 (when (or (get symbol 'system::setf-function) ; e.g. #'(setf elt)
170     (get symbol 'system::setf-expander)); defsetf
171     (maybe-push :setf (doc 'setf)))
172     (when (or (get symbol 'system::type-symbol); cf. clisp/src/describe.lisp
173     (get symbol 'system::defstruct-description)
174     (get symbol 'system::deftype-expander))
175     (maybe-push :type (doc 'type))) ; even for 'structure
176     (when (find-class symbol nil)
177     (maybe-push :class (doc 'type)))
178 heller 1.48 ;; Let this code work compiled in images without FFI
179     (let ((types (load-time-value
180     (and (find-package "FFI")
181     (symbol-value
182     (find-symbol "*C-TYPE-TABLE*" "FFI"))))))
183     ;; Use ffi::*c-type-table* so as not to suffer the overhead of
184     ;; (ignore-errors (ffi:parse-c-type symbol)) for 99.9% of symbols
185     ;; which are not FFI type names.
186     (when (and types (nth-value 1 (gethash symbol types)))
187     ;; Maybe use (case (head (ffi:deparse-c-type)))
188     ;; to distinguish struct and union types?
189     (maybe-push :alien-type :not-documented)))
190 heller 1.1 result)))
191    
192 heller 1.25 (defimplementation describe-definition (symbol namespace)
193     (ecase namespace
194     (:variable (describe symbol))
195     (:macro (describe (macro-function symbol)))
196     (:function (describe (symbol-function symbol)))
197     (:class (describe (find-class symbol)))))
198    
199 heller 1.26 (defun fspec-pathname (symbol)
200 heller 1.1 (let ((path (getf (gethash symbol sys::*documentation*) 'sys::file)))
201     (if (and path
202     (member (pathname-type path)
203     custom:*compiled-file-types* :test #'string=))
204 heller 1.26 (loop for suffix in custom:*source-file-types*
205     thereis (make-pathname :defaults path :type suffix))
206 heller 1.1 path)))
207    
208 heller 1.26 (defun fspec-location (fspec)
209     (let ((file (fspec-pathname fspec)))
210     (cond (file
211     (multiple-value-bind (truename c) (ignore-errors (truename file))
212     (cond (truename
213     (make-location (list :file (namestring truename))
214     (list :function-name (string fspec))))
215     (t (list :error (princ-to-string c))))))
216     (t (list :error (format nil "No source information available for: ~S"
217     fspec))))))
218 heller 1.25
219     (defimplementation find-definitions (name)
220 heller 1.26 (list (list name (fspec-location name))))
221 heller 1.1
222     (defvar *sldb-topframe*)
223     (defvar *sldb-botframe*)
224     (defvar *sldb-source*)
225     (defvar *sldb-debugmode* 4)
226    
227 heller 1.30 (defun frame-down (frame)
228     (sys::frame-down-1 frame sys::*debug-mode*))
229    
230     (defun frame-up (frame)
231     (sys::frame-up-1 frame sys::*debug-mode*))
232    
233 wjenkner 1.14 (defimplementation call-with-debugging-environment (debugger-loop-fn)
234 heller 1.1 (let* ((sys::*break-count* (1+ sys::*break-count*))
235     (sys::*driver* debugger-loop-fn)
236     (sys::*fasoutput-stream* nil)
237     (sys::*frame-limit1* (sys::frame-limit1 0))
238 heller 1.30 (sys::*frame-limit2* (sys::frame-limit2))
239 heller 1.1 (sys::*debug-mode* *sldb-debugmode*)
240 heller 1.30 (*sldb-topframe* sys::*frame-limit1*))
241 heller 1.1 (funcall debugger-loop-fn)))
242    
243     (defun nth-frame (index)
244 heller 1.30 (loop for frame = *sldb-topframe* then (frame-up frame)
245 heller 1.1 repeat index
246 heller 1.15 finally (return frame)))
247 heller 1.1
248 heller 1.25 (defimplementation compute-backtrace (start end)
249 heller 1.1 (let ((end (or end most-positive-fixnum)))
250 heller 1.30 (loop for last = nil then frame
251     for frame = (nth-frame start) then (frame-up frame)
252 heller 1.1 for i from start below end
253 heller 1.30 until (or (eq frame last) (system::driver-frame-p frame))
254     collect frame)))
255 heller 1.1
256 heller 1.25 (defimplementation print-frame (frame stream)
257     (write-string (string-left-trim '(#\Newline)
258     (with-output-to-string (stream)
259     (sys::describe-frame stream frame)))
260     stream))
261 heller 1.1
262 wjenkner 1.14 (defimplementation eval-in-frame (form frame-number)
263 heller 1.1 (sys::eval-at (nth-frame frame-number) form))
264    
265 wjenkner 1.14 (defimplementation frame-locals (frame-number)
266 heller 1.1 (let* ((frame (nth-frame frame-number))
267     (frame-env (sys::eval-at frame '(sys::the-environment))))
268     (append
269     (frame-do-venv frame (svref frame-env 0))
270     (frame-do-fenv frame (svref frame-env 1))
271     (frame-do-benv frame (svref frame-env 2))
272     (frame-do-genv frame (svref frame-env 3))
273     (frame-do-denv frame (svref frame-env 4)))))
274 heller 1.33
275     (defimplementation frame-var-value (frame var)
276     (getf (nth var (frame-locals frame)) :value))
277 heller 1.1
278     ;; Interpreter-Variablen-Environment has the shape
279     ;; NIL or #(v1 val1 ... vn valn NEXT-ENV).
280    
281     (defun frame-do-venv (frame venv)
282 heller 1.2 (loop for i from 1 below (length venv) by 2
283     as symbol = (svref venv (1- i))
284     and value = (svref venv i)
285 mbaringer 1.24 collect (list :name symbol :id 0
286     :value (if (eq sys::specdecl value)
287     ;; special variable
288     (sys::eval-at frame symbol)
289     ;; lexical variable or symbol macro
290     value))))
291 heller 1.1
292     (defun frame-do-fenv (frame fenv)
293     (declare (ignore frame fenv))
294     nil)
295    
296     (defun frame-do-benv (frame benv)
297     (declare (ignore frame benv))
298     nil)
299    
300     (defun frame-do-genv (frame genv)
301     (declare (ignore frame genv))
302     nil)
303    
304     (defun frame-do-denv (frame denv)
305     (declare (ignore frame denv))
306     nil)
307    
308 wjenkner 1.14 (defimplementation frame-catch-tags (index)
309 heller 1.1 (declare (ignore index))
310     nil)
311    
312 wjenkner 1.14 (defimplementation return-from-frame (index form)
313 heller 1.25 (sys::return-from-eval-frame (nth-frame index) form))
314 wjenkner 1.14
315     (defimplementation restart-frame (index)
316     (sys::redo-eval-frame (nth-frame index)))
317    
318     (defimplementation frame-source-location-for-emacs (index)
319 heller 1.39 (let ((f (nth-frame index)))
320     (list :error (format nil "Cannot find source for frame: ~A ~A ~A"
321     f
322     (sys::eval-frame-p f)
323     (sys::the-frame)))))
324 heller 1.1
325 wjenkner 1.16 ;;; Profiling
326    
327     (defimplementation profile (fname)
328     (eval `(mon:monitor ,fname))) ;monitor is a macro
329    
330     (defimplementation profiled-functions ()
331     mon:*monitored-functions*)
332    
333     (defimplementation unprofile (fname)
334     (eval `(mon:unmonitor ,fname))) ;unmonitor is a macro
335    
336     (defimplementation unprofile-all ()
337     (mon:unmonitor))
338    
339     (defimplementation profile-report ()
340     (mon:report-monitoring))
341    
342     (defimplementation profile-reset ()
343     (mon:reset-all-monitoring))
344    
345     (defimplementation profile-package (package callers-p methods)
346     (declare (ignore callers-p methods))
347     (mon:monitor-all package))
348 heller 1.1
349     ;;; Handle compiler conditions (find out location of error etc.)
350    
351     (defmacro compile-file-frobbing-notes ((&rest args) &body body)
352     "Pass ARGS to COMPILE-FILE, send the compiler notes to
353     *STANDARD-INPUT* and frob them in BODY."
354     `(let ((*error-output* (make-string-output-stream))
355     (*compile-verbose* t))
356     (multiple-value-prog1
357 vsedach 1.6 (compile-file ,@args)
358     (handler-case
359 heller 1.1 (with-input-from-string
360 vsedach 1.6 (*standard-input* (get-output-stream-string *error-output*))
361     ,@body)
362     (sys::simple-end-of-file () nil)))))
363 heller 1.1
364 heller 1.25 (defvar *orig-c-warn* (symbol-function 'system::c-warn))
365     (defvar *orig-c-style-warn* (symbol-function 'system::c-style-warn))
366     (defvar *orig-c-error* (symbol-function 'system::c-error))
367     (defvar *orig-c-report-problems* (symbol-function 'system::c-report-problems))
368    
369     (defmacro dynamic-flet (names-functions &body body)
370     "(dynamic-flet ((NAME FUNCTION) ...) BODY ...)
371 heller 1.46 Execute BODY with NAME's function slot set to FUNCTION."
372 heller 1.25 `(ext:letf* ,(loop for (name function) in names-functions
373     collect `((symbol-function ',name) ,function))
374     ,@body))
375 heller 1.45
376     (defvar *buffer-name* nil)
377     (defvar *buffer-offset*)
378    
379 heller 1.25 (defun compiler-note-location ()
380 heller 1.27 "Return the current compiler location."
381 heller 1.25 (let ((lineno1 sys::*compile-file-lineno1*)
382     (lineno2 sys::*compile-file-lineno2*)
383     (file sys::*compile-file-truename*))
384     (cond ((and file lineno1 lineno2)
385 heller 1.31 (make-location (list ':file (namestring file))
386     (list ':line lineno1)))
387 heller 1.25 (*buffer-name*
388 heller 1.31 (make-location (list ':buffer *buffer-name*)
389     (list ':position *buffer-offset*)))
390 heller 1.25 (t
391     (list :error "No error location available")))))
392    
393     (defun signal-compiler-warning (cstring args severity orig-fn)
394     (signal (make-condition 'compiler-condition
395     :severity severity
396     :message (apply #'format nil cstring args)
397     :location (compiler-note-location)))
398     (apply orig-fn cstring args))
399    
400     (defun c-warn (cstring &rest args)
401     (signal-compiler-warning cstring args :warning *orig-c-warn*))
402    
403     (defun c-style-warn (cstring &rest args)
404     (dynamic-flet ((sys::c-warn *orig-c-warn*))
405     (signal-compiler-warning cstring args :style-warning *orig-c-style-warn*)))
406    
407     (defun c-error (cstring &rest args)
408     (signal-compiler-warning cstring args :error *orig-c-error*))
409    
410 wjenkner 1.14 (defimplementation call-with-compilation-hooks (function)
411 heller 1.25 (handler-bind ((warning #'handle-notification-condition))
412     (dynamic-flet ((system::c-warn #'c-warn)
413     (system::c-style-warn #'c-style-warn)
414     (system::c-error #'c-error))
415     (funcall function))))
416 heller 1.1
417     (defun handle-notification-condition (condition)
418     "Handle a condition caused by a compiler warning."
419 heller 1.25 (signal (make-condition 'compiler-condition
420     :original-condition condition
421     :severity :warning
422     :message (princ-to-string condition)
423     :location (compiler-note-location))))
424 heller 1.1
425 heller 1.25 (defimplementation swank-compile-file (filename load-p)
426 heller 1.1 (with-compilation-hooks ()
427 heller 1.25 (with-compilation-unit ()
428     (let ((fasl-file (compile-file filename)))
429     (when (and load-p fasl-file)
430     (load fasl-file))
431     nil))))
432 heller 1.1
433 pseibel 1.34 (defimplementation swank-compile-string (string &key buffer position directory)
434     (declare (ignore directory))
435 heller 1.1 (with-compilation-hooks ()
436 heller 1.25 (let ((*buffer-name* buffer)
437 heller 1.1 (*buffer-offset* position))
438 heller 1.25 (funcall (compile nil (read-from-string
439 heller 1.27 (format nil "(~S () ~A)" 'lambda string)))))))
440 heller 1.1
441     ;;; Portable XREF from the CMU AI repository.
442    
443 lgorrie 1.32 (setq pxref::*handle-package-forms* '(cl:in-package))
444 heller 1.1
445 heller 1.25 (defmacro defxref (name function)
446     `(defimplementation ,name (name)
447     (xref-results (,function name))))
448    
449 lgorrie 1.32 (defxref who-calls pxref:list-callers)
450     (defxref who-references pxref:list-readers)
451     (defxref who-binds pxref:list-setters)
452     (defxref who-sets pxref:list-setters)
453     (defxref list-callers pxref:list-callers)
454     (defxref list-callees pxref:list-callees)
455 heller 1.1
456 heller 1.28 (defun xref-results (symbols)
457 heller 1.1 (let ((xrefs '()))
458 heller 1.28 (dolist (symbol symbols)
459     (push (list symbol (fspec-location symbol)) xrefs))
460 heller 1.25 xrefs))
461 heller 1.1
462     (when (find-package :swank-loader)
463     (setf (symbol-function (intern "USER-INIT-FILE" :swank-loader))
464     (lambda ()
465     (let ((home (user-homedir-pathname)))
466     (and (ext:probe-directory home)
467     (probe-file (format nil "~A/.swank.lisp"
468     (namestring (truename home)))))))))
469    
470     ;; Don't set *debugger-hook* to nil on break.
471     (ext:without-package-lock ()
472     (defun break (&optional (format-string "Break") &rest args)
473     (if (not sys::*use-clcs*)
474     (progn
475     (terpri *error-output*)
476     (apply #'format *error-output*
477     (concatenate 'string "*** - " format-string)
478     args)
479     (funcall ext:*break-driver* t))
480     (let ((condition
481     (make-condition 'simple-condition
482     :format-control format-string
483     :format-arguments args))
484     ;;(*debugger-hook* nil)
485     ;; Issue 91
486     )
487     (ext:with-restarts
488 heller 1.28 ((continue
489 heller 1.1 :report (lambda (stream)
490 heller 1.28 (format stream (sys::text "Return from ~S loop")
491 heller 1.1 'break))
492     ()))
493 heller 1.28 (with-condition-restarts condition (list (find-restart 'continue))
494 heller 1.1 (invoke-debugger condition)))))
495     nil))
496 heller 1.40
497 heller 1.23 ;;; Inspecting
498    
499 mbaringer 1.35 (defclass clisp-inspector (inspector)
500     ())
501    
502     (defimplementation make-default-inspector ()
503     (make-instance 'clisp-inspector))
504    
505     (defmethod inspect-for-emacs ((o t) (inspector clisp-inspector))
506     (declare (ignore inspector))
507 heller 1.23 (let* ((*print-array* nil) (*print-pretty* t)
508     (*print-circle* t) (*print-escape* t)
509     (*print-lines* custom:*inspect-print-lines*)
510     (*print-level* custom:*inspect-print-level*)
511     (*print-length* custom:*inspect-print-length*)
512     (sys::*inspect-all* (make-array 10 :fill-pointer 0 :adjustable t))
513     (tmp-pack (make-package (gensym "INSPECT-TMP-PACKAGE-")))
514     (*package* tmp-pack)
515     (sys::*inspect-unbound-value* (intern "#<unbound>" tmp-pack)))
516     (let ((inspection (sys::inspect-backend o)))
517     (values (format nil "~S~% ~A~{~%~A~}" o
518     (sys::insp-title inspection)
519     (sys::insp-blurb inspection))
520 mbaringer 1.35 (loop with count = (sys::insp-num-slots inspection)
521     for i upto count
522 heller 1.44 for (value name) = (multiple-value-list
523     (funcall (sys::insp-nth-slot
524     inspection) i))
525     collect `((:value ,name) " = " (:value ,value)
526     (:newline)))))))
527 heller 1.1
528 mbaringer 1.29 (defimplementation quit-lisp ()
529 heller 1.39 #+lisp=cl (ext:quit)
530     #-lisp=cl (lisp:quit))
531 mbaringer 1.29
532 heller 1.1 ;;; Local Variables:
533     ;;; eval: (put 'compile-file-frobbing-notes 'lisp-indent-function 1)
534 heller 1.25 ;;; eval: (put 'dynamic-flet 'common-lisp-indent-function 1)
535 heller 1.1 ;;; End:

  ViewVC Help
Powered by ViewVC 1.1.5