⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lread.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -