/
lread.c
4571 lines (3939 loc) · 128 KB
/
lread.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Lisp parsing and input streams.
Copyright (C) 1985-1989, 1993-1995, 1997-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <errno.h>
#include <limits.h> /* for CHAR_BIT */
#include <setjmp.h>
#include "lisp.h"
#include "intervals.h"
#include "buffer.h"
#include "character.h"
#include "charset.h"
#include "coding.h"
#include <epaths.h>
#include "commands.h"
#include "keyboard.h"
#include "frame.h"
#include "termhooks.h"
#include "coding.h"
#include "blockinput.h"
#ifdef MSDOS
#include "msdos.h"
#endif
#include <unistd.h>
#include <math.h>
#ifdef HAVE_SETLOCALE
#include <locale.h>
#endif /* HAVE_SETLOCALE */
#include <fcntl.h>
#ifdef HAVE_FSEEKO
#define file_offset off_t
#define file_tell ftello
#else
#define file_offset long
#define file_tell ftell
#endif
/* hash table read constants */
static Lisp_Object Qhash_table, Qdata;
static Lisp_Object Qtest, Qsize;
static Lisp_Object Qweakness;
static Lisp_Object Qrehash_size;
static Lisp_Object Qrehash_threshold;
static Lisp_Object Qread_char, Qget_file_char, Qcurrent_load_list;
Lisp_Object Qstandard_input;
Lisp_Object Qvariable_documentation;
static Lisp_Object Qascii_character, Qload, Qload_file_name;
Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
static Lisp_Object Qinhibit_file_name_operation;
static Lisp_Object Qeval_buffer_list;
static Lisp_Object Qlexical_binding;
static Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */
/* Used instead of Qget_file_char while loading *.elc files compiled
by Emacs 21 or older. */
static Lisp_Object Qget_emacs_mule_file_char;
static Lisp_Object Qload_force_doc_strings;
extern Lisp_Object Qinternal_interpreter_environment;
static Lisp_Object Qload_in_progress;
/* The association list of objects read with the #n=object form.
Each member of the list has the form (n . object), and is used to
look up the object for the corresponding #n# construct.
It must be set to nil before all top-level calls to read0. */
static Lisp_Object read_objects;
/* Nonzero means READCHAR should read bytes one by one (not character)
when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char.
This is set to 1 by read1 temporarily while handling #@NUMBER. */
static int load_each_byte;
/* List of descriptors now open for Fload. */
static Lisp_Object load_descriptor_list;
/* File for get_file_char to read from. Use by load. */
static FILE *instream;
/* When nonzero, read conses in pure space */
static int read_pure;
/* For use within read-from-string (this reader is non-reentrant!!) */
static EMACS_INT read_from_string_index;
static EMACS_INT read_from_string_index_byte;
static EMACS_INT read_from_string_limit;
/* Number of characters read in the current call to Fread or
Fread_from_string. */
static EMACS_INT readchar_count;
/* This contains the last string skipped with #@. */
static char *saved_doc_string;
/* Length of buffer allocated in saved_doc_string. */
static ptrdiff_t saved_doc_string_size;
/* Length of actual data in saved_doc_string. */
static ptrdiff_t saved_doc_string_length;
/* This is the file position that string came from. */
static file_offset saved_doc_string_position;
/* This contains the previous string skipped with #@.
We copy it from saved_doc_string when a new string
is put in saved_doc_string. */
static char *prev_saved_doc_string;
/* Length of buffer allocated in prev_saved_doc_string. */
static ptrdiff_t prev_saved_doc_string_size;
/* Length of actual data in prev_saved_doc_string. */
static ptrdiff_t prev_saved_doc_string_length;
/* This is the file position that string came from. */
static file_offset prev_saved_doc_string_position;
/* Nonzero means inside a new-style backquote
with no surrounding parentheses.
Fread initializes this to zero, so we need not specbind it
or worry about what happens to it when there is an error. */
static int new_backquote_flag;
static Lisp_Object Qold_style_backquotes;
/* A list of file names for files being loaded in Fload. Used to
check for recursive loads. */
static Lisp_Object Vloads_in_progress;
static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
Lisp_Object);
static void readevalloop (Lisp_Object, FILE*, Lisp_Object, int,
Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
static Lisp_Object load_unwind (Lisp_Object);
static Lisp_Object load_descriptor_unwind (Lisp_Object);
static void invalid_syntax (const char *) NO_RETURN;
static void end_of_file_error (void) NO_RETURN;
/* Functions that read one byte from the current source READCHARFUN
or unreads one byte. If the integer argument C is -1, it returns
one read byte, or -1 when there's no more byte in the source. If C
is 0 or positive, it unreads C, and the return value is not
interesting. */
static int readbyte_for_lambda (int, Lisp_Object);
static int readbyte_from_file (int, Lisp_Object);
static int readbyte_from_string (int, Lisp_Object);
/* Handle unreading and rereading of characters.
Write READCHAR to read a character,
UNREAD(c) to unread c to be read again.
These macros correctly read/unread multibyte characters. */
#define READCHAR readchar (readcharfun, NULL)
#define UNREAD(c) unreadchar (readcharfun, c)
/* Same as READCHAR but set *MULTIBYTE to the multibyteness of the source. */
#define READCHAR_REPORT_MULTIBYTE(multibyte) readchar (readcharfun, multibyte)
/* When READCHARFUN is Qget_file_char, Qget_emacs_mule_file_char,
Qlambda, or a cons, we use this to keep an unread character because
a file stream can't handle multibyte-char unreading. The value -1
means that there's no unread character. */
static int unread_char;
static int
readchar (Lisp_Object readcharfun, int *multibyte)
{
Lisp_Object tem;
register int c;
int (*readbyte) (int, Lisp_Object);
unsigned char buf[MAX_MULTIBYTE_LENGTH];
int i, len;
int emacs_mule_encoding = 0;
if (multibyte)
*multibyte = 0;
readchar_count++;
if (BUFFERP (readcharfun))
{
register struct buffer *inbuffer = XBUFFER (readcharfun);
EMACS_INT pt_byte = BUF_PT_BYTE (inbuffer);
if (pt_byte >= BUF_ZV_BYTE (inbuffer))
return -1;
if (! NILP (BVAR (inbuffer, enable_multibyte_characters)))
{
/* Fetch the character code from the buffer. */
unsigned char *p = BUF_BYTE_ADDRESS (inbuffer, pt_byte);
BUF_INC_POS (inbuffer, pt_byte);
c = STRING_CHAR (p);
if (multibyte)
*multibyte = 1;
}
else
{
c = BUF_FETCH_BYTE (inbuffer, pt_byte);
if (! ASCII_BYTE_P (c))
c = BYTE8_TO_CHAR (c);
pt_byte++;
}
SET_BUF_PT_BOTH (inbuffer, BUF_PT (inbuffer) + 1, pt_byte);
return c;
}
if (MARKERP (readcharfun))
{
register struct buffer *inbuffer = XMARKER (readcharfun)->buffer;
EMACS_INT bytepos = marker_byte_position (readcharfun);
if (bytepos >= BUF_ZV_BYTE (inbuffer))
return -1;
if (! NILP (BVAR (inbuffer, enable_multibyte_characters)))
{
/* Fetch the character code from the buffer. */
unsigned char *p = BUF_BYTE_ADDRESS (inbuffer, bytepos);
BUF_INC_POS (inbuffer, bytepos);
c = STRING_CHAR (p);
if (multibyte)
*multibyte = 1;
}
else
{
c = BUF_FETCH_BYTE (inbuffer, bytepos);
if (! ASCII_BYTE_P (c))
c = BYTE8_TO_CHAR (c);
bytepos++;
}
XMARKER (readcharfun)->bytepos = bytepos;
XMARKER (readcharfun)->charpos++;
return c;
}
if (EQ (readcharfun, Qlambda))
{
readbyte = readbyte_for_lambda;
goto read_multibyte;
}
if (EQ (readcharfun, Qget_file_char))
{
readbyte = readbyte_from_file;
goto read_multibyte;
}
if (STRINGP (readcharfun))
{
if (read_from_string_index >= read_from_string_limit)
c = -1;
else if (STRING_MULTIBYTE (readcharfun))
{
if (multibyte)
*multibyte = 1;
FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, readcharfun,
read_from_string_index,
read_from_string_index_byte);
}
else
{
c = SREF (readcharfun, read_from_string_index_byte);
read_from_string_index++;
read_from_string_index_byte++;
}
return c;
}
if (CONSP (readcharfun))
{
/* This is the case that read_vector is reading from a unibyte
string that contains a byte sequence previously skipped
because of #@NUMBER. The car part of readcharfun is that
string, and the cdr part is a value of readcharfun given to
read_vector. */
readbyte = readbyte_from_string;
if (EQ (XCDR (readcharfun), Qget_emacs_mule_file_char))
emacs_mule_encoding = 1;
goto read_multibyte;
}
if (EQ (readcharfun, Qget_emacs_mule_file_char))
{
readbyte = readbyte_from_file;
emacs_mule_encoding = 1;
goto read_multibyte;
}
tem = call0 (readcharfun);
if (NILP (tem))
return -1;
return XINT (tem);
read_multibyte:
if (unread_char >= 0)
{
c = unread_char;
unread_char = -1;
return c;
}
c = (*readbyte) (-1, readcharfun);
if (c < 0 || load_each_byte)
return c;
if (multibyte)
*multibyte = 1;
if (ASCII_BYTE_P (c))
return c;
if (emacs_mule_encoding)
return read_emacs_mule_char (c, readbyte, readcharfun);
i = 0;
buf[i++] = c;
len = BYTES_BY_CHAR_HEAD (c);
while (i < len)
{
c = (*readbyte) (-1, readcharfun);
if (c < 0 || ! TRAILING_CODE_P (c))
{
while (--i > 1)
(*readbyte) (buf[i], readcharfun);
return BYTE8_TO_CHAR (buf[0]);
}
buf[i++] = c;
}
return STRING_CHAR (buf);
}
/* Unread the character C in the way appropriate for the stream READCHARFUN.
If the stream is a user function, call it with the char as argument. */
static void
unreadchar (Lisp_Object readcharfun, int c)
{
readchar_count--;
if (c == -1)
/* Don't back up the pointer if we're unreading the end-of-input mark,
since readchar didn't advance it when we read it. */
;
else if (BUFFERP (readcharfun))
{
struct buffer *b = XBUFFER (readcharfun);
EMACS_INT charpos = BUF_PT (b);
EMACS_INT bytepos = BUF_PT_BYTE (b);
if (! NILP (BVAR (b, enable_multibyte_characters)))
BUF_DEC_POS (b, bytepos);
else
bytepos--;
SET_BUF_PT_BOTH (b, charpos - 1, bytepos);
}
else if (MARKERP (readcharfun))
{
struct buffer *b = XMARKER (readcharfun)->buffer;
EMACS_INT bytepos = XMARKER (readcharfun)->bytepos;
XMARKER (readcharfun)->charpos--;
if (! NILP (BVAR (b, enable_multibyte_characters)))
BUF_DEC_POS (b, bytepos);
else
bytepos--;
XMARKER (readcharfun)->bytepos = bytepos;
}
else if (STRINGP (readcharfun))
{
read_from_string_index--;
read_from_string_index_byte
= string_char_to_byte (readcharfun, read_from_string_index);
}
else if (CONSP (readcharfun))
{
unread_char = c;
}
else if (EQ (readcharfun, Qlambda))
{
unread_char = c;
}
else if (EQ (readcharfun, Qget_file_char)
|| EQ (readcharfun, Qget_emacs_mule_file_char))
{
if (load_each_byte)
{
BLOCK_INPUT;
ungetc (c, instream);
UNBLOCK_INPUT;
}
else
unread_char = c;
}
else
call1 (readcharfun, make_number (c));
}
static int
readbyte_for_lambda (int c, Lisp_Object readcharfun)
{
return read_bytecode_char (c >= 0);
}
static int
readbyte_from_file (int c, Lisp_Object readcharfun)
{
if (c >= 0)
{
BLOCK_INPUT;
ungetc (c, instream);
UNBLOCK_INPUT;
return 0;
}
BLOCK_INPUT;
c = getc (instream);
#ifdef EINTR
/* Interrupted reads have been observed while reading over the network */
while (c == EOF && ferror (instream) && errno == EINTR)
{
UNBLOCK_INPUT;
QUIT;
BLOCK_INPUT;
clearerr (instream);
c = getc (instream);
}
#endif
UNBLOCK_INPUT;
return (c == EOF ? -1 : c);
}
static int
readbyte_from_string (int c, Lisp_Object readcharfun)
{
Lisp_Object string = XCAR (readcharfun);
if (c >= 0)
{
read_from_string_index--;
read_from_string_index_byte
= string_char_to_byte (string, read_from_string_index);
}
if (read_from_string_index >= read_from_string_limit)
c = -1;
else
FETCH_STRING_CHAR_ADVANCE (c, string,
read_from_string_index,
read_from_string_index_byte);
return c;
}
/* Read one non-ASCII character from INSTREAM. The character is
encoded in `emacs-mule' and the first byte is already read in
C. */
static int
read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object readcharfun)
{
/* Emacs-mule coding uses at most 4-byte for one character. */
unsigned char buf[4];
int len = emacs_mule_bytes[c];
struct charset *charset;
int i;
unsigned code;
if (len == 1)
/* C is not a valid leading-code of `emacs-mule'. */
return BYTE8_TO_CHAR (c);
i = 0;
buf[i++] = c;
while (i < len)
{
c = (*readbyte) (-1, readcharfun);
if (c < 0xA0)
{
while (--i > 1)
(*readbyte) (buf[i], readcharfun);
return BYTE8_TO_CHAR (buf[0]);
}
buf[i++] = c;
}
if (len == 2)
{
charset = CHARSET_FROM_ID (emacs_mule_charset[buf[0]]);
code = buf[1] & 0x7F;
}
else if (len == 3)
{
if (buf[0] == EMACS_MULE_LEADING_CODE_PRIVATE_11
|| buf[0] == EMACS_MULE_LEADING_CODE_PRIVATE_12)
{
charset = CHARSET_FROM_ID (emacs_mule_charset[buf[1]]);
code = buf[2] & 0x7F;
}
else
{
charset = CHARSET_FROM_ID (emacs_mule_charset[buf[0]]);
code = ((buf[1] << 8) | buf[2]) & 0x7F7F;
}
}
else
{
charset = CHARSET_FROM_ID (emacs_mule_charset[buf[1]]);
code = ((buf[2] << 8) | buf[3]) & 0x7F7F;
}
c = DECODE_CHAR (charset, code);
if (c < 0)
Fsignal (Qinvalid_read_syntax,
Fcons (build_string ("invalid multibyte form"), Qnil));
return c;
}
static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object,
Lisp_Object);
static Lisp_Object read0 (Lisp_Object);
static Lisp_Object read1 (Lisp_Object, int *, int);
static Lisp_Object read_list (int, Lisp_Object);
static Lisp_Object read_vector (Lisp_Object, int);
static Lisp_Object substitute_object_recurse (Lisp_Object, Lisp_Object,
Lisp_Object);
static void substitute_object_in_subtree (Lisp_Object,
Lisp_Object);
static void substitute_in_interval (INTERVAL, Lisp_Object);
/* Get a character from the tty. */
/* Read input events until we get one that's acceptable for our purposes.
If NO_SWITCH_FRAME is non-zero, switch-frame events are stashed
until we get a character we like, and then stuffed into
unread_switch_frame.
If ASCII_REQUIRED is non-zero, we check function key events to see
if the unmodified version of the symbol has a Qascii_character
property, and use that character, if present.
If ERROR_NONASCII is non-zero, we signal an error if the input we
get isn't an ASCII character with modifiers. If it's zero but
ASCII_REQUIRED is non-zero, we just re-read until we get an ASCII
character.
If INPUT_METHOD is nonzero, we invoke the current input method
if the character warrants that.
If SECONDS is a number, we wait that many seconds for input, and
return Qnil if no input arrives within that time. */
static Lisp_Object
read_filtered_event (int no_switch_frame, int ascii_required,
int error_nonascii, int input_method, Lisp_Object seconds)
{
Lisp_Object val, delayed_switch_frame;
EMACS_TIME end_time;
#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
cancel_hourglass ();
#endif
delayed_switch_frame = Qnil;
/* Compute timeout. */
if (NUMBERP (seconds))
{
EMACS_TIME wait_time;
int sec, usec;
double duration = extract_float (seconds);
sec = (int) duration;
usec = (duration - sec) * 1000000;
EMACS_GET_TIME (end_time);
EMACS_SET_SECS_USECS (wait_time, sec, usec);
EMACS_ADD_TIME (end_time, end_time, wait_time);
}
/* Read until we get an acceptable event. */
retry:
do
val = read_char (0, 0, 0, (input_method ? Qnil : Qt), 0,
NUMBERP (seconds) ? &end_time : NULL);
while (INTEGERP (val) && XINT (val) == -2); /* wrong_kboard_jmpbuf */
if (BUFFERP (val))
goto retry;
/* switch-frame events are put off until after the next ASCII
character. This is better than signaling an error just because
the last characters were typed to a separate minibuffer frame,
for example. Eventually, some code which can deal with
switch-frame events will read it and process it. */
if (no_switch_frame
&& EVENT_HAS_PARAMETERS (val)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (val)), Qswitch_frame))
{
delayed_switch_frame = val;
goto retry;
}
if (ascii_required && !(NUMBERP (seconds) && NILP (val)))
{
/* Convert certain symbols to their ASCII equivalents. */
if (SYMBOLP (val))
{
Lisp_Object tem, tem1;
tem = Fget (val, Qevent_symbol_element_mask);
if (!NILP (tem))
{
tem1 = Fget (Fcar (tem), Qascii_character);
/* Merge this symbol's modifier bits
with the ASCII equivalent of its basic code. */
if (!NILP (tem1))
XSETFASTINT (val, XINT (tem1) | XINT (Fcar (Fcdr (tem))));
}
}
/* If we don't have a character now, deal with it appropriately. */
if (!INTEGERP (val))
{
if (error_nonascii)
{
Vunread_command_events = Fcons (val, Qnil);
error ("Non-character input-event");
}
else
goto retry;
}
}
if (! NILP (delayed_switch_frame))
unread_switch_frame = delayed_switch_frame;
#if 0
#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
start_hourglass ();
#endif
#endif
return val;
}
DEFUN ("read-char", Fread_char, Sread_char, 0, 3, 0,
doc: /* Read a character from the command input (keyboard or macro).
It is returned as a number.
If the character has modifiers, they are resolved and reflected to the
character code if possible (e.g. C-SPC -> 0).
If the user generates an event which is not a character (i.e. a mouse
click or function key event), `read-char' signals an error. As an
exception, switch-frame events are put off until non-character events
can be read.
If you want to read non-character events, or ignore them, call
`read-event' or `read-char-exclusive' instead.
If the optional argument PROMPT is non-nil, display that as a prompt.
If the optional argument INHERIT-INPUT-METHOD is non-nil and some
input method is turned on in the current buffer, that input method
is used for reading a character.
If the optional argument SECONDS is non-nil, it should be a number
specifying the maximum number of seconds to wait for input. If no
input arrives in that time, return nil. SECONDS may be a
floating-point value. */)
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
{
Lisp_Object val;
if (! NILP (prompt))
message_with_string ("%s", prompt, 0);
val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds);
return (NILP (val) ? Qnil
: make_number (char_resolve_modifier_mask (XINT (val))));
}
DEFUN ("read-event", Fread_event, Sread_event, 0, 3, 0,
doc: /* Read an event object from the input stream.
If the optional argument PROMPT is non-nil, display that as a prompt.
If the optional argument INHERIT-INPUT-METHOD is non-nil and some
input method is turned on in the current buffer, that input method
is used for reading a character.
If the optional argument SECONDS is non-nil, it should be a number
specifying the maximum number of seconds to wait for input. If no
input arrives in that time, return nil. SECONDS may be a
floating-point value. */)
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
{
if (! NILP (prompt))
message_with_string ("%s", prompt, 0);
return read_filtered_event (0, 0, 0, ! NILP (inherit_input_method), seconds);
}
DEFUN ("read-char-exclusive", Fread_char_exclusive, Sread_char_exclusive, 0, 3, 0,
doc: /* Read a character from the command input (keyboard or macro).
It is returned as a number. Non-character events are ignored.
If the character has modifiers, they are resolved and reflected to the
character code if possible (e.g. C-SPC -> 0).
If the optional argument PROMPT is non-nil, display that as a prompt.
If the optional argument INHERIT-INPUT-METHOD is non-nil and some
input method is turned on in the current buffer, that input method
is used for reading a character.
If the optional argument SECONDS is non-nil, it should be a number
specifying the maximum number of seconds to wait for input. If no
input arrives in that time, return nil. SECONDS may be a
floating-point value. */)
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
{
Lisp_Object val;
if (! NILP (prompt))
message_with_string ("%s", prompt, 0);
val = read_filtered_event (1, 1, 0, ! NILP (inherit_input_method), seconds);
return (NILP (val) ? Qnil
: make_number (char_resolve_modifier_mask (XINT (val))));
}
DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
doc: /* Don't use this yourself. */)
(void)
{
register Lisp_Object val;
BLOCK_INPUT;
XSETINT (val, getc (instream));
UNBLOCK_INPUT;
return val;
}
/* Return true if the lisp code read using READCHARFUN defines a non-nil
`lexical-binding' file variable. After returning, the stream is
positioned following the first line, if it is a comment, otherwise
nothing is read. */
static int
lisp_file_lexically_bound_p (Lisp_Object readcharfun)
{
int ch = READCHAR;
if (ch != ';')
/* The first line isn't a comment, just give up. */
{
UNREAD (ch);
return 0;
}
else
/* Look for an appropriate file-variable in the first line. */
{
int rv = 0;
enum {
NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX,
} beg_end_state = NOMINAL;
int in_file_vars = 0;
#define UPDATE_BEG_END_STATE(ch) \
if (beg_end_state == NOMINAL) \
beg_end_state = (ch == '-' ? AFTER_FIRST_DASH : NOMINAL); \
else if (beg_end_state == AFTER_FIRST_DASH) \
beg_end_state = (ch == '*' ? AFTER_ASTERIX : NOMINAL); \
else if (beg_end_state == AFTER_ASTERIX) \
{ \
if (ch == '-') \
in_file_vars = !in_file_vars; \
beg_end_state = NOMINAL; \
}
/* Skip until we get to the file vars, if any. */
do
{
ch = READCHAR;
UPDATE_BEG_END_STATE (ch);
}
while (!in_file_vars && ch != '\n' && ch != EOF);
while (in_file_vars)
{
char var[100], val[100];
unsigned i;
ch = READCHAR;
/* Read a variable name. */
while (ch == ' ' || ch == '\t')
ch = READCHAR;
i = 0;
while (ch != ':' && ch != '\n' && ch != EOF && in_file_vars)
{
if (i < sizeof var - 1)
var[i++] = ch;
UPDATE_BEG_END_STATE (ch);
ch = READCHAR;
}
/* Stop scanning if no colon was found before end marker. */
if (!in_file_vars)
break;
while (i > 0 && (var[i - 1] == ' ' || var[i - 1] == '\t'))
i--;
var[i] = '\0';
if (ch == ':')
{
/* Read a variable value. */
ch = READCHAR;
while (ch == ' ' || ch == '\t')
ch = READCHAR;
i = 0;
while (ch != ';' && ch != '\n' && ch != EOF && in_file_vars)
{
if (i < sizeof val - 1)
val[i++] = ch;
UPDATE_BEG_END_STATE (ch);
ch = READCHAR;
}
if (! in_file_vars)
/* The value was terminated by an end-marker, which
remove. */
i -= 3;
while (i > 0 && (val[i - 1] == ' ' || val[i - 1] == '\t'))
i--;
val[i] = '\0';
if (strcmp (var, "lexical-binding") == 0)
/* This is it... */
{
rv = (strcmp (val, "nil") != 0);
break;
}
}
}
while (ch != '\n' && ch != EOF)
ch = READCHAR;
return rv;
}
}
/* Value is a version number of byte compiled code if the file
associated with file descriptor FD is a compiled Lisp file that's
safe to load. Only files compiled with Emacs are safe to load.
Files compiled with XEmacs can lead to a crash in Fbyte_code
because of an incompatible change in the byte compiler. */
static int
safe_to_load_p (int fd)
{
char buf[512];
int nbytes, i;
int safe_p = 1;
int version = 1;
/* Read the first few bytes from the file, and look for a line
specifying the byte compiler version used. */
nbytes = emacs_read (fd, buf, sizeof buf - 1);
if (nbytes > 0)
{
buf[nbytes] = '\0';
/* Skip to the next newline, skipping over the initial `ELC'
with NUL bytes following it, but note the version. */
for (i = 0; i < nbytes && buf[i] != '\n'; ++i)
if (i == 4)
version = buf[i];
if (i >= nbytes
|| fast_c_string_match_ignore_case (Vbytecomp_version_regexp,
buf + i) < 0)
safe_p = 0;
}
if (safe_p)
safe_p = version;
lseek (fd, 0, SEEK_SET);
return safe_p;
}
/* Callback for record_unwind_protect. Restore the old load list OLD,
after loading a file successfully. */
static Lisp_Object
record_load_unwind (Lisp_Object old)
{
return Vloads_in_progress = old;
}
/* This handler function is used via internal_condition_case_1. */
static Lisp_Object
load_error_handler (Lisp_Object data)
{
return Qnil;
}
static Lisp_Object
load_warn_old_style_backquotes (Lisp_Object file)
{
if (!NILP (Vold_style_backquotes))
{
Lisp_Object args[2];
args[0] = build_string ("Loading `%s': old-style backquotes detected!");
args[1] = file;
Fmessage (2, args);
}
return Qnil;
}
DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0,
doc: /* Return the suffixes that `load' should try if a suffix is \
required.
This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */)
(void)
{
Lisp_Object lst = Qnil, suffixes = Vload_suffixes, suffix, ext;
while (CONSP (suffixes))
{
Lisp_Object exts = Vload_file_rep_suffixes;
suffix = XCAR (suffixes);
suffixes = XCDR (suffixes);
while (CONSP (exts))
{
ext = XCAR (exts);
exts = XCDR (exts);
lst = Fcons (concat2 (suffix, ext), lst);
}
}
return Fnreverse (lst);
}
DEFUN ("load", Fload, Sload, 1, 5, 0,
doc: /* Execute a file of Lisp code named FILE.
First try FILE with `.elc' appended, then try with `.el',
then try FILE unmodified (the exact suffixes in the exact order are
determined by `load-suffixes'). Environment variable references in
FILE are replaced with their values by calling `substitute-in-file-name'.
This function searches the directories in `load-path'.
If optional second arg NOERROR is non-nil,
report no error if FILE doesn't exist.
Print messages at start and end of loading unless
optional third arg NOMESSAGE is non-nil (but `force-load-messages'
overrides that).
If optional fourth arg NOSUFFIX is non-nil, don't try adding
suffixes `.elc' or `.el' to the specified name FILE.
If optional fifth arg MUST-SUFFIX is non-nil, insist on
the suffix `.elc' or `.el'; don't accept just FILE unless
it ends in one of those suffixes or includes a directory name.
If this function fails to find a file, it may look for different