Miscellanous cleanups in preparation for the merge.
[bpt/emacs.git] / src / bytecode.c
CommitLineData
36f7ba0a 1/* Execution of byte code produced by bytecomp.el.
73b0cd50 2 Copyright (C) 1985-1988, 1993, 2000-2011 Free Software Foundation, Inc.
36f7ba0a
JB
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
36f7ba0a 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
36f7ba0a
JB
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36f7ba0a 18
9ec0b715 19/*
63639d44 20hacked on by jwz@lucid.com 17-jun-91
36f7ba0a
JB
21 o added a compile-time switch to turn on simple sanity checking;
22 o put back the obsolete byte-codes for error-detection;
8e11578b 23 o added a new instruction, unbind_all, which I will use for
36f7ba0a 24 tail-recursion elimination;
63639d44 25 o made temp_output_buffer_show be called with the right number
36f7ba0a
JB
26 of args;
27 o made the new bytecodes be called with args in the right order;
28 o added metering support.
29
30by Hallvard:
3ffbe76b 31 o added relative jump instructions;
36f7ba0a
JB
32 o all conditionals now only do QUIT if they jump.
33 */
34
18160b98 35#include <config.h>
d7306fe6 36#include <setjmp.h>
36f7ba0a
JB
37#include "lisp.h"
38#include "buffer.h"
83be827a 39#include "character.h"
36f7ba0a 40#include "syntax.h"
3f6abfd7 41#include "window.h"
36f7ba0a 42
ad7de7d7
GM
43#ifdef CHECK_FRAME_FONT
44#include "frame.h"
45#include "xterm.h"
46#endif
47
63639d44 48/*
8e11578b 49 * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for
63639d44
JB
50 * debugging the byte compiler...)
51 *
8e11578b 52 * define BYTE_CODE_METER to enable generation of a byte-op usage histogram.
36f7ba0a 53 */
7200d79c 54/* #define BYTE_CODE_SAFE */
63639d44 55/* #define BYTE_CODE_METER */
36f7ba0a
JB
56
57\f
58#ifdef BYTE_CODE_METER
59
29208e82 60Lisp_Object Qbyte_code_meter;
63639d44 61#define METER_2(code1, code2) \
36f7ba0a
JB
62 XFASTINT (XVECTOR (XVECTOR (Vbyte_code_meter)->contents[(code1)]) \
63 ->contents[(code2)])
64
63639d44
JB
65#define METER_1(code) METER_2 (0, (code))
66
2e3bf02a
GM
67#define METER_CODE(last_code, this_code) \
68{ \
69 if (byte_metering_on) \
70 { \
71 if (METER_1 (this_code) < MOST_POSITIVE_FIXNUM) \
72 METER_1 (this_code)++; \
73 if (last_code \
74 && METER_2 (last_code, this_code) < MOST_POSITIVE_FIXNUM) \
75 METER_2 (last_code, this_code)++; \
76 } \
63639d44 77}
36f7ba0a 78
615f2d59 79#endif /* BYTE_CODE_METER */
36f7ba0a
JB
80\f
81
82Lisp_Object Qbytecode;
b9598260 83extern Lisp_Object Qand_optional, Qand_rest;
36f7ba0a
JB
84
85/* Byte codes: */
86
3e21b6a7 87#define Bstack_ref 0 /* Actually, Bstack_ref+0 is not implemented: use dup. */
36f7ba0a
JB
88#define Bvarref 010
89#define Bvarset 020
90#define Bvarbind 030
91#define Bcall 040
92#define Bunbind 050
93
94#define Bnth 070
95#define Bsymbolp 071
96#define Bconsp 072
97#define Bstringp 073
98#define Blistp 074
99#define Beq 075
100#define Bmemq 076
101#define Bnot 077
102#define Bcar 0100
103#define Bcdr 0101
104#define Bcons 0102
105#define Blist1 0103
106#define Blist2 0104
107#define Blist3 0105
108#define Blist4 0106
109#define Blength 0107
110#define Baref 0110
111#define Baset 0111
112#define Bsymbol_value 0112
63639d44 113#define Bsymbol_function 0113
36f7ba0a 114#define Bset 0114
63639d44 115#define Bfset 0115
36f7ba0a
JB
116#define Bget 0116
117#define Bsubstring 0117
118#define Bconcat2 0120
119#define Bconcat3 0121
120#define Bconcat4 0122
121#define Bsub1 0123
122#define Badd1 0124
123#define Beqlsign 0125
124#define Bgtr 0126
125#define Blss 0127
126#define Bleq 0130
127#define Bgeq 0131
128#define Bdiff 0132
129#define Bnegate 0133
130#define Bplus 0134
131#define Bmax 0135
132#define Bmin 0136
133#define Bmult 0137
134
135#define Bpoint 0140
3b841abc 136/* Was Bmark in v17. */
e0f57e65 137#define Bsave_current_buffer 0141 /* Obsolete. */
36f7ba0a
JB
138#define Bgoto_char 0142
139#define Binsert 0143
140#define Bpoint_max 0144
141#define Bpoint_min 0145
142#define Bchar_after 0146
143#define Bfollowing_char 0147
144#define Bpreceding_char 0150
145#define Bcurrent_column 0151
146#define Bindent_to 0152
615f2d59 147#ifdef BYTE_CODE_SAFE
36f7ba0a 148#define Bscan_buffer 0153 /* No longer generated as of v18 */
615f2d59 149#endif
36f7ba0a
JB
150#define Beolp 0154
151#define Beobp 0155
152#define Bbolp 0156
153#define Bbobp 0157
154#define Bcurrent_buffer 0160
155#define Bset_buffer 0161
80402f25 156#define Bsave_current_buffer_1 0162 /* Replacing Bsave_current_buffer. */
615f2d59 157#if 0
63639d44 158#define Bread_char 0162 /* No longer generated as of v19 */
615f2d59
PE
159#endif
160#ifdef BYTE_CODE_SAFE
36f7ba0a 161#define Bset_mark 0163 /* this loser is no longer generated as of v18 */
615f2d59 162#endif
7200d79c 163#define Binteractive_p 0164 /* Obsolete since Emacs-24.1. */
36f7ba0a
JB
164
165#define Bforward_char 0165
166#define Bforward_word 0166
167#define Bskip_chars_forward 0167
168#define Bskip_chars_backward 0170
169#define Bforward_line 0171
170#define Bchar_syntax 0172
171#define Bbuffer_substring 0173
172#define Bdelete_region 0174
173#define Bnarrow_to_region 0175
174#define Bwiden 0176
63639d44 175#define Bend_of_line 0177
36f7ba0a
JB
176
177#define Bconstant2 0201
178#define Bgoto 0202
179#define Bgotoifnil 0203
180#define Bgotoifnonnil 0204
181#define Bgotoifnilelsepop 0205
182#define Bgotoifnonnilelsepop 0206
183#define Breturn 0207
184#define Bdiscard 0210
185#define Bdup 0211
186
187#define Bsave_excursion 0212
7200d79c 188#define Bsave_window_excursion 0213 /* Obsolete since Emacs-24.1. */
36f7ba0a
JB
189#define Bsave_restriction 0214
190#define Bcatch 0215
191
192#define Bunwind_protect 0216
193#define Bcondition_case 0217
7200d79c
SM
194#define Btemp_output_buffer_setup 0220 /* Obsolete since Emacs-24.1. */
195#define Btemp_output_buffer_show 0221 /* Obsolete since Emacs-24.1. */
36f7ba0a 196
7200d79c 197#define Bunbind_all 0222 /* Obsolete. Never used. */
36f7ba0a 198
63639d44
JB
199#define Bset_marker 0223
200#define Bmatch_beginning 0224
201#define Bmatch_end 0225
202#define Bupcase 0226
203#define Bdowncase 0227
204
36f7ba0a
JB
205#define Bstringeqlsign 0230
206#define Bstringlss 0231
207#define Bequal 0232
208#define Bnthcdr 0233
209#define Belt 0234
210#define Bmember 0235
211#define Bassq 0236
212#define Bnreverse 0237
213#define Bsetcar 0240
214#define Bsetcdr 0241
215#define Bcar_safe 0242
216#define Bcdr_safe 0243
217#define Bnconc 0244
218#define Bquo 0245
219#define Brem 0246
220#define Bnumberp 0247
221#define Bintegerp 0250
222
63639d44
JB
223#define BRgoto 0252
224#define BRgotoifnil 0253
225#define BRgotoifnonnil 0254
226#define BRgotoifnilelsepop 0255
227#define BRgotoifnonnilelsepop 0256
228
229#define BlistN 0257
230#define BconcatN 0260
231#define BinsertN 0261
232
b9598260
SM
233/* Bstack_ref is code 0. */
234#define Bstack_set 0262
235#define Bstack_set2 0263
b9598260
SM
236#define BdiscardN 0266
237
36f7ba0a 238#define Bconstant 0300
7ca1e8b7 239
b286858c
SM
240/* Whether to maintain a `top' and `bottom' field in the stack frame. */
241#define BYTE_MAINTAIN_TOP (BYTE_CODE_SAFE || BYTE_MARK_STACK)
4015b3c0 242\f
7ca1e8b7
GM
243/* Structure describing a value stack used during byte-code execution
244 in Fbyte_code. */
245
246struct byte_stack
247{
248 /* Program counter. This points into the byte_string below
249 and is relocated when that string is relocated. */
33b6c007 250 const unsigned char *pc;
7ca1e8b7
GM
251
252 /* Top and bottom of stack. The bottom points to an area of memory
253 allocated with alloca in Fbyte_code. */
b286858c 254#if BYTE_MAINTAIN_TOP
7ca1e8b7 255 Lisp_Object *top, *bottom;
b286858c 256#endif
7ca1e8b7
GM
257
258 /* The string containing the byte-code, and its current address.
259 Storing this here protects it from GC because mark_byte_stack
260 marks it. */
261 Lisp_Object byte_string;
33b6c007 262 const unsigned char *byte_string_start;
7ca1e8b7
GM
263
264 /* The vector of constants used during byte-code execution. Storing
265 this here protects it from GC because mark_byte_stack marks it. */
266 Lisp_Object constants;
267
268 /* Next entry in byte_stack_list. */
269 struct byte_stack *next;
270};
271
272/* A list of currently active byte-code execution value stacks.
273 Fbyte_code adds an entry to the head of this list before it starts
274 processing byte-code, and it removed the entry again when it is
275 done. Signalling an error truncates the list analoguous to
276 gcprolist. */
277
278struct byte_stack *byte_stack_list;
279
4015b3c0 280\f
7ca1e8b7
GM
281/* Mark objects on byte_stack_list. Called during GC. */
282
b286858c 283#if BYTE_MARK_STACK
7ca1e8b7 284void
971de7fb 285mark_byte_stack (void)
7ca1e8b7
GM
286{
287 struct byte_stack *stack;
288 Lisp_Object *obj;
289
290 for (stack = byte_stack_list; stack; stack = stack->next)
291 {
dff13d03
GM
292 /* If STACK->top is null here, this means there's an opcode in
293 Fbyte_code that wasn't expected to GC, but did. To find out
294 which opcode this is, record the value of `stack', and walk
295 up the stack in a debugger, stopping in frames of Fbyte_code.
296 The culprit is found in the frame of Fbyte_code where the
297 address of its local variable `stack' is equal to the
298 recorded value of `stack' here. */
6b61353c 299 eassert (stack->top);
8e11578b 300
7ca1e8b7 301 for (obj = stack->bottom; obj <= stack->top; ++obj)
6b61353c 302 mark_object (*obj);
a719d13e 303
6b61353c
KH
304 mark_object (stack->byte_string);
305 mark_object (stack->constants);
7ca1e8b7
GM
306 }
307}
b286858c 308#endif
7ca1e8b7 309
a719d13e
GM
310/* Unmark objects in the stacks on byte_stack_list. Relocate program
311 counters. Called when GC has completed. */
7ca1e8b7 312
8e11578b 313void
971de7fb 314unmark_byte_stack (void)
7ca1e8b7
GM
315{
316 struct byte_stack *stack;
317
318 for (stack = byte_stack_list; stack; stack = stack->next)
a719d13e 319 {
d5db4077 320 if (stack->byte_string_start != SDATA (stack->byte_string))
a719d13e
GM
321 {
322 int offset = stack->pc - stack->byte_string_start;
d5db4077 323 stack->byte_string_start = SDATA (stack->byte_string);
a719d13e
GM
324 stack->pc = stack->byte_string_start + offset;
325 }
326 }
7ca1e8b7
GM
327}
328
36f7ba0a
JB
329\f
330/* Fetch the next byte from the bytecode stream */
331
7ca1e8b7 332#define FETCH *stack.pc++
36f7ba0a 333
4015b3c0
GM
334/* Fetch two bytes from the bytecode stream and make a 16-bit number
335 out of them */
36f7ba0a
JB
336
337#define FETCH2 (op = FETCH, op + (FETCH << 8))
338
4015b3c0
GM
339/* Push x onto the execution stack. This used to be #define PUSH(x)
340 (*++stackp = (x)) This oddity is necessary because Alliant can't be
341 bothered to compile the preincrement operator properly, as of 4/91.
342 -JimB */
7ca1e8b7
GM
343
344#define PUSH(x) (top++, *top = (x))
36f7ba0a
JB
345
346/* Pop a value off the execution stack. */
347
7ca1e8b7 348#define POP (*top--)
36f7ba0a
JB
349
350/* Discard n values from the execution stack. */
351
7ca1e8b7
GM
352#define DISCARD(n) (top -= (n))
353
354/* Get the value which is at the top of the execution stack, but don't
355 pop it. */
356
357#define TOP (*top)
36f7ba0a 358
4015b3c0 359/* Actions that must be performed before and after calling a function
7ca1e8b7 360 that might GC. */
36f7ba0a 361
b286858c
SM
362#if !BYTE_MAINTAIN_TOP
363#define BEFORE_POTENTIAL_GC() ((void)0)
364#define AFTER_POTENTIAL_GC() ((void)0)
365#else
7ca1e8b7
GM
366#define BEFORE_POTENTIAL_GC() stack.top = top
367#define AFTER_POTENTIAL_GC() stack.top = NULL
b286858c 368#endif
36f7ba0a 369
14726871
RS
370/* Garbage collect if we have consed enough since the last time.
371 We do this at every branch, to avoid loops that never GC. */
372
3414f2d8 373#define MAYBE_GC() \
7914961c 374 do { \
3414f2d8
RS
375 if (consing_since_gc > gc_cons_threshold \
376 && consing_since_gc > gc_relative_threshold) \
377 { \
378 BEFORE_POTENTIAL_GC (); \
379 Fgarbage_collect (); \
380 AFTER_POTENTIAL_GC (); \
381 } \
7914961c 382 } while (0)
5e7ed093 383
3d5fc37b 384/* Check for jumping out of range. */
7ca1e8b7
GM
385
386#ifdef BYTE_CODE_SAFE
387
4015b3c0 388#define CHECK_RANGE(ARG) \
3d5fc37b
RS
389 if (ARG >= bytestr_length) abort ()
390
4015b3c0 391#else /* not BYTE_CODE_SAFE */
7ca1e8b7
GM
392
393#define CHECK_RANGE(ARG)
394
4015b3c0 395#endif /* not BYTE_CODE_SAFE */
7ca1e8b7 396
e12ea64e
GM
397/* A version of the QUIT macro which makes sure that the stack top is
398 set before signaling `quit'. */
399
400#define BYTE_CODE_QUIT \
401 do { \
402 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
403 { \
731475e7 404 Lisp_Object flag = Vquit_flag; \
e12ea64e
GM
405 Vquit_flag = Qnil; \
406 BEFORE_POTENTIAL_GC (); \
731475e7 407 if (EQ (Vthrow_on_input, flag)) \
a8f0f551 408 Fthrow (Vthrow_on_input, Qt); \
e12ea64e 409 Fsignal (Qquit, Qnil); \
892a8eb5 410 AFTER_POTENTIAL_GC (); \
e12ea64e 411 } \
c0335e02 412 ELSE_PENDING_SIGNALS \
e12ea64e
GM
413 } while (0)
414
7ca1e8b7 415
7200d79c 416DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
39f624fa
PJ
417 doc: /* Function used internally in byte-compiled code.
418The first argument, BYTESTR, is a string of byte code;
419the second, VECTOR, a vector of constants;
420the third, MAXDEPTH, the maximum stack depth used in this function.
7200d79c
SM
421If the third argument is incorrect, Emacs may crash. */)
422 (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth)
b9598260 423{
7200d79c 424 return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL);
b9598260
SM
425}
426
427/* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and
428 MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect,
429 emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp
430 argument list (including &rest, &optional, etc.), and ARGS, of size
431 NARGS, should be a vector of the actual arguments. The arguments in
432 ARGS are pushed on the stack according to ARGS_TEMPLATE before
433 executing BYTESTR. */
434
435Lisp_Object
0ee81a0c
SM
436exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
437 Lisp_Object args_template, int nargs, Lisp_Object *args)
36f7ba0a 438{
aed13378 439 int count = SPECPDL_INDEX ();
36f7ba0a
JB
440#ifdef BYTE_CODE_METER
441 int this_op = 0;
442 int prev_op;
443#endif
7ca1e8b7 444 int op;
4015b3c0 445 /* Lisp_Object v1, v2; */
089b985f 446 Lisp_Object *vectorp;
36f7ba0a 447#ifdef BYTE_CODE_SAFE
7ca1e8b7
GM
448 int const_length = XVECTOR (vector)->size;
449 Lisp_Object *stacke;
36f7ba0a 450#endif
089b985f 451 int bytestr_length;
7ca1e8b7
GM
452 struct byte_stack stack;
453 Lisp_Object *top;
4015b3c0 454 Lisp_Object result;
36f7ba0a 455
603a0937 456#if 0 /* CHECK_FRAME_FONT */
ad7de7d7
GM
457 {
458 struct frame *f = SELECTED_FRAME ();
459 if (FRAME_X_P (f)
460 && FRAME_FONT (f)->direction != 0
461 && FRAME_FONT (f)->direction != 1)
462 abort ();
463 }
464#endif
465
b7826503 466 CHECK_STRING (bytestr);
c616acb8 467 CHECK_VECTOR (vector);
b7826503 468 CHECK_NUMBER (maxdepth);
36f7ba0a 469
089b985f
KH
470 if (STRING_MULTIBYTE (bytestr))
471 /* BYTESTR must have been produced by Emacs 20.2 or the earlier
472 because they produced a raw 8-bit string for byte-code and now
473 such a byte-code string is loaded as multibyte while raw 8-bit
474 characters converted to multibyte form. Thus, now we must
fbd98f82 475 convert them back to the originally intended unibyte form. */
5274126b 476 bytestr = Fstring_as_unibyte (bytestr);
089b985f 477
d5db4077 478 bytestr_length = SBYTES (bytestr);
089b985f
KH
479 vectorp = XVECTOR (vector)->contents;
480
7ca1e8b7 481 stack.byte_string = bytestr;
d5db4077 482 stack.pc = stack.byte_string_start = SDATA (bytestr);
7ca1e8b7 483 stack.constants = vector;
b286858c 484 top = (Lisp_Object *) alloca (XFASTINT (maxdepth)
7ca1e8b7 485 * sizeof (Lisp_Object));
b286858c
SM
486#if BYTE_MAINTAIN_TOP
487 stack.bottom = top;
7ca1e8b7 488 stack.top = NULL;
b286858c
SM
489#endif
490 top -= 1;
7ca1e8b7
GM
491 stack.next = byte_stack_list;
492 byte_stack_list = &stack;
36f7ba0a 493
7ca1e8b7
GM
494#ifdef BYTE_CODE_SAFE
495 stacke = stack.bottom - 1 + XFASTINT (maxdepth);
496#endif
8e11578b 497
e2abe5a1 498 if (INTEGERP (args_template))
b9598260 499 {
e2abe5a1
SM
500 int at = XINT (args_template);
501 int rest = at & 128;
502 int mandatory = at & 127;
503 int nonrest = at >> 8;
504 eassert (mandatory <= nonrest);
505 if (nargs <= nonrest)
506 {
507 int i;
508 for (i = 0 ; i < nargs; i++, args++)
509 PUSH (*args);
510 if (nargs < mandatory)
511 /* Too few arguments. */
512 Fsignal (Qwrong_number_of_arguments,
513 Fcons (Fcons (make_number (mandatory),
514 rest ? Qand_rest : make_number (nonrest)),
515 Fcons (make_number (nargs), Qnil)));
516 else
517 {
518 for (; i < nonrest; i++)
519 PUSH (Qnil);
520 if (rest)
521 PUSH (Qnil);
522 }
523 }
524 else if (rest)
525 {
526 int i;
527 for (i = 0 ; i < nonrest; i++, args++)
528 PUSH (*args);
529 PUSH (Flist (nargs - nonrest, args));
530 }
531 else
532 /* Too many arguments. */
b9598260 533 Fsignal (Qwrong_number_of_arguments,
e2abe5a1
SM
534 Fcons (Fcons (make_number (mandatory),
535 make_number (nonrest)),
536 Fcons (make_number (nargs), Qnil)));
537 }
538 else if (! NILP (args_template))
539 /* We should push some arguments on the stack. */
540 {
541 error ("Unknown args template!");
b9598260
SM
542 }
543
36f7ba0a
JB
544 while (1)
545 {
546#ifdef BYTE_CODE_SAFE
9e49c990 547 if (top > stacke)
cc94f3b2 548 abort ();
7ca1e8b7 549 else if (top < stack.bottom - 1)
cc94f3b2 550 abort ();
36f7ba0a
JB
551#endif
552
36f7ba0a
JB
553#ifdef BYTE_CODE_METER
554 prev_op = this_op;
555 this_op = op = FETCH;
556 METER_CODE (prev_op, op);
36f7ba0a 557#else
4015b3c0 558 op = FETCH;
36f7ba0a 559#endif
36f7ba0a 560
4015b3c0
GM
561 switch (op)
562 {
563 case Bvarref + 7:
36f7ba0a
JB
564 op = FETCH2;
565 goto varref;
566
8e11578b
TTN
567 case Bvarref:
568 case Bvarref + 1:
569 case Bvarref + 2:
4015b3c0 570 case Bvarref + 3:
8e11578b 571 case Bvarref + 4:
4015b3c0 572 case Bvarref + 5:
36f7ba0a 573 op = op - Bvarref;
4015b3c0
GM
574 goto varref;
575
576 /* This seems to be the most frequently executed byte-code
577 among the Bvarref's, so avoid a goto here. */
578 case Bvarref+6:
579 op = FETCH;
36f7ba0a 580 varref:
4015b3c0
GM
581 {
582 Lisp_Object v1, v2;
583
584 v1 = vectorp[op];
585 if (SYMBOLP (v1))
586 {
ce5b453a
SM
587 if (XSYMBOL (v1)->redirect != SYMBOL_PLAINVAL
588 || (v2 = SYMBOL_VAL (XSYMBOL (v1)),
589 EQ (v2, Qunbound)))
bf1de43e
GM
590 {
591 BEFORE_POTENTIAL_GC ();
592 v2 = Fsymbol_value (v1);
593 AFTER_POTENTIAL_GC ();
594 }
4015b3c0
GM
595 }
596 else
bf1de43e
GM
597 {
598 BEFORE_POTENTIAL_GC ();
599 v2 = Fsymbol_value (v1);
600 AFTER_POTENTIAL_GC ();
601 }
4015b3c0
GM
602 PUSH (v2);
603 break;
604 }
605
606 case Bgotoifnil:
21ed6de3
KR
607 {
608 Lisp_Object v1;
609 MAYBE_GC ();
610 op = FETCH2;
611 v1 = POP;
612 if (NILP (v1))
613 {
614 BYTE_CODE_QUIT;
615 CHECK_RANGE (op);
616 stack.pc = stack.byte_string_start + op;
617 }
618 break;
619 }
36f7ba0a 620
4015b3c0
GM
621 case Bcar:
622 {
623 Lisp_Object v1;
624 v1 = TOP;
1c470562
SM
625 if (CONSP (v1))
626 TOP = XCAR (v1);
627 else if (NILP (v1))
628 TOP = Qnil;
629 else
630 {
631 BEFORE_POTENTIAL_GC ();
632 wrong_type_argument (Qlistp, v1);
633 AFTER_POTENTIAL_GC ();
634 }
4015b3c0
GM
635 break;
636 }
637
638 case Beq:
639 {
640 Lisp_Object v1;
641 v1 = POP;
642 TOP = EQ (v1, TOP) ? Qt : Qnil;
643 break;
644 }
645
646 case Bmemq:
647 {
648 Lisp_Object v1;
bf1de43e 649 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
650 v1 = POP;
651 TOP = Fmemq (TOP, v1);
bf1de43e 652 AFTER_POTENTIAL_GC ();
4015b3c0
GM
653 break;
654 }
655
656 case Bcdr:
657 {
658 Lisp_Object v1;
659 v1 = TOP;
1c470562
SM
660 if (CONSP (v1))
661 TOP = XCDR (v1);
662 else if (NILP (v1))
663 TOP = Qnil;
664 else
665 {
666 BEFORE_POTENTIAL_GC ();
667 wrong_type_argument (Qlistp, v1);
668 AFTER_POTENTIAL_GC ();
669 }
670 break;
4015b3c0
GM
671 break;
672 }
36f7ba0a 673
620cc5fa
GM
674 case Bvarset:
675 case Bvarset+1:
676 case Bvarset+2:
677 case Bvarset+3:
678 case Bvarset+4:
679 case Bvarset+5:
680 op -= Bvarset;
36f7ba0a
JB
681 goto varset;
682
620cc5fa
GM
683 case Bvarset+7:
684 op = FETCH2;
4015b3c0
GM
685 goto varset;
686
687 case Bvarset+6:
688 op = FETCH;
36f7ba0a 689 varset:
620cc5fa
GM
690 {
691 Lisp_Object sym, val;
8e11578b 692
620cc5fa 693 sym = vectorp[op];
bf1de43e 694 val = TOP;
620cc5fa
GM
695
696 /* Inline the most common case. */
697 if (SYMBOLP (sym)
698 && !EQ (val, Qunbound)
ce5b453a
SM
699 && !XSYMBOL (sym)->redirect
700 && !SYMBOL_CONSTANT_P (sym))
701 XSYMBOL (sym)->val.value = val;
620cc5fa 702 else
bf1de43e
GM
703 {
704 BEFORE_POTENTIAL_GC ();
94b612ad 705 set_internal (sym, val, Qnil, 0);
bf1de43e
GM
706 AFTER_POTENTIAL_GC ();
707 }
620cc5fa 708 }
3789dcdf 709 (void) POP;
36f7ba0a
JB
710 break;
711
4015b3c0
GM
712 case Bdup:
713 {
714 Lisp_Object v1;
715 v1 = TOP;
716 PUSH (v1);
717 break;
718 }
719
720 /* ------------------ */
721
36f7ba0a
JB
722 case Bvarbind+6:
723 op = FETCH;
724 goto varbind;
725
726 case Bvarbind+7:
727 op = FETCH2;
728 goto varbind;
729
fa9aabf6
GM
730 case Bvarbind:
731 case Bvarbind+1:
732 case Bvarbind+2:
733 case Bvarbind+3:
734 case Bvarbind+4:
735 case Bvarbind+5:
36f7ba0a
JB
736 op -= Bvarbind;
737 varbind:
56b8eef5
GM
738 /* Specbind can signal and thus GC. */
739 BEFORE_POTENTIAL_GC ();
36f7ba0a 740 specbind (vectorp[op], POP);
56b8eef5 741 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
742 break;
743
744 case Bcall+6:
745 op = FETCH;
746 goto docall;
747
748 case Bcall+7:
749 op = FETCH2;
750 goto docall;
751
fa9aabf6
GM
752 case Bcall:
753 case Bcall+1:
754 case Bcall+2:
755 case Bcall+3:
756 case Bcall+4:
757 case Bcall+5:
36f7ba0a
JB
758 op -= Bcall;
759 docall:
4015b3c0 760 {
fa9aabf6 761 BEFORE_POTENTIAL_GC ();
4015b3c0 762 DISCARD (op);
63639d44 763#ifdef BYTE_CODE_METER
4015b3c0
GM
764 if (byte_metering_on && SYMBOLP (TOP))
765 {
766 Lisp_Object v1, v2;
767
768 v1 = TOP;
769 v2 = Fget (v1, Qbyte_code_meter);
770 if (INTEGERP (v2)
f28e6371 771 && XINT (v2) < MOST_POSITIVE_FIXNUM)
4015b3c0
GM
772 {
773 XSETINT (v2, XINT (v2) + 1);
774 Fput (v1, Qbyte_code_meter, v2);
775 }
776 }
63639d44 777#endif
4015b3c0
GM
778 TOP = Ffuncall (op + 1, &TOP);
779 AFTER_POTENTIAL_GC ();
780 break;
781 }
36f7ba0a
JB
782
783 case Bunbind+6:
784 op = FETCH;
785 goto dounbind;
786
787 case Bunbind+7:
788 op = FETCH2;
789 goto dounbind;
790
fa9aabf6
GM
791 case Bunbind:
792 case Bunbind+1:
793 case Bunbind+2:
794 case Bunbind+3:
795 case Bunbind+4:
796 case Bunbind+5:
36f7ba0a
JB
797 op -= Bunbind;
798 dounbind:
7ca1e8b7 799 BEFORE_POTENTIAL_GC ();
aed13378 800 unbind_to (SPECPDL_INDEX () - op, Qnil);
7ca1e8b7 801 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
802 break;
803
7200d79c 804 case Bunbind_all: /* Obsolete. Never used. */
36f7ba0a 805 /* To unbind back to the beginning of this frame. Not used yet,
63639d44 806 but will be needed for tail-recursion elimination. */
7ca1e8b7 807 BEFORE_POTENTIAL_GC ();
36f7ba0a 808 unbind_to (count, Qnil);
7ca1e8b7 809 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
810 break;
811
812 case Bgoto:
14726871 813 MAYBE_GC ();
e12ea64e 814 BYTE_CODE_QUIT;
36f7ba0a 815 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
3d5fc37b 816 CHECK_RANGE (op);
7ca1e8b7 817 stack.pc = stack.byte_string_start + op;
36f7ba0a
JB
818 break;
819
36f7ba0a 820 case Bgotoifnonnil:
21ed6de3
KR
821 {
822 Lisp_Object v1;
823 MAYBE_GC ();
824 op = FETCH2;
825 v1 = POP;
826 if (!NILP (v1))
827 {
828 BYTE_CODE_QUIT;
829 CHECK_RANGE (op);
830 stack.pc = stack.byte_string_start + op;
831 }
832 break;
833 }
36f7ba0a
JB
834
835 case Bgotoifnilelsepop:
14726871 836 MAYBE_GC ();
36f7ba0a 837 op = FETCH2;
921a8935 838 if (NILP (TOP))
36f7ba0a 839 {
e12ea64e 840 BYTE_CODE_QUIT;
3d5fc37b 841 CHECK_RANGE (op);
7ca1e8b7 842 stack.pc = stack.byte_string_start + op;
36f7ba0a 843 }
63639d44 844 else DISCARD (1);
36f7ba0a
JB
845 break;
846
847 case Bgotoifnonnilelsepop:
14726871 848 MAYBE_GC ();
36f7ba0a 849 op = FETCH2;
921a8935 850 if (!NILP (TOP))
36f7ba0a 851 {
e12ea64e 852 BYTE_CODE_QUIT;
3d5fc37b 853 CHECK_RANGE (op);
7ca1e8b7 854 stack.pc = stack.byte_string_start + op;
36f7ba0a 855 }
63639d44
JB
856 else DISCARD (1);
857 break;
858
859 case BRgoto:
14726871 860 MAYBE_GC ();
e12ea64e 861 BYTE_CODE_QUIT;
7ca1e8b7 862 stack.pc += (int) *stack.pc - 127;
63639d44
JB
863 break;
864
865 case BRgotoifnil:
21ed6de3
KR
866 {
867 Lisp_Object v1;
868 MAYBE_GC ();
869 v1 = POP;
870 if (NILP (v1))
871 {
872 BYTE_CODE_QUIT;
873 stack.pc += (int) *stack.pc - 128;
874 }
875 stack.pc++;
876 break;
877 }
63639d44
JB
878
879 case BRgotoifnonnil:
21ed6de3
KR
880 {
881 Lisp_Object v1;
882 MAYBE_GC ();
883 v1 = POP;
884 if (!NILP (v1))
885 {
886 BYTE_CODE_QUIT;
887 stack.pc += (int) *stack.pc - 128;
888 }
889 stack.pc++;
890 break;
891 }
63639d44
JB
892
893 case BRgotoifnilelsepop:
14726871 894 MAYBE_GC ();
7ca1e8b7 895 op = *stack.pc++;
63639d44
JB
896 if (NILP (TOP))
897 {
e12ea64e 898 BYTE_CODE_QUIT;
7ca1e8b7 899 stack.pc += op - 128;
63639d44
JB
900 }
901 else DISCARD (1);
902 break;
903
904 case BRgotoifnonnilelsepop:
14726871 905 MAYBE_GC ();
7ca1e8b7 906 op = *stack.pc++;
63639d44
JB
907 if (!NILP (TOP))
908 {
e12ea64e 909 BYTE_CODE_QUIT;
7ca1e8b7 910 stack.pc += op - 128;
63639d44
JB
911 }
912 else DISCARD (1);
98bf0c8d
JB
913 break;
914
36f7ba0a 915 case Breturn:
4015b3c0 916 result = POP;
36f7ba0a
JB
917 goto exit;
918
919 case Bdiscard:
63639d44 920 DISCARD (1);
36f7ba0a
JB
921 break;
922
36f7ba0a
JB
923 case Bconstant2:
924 PUSH (vectorp[FETCH2]);
925 break;
926
927 case Bsave_excursion:
fa9aabf6
GM
928 record_unwind_protect (save_excursion_restore,
929 save_excursion_save ());
36f7ba0a
JB
930 break;
931
7200d79c 932 case Bsave_current_buffer: /* Obsolete since ??. */
80402f25 933 case Bsave_current_buffer_1:
de404585 934 record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
3b841abc
RS
935 break;
936
7200d79c 937 case Bsave_window_excursion: /* Obsolete since 24.1. */
e0f57e65 938 {
e0f57e65 939 register int count = SPECPDL_INDEX ();
e0f57e65
SM
940 record_unwind_protect (Fset_window_configuration,
941 Fcurrent_window_configuration (Qnil));
942 BEFORE_POTENTIAL_GC ();
943 TOP = Fprogn (TOP);
944 unbind_to (count, TOP);
945 AFTER_POTENTIAL_GC ();
946 break;
947 }
36f7ba0a
JB
948
949 case Bsave_restriction:
fa9aabf6
GM
950 record_unwind_protect (save_restriction_restore,
951 save_restriction_save ());
36f7ba0a
JB
952 break;
953
ca105506 954 case Bcatch: /* FIXME: ill-suited for lexbind */
4015b3c0
GM
955 {
956 Lisp_Object v1;
4015b3c0 957 BEFORE_POTENTIAL_GC ();
bf1de43e 958 v1 = POP;
ca105506 959 TOP = internal_catch (TOP, eval_sub, v1);
4015b3c0
GM
960 AFTER_POTENTIAL_GC ();
961 break;
962 }
36f7ba0a 963
ca105506
SM
964 case Bunwind_protect: /* FIXME: avoid closure for lexbind */
965 record_unwind_protect (Fprogn, POP);
36f7ba0a
JB
966 break;
967
ca105506 968 case Bcondition_case: /* FIXME: ill-suited for lexbind */
4015b3c0 969 {
5c125a13
RS
970 Lisp_Object handlers, body;
971 handlers = POP;
972 body = POP;
4015b3c0 973 BEFORE_POTENTIAL_GC ();
ca105506 974 TOP = internal_lisp_condition_case (TOP, body, handlers);
4015b3c0
GM
975 AFTER_POTENTIAL_GC ();
976 break;
977 }
36f7ba0a 978
7200d79c 979 case Btemp_output_buffer_setup: /* Obsolete since 24.1. */
4015b3c0 980 BEFORE_POTENTIAL_GC ();
b7826503 981 CHECK_STRING (TOP);
42a5b22f 982 temp_output_buffer_setup (SSDATA (TOP));
4015b3c0 983 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
984 TOP = Vstandard_output;
985 break;
986
7200d79c 987 case Btemp_output_buffer_show: /* Obsolete since 24.1. */
4015b3c0
GM
988 {
989 Lisp_Object v1;
4015b3c0 990 BEFORE_POTENTIAL_GC ();
bf1de43e 991 v1 = POP;
4015b3c0
GM
992 temp_output_buffer_show (TOP);
993 TOP = v1;
994 /* pop binding of standard-output */
aed13378 995 unbind_to (SPECPDL_INDEX () - 1, Qnil);
4015b3c0
GM
996 AFTER_POTENTIAL_GC ();
997 break;
998 }
36f7ba0a
JB
999
1000 case Bnth:
4015b3c0
GM
1001 {
1002 Lisp_Object v1, v2;
bf1de43e 1003 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1004 v1 = POP;
1005 v2 = TOP;
b7826503 1006 CHECK_NUMBER (v2);
4015b3c0
GM
1007 op = XINT (v2);
1008 immediate_quit = 1;
14c5155a
KS
1009 while (--op >= 0 && CONSP (v1))
1010 v1 = XCDR (v1);
4015b3c0 1011 immediate_quit = 0;
14c5155a 1012 TOP = CAR (v1);
1c470562 1013 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1014 break;
1015 }
36f7ba0a
JB
1016
1017 case Bsymbolp:
617bd3f6 1018 TOP = SYMBOLP (TOP) ? Qt : Qnil;
36f7ba0a
JB
1019 break;
1020
1021 case Bconsp:
1022 TOP = CONSP (TOP) ? Qt : Qnil;
1023 break;
1024
1025 case Bstringp:
617bd3f6 1026 TOP = STRINGP (TOP) ? Qt : Qnil;
36f7ba0a
JB
1027 break;
1028
1029 case Blistp:
921a8935 1030 TOP = CONSP (TOP) || NILP (TOP) ? Qt : Qnil;
36f7ba0a
JB
1031 break;
1032
36f7ba0a 1033 case Bnot:
921a8935 1034 TOP = NILP (TOP) ? Qt : Qnil;
36f7ba0a
JB
1035 break;
1036
36f7ba0a 1037 case Bcons:
4015b3c0
GM
1038 {
1039 Lisp_Object v1;
1040 v1 = POP;
1041 TOP = Fcons (TOP, v1);
1042 break;
1043 }
36f7ba0a
JB
1044
1045 case Blist1:
1046 TOP = Fcons (TOP, Qnil);
1047 break;
1048
1049 case Blist2:
4015b3c0
GM
1050 {
1051 Lisp_Object v1;
1052 v1 = POP;
1053 TOP = Fcons (TOP, Fcons (v1, Qnil));
1054 break;
1055 }
36f7ba0a
JB
1056
1057 case Blist3:
63639d44 1058 DISCARD (2);
36f7ba0a
JB
1059 TOP = Flist (3, &TOP);
1060 break;
1061
1062 case Blist4:
63639d44 1063 DISCARD (3);
36f7ba0a
JB
1064 TOP = Flist (4, &TOP);
1065 break;
1066
63639d44
JB
1067 case BlistN:
1068 op = FETCH;
1069 DISCARD (op - 1);
1070 TOP = Flist (op, &TOP);
1071 break;
1072
36f7ba0a 1073 case Blength:
bf1de43e 1074 BEFORE_POTENTIAL_GC ();
36f7ba0a 1075 TOP = Flength (TOP);
bf1de43e 1076 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1077 break;
1078
1079 case Baref:
4015b3c0
GM
1080 {
1081 Lisp_Object v1;
bf1de43e 1082 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1083 v1 = POP;
1084 TOP = Faref (TOP, v1);
bf1de43e 1085 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1086 break;
1087 }
36f7ba0a
JB
1088
1089 case Baset:
4015b3c0
GM
1090 {
1091 Lisp_Object v1, v2;
bf1de43e 1092 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1093 v2 = POP; v1 = POP;
1094 TOP = Faset (TOP, v1, v2);
bf1de43e 1095 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1096 break;
1097 }
36f7ba0a
JB
1098
1099 case Bsymbol_value:
bf1de43e 1100 BEFORE_POTENTIAL_GC ();
36f7ba0a 1101 TOP = Fsymbol_value (TOP);
bf1de43e 1102 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1103 break;
1104
1105 case Bsymbol_function:
bf1de43e 1106 BEFORE_POTENTIAL_GC ();
36f7ba0a 1107 TOP = Fsymbol_function (TOP);
bf1de43e 1108 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1109 break;
1110
1111 case Bset:
4015b3c0
GM
1112 {
1113 Lisp_Object v1;
bf1de43e 1114 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1115 v1 = POP;
1116 TOP = Fset (TOP, v1);
bf1de43e 1117 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1118 break;
1119 }
36f7ba0a
JB
1120
1121 case Bfset:
4015b3c0
GM
1122 {
1123 Lisp_Object v1;
bf1de43e 1124 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1125 v1 = POP;
1126 TOP = Ffset (TOP, v1);
bf1de43e 1127 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1128 break;
1129 }
36f7ba0a
JB
1130
1131 case Bget:
4015b3c0
GM
1132 {
1133 Lisp_Object v1;
bf1de43e 1134 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1135 v1 = POP;
1136 TOP = Fget (TOP, v1);
bf1de43e 1137 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1138 break;
1139 }
36f7ba0a
JB
1140
1141 case Bsubstring:
4015b3c0
GM
1142 {
1143 Lisp_Object v1, v2;
fa9aabf6 1144 BEFORE_POTENTIAL_GC ();
bf1de43e 1145 v2 = POP; v1 = POP;
4015b3c0 1146 TOP = Fsubstring (TOP, v1, v2);
fa9aabf6 1147 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1148 break;
1149 }
36f7ba0a
JB
1150
1151 case Bconcat2:
bf1de43e 1152 BEFORE_POTENTIAL_GC ();
63639d44 1153 DISCARD (1);
36f7ba0a 1154 TOP = Fconcat (2, &TOP);
bf1de43e 1155 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1156 break;
1157
1158 case Bconcat3:
bf1de43e 1159 BEFORE_POTENTIAL_GC ();
63639d44 1160 DISCARD (2);
36f7ba0a 1161 TOP = Fconcat (3, &TOP);
bf1de43e 1162 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1163 break;
1164
1165 case Bconcat4:
bf1de43e 1166 BEFORE_POTENTIAL_GC ();
63639d44 1167 DISCARD (3);
36f7ba0a 1168 TOP = Fconcat (4, &TOP);
bf1de43e 1169 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1170 break;
1171
63639d44
JB
1172 case BconcatN:
1173 op = FETCH;
bf1de43e 1174 BEFORE_POTENTIAL_GC ();
63639d44
JB
1175 DISCARD (op - 1);
1176 TOP = Fconcat (op, &TOP);
bf1de43e 1177 AFTER_POTENTIAL_GC ();
63639d44
JB
1178 break;
1179
36f7ba0a 1180 case Bsub1:
4015b3c0
GM
1181 {
1182 Lisp_Object v1;
1183 v1 = TOP;
1184 if (INTEGERP (v1))
1185 {
1186 XSETINT (v1, XINT (v1) - 1);
1187 TOP = v1;
1188 }
1189 else
e494eee5
MB
1190 {
1191 BEFORE_POTENTIAL_GC ();
1192 TOP = Fsub1 (v1);
1193 AFTER_POTENTIAL_GC ();
1194 }
4015b3c0
GM
1195 break;
1196 }
36f7ba0a
JB
1197
1198 case Badd1:
4015b3c0
GM
1199 {
1200 Lisp_Object v1;
1201 v1 = TOP;
1202 if (INTEGERP (v1))
1203 {
1204 XSETINT (v1, XINT (v1) + 1);
1205 TOP = v1;
1206 }
1207 else
bf1de43e
GM
1208 {
1209 BEFORE_POTENTIAL_GC ();
1210 TOP = Fadd1 (v1);
1211 AFTER_POTENTIAL_GC ();
1212 }
4015b3c0
GM
1213 break;
1214 }
36f7ba0a
JB
1215
1216 case Beqlsign:
4015b3c0
GM
1217 {
1218 Lisp_Object v1, v2;
f5941bf8 1219 BEFORE_POTENTIAL_GC ();
bf1de43e 1220 v2 = POP; v1 = TOP;
b7826503
PJ
1221 CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v1);
1222 CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v2);
f5941bf8 1223 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1224 if (FLOATP (v1) || FLOATP (v2))
1225 {
1226 double f1, f2;
1227
1228 f1 = (FLOATP (v1) ? XFLOAT_DATA (v1) : XINT (v1));
1229 f2 = (FLOATP (v2) ? XFLOAT_DATA (v2) : XINT (v2));
1230 TOP = (f1 == f2 ? Qt : Qnil);
1231 }
1232 else
4015b3c0
GM
1233 TOP = (XINT (v1) == XINT (v2) ? Qt : Qnil);
1234 break;
1235 }
36f7ba0a
JB
1236
1237 case Bgtr:
4015b3c0
GM
1238 {
1239 Lisp_Object v1;
bf1de43e 1240 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1241 v1 = POP;
1242 TOP = Fgtr (TOP, v1);
bf1de43e 1243 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1244 break;
1245 }
36f7ba0a
JB
1246
1247 case Blss:
4015b3c0
GM
1248 {
1249 Lisp_Object v1;
bf1de43e 1250 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1251 v1 = POP;
1252 TOP = Flss (TOP, v1);
bf1de43e 1253 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1254 break;
1255 }
36f7ba0a
JB
1256
1257 case Bleq:
4015b3c0
GM
1258 {
1259 Lisp_Object v1;
bf1de43e 1260 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1261 v1 = POP;
1262 TOP = Fleq (TOP, v1);
bf1de43e 1263 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1264 break;
1265 }
36f7ba0a
JB
1266
1267 case Bgeq:
4015b3c0
GM
1268 {
1269 Lisp_Object v1;
d9c1f6f9 1270 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1271 v1 = POP;
1272 TOP = Fgeq (TOP, v1);
d9c1f6f9 1273 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1274 break;
1275 }
36f7ba0a
JB
1276
1277 case Bdiff:
bf1de43e 1278 BEFORE_POTENTIAL_GC ();
63639d44 1279 DISCARD (1);
36f7ba0a 1280 TOP = Fminus (2, &TOP);
bf1de43e 1281 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1282 break;
1283
1284 case Bnegate:
4015b3c0
GM
1285 {
1286 Lisp_Object v1;
1287 v1 = TOP;
1288 if (INTEGERP (v1))
1289 {
1290 XSETINT (v1, - XINT (v1));
1291 TOP = v1;
1292 }
1293 else
bf1de43e
GM
1294 {
1295 BEFORE_POTENTIAL_GC ();
1296 TOP = Fminus (1, &TOP);
1297 AFTER_POTENTIAL_GC ();
1298 }
4015b3c0
GM
1299 break;
1300 }
36f7ba0a
JB
1301
1302 case Bplus:
bf1de43e 1303 BEFORE_POTENTIAL_GC ();
63639d44 1304 DISCARD (1);
36f7ba0a 1305 TOP = Fplus (2, &TOP);
bf1de43e 1306 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1307 break;
1308
1309 case Bmax:
bf1de43e 1310 BEFORE_POTENTIAL_GC ();
63639d44 1311 DISCARD (1);
36f7ba0a 1312 TOP = Fmax (2, &TOP);
bf1de43e 1313 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1314 break;
1315
1316 case Bmin:
bf1de43e 1317 BEFORE_POTENTIAL_GC ();
63639d44 1318 DISCARD (1);
36f7ba0a 1319 TOP = Fmin (2, &TOP);
bf1de43e 1320 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1321 break;
1322
1323 case Bmult:
bf1de43e 1324 BEFORE_POTENTIAL_GC ();
63639d44 1325 DISCARD (1);
36f7ba0a 1326 TOP = Ftimes (2, &TOP);
bf1de43e 1327 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1328 break;
1329
1330 case Bquo:
bf1de43e 1331 BEFORE_POTENTIAL_GC ();
63639d44 1332 DISCARD (1);
36f7ba0a 1333 TOP = Fquo (2, &TOP);
bf1de43e 1334 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1335 break;
1336
1337 case Brem:
4015b3c0
GM
1338 {
1339 Lisp_Object v1;
bf1de43e 1340 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1341 v1 = POP;
1342 TOP = Frem (TOP, v1);
bf1de43e 1343 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1344 break;
1345 }
36f7ba0a
JB
1346
1347 case Bpoint:
4015b3c0
GM
1348 {
1349 Lisp_Object v1;
1350 XSETFASTINT (v1, PT);
1351 PUSH (v1);
1352 break;
1353 }
36f7ba0a
JB
1354
1355 case Bgoto_char:
4015b3c0 1356 BEFORE_POTENTIAL_GC ();
36f7ba0a 1357 TOP = Fgoto_char (TOP);
4015b3c0 1358 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1359 break;
1360
1361 case Binsert:
4015b3c0 1362 BEFORE_POTENTIAL_GC ();
36f7ba0a 1363 TOP = Finsert (1, &TOP);
4015b3c0 1364 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1365 break;
1366
63639d44
JB
1367 case BinsertN:
1368 op = FETCH;
4015b3c0 1369 BEFORE_POTENTIAL_GC ();
fa9aabf6 1370 DISCARD (op - 1);
63639d44 1371 TOP = Finsert (op, &TOP);
4015b3c0 1372 AFTER_POTENTIAL_GC ();
63639d44
JB
1373 break;
1374
36f7ba0a 1375 case Bpoint_max:
4015b3c0
GM
1376 {
1377 Lisp_Object v1;
1378 XSETFASTINT (v1, ZV);
1379 PUSH (v1);
1380 break;
1381 }
36f7ba0a
JB
1382
1383 case Bpoint_min:
4015b3c0
GM
1384 {
1385 Lisp_Object v1;
1386 XSETFASTINT (v1, BEGV);
1387 PUSH (v1);
1388 break;
1389 }
36f7ba0a
JB
1390
1391 case Bchar_after:
bf1de43e 1392 BEFORE_POTENTIAL_GC ();
36f7ba0a 1393 TOP = Fchar_after (TOP);
bf1de43e 1394 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1395 break;
1396
1397 case Bfollowing_char:
4015b3c0
GM
1398 {
1399 Lisp_Object v1;
bf1de43e 1400 BEFORE_POTENTIAL_GC ();
4015b3c0 1401 v1 = Ffollowing_char ();
bf1de43e 1402 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1403 PUSH (v1);
1404 break;
1405 }
36f7ba0a
JB
1406
1407 case Bpreceding_char:
4015b3c0
GM
1408 {
1409 Lisp_Object v1;
bf1de43e 1410 BEFORE_POTENTIAL_GC ();
4015b3c0 1411 v1 = Fprevious_char ();
bf1de43e 1412 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1413 PUSH (v1);
1414 break;
1415 }
36f7ba0a
JB
1416
1417 case Bcurrent_column:
4015b3c0
GM
1418 {
1419 Lisp_Object v1;
96111f48 1420 BEFORE_POTENTIAL_GC ();
7831777b 1421 XSETFASTINT (v1, current_column ());
96111f48 1422 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1423 PUSH (v1);
1424 break;
1425 }
36f7ba0a
JB
1426
1427 case Bindent_to:
4015b3c0 1428 BEFORE_POTENTIAL_GC ();
36f7ba0a 1429 TOP = Findent_to (TOP, Qnil);
4015b3c0 1430 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1431 break;
1432
1433 case Beolp:
1434 PUSH (Feolp ());
1435 break;
1436
1437 case Beobp:
1438 PUSH (Feobp ());
1439 break;
1440
1441 case Bbolp:
1442 PUSH (Fbolp ());
1443 break;
1444
1445 case Bbobp:
1446 PUSH (Fbobp ());
1447 break;
1448
1449 case Bcurrent_buffer:
1450 PUSH (Fcurrent_buffer ());
1451 break;
1452
1453 case Bset_buffer:
4015b3c0 1454 BEFORE_POTENTIAL_GC ();
36f7ba0a 1455 TOP = Fset_buffer (TOP);
4015b3c0 1456 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1457 break;
1458
7200d79c 1459 case Binteractive_p: /* Obsolete since 24.1. */
36f7ba0a
JB
1460 PUSH (Finteractive_p ());
1461 break;
1462
1463 case Bforward_char:
4015b3c0 1464 BEFORE_POTENTIAL_GC ();
36f7ba0a 1465 TOP = Fforward_char (TOP);
4015b3c0 1466 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1467 break;
1468
1469 case Bforward_word:
4015b3c0 1470 BEFORE_POTENTIAL_GC ();
36f7ba0a 1471 TOP = Fforward_word (TOP);
4015b3c0 1472 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1473 break;
1474
1475 case Bskip_chars_forward:
4015b3c0
GM
1476 {
1477 Lisp_Object v1;
4015b3c0 1478 BEFORE_POTENTIAL_GC ();
bf1de43e 1479 v1 = POP;
4015b3c0
GM
1480 TOP = Fskip_chars_forward (TOP, v1);
1481 AFTER_POTENTIAL_GC ();
1482 break;
1483 }
36f7ba0a
JB
1484
1485 case Bskip_chars_backward:
4015b3c0
GM
1486 {
1487 Lisp_Object v1;
4015b3c0 1488 BEFORE_POTENTIAL_GC ();
bf1de43e 1489 v1 = POP;
4015b3c0
GM
1490 TOP = Fskip_chars_backward (TOP, v1);
1491 AFTER_POTENTIAL_GC ();
1492 break;
1493 }
36f7ba0a
JB
1494
1495 case Bforward_line:
4015b3c0 1496 BEFORE_POTENTIAL_GC ();
36f7ba0a 1497 TOP = Fforward_line (TOP);
4015b3c0 1498 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1499 break;
1500
1501 case Bchar_syntax:
9281d077
KH
1502 {
1503 int c;
1504
1505 BEFORE_POTENTIAL_GC ();
1506 CHECK_CHARACTER (TOP);
1507 AFTER_POTENTIAL_GC ();
1508 c = XFASTINT (TOP);
4b4deea2 1509 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
9281d077
KH
1510 MAKE_CHAR_MULTIBYTE (c);
1511 XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (c)]);
8f924df7 1512 }
36f7ba0a
JB
1513 break;
1514
1515 case Bbuffer_substring:
4015b3c0
GM
1516 {
1517 Lisp_Object v1;
4015b3c0 1518 BEFORE_POTENTIAL_GC ();
bf1de43e 1519 v1 = POP;
4015b3c0
GM
1520 TOP = Fbuffer_substring (TOP, v1);
1521 AFTER_POTENTIAL_GC ();
1522 break;
1523 }
36f7ba0a
JB
1524
1525 case Bdelete_region:
4015b3c0
GM
1526 {
1527 Lisp_Object v1;
4015b3c0 1528 BEFORE_POTENTIAL_GC ();
bf1de43e 1529 v1 = POP;
4015b3c0
GM
1530 TOP = Fdelete_region (TOP, v1);
1531 AFTER_POTENTIAL_GC ();
1532 break;
1533 }
36f7ba0a
JB
1534
1535 case Bnarrow_to_region:
4015b3c0
GM
1536 {
1537 Lisp_Object v1;
4015b3c0 1538 BEFORE_POTENTIAL_GC ();
bf1de43e 1539 v1 = POP;
4015b3c0
GM
1540 TOP = Fnarrow_to_region (TOP, v1);
1541 AFTER_POTENTIAL_GC ();
1542 break;
1543 }
36f7ba0a
JB
1544
1545 case Bwiden:
4015b3c0 1546 BEFORE_POTENTIAL_GC ();
36f7ba0a 1547 PUSH (Fwiden ());
4015b3c0 1548 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1549 break;
1550
63639d44 1551 case Bend_of_line:
4015b3c0 1552 BEFORE_POTENTIAL_GC ();
63639d44 1553 TOP = Fend_of_line (TOP);
4015b3c0 1554 AFTER_POTENTIAL_GC ();
63639d44
JB
1555 break;
1556
1557 case Bset_marker:
4015b3c0
GM
1558 {
1559 Lisp_Object v1, v2;
bf1de43e 1560 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1561 v1 = POP;
1562 v2 = POP;
1563 TOP = Fset_marker (TOP, v2, v1);
bf1de43e 1564 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1565 break;
1566 }
63639d44
JB
1567
1568 case Bmatch_beginning:
bf1de43e 1569 BEFORE_POTENTIAL_GC ();
63639d44 1570 TOP = Fmatch_beginning (TOP);
bf1de43e 1571 AFTER_POTENTIAL_GC ();
63639d44
JB
1572 break;
1573
1574 case Bmatch_end:
bf1de43e 1575 BEFORE_POTENTIAL_GC ();
63639d44 1576 TOP = Fmatch_end (TOP);
bf1de43e 1577 AFTER_POTENTIAL_GC ();
63639d44
JB
1578 break;
1579
1580 case Bupcase:
bf1de43e 1581 BEFORE_POTENTIAL_GC ();
63639d44 1582 TOP = Fupcase (TOP);
bf1de43e 1583 AFTER_POTENTIAL_GC ();
63639d44
JB
1584 break;
1585
1586 case Bdowncase:
bf1de43e 1587 BEFORE_POTENTIAL_GC ();
63639d44 1588 TOP = Fdowncase (TOP);
bf1de43e 1589 AFTER_POTENTIAL_GC ();
63639d44
JB
1590 break;
1591
36f7ba0a 1592 case Bstringeqlsign:
4015b3c0
GM
1593 {
1594 Lisp_Object v1;
bf1de43e 1595 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1596 v1 = POP;
1597 TOP = Fstring_equal (TOP, v1);
bf1de43e 1598 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1599 break;
1600 }
36f7ba0a
JB
1601
1602 case Bstringlss:
4015b3c0
GM
1603 {
1604 Lisp_Object v1;
bf1de43e 1605 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1606 v1 = POP;
1607 TOP = Fstring_lessp (TOP, v1);
bf1de43e 1608 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1609 break;
1610 }
36f7ba0a
JB
1611
1612 case Bequal:
4015b3c0
GM
1613 {
1614 Lisp_Object v1;
1615 v1 = POP;
1616 TOP = Fequal (TOP, v1);
1617 break;
1618 }
36f7ba0a
JB
1619
1620 case Bnthcdr:
4015b3c0
GM
1621 {
1622 Lisp_Object v1;
bf1de43e 1623 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1624 v1 = POP;
1625 TOP = Fnthcdr (TOP, v1);
bf1de43e 1626 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1627 break;
1628 }
36f7ba0a
JB
1629
1630 case Belt:
4015b3c0
GM
1631 {
1632 Lisp_Object v1, v2;
1633 if (CONSP (TOP))
1634 {
1635 /* Exchange args and then do nth. */
bf1de43e 1636 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1637 v2 = POP;
1638 v1 = TOP;
b7826503 1639 CHECK_NUMBER (v2);
f5941bf8 1640 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1641 op = XINT (v2);
1642 immediate_quit = 1;
14c5155a
KS
1643 while (--op >= 0 && CONSP (v1))
1644 v1 = XCDR (v1);
4015b3c0 1645 immediate_quit = 0;
14c5155a 1646 TOP = CAR (v1);
4015b3c0
GM
1647 }
1648 else
1649 {
bf1de43e 1650 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1651 v1 = POP;
1652 TOP = Felt (TOP, v1);
bf1de43e 1653 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1654 }
1655 break;
1656 }
36f7ba0a
JB
1657
1658 case Bmember:
4015b3c0
GM
1659 {
1660 Lisp_Object v1;
bf1de43e 1661 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1662 v1 = POP;
1663 TOP = Fmember (TOP, v1);
bf1de43e 1664 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1665 break;
1666 }
36f7ba0a
JB
1667
1668 case Bassq:
4015b3c0
GM
1669 {
1670 Lisp_Object v1;
bf1de43e 1671 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1672 v1 = POP;
1673 TOP = Fassq (TOP, v1);
bf1de43e 1674 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1675 break;
1676 }
36f7ba0a
JB
1677
1678 case Bnreverse:
bf1de43e 1679 BEFORE_POTENTIAL_GC ();
36f7ba0a 1680 TOP = Fnreverse (TOP);
bf1de43e 1681 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1682 break;
1683
1684 case Bsetcar:
4015b3c0
GM
1685 {
1686 Lisp_Object v1;
bf1de43e 1687 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1688 v1 = POP;
1689 TOP = Fsetcar (TOP, v1);
bf1de43e 1690 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1691 break;
1692 }
36f7ba0a
JB
1693
1694 case Bsetcdr:
4015b3c0
GM
1695 {
1696 Lisp_Object v1;
bf1de43e 1697 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1698 v1 = POP;
1699 TOP = Fsetcdr (TOP, v1);
bf1de43e 1700 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1701 break;
1702 }
36f7ba0a
JB
1703
1704 case Bcar_safe:
4015b3c0
GM
1705 {
1706 Lisp_Object v1;
1707 v1 = TOP;
14c5155a 1708 TOP = CAR_SAFE (v1);
4015b3c0
GM
1709 break;
1710 }
36f7ba0a
JB
1711
1712 case Bcdr_safe:
4015b3c0
GM
1713 {
1714 Lisp_Object v1;
1715 v1 = TOP;
14c5155a 1716 TOP = CDR_SAFE (v1);
4015b3c0
GM
1717 break;
1718 }
36f7ba0a
JB
1719
1720 case Bnconc:
bf1de43e 1721 BEFORE_POTENTIAL_GC ();
63639d44 1722 DISCARD (1);
36f7ba0a 1723 TOP = Fnconc (2, &TOP);
bf1de43e 1724 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1725 break;
1726
1727 case Bnumberp:
63639d44 1728 TOP = (NUMBERP (TOP) ? Qt : Qnil);
36f7ba0a
JB
1729 break;
1730
1731 case Bintegerp:
617bd3f6 1732 TOP = INTEGERP (TOP) ? Qt : Qnil;
36f7ba0a
JB
1733 break;
1734
1735#ifdef BYTE_CODE_SAFE
1736 case Bset_mark:
f5941bf8 1737 BEFORE_POTENTIAL_GC ();
36f7ba0a 1738 error ("set-mark is an obsolete bytecode");
f5941bf8 1739 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1740 break;
1741 case Bscan_buffer:
f5941bf8 1742 BEFORE_POTENTIAL_GC ();
36f7ba0a 1743 error ("scan-buffer is an obsolete bytecode");
f5941bf8 1744 AFTER_POTENTIAL_GC ();
36f7ba0a 1745 break;
36f7ba0a
JB
1746#endif
1747
876c194c
SM
1748 case 0:
1749 /* Actually this is Bstack_ref with offset 0, but we use Bdup
1750 for that instead. */
1751 /* case Bstack_ref: */
1752 abort ();
1753
b9598260 1754 /* Handy byte-codes for lexical binding. */
b9598260
SM
1755 case Bstack_ref+1:
1756 case Bstack_ref+2:
1757 case Bstack_ref+3:
1758 case Bstack_ref+4:
1759 case Bstack_ref+5:
3e21b6a7
SM
1760 {
1761 Lisp_Object *ptr = top - (op - Bstack_ref);
1762 PUSH (*ptr);
1763 break;
1764 }
b9598260 1765 case Bstack_ref+6:
3e21b6a7
SM
1766 {
1767 Lisp_Object *ptr = top - (FETCH);
1768 PUSH (*ptr);
1769 break;
1770 }
b9598260 1771 case Bstack_ref+7:
3e21b6a7
SM
1772 {
1773 Lisp_Object *ptr = top - (FETCH2);
1774 PUSH (*ptr);
1775 break;
1776 }
1777 /* stack-set-0 = discard; stack-set-1 = discard-1-preserve-tos. */
b9598260 1778 case Bstack_set:
3e21b6a7
SM
1779 {
1780 Lisp_Object *ptr = top - (FETCH);
1781 *ptr = POP;
1782 break;
1783 }
b9598260 1784 case Bstack_set2:
3e21b6a7
SM
1785 {
1786 Lisp_Object *ptr = top - (FETCH2);
1787 *ptr = POP;
1788 break;
1789 }
b9598260
SM
1790 case BdiscardN:
1791 op = FETCH;
1792 if (op & 0x80)
1793 {
1794 op &= 0x7F;
1795 top[-op] = TOP;
1796 }
1797 DISCARD (op);
1798 break;
c96d71f7
RS
1799
1800 case 255:
36f7ba0a
JB
1801 default:
1802#ifdef BYTE_CODE_SAFE
1803 if (op < Bconstant)
f5941bf8 1804 {
cc94f3b2 1805 abort ();
f5941bf8 1806 }
36f7ba0a 1807 if ((op -= Bconstant) >= const_length)
f5941bf8 1808 {
cc94f3b2 1809 abort ();
f5941bf8 1810 }
36f7ba0a
JB
1811 PUSH (vectorp[op]);
1812#else
1813 PUSH (vectorp[op - Bconstant]);
1814#endif
1815 }
1816 }
1817
1818 exit:
7ca1e8b7
GM
1819
1820 byte_stack_list = byte_stack_list->next;
1821
36f7ba0a 1822 /* Binds and unbinds are supposed to be compiled balanced. */
aed13378 1823 if (SPECPDL_INDEX () != count)
36f7ba0a
JB
1824#ifdef BYTE_CODE_SAFE
1825 error ("binding stack not balanced (serious byte compiler bug)");
1826#else
1827 abort ();
1828#endif
8e11578b 1829
4015b3c0 1830 return result;
36f7ba0a
JB
1831}
1832
dfcf069d 1833void
971de7fb 1834syms_of_bytecode (void)
36f7ba0a 1835{
d67b4f80 1836 Qbytecode = intern_c_string ("byte-code");
36f7ba0a
JB
1837 staticpro (&Qbytecode);
1838
1839 defsubr (&Sbyte_code);
1840
1841#ifdef BYTE_CODE_METER
1842
29208e82 1843 DEFVAR_LISP ("byte-code-meter", Vbyte_code_meter,
39f624fa
PJ
1844 doc: /* A vector of vectors which holds a histogram of byte-code usage.
1845\(aref (aref byte-code-meter 0) CODE) indicates how many times the byte
1846opcode CODE has been executed.
1847\(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0,
1848indicates how many times the byte opcodes CODE1 and CODE2 have been
1849executed in succession. */);
8e11578b 1850
29208e82 1851 DEFVAR_BOOL ("byte-metering-on", byte_metering_on,
39f624fa
PJ
1852 doc: /* If non-nil, keep profiling information on byte code usage.
1853The variable byte-code-meter indicates how often each byte opcode is used.
1854If a symbol has a property named `byte-code-meter' whose value is an
1855integer, it is incremented each time that symbol's function is called. */);
36f7ba0a
JB
1856
1857 byte_metering_on = 0;
63639d44 1858 Vbyte_code_meter = Fmake_vector (make_number (256), make_number (0));
d67b4f80 1859 Qbyte_code_meter = intern_c_string ("byte-code-meter");
63639d44 1860 staticpro (&Qbyte_code_meter);
36f7ba0a
JB
1861 {
1862 int i = 256;
1863 while (i--)
63639d44
JB
1864 XVECTOR (Vbyte_code_meter)->contents[i] =
1865 Fmake_vector (make_number (256), make_number (0));
36f7ba0a
JB
1866 }
1867#endif
1868}