Mercurial > emacs
annotate src/lread.c @ 1016:817b0ce337d7
* window.c (Fset_window_configuration): Removed #if 0'd code which
assumes that minibuf_window is on the same frame as the window
configuration. Removed special case for windows whose prevs
point to themselves.
* window.c (Fset_window_configuration): Rename the argument from
ARG to CONFIGURATION, so it matches the docstring. The
make-docfile program cares.
* window.c [MULTI_FRAME] (syms_of_window): Don't staticpro
minibuf_window; the frame list will take care of it.
* window.c (window_loop): This used to keep track of the first
window processed and wait until we came back around to it. Sadly,
this doesn't work if that window gets deleted. So instead, use
Fprevious_window to find the last window to process, and loop
until we've done that one.
* window.c [not MULTI_FRAME] (init_window_once): Don't forget to
set the `mini_p' flag on the new minibuffer window to t.
* window.c (Fwindow_at): Don't check the type of the frame
argument.
* window.c [not MULTI_FRAME] (window_loop): Set frame to zero,
instead of trying to decode it.
* window.c (init_window_once): Initialize minibuf_window before
FRAME_ROOT_WINDOW, so the latter actually points to something.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Wed, 19 Aug 1992 06:40:02 +0000 |
parents | bf78b5ea9b3a |
children | c2259db856ee |
rev | line source |
---|---|
341 | 1 /* Lisp parsing and input streams. |
692 | 2 Copyright (C) 1985, 1986, 1987, 1988, 1989, |
3 1992 Free Software Foundation, Inc. | |
341 | 4 |
5 This file is part of GNU Emacs. | |
6 | |
7 GNU Emacs is free software; you can redistribute it and/or modify | |
8 it under the terms of the GNU General Public License as published by | |
617 | 9 the Free Software Foundation; either version 2, or (at your option) |
341 | 10 any later version. |
11 | |
12 GNU Emacs is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GNU Emacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | |
21 | |
22 #include <stdio.h> | |
23 #include <sys/types.h> | |
24 #include <sys/stat.h> | |
25 #include <sys/file.h> | |
796 | 26 #include <ctype.h> |
341 | 27 #undef NULL |
28 #include "config.h" | |
29 #include "lisp.h" | |
30 | |
31 #ifndef standalone | |
32 #include "buffer.h" | |
33 #include "paths.h" | |
34 #include "commands.h" | |
35 #endif | |
36 | |
37 #ifdef lint | |
38 #include <sys/inode.h> | |
39 #endif /* lint */ | |
40 | |
41 #ifndef X_OK | |
42 #define X_OK 01 | |
43 #endif | |
44 | |
45 #ifdef LISP_FLOAT_TYPE | |
46 #include <math.h> | |
47 #endif /* LISP_FLOAT_TYPE */ | |
48 | |
49 Lisp_Object Qread_char, Qget_file_char, Qstandard_input; | |
50 Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist; | |
51 | |
52 /* non-zero if inside `load' */ | |
53 int load_in_progress; | |
54 | |
55 /* Search path for files to be loaded. */ | |
56 Lisp_Object Vload_path; | |
57 | |
58 /* File for get_file_char to read from. Use by load */ | |
59 static FILE *instream; | |
60 | |
61 /* When nonzero, read conses in pure space */ | |
62 static int read_pure; | |
63 | |
64 /* For use within read-from-string (this reader is non-reentrant!!) */ | |
65 static int read_from_string_index; | |
66 static int read_from_string_limit; | |
67 | |
68 /* Handle unreading and rereading of characters. | |
69 Write READCHAR to read a character, | |
70 UNREAD(c) to unread c to be read again. */ | |
71 | |
72 #define READCHAR readchar (readcharfun) | |
73 #define UNREAD(c) unreadchar (readcharfun, c) | |
74 | |
75 static int | |
76 readchar (readcharfun) | |
77 Lisp_Object readcharfun; | |
78 { | |
79 Lisp_Object tem; | |
80 register struct buffer *inbuffer; | |
81 register int c, mpos; | |
82 | |
83 if (XTYPE (readcharfun) == Lisp_Buffer) | |
84 { | |
85 inbuffer = XBUFFER (readcharfun); | |
86 | |
87 if (BUF_PT (inbuffer) >= BUF_ZV (inbuffer)) | |
88 return -1; | |
89 c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, BUF_PT (inbuffer)); | |
90 SET_BUF_PT (inbuffer, BUF_PT (inbuffer) + 1); | |
91 | |
92 return c; | |
93 } | |
94 if (XTYPE (readcharfun) == Lisp_Marker) | |
95 { | |
96 inbuffer = XMARKER (readcharfun)->buffer; | |
97 | |
98 mpos = marker_position (readcharfun); | |
99 | |
100 if (mpos > BUF_ZV (inbuffer) - 1) | |
101 return -1; | |
102 c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, mpos); | |
103 if (mpos != BUF_GPT (inbuffer)) | |
104 XMARKER (readcharfun)->bufpos++; | |
105 else | |
106 Fset_marker (readcharfun, make_number (mpos + 1), | |
107 Fmarker_buffer (readcharfun)); | |
108 return c; | |
109 } | |
110 if (EQ (readcharfun, Qget_file_char)) | |
111 return getc (instream); | |
112 | |
113 if (XTYPE (readcharfun) == Lisp_String) | |
114 { | |
115 register int c; | |
116 /* This used to be return of a conditional expression, | |
117 but that truncated -1 to a char on VMS. */ | |
118 if (read_from_string_index < read_from_string_limit) | |
119 c = XSTRING (readcharfun)->data[read_from_string_index++]; | |
120 else | |
121 c = -1; | |
122 return c; | |
123 } | |
124 | |
125 tem = call0 (readcharfun); | |
126 | |
485 | 127 if (NILP (tem)) |
341 | 128 return -1; |
129 return XINT (tem); | |
130 } | |
131 | |
132 /* Unread the character C in the way appropriate for the stream READCHARFUN. | |
133 If the stream is a user function, call it with the char as argument. */ | |
134 | |
135 static void | |
136 unreadchar (readcharfun, c) | |
137 Lisp_Object readcharfun; | |
138 int c; | |
139 { | |
140 if (XTYPE (readcharfun) == Lisp_Buffer) | |
141 { | |
142 if (XBUFFER (readcharfun) == current_buffer) | |
143 SET_PT (point - 1); | |
144 else | |
145 SET_BUF_PT (XBUFFER (readcharfun), BUF_PT (XBUFFER (readcharfun)) - 1); | |
146 } | |
147 else if (XTYPE (readcharfun) == Lisp_Marker) | |
148 XMARKER (readcharfun)->bufpos--; | |
149 else if (XTYPE (readcharfun) == Lisp_String) | |
150 read_from_string_index--; | |
151 else if (EQ (readcharfun, Qget_file_char)) | |
152 ungetc (c, instream); | |
153 else | |
154 call1 (readcharfun, make_number (c)); | |
155 } | |
156 | |
157 static Lisp_Object read0 (), read1 (), read_list (), read_vector (); | |
158 | |
159 /* get a character from the tty */ | |
160 | |
161 DEFUN ("read-char", Fread_char, Sread_char, 0, 0, 0, | |
162 "Read a character from the command input (keyboard or macro).\n\ | |
851 | 163 It is returned as a number.\n\ |
164 If the user generates an event which is not a character (i.e. a mouse\n\ | |
165 click or function key event), `read-char' signals an error. If you\n\ | |
166 want to read non-character events, or ignore them, call `read-event'\n\ | |
167 or `read-char-exclusive' instead.") | |
341 | 168 () |
169 { | |
170 register Lisp_Object val; | |
171 | |
172 #ifndef standalone | |
173 val = read_char (0); | |
174 if (XTYPE (val) != Lisp_Int) | |
175 { | |
176 unread_command_char = val; | |
177 error ("Object read was not a character"); | |
178 } | |
179 #else | |
180 val = getchar (); | |
181 #endif | |
182 | |
183 return val; | |
184 } | |
185 | |
186 DEFUN ("read-event", Fread_event, Sread_event, 0, 0, 0, | |
187 "Read an event object from the input stream.") | |
188 () | |
189 { | |
190 register Lisp_Object val; | |
191 | |
192 val = read_char (0); | |
193 return val; | |
194 } | |
195 | |
196 DEFUN ("read-char-exclusive", Fread_char_exclusive, Sread_char_exclusive, 0, 0, 0, | |
197 "Read a character from the command input (keyboard or macro).\n\ | |
198 It is returned as a number. Non character events are ignored.") | |
199 () | |
200 { | |
201 register Lisp_Object val; | |
202 | |
203 #ifndef standalone | |
851 | 204 do |
205 { | |
206 val = read_char (0); | |
207 } | |
208 while (XTYPE (val) != Lisp_Int); | |
341 | 209 #else |
210 val = getchar (); | |
211 #endif | |
212 | |
213 return val; | |
214 } | |
215 | |
216 DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0, | |
217 "Don't use this yourself.") | |
218 () | |
219 { | |
220 register Lisp_Object val; | |
221 XSET (val, Lisp_Int, getc (instream)); | |
222 return val; | |
223 } | |
224 | |
225 static void readevalloop (); | |
226 static Lisp_Object load_unwind (); | |
227 | |
228 DEFUN ("load", Fload, Sload, 1, 4, 0, | |
229 "Execute a file of Lisp code named FILE.\n\ | |
230 First try FILE with `.elc' appended, then try with `.el',\n\ | |
231 then try FILE unmodified.\n\ | |
232 This function searches the directories in `load-path'.\n\ | |
233 If optional second arg NOERROR is non-nil,\n\ | |
234 report no error if FILE doesn't exist.\n\ | |
235 Print messages at start and end of loading unless\n\ | |
236 optional third arg NOMESSAGE is non-nil.\n\ | |
237 If optional fourth arg NOSUFFIX is non-nil, don't try adding\n\ | |
238 suffixes `.elc' or `.el' to the specified name FILE.\n\ | |
239 Return t if file exists.") | |
240 (str, noerror, nomessage, nosuffix) | |
241 Lisp_Object str, noerror, nomessage, nosuffix; | |
242 { | |
243 register FILE *stream; | |
244 register int fd = -1; | |
245 register Lisp_Object lispstream; | |
246 register FILE **ptr; | |
247 int count = specpdl_ptr - specpdl; | |
248 Lisp_Object temp; | |
249 struct gcpro gcpro1; | |
250 Lisp_Object found; | |
251 | |
252 CHECK_STRING (str, 0); | |
253 str = Fsubstitute_in_file_name (str); | |
254 | |
255 /* Avoid weird lossage with null string as arg, | |
256 since it would try to load a directory as a Lisp file */ | |
257 if (XSTRING (str)->size > 0) | |
258 { | |
485 | 259 fd = openp (Vload_path, str, !NILP (nosuffix) ? "" : ".elc:.el:", |
341 | 260 &found, 0); |
261 } | |
262 | |
263 if (fd < 0) | |
264 { | |
485 | 265 if (NILP (noerror)) |
341 | 266 while (1) |
267 Fsignal (Qfile_error, Fcons (build_string ("Cannot open load file"), | |
268 Fcons (str, Qnil))); | |
269 else | |
270 return Qnil; | |
271 } | |
272 | |
273 if (!bcmp (&(XSTRING (found)->data[XSTRING (found)->size - 4]), | |
274 ".elc", 4)) | |
275 { | |
276 struct stat s1, s2; | |
277 int result; | |
278 | |
279 stat (XSTRING (found)->data, &s1); | |
280 XSTRING (found)->data[XSTRING (found)->size - 1] = 0; | |
281 result = stat (XSTRING (found)->data, &s2); | |
282 if (result >= 0 && (unsigned) s1.st_mtime < (unsigned) s2.st_mtime) | |
283 message ("Source file `%s' newer than byte-compiled file", | |
284 XSTRING (found)->data); | |
285 XSTRING (found)->data[XSTRING (found)->size - 1] = 'c'; | |
286 } | |
287 | |
288 stream = fdopen (fd, "r"); | |
289 if (stream == 0) | |
290 { | |
291 close (fd); | |
292 error ("Failure to create stdio stream for %s", XSTRING (str)->data); | |
293 } | |
294 | |
485 | 295 if (NILP (nomessage)) |
341 | 296 message ("Loading %s...", XSTRING (str)->data); |
297 | |
298 GCPRO1 (str); | |
299 /* We may not be able to store STREAM itself as a Lisp_Object pointer | |
300 since that is guaranteed to work only for data that has been malloc'd. | |
301 So malloc a full-size pointer, and record the address of that pointer. */ | |
302 ptr = (FILE **) xmalloc (sizeof (FILE *)); | |
303 *ptr = stream; | |
304 XSET (lispstream, Lisp_Internal_Stream, (int) ptr); | |
305 record_unwind_protect (load_unwind, lispstream); | |
306 load_in_progress++; | |
307 readevalloop (Qget_file_char, stream, Feval, 0); | |
308 unbind_to (count, Qnil); | |
309 | |
310 /* Run any load-hooks for this file. */ | |
311 temp = Fassoc (str, Vafter_load_alist); | |
485 | 312 if (!NILP (temp)) |
341 | 313 Fprogn (Fcdr (temp)); |
314 UNGCPRO; | |
315 | |
485 | 316 if (!noninteractive && NILP (nomessage)) |
341 | 317 message ("Loading %s...done", XSTRING (str)->data); |
318 return Qt; | |
319 } | |
320 | |
321 static Lisp_Object | |
322 load_unwind (stream) /* used as unwind-protect function in load */ | |
323 Lisp_Object stream; | |
324 { | |
325 fclose (*(FILE **) XSTRING (stream)); | |
326 free (XPNTR (stream)); | |
327 if (--load_in_progress < 0) load_in_progress = 0; | |
328 return Qnil; | |
329 } | |
330 | |
331 | |
332 static int | |
333 complete_filename_p (pathname) | |
334 Lisp_Object pathname; | |
335 { | |
336 register unsigned char *s = XSTRING (pathname)->data; | |
337 return (*s == '/' | |
338 #ifdef ALTOS | |
339 || *s == '@' | |
340 #endif | |
341 #ifdef VMS | |
342 || index (s, ':') | |
343 #endif /* VMS */ | |
344 ); | |
345 } | |
346 | |
347 /* Search for a file whose name is STR, looking in directories | |
348 in the Lisp list PATH, and trying suffixes from SUFFIX. | |
349 SUFFIX is a string containing possible suffixes separated by colons. | |
350 On success, returns a file descriptor. On failure, returns -1. | |
351 | |
352 EXEC_ONLY nonzero means don't open the files, | |
353 just look for one that is executable. In this case, | |
354 returns 1 on success. | |
355 | |
356 If STOREPTR is nonzero, it points to a slot where the name of | |
357 the file actually found should be stored as a Lisp string. | |
358 Nil is stored there on failure. */ | |
359 | |
360 int | |
361 openp (path, str, suffix, storeptr, exec_only) | |
362 Lisp_Object path, str; | |
363 char *suffix; | |
364 Lisp_Object *storeptr; | |
365 int exec_only; | |
366 { | |
367 register int fd; | |
368 int fn_size = 100; | |
369 char buf[100]; | |
370 register char *fn = buf; | |
371 int absolute = 0; | |
372 int want_size; | |
373 register Lisp_Object filename; | |
374 struct stat st; | |
375 | |
376 if (storeptr) | |
377 *storeptr = Qnil; | |
378 | |
379 if (complete_filename_p (str)) | |
380 absolute = 1; | |
381 | |
485 | 382 for (; !NILP (path); path = Fcdr (path)) |
341 | 383 { |
384 char *nsuffix; | |
385 | |
386 filename = Fexpand_file_name (str, Fcar (path)); | |
387 if (!complete_filename_p (filename)) | |
388 /* If there are non-absolute elts in PATH (eg ".") */ | |
389 /* Of course, this could conceivably lose if luser sets | |
390 default-directory to be something non-absolute... */ | |
391 { | |
392 filename = Fexpand_file_name (filename, current_buffer->directory); | |
393 if (!complete_filename_p (filename)) | |
394 /* Give up on this path element! */ | |
395 continue; | |
396 } | |
397 | |
398 /* Calculate maximum size of any filename made from | |
399 this path element/specified file name and any possible suffix. */ | |
400 want_size = strlen (suffix) + XSTRING (filename)->size + 1; | |
401 if (fn_size < want_size) | |
402 fn = (char *) alloca (fn_size = 100 + want_size); | |
403 | |
404 nsuffix = suffix; | |
405 | |
406 /* Loop over suffixes. */ | |
407 while (1) | |
408 { | |
409 char *esuffix = (char *) index (nsuffix, ':'); | |
410 int lsuffix = esuffix ? esuffix - nsuffix : strlen (nsuffix); | |
411 | |
412 /* Concatenate path element/specified name with the suffix. */ | |
413 strncpy (fn, XSTRING (filename)->data, XSTRING (filename)->size); | |
414 fn[XSTRING (filename)->size] = 0; | |
415 if (lsuffix != 0) /* Bug happens on CCI if lsuffix is 0. */ | |
416 strncat (fn, nsuffix, lsuffix); | |
417 | |
418 /* Ignore file if it's a directory. */ | |
419 if (stat (fn, &st) >= 0 | |
420 && (st.st_mode & S_IFMT) != S_IFDIR) | |
421 { | |
422 /* Check that we can access or open it. */ | |
423 if (exec_only) | |
424 fd = (access (fn, X_OK) == 0) ? 1 : -1; | |
425 else | |
426 fd = open (fn, 0, 0); | |
427 | |
428 if (fd >= 0) | |
429 { | |
430 /* We succeeded; return this descriptor and filename. */ | |
431 if (storeptr) | |
432 *storeptr = build_string (fn); | |
433 return fd; | |
434 } | |
435 } | |
436 | |
437 /* Advance to next suffix. */ | |
438 if (esuffix == 0) | |
439 break; | |
440 nsuffix += lsuffix + 1; | |
441 } | |
442 if (absolute) return -1; | |
443 } | |
444 | |
445 return -1; | |
446 } | |
447 | |
448 | |
449 Lisp_Object | |
450 unreadpure () /* Used as unwind-protect function in readevalloop */ | |
451 { | |
452 read_pure = 0; | |
453 return Qnil; | |
454 } | |
455 | |
456 static void | |
457 readevalloop (readcharfun, stream, evalfun, printflag) | |
458 Lisp_Object readcharfun; | |
459 FILE *stream; | |
460 Lisp_Object (*evalfun) (); | |
461 int printflag; | |
462 { | |
463 register int c; | |
464 register Lisp_Object val; | |
465 int count = specpdl_ptr - specpdl; | |
466 | |
467 specbind (Qstandard_input, readcharfun); | |
468 | |
469 while (1) | |
470 { | |
471 instream = stream; | |
472 c = READCHAR; | |
473 if (c == ';') | |
474 { | |
475 while ((c = READCHAR) != '\n' && c != -1); | |
476 continue; | |
477 } | |
478 if (c < 0) break; | |
479 if (c == ' ' || c == '\t' || c == '\n' || c == '\f') continue; | |
480 | |
485 | 481 if (!NILP (Vpurify_flag) && c == '(') |
341 | 482 { |
483 record_unwind_protect (unreadpure, Qnil); | |
484 val = read_list (-1, readcharfun); | |
485 unbind_to (count + 1, Qnil); | |
486 } | |
487 else | |
488 { | |
489 UNREAD (c); | |
490 val = read0 (readcharfun); | |
491 } | |
492 | |
493 val = (*evalfun) (val); | |
494 if (printflag) | |
495 { | |
496 Vvalues = Fcons (val, Vvalues); | |
497 if (EQ (Vstandard_output, Qt)) | |
498 Fprin1 (val, Qnil); | |
499 else | |
500 Fprint (val, Qnil); | |
501 } | |
502 } | |
503 | |
504 unbind_to (count, Qnil); | |
505 } | |
506 | |
507 #ifndef standalone | |
508 | |
732 | 509 DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 2, "", |
675
85fd29f25c75
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
673
diff
changeset
|
510 "Execute the current buffer as Lisp code.\n\ |
85fd29f25c75
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
673
diff
changeset
|
511 Programs can pass two arguments, BUFFER and PRINTFLAG.\n\ |
85fd29f25c75
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
673
diff
changeset
|
512 BUFFER is the buffer to evaluate (nil means use current buffer).\n\ |
85fd29f25c75
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
673
diff
changeset
|
513 PRINTFLAG controls printing of output:\n\ |
672 | 514 nil means discard it; anything else is stream for print.\n\ |
515 \n\ | |
516 If there is no error, point does not move. If there is an error,\n\ | |
517 point remains at the end of the last character read from the buffer.") | |
518 (bufname, printflag) | |
519 Lisp_Object bufname, printflag; | |
520 { | |
521 int count = specpdl_ptr - specpdl; | |
522 Lisp_Object tem, buf; | |
523 | |
673 | 524 if (NILP (bufname)) |
672 | 525 buf = Fcurrent_buffer (); |
526 else | |
527 buf = Fget_buffer (bufname); | |
673 | 528 if (NILP (buf)) |
672 | 529 error ("No such buffer."); |
530 | |
673 | 531 if (NILP (printflag)) |
672 | 532 tem = Qsymbolp; |
533 else | |
534 tem = printflag; | |
535 specbind (Qstandard_output, tem); | |
536 record_unwind_protect (save_excursion_restore, save_excursion_save ()); | |
537 BUF_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); | |
673 | 538 readevalloop (buf, 0, Feval, !NILP (printflag)); |
672 | 539 unbind_to (count); |
540 | |
541 return Qnil; | |
542 } | |
543 | |
544 #if 0 | |
341 | 545 DEFUN ("eval-current-buffer", Feval_current_buffer, Seval_current_buffer, 0, 1, "", |
546 "Execute the current buffer as Lisp code.\n\ | |
547 Programs can pass argument PRINTFLAG which controls printing of output:\n\ | |
548 nil means discard it; anything else is stream for print.\n\ | |
549 \n\ | |
550 If there is no error, point does not move. If there is an error,\n\ | |
551 point remains at the end of the last character read from the buffer.") | |
552 (printflag) | |
553 Lisp_Object printflag; | |
554 { | |
555 int count = specpdl_ptr - specpdl; | |
556 Lisp_Object tem; | |
557 | |
485 | 558 if (NILP (printflag)) |
341 | 559 tem = Qsymbolp; |
560 else | |
561 tem = printflag; | |
562 specbind (Qstandard_output, tem); | |
563 record_unwind_protect (save_excursion_restore, save_excursion_save ()); | |
564 SET_PT (BEGV); | |
485 | 565 readevalloop (Fcurrent_buffer (), 0, Feval, !NILP (printflag)); |
341 | 566 return unbind_to (count, Qnil); |
567 } | |
672 | 568 #endif |
341 | 569 |
570 DEFUN ("eval-region", Feval_region, Seval_region, 2, 3, "r", | |
571 "Execute the region as Lisp code.\n\ | |
572 When called from programs, expects two arguments,\n\ | |
573 giving starting and ending indices in the current buffer\n\ | |
574 of the text to be executed.\n\ | |
575 Programs can pass third argument PRINTFLAG which controls output:\n\ | |
576 nil means discard it; anything else is stream for printing it.\n\ | |
577 \n\ | |
578 If there is no error, point does not move. If there is an error,\n\ | |
579 point remains at the end of the last character read from the buffer.") | |
580 (b, e, printflag) | |
581 Lisp_Object b, e, printflag; | |
582 { | |
583 int count = specpdl_ptr - specpdl; | |
584 Lisp_Object tem; | |
585 | |
485 | 586 if (NILP (printflag)) |
341 | 587 tem = Qsymbolp; |
588 else | |
589 tem = printflag; | |
590 specbind (Qstandard_output, tem); | |
591 | |
485 | 592 if (NILP (printflag)) |
341 | 593 record_unwind_protect (save_excursion_restore, save_excursion_save ()); |
594 record_unwind_protect (save_restriction_restore, save_restriction_save ()); | |
595 | |
596 /* This both uses b and checks its type. */ | |
597 Fgoto_char (b); | |
598 Fnarrow_to_region (make_number (BEGV), e); | |
485 | 599 readevalloop (Fcurrent_buffer (), 0, Feval, !NILP (printflag)); |
341 | 600 |
601 return unbind_to (count, Qnil); | |
602 } | |
603 | |
604 #endif /* standalone */ | |
605 | |
606 DEFUN ("read", Fread, Sread, 0, 1, 0, | |
607 "Read one Lisp expression as text from STREAM, return as Lisp object.\n\ | |
608 If STREAM is nil, use the value of `standard-input' (which see).\n\ | |
609 STREAM or the value of `standard-input' may be:\n\ | |
610 a buffer (read from point and advance it)\n\ | |
611 a marker (read from where it points and advance it)\n\ | |
612 a function (call it with no arguments for each character,\n\ | |
613 call it with a char as argument to push a char back)\n\ | |
614 a string (takes text from string, starting at the beginning)\n\ | |
615 t (read text line using minibuffer and use it).") | |
616 (readcharfun) | |
617 Lisp_Object readcharfun; | |
618 { | |
619 extern Lisp_Object Fread_minibuffer (); | |
620 | |
485 | 621 if (NILP (readcharfun)) |
341 | 622 readcharfun = Vstandard_input; |
623 if (EQ (readcharfun, Qt)) | |
624 readcharfun = Qread_char; | |
625 | |
626 #ifndef standalone | |
627 if (EQ (readcharfun, Qread_char)) | |
628 return Fread_minibuffer (build_string ("Lisp expression: "), Qnil); | |
629 #endif | |
630 | |
631 if (XTYPE (readcharfun) == Lisp_String) | |
632 return Fcar (Fread_from_string (readcharfun, Qnil, Qnil)); | |
633 | |
634 return read0 (readcharfun); | |
635 } | |
636 | |
637 DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0, | |
638 "Read one Lisp expression which is represented as text by STRING.\n\ | |
639 Returns a cons: (OBJECT-READ . FINAL-STRING-INDEX).\n\ | |
640 START and END optionally delimit a substring of STRING from which to read;\n\ | |
641 they default to 0 and (length STRING) respectively.") | |
642 (string, start, end) | |
643 Lisp_Object string, start, end; | |
644 { | |
645 int startval, endval; | |
646 Lisp_Object tem; | |
647 | |
648 CHECK_STRING (string,0); | |
649 | |
485 | 650 if (NILP (end)) |
341 | 651 endval = XSTRING (string)->size; |
652 else | |
653 { CHECK_NUMBER (end,2); | |
654 endval = XINT (end); | |
655 if (endval < 0 || endval > XSTRING (string)->size) | |
656 args_out_of_range (string, end); | |
657 } | |
658 | |
485 | 659 if (NILP (start)) |
341 | 660 startval = 0; |
661 else | |
662 { CHECK_NUMBER (start,1); | |
663 startval = XINT (start); | |
664 if (startval < 0 || startval > endval) | |
665 args_out_of_range (string, start); | |
666 } | |
667 | |
668 read_from_string_index = startval; | |
669 read_from_string_limit = endval; | |
670 | |
671 tem = read0 (string); | |
672 return Fcons (tem, make_number (read_from_string_index)); | |
673 } | |
674 | |
675 /* Use this for recursive reads, in contexts where internal tokens are not allowed. */ | |
676 | |
677 static Lisp_Object | |
678 read0 (readcharfun) | |
679 Lisp_Object readcharfun; | |
680 { | |
681 register Lisp_Object val; | |
682 char c; | |
683 | |
684 val = read1 (readcharfun); | |
685 if (XTYPE (val) == Lisp_Internal) | |
686 { | |
687 c = XINT (val); | |
688 return Fsignal (Qinvalid_read_syntax, Fcons (make_string (&c, 1), Qnil)); | |
689 } | |
690 | |
691 return val; | |
692 } | |
693 | |
694 static int read_buffer_size; | |
695 static char *read_buffer; | |
696 | |
697 static int | |
698 read_escape (readcharfun) | |
699 Lisp_Object readcharfun; | |
700 { | |
701 register int c = READCHAR; | |
702 switch (c) | |
703 { | |
704 case 'a': | |
485 | 705 return '\007'; |
341 | 706 case 'b': |
707 return '\b'; | |
708 case 'e': | |
709 return 033; | |
710 case 'f': | |
711 return '\f'; | |
712 case 'n': | |
713 return '\n'; | |
714 case 'r': | |
715 return '\r'; | |
716 case 't': | |
717 return '\t'; | |
718 case 'v': | |
719 return '\v'; | |
720 case '\n': | |
721 return -1; | |
722 | |
723 case 'M': | |
724 c = READCHAR; | |
725 if (c != '-') | |
726 error ("Invalid escape character syntax"); | |
727 c = READCHAR; | |
728 if (c == '\\') | |
729 c = read_escape (readcharfun); | |
730 return c | 0200; | |
731 | |
732 case 'C': | |
733 c = READCHAR; | |
734 if (c != '-') | |
735 error ("Invalid escape character syntax"); | |
736 case '^': | |
737 c = READCHAR; | |
738 if (c == '\\') | |
739 c = read_escape (readcharfun); | |
740 if (c == '?') | |
741 return 0177; | |
742 else | |
743 return (c & (0200 | 037)); | |
744 | |
745 case '0': | |
746 case '1': | |
747 case '2': | |
748 case '3': | |
749 case '4': | |
750 case '5': | |
751 case '6': | |
752 case '7': | |
753 /* An octal escape, as in ANSI C. */ | |
754 { | |
755 register int i = c - '0'; | |
756 register int count = 0; | |
757 while (++count < 3) | |
758 { | |
759 if ((c = READCHAR) >= '0' && c <= '7') | |
760 { | |
761 i *= 8; | |
762 i += c - '0'; | |
763 } | |
764 else | |
765 { | |
766 UNREAD (c); | |
767 break; | |
768 } | |
769 } | |
770 return i; | |
771 } | |
772 | |
773 case 'x': | |
774 /* A hex escape, as in ANSI C. */ | |
775 { | |
776 int i = 0; | |
777 while (1) | |
778 { | |
779 c = READCHAR; | |
780 if (c >= '0' && c <= '9') | |
781 { | |
782 i *= 16; | |
783 i += c - '0'; | |
784 } | |
785 else if ((c >= 'a' && c <= 'f') | |
786 || (c >= 'A' && c <= 'F')) | |
787 { | |
788 i *= 16; | |
789 if (c >= 'a' && c <= 'f') | |
790 i += c - 'a' + 10; | |
791 else | |
792 i += c - 'A' + 10; | |
793 } | |
794 else | |
795 { | |
796 UNREAD (c); | |
797 break; | |
798 } | |
799 } | |
800 return i; | |
801 } | |
802 | |
803 default: | |
804 return c; | |
805 } | |
806 } | |
807 | |
808 static Lisp_Object | |
809 read1 (readcharfun) | |
810 register Lisp_Object readcharfun; | |
811 { | |
812 register int c; | |
813 | |
814 retry: | |
815 | |
816 c = READCHAR; | |
817 if (c < 0) return Fsignal (Qend_of_file, Qnil); | |
818 | |
819 switch (c) | |
820 { | |
821 case '(': | |
822 return read_list (0, readcharfun); | |
823 | |
824 case '[': | |
825 return read_vector (readcharfun); | |
826 | |
827 case ')': | |
828 case ']': | |
829 { | |
830 register Lisp_Object val; | |
831 XSET (val, Lisp_Internal, c); | |
832 return val; | |
833 } | |
834 | |
835 case '#': | |
373
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
836 c = READCHAR; |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
837 if (c == '[') |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
838 { |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
839 /* Accept compiled functions at read-time so that we don't have to |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
840 build them using function calls. */ |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
841 Lisp_Object tmp = read_vector (readcharfun); |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
842 return Fmake_byte_code (XVECTOR(tmp)->size, XVECTOR (tmp)->contents); |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
843 } |
7c6f74ef31a3
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
364
diff
changeset
|
844 UNREAD (c); |
341 | 845 return Fsignal (Qinvalid_read_syntax, Fcons (make_string ("#", 1), Qnil)); |
846 | |
847 case ';': | |
848 while ((c = READCHAR) >= 0 && c != '\n'); | |
849 goto retry; | |
850 | |
851 case '\'': | |
852 { | |
853 return Fcons (Qquote, Fcons (read0 (readcharfun), Qnil)); | |
854 } | |
855 | |
856 case '?': | |
857 { | |
858 register Lisp_Object val; | |
859 | |
860 c = READCHAR; | |
861 if (c < 0) return Fsignal (Qend_of_file, Qnil); | |
862 | |
863 if (c == '\\') | |
864 XSET (val, Lisp_Int, read_escape (readcharfun)); | |
865 else | |
866 XSET (val, Lisp_Int, c); | |
867 | |
868 return val; | |
869 } | |
870 | |
871 case '\"': | |
872 { | |
873 register char *p = read_buffer; | |
874 register char *end = read_buffer + read_buffer_size; | |
875 register int c; | |
876 int cancel = 0; | |
877 | |
878 while ((c = READCHAR) >= 0 | |
879 && c != '\"') | |
880 { | |
881 if (p == end) | |
882 { | |
883 char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2); | |
884 p += new - read_buffer; | |
885 read_buffer += new - read_buffer; | |
886 end = read_buffer + read_buffer_size; | |
887 } | |
888 if (c == '\\') | |
889 c = read_escape (readcharfun); | |
890 /* c is -1 if \ newline has just been seen */ | |
891 if (c < 0) | |
892 { | |
893 if (p == read_buffer) | |
894 cancel = 1; | |
895 } | |
896 else | |
897 *p++ = c; | |
898 } | |
899 if (c < 0) return Fsignal (Qend_of_file, Qnil); | |
900 | |
901 /* If purifying, and string starts with \ newline, | |
902 return zero instead. This is for doc strings | |
604 | 903 that we are really going to find in etc/DOC.nn.nn */ |
485 | 904 if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel) |
341 | 905 return make_number (0); |
906 | |
907 if (read_pure) | |
908 return make_pure_string (read_buffer, p - read_buffer); | |
909 else | |
910 return make_string (read_buffer, p - read_buffer); | |
911 } | |
912 | |
762 | 913 case '.': |
914 { | |
915 #ifdef LISP_FLOAT_TYPE | |
916 /* If a period is followed by a number, then we should read it | |
917 as a floating point number. Otherwise, it denotes a dotted | |
918 pair. */ | |
919 int next_char = READCHAR; | |
920 UNREAD (next_char); | |
921 | |
922 if (! isdigit (next_char)) | |
923 #endif | |
924 { | |
925 register Lisp_Object val; | |
926 XSET (val, Lisp_Internal, c); | |
927 return val; | |
928 } | |
929 | |
930 /* Otherwise, we fall through! Note that the atom-reading loop | |
931 below will now loop at least once, assuring that we will not | |
932 try to UNREAD two characters in a row. */ | |
933 } | |
341 | 934 default: |
935 if (c <= 040) goto retry; | |
936 { | |
937 register char *p = read_buffer; | |
938 | |
939 { | |
940 register char *end = read_buffer + read_buffer_size; | |
941 | |
942 while (c > 040 && | |
943 !(c == '\"' || c == '\'' || c == ';' || c == '?' | |
944 || c == '(' || c == ')' | |
762 | 945 #ifndef LISP_FLOAT_TYPE |
946 /* If we have floating-point support, then we need | |
947 to allow <digits><dot><digits>. */ | |
341 | 948 || c =='.' |
949 #endif /* not LISP_FLOAT_TYPE */ | |
950 || c == '[' || c == ']' || c == '#' | |
951 )) | |
952 { | |
953 if (p == end) | |
954 { | |
955 register char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2); | |
956 p += new - read_buffer; | |
957 read_buffer += new - read_buffer; | |
958 end = read_buffer + read_buffer_size; | |
959 } | |
960 if (c == '\\') | |
961 c = READCHAR; | |
962 *p++ = c; | |
963 c = READCHAR; | |
964 } | |
965 | |
966 if (p == end) | |
967 { | |
968 char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2); | |
969 p += new - read_buffer; | |
970 read_buffer += new - read_buffer; | |
971 /* end = read_buffer + read_buffer_size; */ | |
972 } | |
973 *p = 0; | |
974 if (c >= 0) | |
975 UNREAD (c); | |
976 } | |
977 | |
978 /* Is it an integer? */ | |
979 { | |
980 register char *p1; | |
981 register Lisp_Object val; | |
982 p1 = read_buffer; | |
983 if (*p1 == '+' || *p1 == '-') p1++; | |
984 if (p1 != p) | |
985 { | |
986 while (p1 != p && (c = *p1) >= '0' && c <= '9') p1++; | |
987 if (p1 == p) | |
988 /* It is. */ | |
989 { | |
990 XSET (val, Lisp_Int, atoi (read_buffer)); | |
991 return val; | |
992 } | |
993 } | |
994 #ifdef LISP_FLOAT_TYPE | |
995 if (isfloat_string (read_buffer)) | |
996 return make_float (atof (read_buffer)); | |
997 #endif | |
998 } | |
999 | |
1000 return intern (read_buffer); | |
1001 } | |
1002 } | |
1003 } | |
1004 | |
1005 #ifdef LISP_FLOAT_TYPE | |
1006 | |
1007 #define LEAD_INT 1 | |
1008 #define DOT_CHAR 2 | |
1009 #define TRAIL_INT 4 | |
1010 #define E_CHAR 8 | |
1011 #define EXP_INT 16 | |
1012 | |
1013 int | |
1014 isfloat_string (cp) | |
1015 register char *cp; | |
1016 { | |
1017 register state; | |
1018 | |
1019 state = 0; | |
1020 if (*cp == '+' || *cp == '-') | |
1021 cp++; | |
1022 | |
1023 if (isdigit(*cp)) | |
1024 { | |
1025 state |= LEAD_INT; | |
1026 while (isdigit (*cp)) | |
1027 cp ++; | |
1028 } | |
1029 if (*cp == '.') | |
1030 { | |
1031 state |= DOT_CHAR; | |
1032 cp++; | |
1033 } | |
1034 if (isdigit(*cp)) | |
1035 { | |
1036 state |= TRAIL_INT; | |
1037 while (isdigit (*cp)) | |
1038 cp++; | |
1039 } | |
1040 if (*cp == 'e') | |
1041 { | |
1042 state |= E_CHAR; | |
1043 cp++; | |
1044 } | |
1045 if ((*cp == '+') || (*cp == '-')) | |
1046 cp++; | |
1047 | |
1048 if (isdigit (*cp)) | |
1049 { | |
1050 state |= EXP_INT; | |
1051 while (isdigit (*cp)) | |
1052 cp++; | |
1053 } | |
1054 return (*cp == 0 | |
1055 && (state == (LEAD_INT|DOT_CHAR|TRAIL_INT) | |
826 | 1056 || state == (DOT_CHAR|TRAIL_INT) |
341 | 1057 || state == (LEAD_INT|E_CHAR|EXP_INT) |
826 | 1058 || state == (LEAD_INT|DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT) |
1059 || state == (DOT_CHAR|TRAIL_INT|E_CHAR|EXP_INT))); | |
341 | 1060 } |
1061 #endif /* LISP_FLOAT_TYPE */ | |
1062 | |
1063 static Lisp_Object | |
1064 read_vector (readcharfun) | |
1065 Lisp_Object readcharfun; | |
1066 { | |
1067 register int i; | |
1068 register int size; | |
1069 register Lisp_Object *ptr; | |
1070 register Lisp_Object tem, vector; | |
1071 register struct Lisp_Cons *otem; | |
1072 Lisp_Object len; | |
1073 | |
1074 tem = read_list (1, readcharfun); | |
1075 len = Flength (tem); | |
1076 vector = (read_pure ? make_pure_vector (XINT (len)) : Fmake_vector (len, Qnil)); | |
1077 | |
1078 | |
1079 size = XVECTOR (vector)->size; | |
1080 ptr = XVECTOR (vector)->contents; | |
1081 for (i = 0; i < size; i++) | |
1082 { | |
1083 ptr[i] = read_pure ? Fpurecopy (Fcar (tem)) : Fcar (tem); | |
1084 otem = XCONS (tem); | |
1085 tem = Fcdr (tem); | |
1086 free_cons (otem); | |
1087 } | |
1088 return vector; | |
1089 } | |
1090 | |
1091 /* flag = 1 means check for ] to terminate rather than ) and . | |
1092 flag = -1 means check for starting with defun | |
1093 and make structure pure. */ | |
1094 | |
1095 static Lisp_Object | |
1096 read_list (flag, readcharfun) | |
1097 int flag; | |
1098 register Lisp_Object readcharfun; | |
1099 { | |
1100 /* -1 means check next element for defun, | |
1101 0 means don't check, | |
1102 1 means already checked and found defun. */ | |
1103 int defunflag = flag < 0 ? -1 : 0; | |
1104 Lisp_Object val, tail; | |
1105 register Lisp_Object elt, tem; | |
1106 struct gcpro gcpro1, gcpro2; | |
1107 | |
1108 val = Qnil; | |
1109 tail = Qnil; | |
1110 | |
1111 while (1) | |
1112 { | |
1113 GCPRO2 (val, tail); | |
1114 elt = read1 (readcharfun); | |
1115 UNGCPRO; | |
1116 if (XTYPE (elt) == Lisp_Internal) | |
1117 { | |
1118 if (flag > 0) | |
1119 { | |
1120 if (XINT (elt) == ']') | |
1121 return val; | |
1122 return Fsignal (Qinvalid_read_syntax, Fcons (make_string (") or . in a vector", 18), Qnil)); | |
1123 } | |
1124 if (XINT (elt) == ')') | |
1125 return val; | |
1126 if (XINT (elt) == '.') | |
1127 { | |
1128 GCPRO2 (val, tail); | |
485 | 1129 if (!NILP (tail)) |
341 | 1130 XCONS (tail)->cdr = read0 (readcharfun); |
1131 else | |
1132 val = read0 (readcharfun); | |
1133 elt = read1 (readcharfun); | |
1134 UNGCPRO; | |
1135 if (XTYPE (elt) == Lisp_Internal && XINT (elt) == ')') | |
1136 return val; | |
1137 return Fsignal (Qinvalid_read_syntax, Fcons (make_string (". in wrong context", 18), Qnil)); | |
1138 } | |
1139 return Fsignal (Qinvalid_read_syntax, Fcons (make_string ("] in a list", 11), Qnil)); | |
1140 } | |
1141 tem = (read_pure && flag <= 0 | |
1142 ? pure_cons (elt, Qnil) | |
1143 : Fcons (elt, Qnil)); | |
485 | 1144 if (!NILP (tail)) |
341 | 1145 XCONS (tail)->cdr = tem; |
1146 else | |
1147 val = tem; | |
1148 tail = tem; | |
1149 if (defunflag < 0) | |
1150 defunflag = EQ (elt, Qdefun); | |
1151 else if (defunflag > 0) | |
1152 read_pure = 1; | |
1153 } | |
1154 } | |
1155 | |
1156 Lisp_Object Vobarray; | |
1157 Lisp_Object initial_obarray; | |
1158 | |
1159 Lisp_Object | |
1160 check_obarray (obarray) | |
1161 Lisp_Object obarray; | |
1162 { | |
1163 while (XTYPE (obarray) != Lisp_Vector || XVECTOR (obarray)->size == 0) | |
1164 { | |
1165 /* If Vobarray is now invalid, force it to be valid. */ | |
1166 if (EQ (Vobarray, obarray)) Vobarray = initial_obarray; | |
1167 | |
1168 obarray = wrong_type_argument (Qvectorp, obarray); | |
1169 } | |
1170 return obarray; | |
1171 } | |
1172 | |
1173 static int hash_string (); | |
1174 Lisp_Object oblookup (); | |
1175 | |
1176 Lisp_Object | |
1177 intern (str) | |
1178 char *str; | |
1179 { | |
1180 Lisp_Object tem; | |
1181 int len = strlen (str); | |
1182 Lisp_Object obarray = Vobarray; | |
1183 | |
1184 if (XTYPE (obarray) != Lisp_Vector || XVECTOR (obarray)->size == 0) | |
1185 obarray = check_obarray (obarray); | |
1186 tem = oblookup (obarray, str, len); | |
1187 if (XTYPE (tem) == Lisp_Symbol) | |
1188 return tem; | |
485 | 1189 return Fintern ((!NILP (Vpurify_flag) |
341 | 1190 ? make_pure_string (str, len) |
1191 : make_string (str, len)), | |
1192 obarray); | |
1193 } | |
1194 | |
1195 DEFUN ("intern", Fintern, Sintern, 1, 2, 0, | |
1196 "Return the canonical symbol whose name is STRING.\n\ | |
1197 If there is none, one is created by this function and returned.\n\ | |
1198 A second optional argument specifies the obarray to use;\n\ | |
1199 it defaults to the value of `obarray'.") | |
1200 (str, obarray) | |
1201 Lisp_Object str, obarray; | |
1202 { | |
1203 register Lisp_Object tem, sym, *ptr; | |
1204 | |
485 | 1205 if (NILP (obarray)) obarray = Vobarray; |
341 | 1206 obarray = check_obarray (obarray); |
1207 | |
1208 CHECK_STRING (str, 0); | |
1209 | |
1210 tem = oblookup (obarray, XSTRING (str)->data, XSTRING (str)->size); | |
1211 if (XTYPE (tem) != Lisp_Int) | |
1212 return tem; | |
1213 | |
485 | 1214 if (!NILP (Vpurify_flag)) |
341 | 1215 str = Fpurecopy (str); |
1216 sym = Fmake_symbol (str); | |
1217 | |
1218 ptr = &XVECTOR (obarray)->contents[XINT (tem)]; | |
1219 if (XTYPE (*ptr) == Lisp_Symbol) | |
1220 XSYMBOL (sym)->next = XSYMBOL (*ptr); | |
1221 else | |
1222 XSYMBOL (sym)->next = 0; | |
1223 *ptr = sym; | |
1224 return sym; | |
1225 } | |
1226 | |
1227 DEFUN ("intern-soft", Fintern_soft, Sintern_soft, 1, 2, 0, | |
1228 "Return the canonical symbol whose name is STRING, or nil if none exists.\n\ | |
1229 A second optional argument specifies the obarray to use;\n\ | |
1230 it defaults to the value of `obarray'.") | |
1231 (str, obarray) | |
1232 Lisp_Object str, obarray; | |
1233 { | |
1234 register Lisp_Object tem; | |
1235 | |
485 | 1236 if (NILP (obarray)) obarray = Vobarray; |
341 | 1237 obarray = check_obarray (obarray); |
1238 | |
1239 CHECK_STRING (str, 0); | |
1240 | |
1241 tem = oblookup (obarray, XSTRING (str)->data, XSTRING (str)->size); | |
1242 if (XTYPE (tem) != Lisp_Int) | |
1243 return tem; | |
1244 return Qnil; | |
1245 } | |
1246 | |
1247 Lisp_Object | |
1248 oblookup (obarray, ptr, size) | |
1249 Lisp_Object obarray; | |
1250 register char *ptr; | |
1251 register int size; | |
1252 { | |
1253 int hash, obsize; | |
1254 register Lisp_Object tail; | |
1255 Lisp_Object bucket, tem; | |
1256 | |
1257 if (XTYPE (obarray) != Lisp_Vector || | |
1258 (obsize = XVECTOR (obarray)->size) == 0) | |
1259 { | |
1260 obarray = check_obarray (obarray); | |
1261 obsize = XVECTOR (obarray)->size; | |
1262 } | |
1263 /* Combining next two lines breaks VMS C 2.3. */ | |
1264 hash = hash_string (ptr, size); | |
1265 hash %= obsize; | |
1266 bucket = XVECTOR (obarray)->contents[hash]; | |
1267 if (XFASTINT (bucket) == 0) | |
1268 ; | |
1269 else if (XTYPE (bucket) != Lisp_Symbol) | |
1270 error ("Bad data in guts of obarray"); /* Like CADR error message */ | |
1271 else for (tail = bucket; ; XSET (tail, Lisp_Symbol, XSYMBOL (tail)->next)) | |
1272 { | |
1273 if (XSYMBOL (tail)->name->size == size && | |
1274 !bcmp (XSYMBOL (tail)->name->data, ptr, size)) | |
1275 return tail; | |
1276 else if (XSYMBOL (tail)->next == 0) | |
1277 break; | |
1278 } | |
1279 XSET (tem, Lisp_Int, hash); | |
1280 return tem; | |
1281 } | |
1282 | |
1283 static int | |
1284 hash_string (ptr, len) | |
1285 unsigned char *ptr; | |
1286 int len; | |
1287 { | |
1288 register unsigned char *p = ptr; | |
1289 register unsigned char *end = p + len; | |
1290 register unsigned char c; | |
1291 register int hash = 0; | |
1292 | |
1293 while (p != end) | |
1294 { | |
1295 c = *p++; | |
1296 if (c >= 0140) c -= 40; | |
1297 hash = ((hash<<3) + (hash>>28) + c); | |
1298 } | |
1299 return hash & 07777777777; | |
1300 } | |
1301 | |
1302 void | |
1303 map_obarray (obarray, fn, arg) | |
1304 Lisp_Object obarray; | |
1305 int (*fn) (); | |
1306 Lisp_Object arg; | |
1307 { | |
1308 register int i; | |
1309 register Lisp_Object tail; | |
1310 CHECK_VECTOR (obarray, 1); | |
1311 for (i = XVECTOR (obarray)->size - 1; i >= 0; i--) | |
1312 { | |
1313 tail = XVECTOR (obarray)->contents[i]; | |
1314 if (XFASTINT (tail) != 0) | |
1315 while (1) | |
1316 { | |
1317 (*fn) (tail, arg); | |
1318 if (XSYMBOL (tail)->next == 0) | |
1319 break; | |
1320 XSET (tail, Lisp_Symbol, XSYMBOL (tail)->next); | |
1321 } | |
1322 } | |
1323 } | |
1324 | |
1325 mapatoms_1 (sym, function) | |
1326 Lisp_Object sym, function; | |
1327 { | |
1328 call1 (function, sym); | |
1329 } | |
1330 | |
1331 DEFUN ("mapatoms", Fmapatoms, Smapatoms, 1, 2, 0, | |
1332 "Call FUNCTION on every symbol in OBARRAY.\n\ | |
1333 OBARRAY defaults to the value of `obarray'.") | |
1334 (function, obarray) | |
1335 Lisp_Object function, obarray; | |
1336 { | |
1337 Lisp_Object tem; | |
1338 | |
485 | 1339 if (NILP (obarray)) obarray = Vobarray; |
341 | 1340 obarray = check_obarray (obarray); |
1341 | |
1342 map_obarray (obarray, mapatoms_1, function); | |
1343 return Qnil; | |
1344 } | |
1345 | |
1346 #define OBARRAY_SIZE 509 | |
1347 | |
1348 void | |
1349 init_obarray () | |
1350 { | |
1351 Lisp_Object oblength; | |
1352 int hash; | |
1353 Lisp_Object *tem; | |
1354 | |
1355 XFASTINT (oblength) = OBARRAY_SIZE; | |
1356 | |
1357 Qnil = Fmake_symbol (make_pure_string ("nil", 3)); | |
1358 Vobarray = Fmake_vector (oblength, make_number (0)); | |
1359 initial_obarray = Vobarray; | |
1360 staticpro (&initial_obarray); | |
1361 /* Intern nil in the obarray */ | |
1362 /* These locals are to kludge around a pyramid compiler bug. */ | |
1363 hash = hash_string ("nil", 3); | |
1364 /* Separate statement here to avoid VAXC bug. */ | |
1365 hash %= OBARRAY_SIZE; | |
1366 tem = &XVECTOR (Vobarray)->contents[hash]; | |
1367 *tem = Qnil; | |
1368 | |
1369 Qunbound = Fmake_symbol (make_pure_string ("unbound", 7)); | |
1370 XSYMBOL (Qnil)->function = Qunbound; | |
1371 XSYMBOL (Qunbound)->value = Qunbound; | |
1372 XSYMBOL (Qunbound)->function = Qunbound; | |
1373 | |
1374 Qt = intern ("t"); | |
1375 XSYMBOL (Qnil)->value = Qnil; | |
1376 XSYMBOL (Qnil)->plist = Qnil; | |
1377 XSYMBOL (Qt)->value = Qt; | |
1378 | |
1379 /* Qt is correct even if CANNOT_DUMP. loadup.el will set to nil at end. */ | |
1380 Vpurify_flag = Qt; | |
1381 | |
1382 Qvariable_documentation = intern ("variable-documentation"); | |
1383 | |
1384 read_buffer_size = 100; | |
1385 read_buffer = (char *) malloc (read_buffer_size); | |
1386 } | |
1387 | |
1388 void | |
1389 defsubr (sname) | |
1390 struct Lisp_Subr *sname; | |
1391 { | |
1392 Lisp_Object sym; | |
1393 sym = intern (sname->symbol_name); | |
1394 XSET (XSYMBOL (sym)->function, Lisp_Subr, sname); | |
1395 } | |
1396 | |
1397 #ifdef NOTDEF /* use fset in subr.el now */ | |
1398 void | |
1399 defalias (sname, string) | |
1400 struct Lisp_Subr *sname; | |
1401 char *string; | |
1402 { | |
1403 Lisp_Object sym; | |
1404 sym = intern (string); | |
1405 XSET (XSYMBOL (sym)->function, Lisp_Subr, sname); | |
1406 } | |
1407 #endif /* NOTDEF */ | |
1408 | |
1409 /* New replacement for DefIntVar; it ignores the doc string argument | |
1410 on the assumption that make-docfile will handle that. */ | |
1411 /* Define an "integer variable"; a symbol whose value is forwarded | |
1412 to a C variable of type int. Sample call: */ | |
1413 /* DEFVARINT ("indent-tabs-mode", &indent_tabs_mode, "Documentation"); */ | |
1414 | |
1415 void | |
1416 defvar_int (namestring, address, doc) | |
1417 char *namestring; | |
1418 int *address; | |
1419 char *doc; | |
1420 { | |
1421 Lisp_Object sym; | |
1422 sym = intern (namestring); | |
1423 XSET (XSYMBOL (sym)->value, Lisp_Intfwd, address); | |
1424 } | |
1425 | |
1426 /* Similar but define a variable whose value is T if address contains 1, | |
1427 NIL if address contains 0 */ | |
1428 | |
1429 void | |
1430 defvar_bool (namestring, address, doc) | |
1431 char *namestring; | |
1432 int *address; | |
1433 char *doc; | |
1434 { | |
1435 Lisp_Object sym; | |
1436 sym = intern (namestring); | |
1437 XSET (XSYMBOL (sym)->value, Lisp_Boolfwd, address); | |
1438 } | |
1439 | |
1440 /* Similar but define a variable whose value is the Lisp Object stored at address. */ | |
1441 | |
1442 void | |
1443 defvar_lisp (namestring, address, doc) | |
1444 char *namestring; | |
1445 Lisp_Object *address; | |
1446 char *doc; | |
1447 { | |
1448 Lisp_Object sym; | |
1449 sym = intern (namestring); | |
1450 XSET (XSYMBOL (sym)->value, Lisp_Objfwd, address); | |
1451 staticpro (address); | |
1452 } | |
1453 | |
1454 /* Similar but don't request gc-marking of the C variable. | |
1455 Used when that variable will be gc-marked for some other reason, | |
1456 since marking the same slot twice can cause trouble with strings. */ | |
1457 | |
1458 void | |
1459 defvar_lisp_nopro (namestring, address, doc) | |
1460 char *namestring; | |
1461 Lisp_Object *address; | |
1462 char *doc; | |
1463 { | |
1464 Lisp_Object sym; | |
1465 sym = intern (namestring); | |
1466 XSET (XSYMBOL (sym)->value, Lisp_Objfwd, address); | |
1467 } | |
1468 | |
1469 #ifndef standalone | |
1470 | |
1471 /* Similar but define a variable whose value is the Lisp Object stored in | |
1472 the current buffer. address is the address of the slot in the buffer that is current now. */ | |
1473 | |
1474 void | |
1009
bf78b5ea9b3a
* lread.c (defvar_per_buffer): Support new TYPE argument, by
Jim Blandy <jimb@redhat.com>
parents:
851
diff
changeset
|
1475 defvar_per_buffer (namestring, address, type, doc) |
341 | 1476 char *namestring; |
1477 Lisp_Object *address; | |
1009
bf78b5ea9b3a
* lread.c (defvar_per_buffer): Support new TYPE argument, by
Jim Blandy <jimb@redhat.com>
parents:
851
diff
changeset
|
1478 Lisp_Object type; |
341 | 1479 char *doc; |
1480 { | |
1481 Lisp_Object sym; | |
1482 int offset; | |
1483 extern struct buffer buffer_local_symbols; | |
1484 | |
1485 sym = intern (namestring); | |
1486 offset = (char *)address - (char *)current_buffer; | |
1487 | |
1488 XSET (XSYMBOL (sym)->value, Lisp_Buffer_Objfwd, | |
1489 (Lisp_Object *) offset); | |
1490 *(Lisp_Object *)(offset + (char *)&buffer_local_symbols) = sym; | |
1009
bf78b5ea9b3a
* lread.c (defvar_per_buffer): Support new TYPE argument, by
Jim Blandy <jimb@redhat.com>
parents:
851
diff
changeset
|
1491 *(Lisp_Object *)(offset + (char *)&buffer_local_types) = type; |
341 | 1492 if (*(int *)(offset + (char *)&buffer_local_flags) == 0) |
1493 /* Did a DEFVAR_PER_BUFFER without initializing the corresponding | |
1494 slot of buffer_local_flags */ | |
1495 abort (); | |
1496 } | |
1497 | |
1498 #endif /* standalone */ | |
1499 | |
364 | 1500 init_lread () |
341 | 1501 { |
617 | 1502 char *normal; |
341 | 1503 |
364 | 1504 /* Compute the default load-path. */ |
617 | 1505 #ifdef CANNOT_DUMP |
1506 normal = PATH_LOADSEARCH; | |
638 | 1507 Vload_path = decode_env_path (0, normal); |
617 | 1508 #else |
1509 if (NILP (Vpurify_flag)) | |
1510 normal = PATH_LOADSEARCH; | |
1511 else | |
1512 normal = PATH_DUMPLOADSEARCH; | |
1513 | |
1514 /* In a dumped Emacs, we normally have to reset the value of | |
1515 Vload_path from PATH_LOADSEARCH, since the value that was dumped | |
1516 uses ../lisp, instead of the path of the installed elisp | |
1517 libraries. However, if it appears that Vload_path was changed | |
1518 from the default before dumping, don't override that value. */ | |
621 | 1519 if (initialized) |
1520 { | |
1521 Lisp_Object dump_path; | |
617 | 1522 |
638 | 1523 dump_path = decode_env_path (0, PATH_DUMPLOADSEARCH); |
621 | 1524 if (! NILP (Fequal (dump_path, Vload_path))) |
638 | 1525 Vload_path = decode_env_path (0, normal); |
621 | 1526 } |
1527 else | |
638 | 1528 Vload_path = decode_env_path (0, normal); |
364 | 1529 #endif |
1530 | |
341 | 1531 /* Warn if dirs in the *standard* path don't exist. */ |
617 | 1532 { |
1533 Lisp_Object path_tail; | |
341 | 1534 |
617 | 1535 for (path_tail = Vload_path; |
1536 !NILP (path_tail); | |
1537 path_tail = XCONS (path_tail)->cdr) | |
1538 { | |
1539 Lisp_Object dirfile; | |
1540 dirfile = Fcar (path_tail); | |
1541 if (XTYPE (dirfile) == Lisp_String) | |
1542 { | |
1543 dirfile = Fdirectory_file_name (dirfile); | |
1544 if (access (XSTRING (dirfile)->data, 0) < 0) | |
1545 printf ("Warning: lisp library (%s) does not exist.\n", | |
1546 XSTRING (Fcar (path_tail))->data); | |
1547 } | |
1548 } | |
1549 } | |
1550 | |
1551 /* If the EMACSLOADPATH environment variable is set, use its value. | |
1552 This doesn't apply if we're dumping. */ | |
1553 if (NILP (Vpurify_flag) | |
1554 && egetenv ("EMACSLOADPATH")) | |
364 | 1555 Vload_path = decode_env_path ("EMACSLOADPATH", normal); |
1556 | |
1557 Vvalues = Qnil; | |
1558 | |
341 | 1559 load_in_progress = 0; |
1560 } | |
1561 | |
1562 void | |
364 | 1563 syms_of_lread () |
341 | 1564 { |
1565 defsubr (&Sread); | |
1566 defsubr (&Sread_from_string); | |
1567 defsubr (&Sintern); | |
1568 defsubr (&Sintern_soft); | |
1569 defsubr (&Sload); | |
672 | 1570 defsubr (&Seval_buffer); |
341 | 1571 defsubr (&Seval_region); |
1572 defsubr (&Sread_char); | |
1573 defsubr (&Sread_char_exclusive); | |
1574 defsubr (&Sread_event); | |
1575 defsubr (&Sget_file_char); | |
1576 defsubr (&Smapatoms); | |
1577 | |
1578 DEFVAR_LISP ("obarray", &Vobarray, | |
1579 "Symbol table for use by `intern' and `read'.\n\ | |
1580 It is a vector whose length ought to be prime for best results.\n\ | |
1581 The vector's contents don't make sense if examined from Lisp programs;\n\ | |
1582 to find all the symbols in an obarray, use `mapatoms'."); | |
1583 | |
1584 DEFVAR_LISP ("values", &Vvalues, | |
1585 "List of values of all expressions which were read, evaluated and printed.\n\ | |
1586 Order is reverse chronological."); | |
1587 | |
1588 DEFVAR_LISP ("standard-input", &Vstandard_input, | |
1589 "Stream for read to get input from.\n\ | |
1590 See documentation of `read' for possible values."); | |
1591 Vstandard_input = Qt; | |
1592 | |
1593 DEFVAR_LISP ("load-path", &Vload_path, | |
1594 "*List of directories to search for files to load.\n\ | |
1595 Each element is a string (directory name) or nil (try default directory).\n\ | |
1596 Initialized based on EMACSLOADPATH environment variable, if any,\n\ | |
1597 otherwise to default specified in by file `paths.h' when Emacs was built."); | |
1598 | |
1599 DEFVAR_BOOL ("load-in-progress", &load_in_progress, | |
1600 "Non-nil iff inside of `load'."); | |
1601 | |
1602 DEFVAR_LISP ("after-load-alist", &Vafter_load_alist, | |
1603 "An alist of expressions to be evalled when particular files are loaded.\n\ | |
1604 Each element looks like (FILENAME FORMS...).\n\ | |
1605 When `load' is run and the file-name argument is FILENAME,\n\ | |
1606 the FORMS in the corresponding element are executed at the end of loading.\n\n\ | |
1607 FILENAME must match exactly! Normally FILENAME is the name of a library,\n\ | |
1608 with no directory specified, since that is how `load' is normally called.\n\ | |
1609 An error in FORMS does not undo the load,\n\ | |
1610 but does prevent execution of the rest of the FORMS."); | |
1611 Vafter_load_alist = Qnil; | |
1612 | |
1613 Qstandard_input = intern ("standard-input"); | |
1614 staticpro (&Qstandard_input); | |
1615 | |
1616 Qread_char = intern ("read-char"); | |
1617 staticpro (&Qread_char); | |
1618 | |
1619 Qget_file_char = intern ("get-file-char"); | |
1620 staticpro (&Qget_file_char); | |
1621 } |