📄 lread.c
字号:
/* Lisp parsing and input streams. Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.This file is part of GNU Emacs.GNU Emacs is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Emacs; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#undef NULL#include "config.h"#include "lisp.h"#ifndef standalone#include "buffer.h"#include "paths.h"#endif#ifdef lint#include <sys/inode.h>#endif /* lint */#ifndef X_OK#define X_OK 01#endifLisp_Object Qread_char, Qget_file_char, Qstandard_input;Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input;/* non-zero if inside `load' */int load_in_progress;/* Search path for files to be loaded. */Lisp_Object Vload_path;/* 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 int read_from_string_index;static int read_from_string_limit;/* Handle unreading and rereading of characters. Write READCHAR to read a character, UNREAD(c) to unread c to be read again. */static int unrch;static int readchar (readcharfun) Lisp_Object readcharfun;{ Lisp_Object tem; register struct buffer *inbuffer; register int c, mpos; if (unrch >= 0) { c = unrch; unrch = -1; return c; } if (XTYPE (readcharfun) == Lisp_Buffer) { inbuffer = XBUFFER (readcharfun); if (BUF_PT (inbuffer) >= BUF_ZV (inbuffer)) return -1; c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, BUF_PT (inbuffer)); SET_BUF_PT (inbuffer, BUF_PT (inbuffer) + 1); return c; } if (XTYPE (readcharfun) == Lisp_Marker) { inbuffer = XMARKER (readcharfun)->buffer; mpos = marker_position (readcharfun); if (mpos > BUF_ZV (inbuffer) - 1) return -1; c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, mpos); if (mpos != BUF_GPT (inbuffer)) XMARKER (readcharfun)->bufpos++; else Fset_marker (readcharfun, make_number (mpos + 1), Fmarker_buffer (readcharfun)); return c; } if (EQ (readcharfun, Qget_file_char)) return getc (instream); if (XTYPE (readcharfun) == Lisp_String) { register int c; /* This used to be return of a conditional expression, but that truncated -1 to a char on VMS. */ if (read_from_string_index < read_from_string_limit) c = XSTRING (readcharfun)->data[read_from_string_index++]; else c = -1; return c; } tem = call0 (readcharfun); if (NULL (tem)) return -1; return XINT (tem);}#define READCHAR readchar(readcharfun)#define UNREAD(c) (unrch = c)static Lisp_Object read0 (), read1 (), read_list (), read_vector ();/* get a character from the tty */DEFUN ("read-char", Fread_char, Sread_char, 0, 0, 0, "Read a character from the command input (keyboard or macro).\n\It is returned as a number.") (){ register Lisp_Object val;#ifndef standalone XSET (val, Lisp_Int, read_command_char (0));#else XSET (val, Lisp_Int, getchar ());#endif return val;}DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0, "Don't use this yourself.") (){ register Lisp_Object val; XSET (val, Lisp_Int, getc (instream)); return val;}void readevalloop ();static Lisp_Object load_unwind ();DEFUN ("load", Fload, Sload, 1, 4, 0, "Execute a file of Lisp code named FILE.\n\First tries FILE with .elc appended, then tries with .el,\n\ then tries FILE unmodified. Searches directories in load-path.\n\If optional second arg NOERROR is non-nil,\n\ report no error if FILE doesn't exist.\n\Print messages at start and end of loading unless\n\ optional third arg NOMESSAGE is non-nil.\n\If optional fourth arg NOSUFFIX is non-nil, don't try adding\n\ suffixes .elc or .el to the specified name FILE.\n\Return t if file exists.") (str, noerror, nomessage, nosuffix) Lisp_Object str, noerror, nomessage, nosuffix;{ register FILE *stream; register int fd = -1; register Lisp_Object lispstream; register FILE **ptr; int count = specpdl_ptr - specpdl; struct gcpro gcpro1; CHECK_STRING (str, 0); str = Fsubstitute_in_file_name (str); /* Avoid weird lossage with null string as arg, since it would try to load a directory as a Lisp file */ if (XSTRING (str)->size > 0) { fd = openp (Vload_path, str, !NULL (nosuffix) ? "" : ".elc:.el:", 0, 0); } if (fd < 0) if (NULL (noerror)) while (1) Fsignal (Qfile_error, Fcons (build_string ("Cannot open load file"), Fcons (str, Qnil))); else return Qnil; stream = fdopen (fd, "r"); if (stream == 0) { close (fd); error ("Failure to create stdio stream for %s", XSTRING (str)->data); } if (NULL (nomessage)) message ("Loading %s...", XSTRING (str)->data); GCPRO1 (str); ptr = (FILE **) xmalloc (sizeof (FILE *)); *ptr = stream; XSET (lispstream, Lisp_Internal_Stream, (int) ptr); record_unwind_protect (load_unwind, lispstream); load_in_progress++; readevalloop (Qget_file_char, stream, Feval, 0); unbind_to (count); UNGCPRO; if (!noninteractive && NULL (nomessage)) message ("Loading %s...done", XSTRING (str)->data); return Qt;}static Lisp_Objectload_unwind (stream) /* used as unwind-protect function in load */ Lisp_Object stream;{ fclose (*(FILE **) XSTRING (stream)); free (XPNTR (stream)); if (--load_in_progress < 0) load_in_progress = 0; return Qnil;}static intabsolute_filename_p (pathname) Lisp_Object pathname;{ register unsigned char *s = XSTRING (pathname)->data; return (*s == '~' || *s == '/'#ifdef VMS || index (s, ':')#endif /* VMS */ );}/* Search for a file whose name is STR, looking in directories in the Lisp list PATH, and trying suffixes from SUFFIX. SUFFIX is a string containing possible suffixes separated by colons. On success, returns a file descriptor. On failure, returns -1. EXEC_ONLY nonzero means don't open the files, just look for one that is executable. In this case, returns 1 on success. If STOREPTR is nonzero, it points to a slot where the name of the file actually found should be stored as a Lisp string. Nil is stored there on failure. */intopenp (path, str, suffix, storeptr, exec_only) Lisp_Object path, str; char *suffix; Lisp_Object *storeptr; int exec_only;{ register int fd; int fn_size = 100; char buf[100]; register char *fn = buf; int absolute = 0; int want_size; register Lisp_Object filename; struct stat st; if (storeptr) *storeptr = Qnil; if (absolute_filename_p (str)) absolute = 1; for (; !NULL (path); path = Fcdr (path)) { char *nsuffix; filename = Fexpand_file_name (str, Fcar (path)); if (!absolute_filename_p (filename)) /* If there are non-absolute elts in PATH (eg ".") */ /* Of course, this could conceivably lose if luser sets default-directory to be something non-absolute... */ { filename = Fexpand_file_name (filename, current_buffer->directory); if (!absolute_filename_p (filename)) /* Give up on this path element! */ continue; } /* Calculate maximum size of any filename made from this path element/specified file name and any possible suffix. */ want_size = strlen (suffix) + XSTRING (filename)->size + 1; if (fn_size < want_size) fn = (char *) alloca (fn_size = 100 + want_size); nsuffix = suffix; /* Loop over suffixes. */ while (1) { char *esuffix = (char *) index (nsuffix, ':'); int lsuffix = esuffix ? esuffix - nsuffix : strlen (nsuffix); /* Concatenate path element/specified name with the suffix. */ strncpy (fn, XSTRING (filename)->data, XSTRING (filename)->size); fn[XSTRING (filename)->size] = 0; if (lsuffix != 0) /* Bug happens on CCI if lsuffix is 0. */ strncat (fn, nsuffix, lsuffix); /* Ignore file if it's a directory. */ if (stat (fn, &st) >= 0 && (st.st_mode & S_IFMT) != S_IFDIR) { /* Check that we can access or open it. */ if (exec_only) fd = !access (fn, X_OK) ? 1 : -1; else fd = open (fn, 0, 0); if (fd >= 0) { /* We succeeded; return this descriptor and filename. */ if (storeptr) *storeptr = build_string (fn); return fd; } } /* Advance to next suffix. */ if (esuffix == 0) break; nsuffix += lsuffix + 1; } if (absolute) return -1; } return -1;}Lisp_Objectunreadpure () /* Used as unwind-protect function in readevalloop */{ read_pure = 0; return Qnil;}static voidreadevalloop (readcharfun, stream, evalfun, printflag) Lisp_Object readcharfun; FILE *stream; Lisp_Object (*evalfun) (); int printflag;{ register int c; register Lisp_Object val; register int xunrch; int count = specpdl_ptr - specpdl; specbind (Qstandard_input, readcharfun); unrch = -1; while (1) { instream = stream; c = READCHAR; if (c == ';') { while ((c = READCHAR) != '\n' && c != -1); continue; } if (c < 0) break; if (c == ' ' || c == '\t' || c == '\n' || c == '\f') continue; if (!NULL (Vpurify_flag) && c == '(') { record_unwind_protect (unreadpure, Qnil); val = read_list (-1, readcharfun); unbind_to (count + 1); } else { UNREAD (c); val = read0 (readcharfun); } xunrch = unrch; unrch = -1; val = (*evalfun) (val); if (printflag) { Vvalues = Fcons (val, Vvalues); if (EQ (Vstandard_output, Qt)) Fprin1 (val, Qnil); else Fprint (val, Qnil); } unrch = xunrch; } unbind_to (count);}#ifndef standaloneDEFUN ("eval-current-buffer", Feval_current_buffer, Seval_current_buffer, 0, 1, "", "Execute the current buffer as Lisp code.\n\Programs can pass argument PRINTFLAG which controls printing of output:\n\nil means discard it; anything else is stream for print.") (printflag) Lisp_Object printflag;{ int count = specpdl_ptr - specpdl; Lisp_Object tem; if (NULL (printflag)) tem = Qsymbolp; else tem = printflag; specbind (Qstandard_output, tem); record_unwind_protect (save_excursion_restore, save_excursion_save ()); SET_PT (BEGV); readevalloop (Fcurrent_buffer (), 0, Feval, !NULL (printflag)); unbind_to (count); return Qnil;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -