annotate src/lisp-disunion.h @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 3d6bfa290dbd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1 /* Fundamental definitions for XEmacs Lisp interpreter -- non-union objects.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
2 Copyright (C) 1985, 1986, 1987, 1992, 1993 Free Software Foundation, Inc.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
3
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
4 This file is part of XEmacs.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
5
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
6 XEmacs is free software; you can redistribute it and/or modify it
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
8 Free Software Foundation; either version 2, or (at your option) any
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
9 later version.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
10
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
14 for more details.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
15
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
17 along with XEmacs; see the file COPYING. If not, write to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
19 Boston, MA 02111-1307, USA. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
20
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
21 /* Synched up with: FSF 19.30. Split out from lisp.h. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
22
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
23 /* If union type is not wanted, define Lisp_Object as just a number
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
24 and define the macros below to extract fields by shifting */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
25
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
26 #define Qzero 0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
27
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
28 /* #define Lisp_Object int */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
29 typedef EMACS_INT Lisp_Object;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
30
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
31 #ifndef VALMASK
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
32 # define VALMASK ((1L << (VALBITS)) - 1L)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
33 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
34 #define GCTYPEMASK ((1L << (GCTYPEBITS)) - 1L)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
35
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
36 /* comment from FSFmacs (perhaps not accurate here):
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
37
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
38 This is set in the car of a cons and in the plist slot of a symbol
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
39 to indicate it is marked. Likewise in the plist slot of an interval,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
40 the chain slot of a marker, the type slot of a float, and the name
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
41 slot of a buffer.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
42
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
43 In strings, this bit in the size field indicates that the string
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
44 is a "large" one, one which was separately malloc'd
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
45 rather than being part of a string block. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
46
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
47 #define MARKBIT (1UL << ((VALBITS) + (GCTYPEBITS)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
48
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
49
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
50 /* These macros extract various sorts of values from a Lisp_Object.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
51 For example, if tem is a Lisp_Object whose type is Lisp_Cons,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
52 XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
53
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
54 /* One need to override this if there must be high bits set in data space
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
55 (doing the result of the below & ((1 << (GCTYPE + 1)) - 1) would work
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
56 on all machines, but would penalise machines which don't need it)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
57 */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
58 #ifndef XTYPE
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
59 # define XTYPE(a) ((enum Lisp_Type) ((a) >> VALBITS))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
60 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
61
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
62 #ifndef XSETTYPE
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
63 # define XSETTYPE(a,b) ((a) = XUINT (a) | ((EMACS_INT)(b) << VALBITS))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
64 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
65
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
66 #define EQ(x,y) ((x) == (y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
67 #define GC_EQ(x,y) (XGCTYPE (x) == XGCTYPE (y) && XPNTR (x) == XPNTR (y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
68
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
69 #if 0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
70 /* XFASTINT is error-prone and saves a few instructions at best,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
71 so there's really no point to it. Just use XINT() or make_int()
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
72 instead. --ben */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
73 /* Use XFASTINT for fast retrieval and storage of integers known
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
74 to be positive. This takes advantage of the fact that Lisp_Int is 0. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
75 #define XFASTINT(a) (a)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
76 #endif /* 0 */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
77
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
78 /* Extract the value of a Lisp_Object as a signed integer. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
79
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
80 #ifndef XREALINT /* Some machines need to do this differently. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
81 # define XREALINT(a) (((a) << (LONGBITS-VALBITS)) >> (LONGBITS-VALBITS))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
82 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
83
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
84 /* Extract the value as an unsigned integer. This is a basis
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
85 for extracting it as a pointer to a structure in storage. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
86
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
87 #ifndef XUINT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
88 # define XUINT(a) ((a) & VALMASK)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
89 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
90
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
91 #ifndef XPNTR
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
92 # ifdef HAVE_SHM
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
93 /* In this representation, data is found in two widely separated segments. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
94 extern int pure_size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
95 # define XPNTR(a) \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
96 (XUINT (a) | (XUINT (a) > pure_size ? DATA_SEG_BITS : PURE_SEG_BITS))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
97 # else /* not HAVE_SHM */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
98 # ifdef DATA_SEG_BITS
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
99 /* This case is used for the rt-pc.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
100 In the diffs I was given, it checked for ptr = 0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
101 and did not adjust it in that case.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
102 But I don't think that zero should ever be found
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
103 in a Lisp object whose data type says it points to something.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
104 */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
105 # define XPNTR(a) (XUINT (a) | DATA_SEG_BITS)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
106 # else
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
107 # define XPNTR(a) XUINT (a)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
108 # endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
109 # endif /* not HAVE_SHM */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
110 #endif /* no XPNTR */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
111
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
112 #ifndef XSETINT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
113 # if 1 /* Back in the dark ages, this def "broke things" */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
114 # define XSETINT(a, b) do { XSETOBJ (a, Lisp_Int, b); } while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
115 # else /* alternate def to work around some putative bug with the above */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
116 # define XSETINT(a, b) do { (a) = (((a) & ~VALMASK) | ((b) & VALMASK)); \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
117 } while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
118 # endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
119 #endif /* !XSETINT */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
120
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
121 #ifndef XSETUINT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
122 #define XSETUINT(a, b) XSETINT (a, b)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
123 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
124
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
125 #ifndef XSETPNTR
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
126 #define XSETPNTR(a, b) XSETINT (a, b)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
127 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
128
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
129 /* characters do not need to sign extend so there's no need for special
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
130 futzing like with ints. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
131 #define XSETCHAR(a, b) do { XSETOBJ (a, Lisp_Char, b); } while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
132
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
133 /* XSETOBJ was formerly named XSET. The name change was made to catch
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
134 C code that attempts to use this macro. You should always use the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
135 individual settor macros (XSETCONS, XSETBUFFER, etc.) instead. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
136
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
137 #ifndef XSETOBJ
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
138 # define XSETOBJ(var,type,ptr) \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
139 do { (var) = (((EMACS_INT) (type) << VALBITS) \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
140 + ((EMACS_INT) (ptr) & VALMASK)); \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
141 } while(0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
142 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
143
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
144 /* During garbage collection, XGCTYPE must be used for extracting types
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
145 so that the mark bit is ignored. XMARKBIT accesses the markbit.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
146 Markbits are used only in particular slots of particular structure types.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
147 Other markbits are always zero.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
148 Outside of garbage collection, all mark bits are always zero. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
149
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
150 #ifndef XGCTYPE
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
151 # define XGCTYPE(a) ((enum Lisp_Type) (((a) >> VALBITS) & GCTYPEMASK))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
152 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
153
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
154 #if ((VALBITS) + (GCTYPEBITS)) == ((LONGBITS) - 1L)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
155 /* Make XMARKBIT faster if mark bit is sign bit. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
156 # ifndef XMARKBIT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
157 # define XMARKBIT(a) ((a) < 0L)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
158 # endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
159 #endif /* markbit is sign bit */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
160
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
161 #ifndef XMARKBIT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
162 # define XMARKBIT(a) ((a) & (MARKBIT))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
163 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
164
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
165 #ifndef XSETMARKBIT
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
166 #define XSETMARKBIT(a,b) \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
167 do { ((a) = ((a) & ~(MARKBIT)) | ((b) ? (MARKBIT) : 0)); } while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
168 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
169
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
170 #ifndef XMARK
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
171 # define XMARK(a) do { ((a) |= (MARKBIT)); } while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
172 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
173
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
174 #ifndef XUNMARK
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
175 /* no 'do {} while' because this is used in a mondo macro in lrecord.h */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
176 # define XUNMARK(a) ((a) &= (~(MARKBIT)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
177 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
178
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
179 /* Use this for turning a (void *) into a Lisp_Object, as when the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
180 Lisp_Object is passed into a toolkit callback function */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
181 #define VOID_TO_LISP(larg,varg) \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
182 do { ((larg) = ((Lisp_Object) (varg))); } while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
183 #define CVOID_TO_LISP VOID_TO_LISP
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
184
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
185 /* Use this for turning a Lisp_Object into a (void *), as when the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
186 Lisp_Object is passed into a toolkit callback function */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
187 #define LISP_TO_VOID(larg) ((void *) (larg))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
188 #define LISP_TO_CVOID(varg) ((CONST void *) (larg))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
189
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
190 /* Convert a Lisp_Object into something that can't be used as an
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
191 lvalue. Useful for type-checking. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
192 #define NON_LVALUE(larg) ((larg) + 0)