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