Exemple #1
0
static u16 global_add(struct global_state *gstate,
		      struct string *name, value val)
{
  struct symbol *pos;
  ivalue old_size, aindex;

  GCCHECK(val);

  GCPRO2(gstate, name);
  old_size = vector_len(gstate->environment->values);
  aindex = env_add_entry(gstate->environment, val);
  if (vector_len(gstate->environment->values) != old_size) /* Increase mvars too */
    {
      struct vector *new_mvars = alloc_vector(vector_len(gstate->environment->values));

      memcpy(new_mvars->data, gstate->mvars->data,
	     gstate->mvars->o.size - sizeof(struct obj));
      gstate->mvars = new_mvars;
    }
  GCPOP(2);
  gstate->mvars->data[aindex] = makeint(var_normal);
  pos = table_add_fast(gstate->global, name, makeint(aindex));
  SET_READONLY(pos); /* index of global vars never changes */

  return aindex;
}
Exemple #2
0
static Lisp_Object
gtk_canonicalize_console_connection (Lisp_Object connection, Error_behavior errb)
{
  Lisp_Object hostname = Qnil;
  struct gcpro gcpro1, gcpro2;

  GCPRO2 (connection, hostname);

  connection = build_string ("gtk");

  RETURN_UNGCPRO (connection);
}
Exemple #3
0
struct symbol *alloc_symbol(struct string *name, value data)
{
  struct symbol *newp;

  GCCHECK(name);
  GCCHECK(data);
  GCPRO2(name, data);
  newp = (struct symbol *)unsafe_allocate_record(type_symbol, 2);
  GCPOP(2);
  newp->name = name;
  newp->data = data;

  return newp;
}
Exemple #4
0
struct list *alloc_list(value car, value cdr)
{
  struct list *newp;

  GCCHECK(car);
  GCCHECK(cdr);
  GCPRO2(car, cdr);
  newp = (struct list *)unsafe_allocate_record(type_pair, 2);
  GCPOP(2);
  newp->car = car;
  newp->cdr = cdr;

  return newp;
}
Exemple #5
0
u16 mglobal_lookup(struct global_state *gstate, struct string *name)
/* Returns: the index for global variable name in environment.
     If name doesn't exist yet, it is created with a variable
     whose value is NULL.
*/
{
  struct symbol *pos;
  struct string *tname;

  if (table_lookup(gstate->global, name->str, &pos))
    return (u16)intval(pos->data);

  GCPRO2(gstate, name);
  tname = alloc_string_n(string_len(name));
  strcpy(tname->str, name->str);
  GCPOP(2);

  return global_add(gstate, tname, NULL);
}
Exemple #6
0
static void write_code(struct oport *f, struct code *c)
{
  u16 nbins, i;

  GCPRO2(f, c);
  nbins = code_length(c);
  if (c->varname)
    {
      write_string(f, prt_display, c->varname);
      pputs(": ", f);
    }
  pprintf(f, "Code[");
  write_string(f, prt_display, c->filename);
  pprintf(f, ":%u] %u bytes:\n", c->lineno, nbins);
  i = 0;
  while (i < nbins)
    i += write_instruction(f, c->ins + i, i);

  pprintf(f, "\n%u locals, %u stack\n",
	  c->nb_locals, c->stkdepth);
  GCPOP(2);
}
Exemple #7
0
static void
single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *skp_v)
{
  Lisp_Object map, item_string, enabled;
  struct gcpro gcpro1, gcpro2;
  bool res;
  struct skp *skp = skp_v;

  /* Parse the menu item and leave the result in item_properties.  */
  GCPRO2 (key, item);
  res = parse_menu_item (item, 0);
  UNGCPRO;
  if (!res)
    return;			/* Not a menu item.  */

  map = AREF (item_properties, ITEM_PROPERTY_MAP);

  enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
  item_string = AREF (item_properties, ITEM_PROPERTY_NAME);

  if (!NILP (map) && SREF (item_string, 0) == '@')
    {
      if (!NILP (enabled))
	/* An enabled separate pane. Remember this to handle it later.  */
	skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)),
				   skp->pending_maps);
      return;
    }

  /* Simulate radio buttons and toggle boxes by putting a prefix in
     front of them.  */
  if (!have_boxes ())
    {
      char const *prefix = 0;
      Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
      if (!NILP (type))
	{
	  Lisp_Object selected
	    = AREF (item_properties, ITEM_PROPERTY_SELECTED);

	  if (skp->notbuttons)
	    /* The first button. Line up previous items in this menu.  */
	    {
	      int idx = skp->notbuttons; /* Index for first item this menu.  */
	      int submenu = 0;
	      Lisp_Object tem;
	      while (idx < menu_items_used)
		{
		  tem
		    = AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
		  if (NILP (tem))
		    {
		      idx++;
		      submenu++;		/* Skip sub menu.  */
		    }
		  else if (EQ (tem, Qlambda))
		    {
		      idx++;
		      submenu--;		/* End sub menu.  */
		    }
		  else if (EQ (tem, Qt))
		    idx += 3;		/* Skip new pane marker. */
		  else if (EQ (tem, Qquote))
		    idx++;		/* Skip a left, right divider. */
		  else
		    {
		      if (!submenu && SREF (tem, 0) != '\0'
			  && SREF (tem, 0) != '-')
			ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
			      concat2 (SCOPED_STRING ("    "), tem));
		      idx += MENU_ITEMS_ITEM_LENGTH;
		    }
		}
	      skp->notbuttons = 0;
	    }

	  /* Calculate prefix, if any, for this item.  */
	  if (EQ (type, QCtoggle))
	    prefix = NILP (selected) ? "[ ] " : "[X] ";
	  else if (EQ (type, QCradio))
	    prefix = NILP (selected) ? "( ) " : "(*) ";
	}
      /* Not a button. If we have earlier buttons, then we need a prefix.  */
      else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
	       && SREF (item_string, 0) != '-')
	prefix = "    ";

      if (prefix)
	item_string = concat2 (SCOPED_STRING (prefix), item_string);
  }

  if ((FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
       || FRAME_MSDOS_P (XFRAME (Vmenu_updating_frame)))
      && !NILP (map))
    /* Indicate visually that this is a submenu.  */
    item_string = concat2 (item_string, SCOPED_STRING (" >"));

  push_menu_item (item_string, enabled, key,
		  AREF (item_properties, ITEM_PROPERTY_DEF),
		  AREF (item_properties, ITEM_PROPERTY_KEYEQ),
		  AREF (item_properties, ITEM_PROPERTY_TYPE),
		  AREF (item_properties, ITEM_PROPERTY_SELECTED),
		  AREF (item_properties, ITEM_PROPERTY_HELP));

#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
  /* Display a submenu using the toolkit.  */
  if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame))
      && ! (NILP (map) || NILP (enabled)))
    {
      push_submenu_start ();
      single_keymap_panes (map, Qnil, key, skp->maxdepth - 1);
      push_submenu_end ();
    }
#endif
}
Exemple #8
0
Lisp_Object
directory_files_internal (Lisp_Object directory, Lisp_Object full,
			  Lisp_Object match, Lisp_Object nosort, bool attrs,
			  Lisp_Object id_format)
{
  DIR *d;
  int fd;
  ptrdiff_t directory_nbytes;
  Lisp_Object list, dirfilename, encoded_directory;
  struct re_pattern_buffer *bufp = NULL;
  bool needsep = 0;
  ptrdiff_t count = SPECPDL_INDEX ();
  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
  struct dirent *dp;
#ifdef WINDOWSNT
  Lisp_Object w32_save = Qnil;
#endif

  /* Don't let the compiler optimize away all copies of DIRECTORY,
     which would break GC; see Bug#16986.  Although this is required
     only in the common case where GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS,
     it shouldn't break anything in the other cases.  */
  Lisp_Object volatile directory_volatile = directory;

  /* Because of file name handlers, these functions might call
     Ffuncall, and cause a GC.  */
  list = encoded_directory = dirfilename = Qnil;
  GCPRO5 (match, directory, list, dirfilename, encoded_directory);
  dirfilename = Fdirectory_file_name (directory);

  if (!NILP (match))
    {
      CHECK_STRING (match);

      /* MATCH might be a flawed regular expression.  Rather than
	 catching and signaling our own errors, we just call
	 compile_pattern to do the work for us.  */
      /* Pass 1 for the MULTIBYTE arg
	 because we do make multibyte strings if the contents warrant.  */
# ifdef WINDOWSNT
      /* Windows users want case-insensitive wildcards.  */
      bufp = compile_pattern (match, 0,
			      BVAR (&buffer_defaults, case_canon_table), 0, 1);
# else	/* !WINDOWSNT */
      bufp = compile_pattern (match, 0, Qnil, 0, 1);
# endif	 /* !WINDOWSNT */
    }

  /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
     run_pre_post_conversion_on_str which calls Lisp directly and
     indirectly.  */
  if (STRING_MULTIBYTE (dirfilename))
    dirfilename = ENCODE_FILE (dirfilename);
  encoded_directory = (STRING_MULTIBYTE (directory)
		       ? ENCODE_FILE (directory) : directory);

  /* Now *bufp is the compiled form of MATCH; don't call anything
     which might compile a new regexp until we're done with the loop!  */

  d = open_directory (SSDATA (dirfilename), &fd);
  if (d == NULL)
    report_file_error ("Opening directory", directory);

  /* Unfortunately, we can now invoke expand-file-name and
     file-attributes on filenames, both of which can throw, so we must
     do a proper unwind-protect.  */
  record_unwind_protect_ptr (directory_files_internal_unwind, d);

#ifdef WINDOWSNT
  if (attrs)
    {
      extern int is_slow_fs (const char *);

      /* Do this only once to avoid doing it (in w32.c:stat) for each
	 file in the directory, when we call Ffile_attributes below.  */
      record_unwind_protect (directory_files_internal_w32_unwind,
			     Vw32_get_true_file_attributes);
      w32_save = Vw32_get_true_file_attributes;
      if (EQ (Vw32_get_true_file_attributes, Qlocal))
	{
	  /* w32.c:stat will notice these bindings and avoid calling
	     GetDriveType for each file.  */
	  if (is_slow_fs (SDATA (dirfilename)))
	    Vw32_get_true_file_attributes = Qnil;
	  else
	    Vw32_get_true_file_attributes = Qt;
	}
    }
#endif

  directory_nbytes = SBYTES (directory);
  re_match_object = Qt;

  /* Decide whether we need to add a directory separator.  */
  if (directory_nbytes == 0
      || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
    needsep = 1;

  /* Loop reading blocks until EOF or error.  */
  for (;;)
    {
      ptrdiff_t len;
      bool wanted = 0;
      Lisp_Object name, finalname;
      struct gcpro gcpro1, gcpro2;

      errno = 0;
      dp = readdir (d);
      if (!dp)
	{
	  if (errno == EAGAIN || errno == EINTR)
	    {
	      QUIT;
	      continue;
	    }
	  break;
	}

      len = dirent_namelen (dp);
      name = finalname = make_unibyte_string (dp->d_name, len);
      GCPRO2 (finalname, name);

      /* Note: DECODE_FILE can GC; it should protect its argument,
	 though.  */
      name = DECODE_FILE (name);
      len = SBYTES (name);

      /* Now that we have unwind_protect in place, we might as well
	 allow matching to be interrupted.  */
      immediate_quit = 1;
      QUIT;

      if (NILP (match)
	  || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0)
	wanted = 1;

      immediate_quit = 0;

      if (wanted)
	{
	  if (!NILP (full))
	    {
	      Lisp_Object fullname;
	      ptrdiff_t nbytes = len + directory_nbytes + needsep;
	      ptrdiff_t nchars;

	      fullname = make_uninit_multibyte_string (nbytes, nbytes);
	      memcpy (SDATA (fullname), SDATA (directory),
		      directory_nbytes);

	      if (needsep)
		SSET (fullname, directory_nbytes, DIRECTORY_SEP);

	      memcpy (SDATA (fullname) + directory_nbytes + needsep,
		      SDATA (name), len);

	      nchars = multibyte_chars_in_text (SDATA (fullname), nbytes);

	      /* Some bug somewhere.  */
	      if (nchars > nbytes)
		emacs_abort ();

	      STRING_SET_CHARS (fullname, nchars);
	      if (nchars == nbytes)
		STRING_SET_UNIBYTE (fullname);

	      finalname = fullname;
	    }
	  else
	    finalname = name;

	  if (attrs)
	    {
	      Lisp_Object fileattrs
		= file_attributes (fd, dp->d_name, id_format);
	      list = Fcons (Fcons (finalname, fileattrs), list);
	    }
	  else
	    list = Fcons (finalname, list);
	}

      UNGCPRO;
    }

  block_input ();
  closedir (d);
  unblock_input ();
#ifdef WINDOWSNT
  if (attrs)
    Vw32_get_true_file_attributes = w32_save;
#endif

  /* Discard the unwind protect.  */
  specpdl_ptr = specpdl + count;

  if (NILP (nosort))
    list = Fsort (Fnreverse (list),
		  attrs ? Qfile_attributes_lessp : Qstring_lessp);

  (void) directory_volatile;
  RETURN_UNGCPRO (list);
}
Exemple #9
0
static void
single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *skp_v)
{
  Lisp_Object map, item_string, enabled;
  struct gcpro gcpro1, gcpro2;
  int res;
  struct skp *skp = skp_v;

  /* Parse the menu item and leave the result in item_properties.  */
  GCPRO2 (key, item);
  res = parse_menu_item (item, 0);
  UNGCPRO;
  if (!res)
    return;			/* Not a menu item.  */

  map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];

  enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
  item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];

  if (!NILP (map) && SREF (item_string, 0) == '@')
    {
      if (!NILP (enabled))
	/* An enabled separate pane. Remember this to handle it later.  */
	skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)),
				   skp->pending_maps);
      return;
    }

#if defined(HAVE_X_WINDOWS) || defined(MSDOS)
#ifndef HAVE_BOXES
  /* Simulate radio buttons and toggle boxes by putting a prefix in
     front of them.  */
  {
    Lisp_Object prefix = Qnil;
    Lisp_Object type = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE];
    if (!NILP (type))
      {
	Lisp_Object selected
	  = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];

	if (skp->notbuttons)
	  /* The first button. Line up previous items in this menu.  */
	  {
	    int index = skp->notbuttons; /* Index for first item this menu.  */
	    int submenu = 0;
	    Lisp_Object tem;
	    while (index < menu_items_used)
	      {
		tem
		  = XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME];
		if (NILP (tem))
		  {
		    index++;
		    submenu++;		/* Skip sub menu.  */
		  }
		else if (EQ (tem, Qlambda))
		  {
		    index++;
		    submenu--;		/* End sub menu.  */
		  }
		else if (EQ (tem, Qt))
		  index += 3;		/* Skip new pane marker. */
		else if (EQ (tem, Qquote))
		  index++;		/* Skip a left, right divider. */
		else
		  {
		    if (!submenu && SREF (tem, 0) != '\0'
			&& SREF (tem, 0) != '-')
		      XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
			= concat2 (build_string ("    "), tem);
		    index += MENU_ITEMS_ITEM_LENGTH;
		  }
	      }
	    skp->notbuttons = 0;
	  }

	/* Calculate prefix, if any, for this item.  */
	if (EQ (type, QCtoggle))
	  prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
	else if (EQ (type, QCradio))
	  prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
      }
    /* Not a button. If we have earlier buttons, then we need a prefix.  */
    else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
	     && SREF (item_string, 0) != '-')
      prefix = build_string ("    ");

    if (!NILP (prefix))
      item_string = concat2 (prefix, item_string);
  }
#endif /* not HAVE_BOXES */

#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
  if (!NILP (map))
    /* Indicate visually that this is a submenu.  */
    item_string = concat2 (item_string, build_string (" >"));
#endif

#endif /* HAVE_X_WINDOWS || MSDOS */

  push_menu_item (item_string, enabled, key,
		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);

#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
  /* Display a submenu using the toolkit.  */
  if (! (NILP (map) || NILP (enabled)))
    {
      push_submenu_start ();
      single_keymap_panes (map, Qnil, key, skp->maxdepth - 1);
      push_submenu_end ();
    }
#endif
}
Exemple #10
0
static Lisp_Object
extract_object_file_name (int fd, EMACS_INT doc_pos,
			  Ibyte *name_nonreloc, Lisp_Object name_reloc,
			  int standard_doc_file)
{
  Ibyte buf[DOC_MAX_FILENAME_LENGTH+1];
  Ibyte *buffer = buf;
  int buffer_size = sizeof (buf) - 1, space_left;
  Ibyte *from, *to;
  REGISTER Ibyte *p = buffer;
  Lisp_Object return_me;
  Lisp_Object fdstream = Qnil, instream = Qnil;
  struct gcpro gcpro1, gcpro2;
  EMACS_INT position, seenS = 0;

  GCPRO2 (fdstream, instream);

  position = doc_pos > buffer_size  ? 
    doc_pos - buffer_size : 0; 

  if (0 > lseek (fd, position, 0))
    {
      if (name_nonreloc)
	name_reloc = build_istring (name_nonreloc);
      return_me = list3 (build_msg_string
			 ("Position out of range in doc string file"),
			  name_reloc, make_fixnum (position));
      goto done;
    }

  fdstream = make_filedesc_input_stream (fd, 0, -1, 0, NULL);
  Lstream_set_buffering (XLSTREAM (fdstream), LSTREAM_UNBUFFERED, 0);
  instream =
    make_coding_input_stream
      (XLSTREAM (fdstream), standard_doc_file ? Qescape_quoted : Qbinary,
       CODING_DECODE, 0);
  Lstream_set_buffering (XLSTREAM (instream), LSTREAM_UNBUFFERED, 0);

  space_left = buffer_size - (p - buffer);
  while (space_left > 0)
    {
      int nread;

      nread = Lstream_read (XLSTREAM (instream), p, space_left);
      if (nread < 0)
	{
	  return_me = list1 (build_msg_string
			     ("Read error on documentation file"));
	  goto done;
	}

      p[nread] = 0;

      if (!nread)
	break;

      p += nread;
      space_left = buffer_size - (p - buffer);
    }

  /* First, search backward for the "\037S" that marks the beginning of the
     file name, then search forward from that to the newline or to the end
     of the buffer. */
  from = p; 

  while (from > buf)
    {
      --from;
      if (seenS)
	{
	  if ('\037' == *from) 
	    {
	      /* Got a file name; adjust `from' to point to it, break out of
		 the loop.  */
	      from += 2;
	      break; 
	    }
	}
      /* Is *from 'S' ? */
      seenS = ('S' == *from);
    }

  if (buf == from)
    {
      /* We've scanned back to the beginning of the buffer without hitting
	 the file name. Either the file name plus the symbol name is longer
	 than DOC_MAX_FILENAME_LENGTH--which shouldn't happen, because it'll
	 trigger an assertion failure in make-docfile, the DOC file is
	 corrupt, or it was produced by a version of make-docfile that
	 doesn't store the file name with the symbol name and docstring.  */ 
      return_me = list1 (build_msg_string
			 ("Object file name not stored in doc file"));
      goto done;
    }

  to = from;
  /* Search for the end of the file name. */
  while (++to < p)
    {
      if ('\n' == *to || '\037' == *to)
	{
	  break;
	}
    }

  /* Don't require the file name to end in a newline. */
  return_me = make_string (from, to - from);

 done:
  if (!NILP (instream))
    {
      Lstream_delete (XLSTREAM (instream));
      Lstream_delete (XLSTREAM (fdstream));
    }

  UNGCPRO;
  return return_me;
}
Exemple #11
0
Lisp_Object
unparesseuxify_doc_string (int fd, EMACS_INT position,
                           Ibyte *name_nonreloc, Lisp_Object name_reloc,
			   int standard_doc_file)
{
  Ibyte buf[512 * 32 + 1];
  Ibyte *buffer = buf;
  int buffer_size = sizeof (buf) - 1;
  Ibyte *from, *to;
  REGISTER Ibyte *p = buffer;
  Lisp_Object return_me;
  Lisp_Object fdstream = Qnil, instream = Qnil;
  struct gcpro gcpro1, gcpro2;

  GCPRO2 (fdstream, instream);

  if (0 > lseek (fd, position, 0))
    {
      if (name_nonreloc)
	name_reloc = build_istring (name_nonreloc);
      return_me = list3 (build_msg_string
			 ("Position out of range in doc string file"),
			  name_reloc, make_fixnum (position));
      goto done;
    }

  fdstream = make_filedesc_input_stream (fd, 0, -1, 0, NULL);
  Lstream_set_buffering (XLSTREAM (fdstream), LSTREAM_UNBUFFERED, 0);
  instream =
    make_coding_input_stream
      /* Major trouble if we are too clever when reading byte-code
	 instructions!

	 #### We should have a way of handling escape-quoted elc files
	 (i.e. files with non-ASCII/Latin-1 chars in them).  Currently this
	 is "solved" in bytecomp.el by never inserting lazy references in
	 such files. */
      (XLSTREAM (fdstream), standard_doc_file ? Qescape_quoted : Qbinary,
       CODING_DECODE, 0);
  Lstream_set_buffering (XLSTREAM (instream), LSTREAM_UNBUFFERED, 0);
  
  /* Read the doc string into a buffer.
     Use the fixed buffer BUF if it is big enough; otherwise allocate one.
     We store the buffer in use in BUFFER and its size in BUFFER_SIZE.  */

  while (1)
    {
      int space_left = buffer_size - (p - buffer);
      int nread;

      /* Switch to a bigger buffer if we need one.  */
      if (space_left == 0)
	{
          Ibyte *old_buffer = buffer;
	  buffer_size *= 2;

	  if (buffer == buf)
	    {
	      buffer = xnew_ibytes (buffer_size + 1);
	      memcpy (buffer, old_buffer, p - old_buffer);
	    }
	  else
            XREALLOC_ARRAY (buffer, Ibyte, buffer_size + 1);
          p += buffer - old_buffer;
	  space_left = buffer_size - (p - buffer);
	}

      /* Don't read too much at one go.  */
      if (space_left > 1024 * 8)
	space_left = 1024 * 8;
      nread = Lstream_read (XLSTREAM (instream), p, space_left);
      if (nread < 0)
	{
	  return_me = list1 (build_msg_string
			     ("Read error on documentation file"));
	  goto done;
	}
      p[nread] = 0;
      if (!nread)
	break;
      {
	Ibyte *p1 = qxestrchr (p, '\037'); /* End of doc string marker */
	if (p1)
	  {
	    *p1 = 0;
	    p = p1;
	    break;
	  }
      }
      p += nread;
    }

  /* Scan the text and remove quoting with ^A (char code 1).
     ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_.  */
  from = to = buffer;
  while (from < p)
    {
      if (*from != 1 /*^A*/)
	*to++ = *from++;
      else
	{
	  int c = *(++from);

	  from++;
          switch (c)
            {
            case 1:   *to++ =  c;     break;
            case '0': *to++ = '\0';   break;
            case '_': *to++ = '\037'; break;
            default:
              return_me = list2 (build_msg_string
	("Invalid data in documentation file -- ^A followed by weird code"),
                                 make_fixnum (c));
              goto done;
            }
	}
    }

  return_me = make_string (buffer, to - buffer);

 done:
  if (!NILP (instream))
    {
      Lstream_delete (XLSTREAM (instream));
      Lstream_delete (XLSTREAM (fdstream));
    }
  UNGCPRO;
  if (buffer != buf) /* We must have allocated buffer above */
    xfree (buffer);
  return return_me;
}
static void
x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
		 Lisp_Object frame)
{
  struct frame *f = XFRAME (frame);
  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
  Time timestamp = last_event_timestamp;
  OSStatus err;
  Selection sel;
  struct gcpro gcpro1, gcpro2;
  Lisp_Object rest, handler_fn, value, target_type;

  GCPRO2 (selection_name, selection_value);

  block_input ();

  err = mac_get_selection_from_symbol (selection_name, 1, &sel);
  if (err == noErr && sel)
    {
      /* Don't allow a quit within the converter.
	 When the user types C-g, he would be surprised
	 if by luck it came during a converter.  */
      ptrdiff_t count = SPECPDL_INDEX ();
      specbind (Qinhibit_quit, Qt);

      for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest))
	{
	  if (!(CONSP (XCAR (rest))
		&& (target_type = XCAR (XCAR (rest)),
		    SYMBOLP (target_type))
		&& mac_valid_selection_target_p (target_type)
		&& (handler_fn = XCDR (XCAR (rest)),
		    SYMBOLP (handler_fn))))
	    continue;

	  if (!NILP (handler_fn))
	    value = call3 (handler_fn, selection_name,
			   target_type, selection_value);
	  else
	    value = Qnil;

	  if (NILP (value))
	    continue;

	  if (mac_valid_selection_value_p (value, target_type))
	    err = mac_put_selection_value (sel, target_type, value);
	  else if (CONSP (value)
		   && EQ (XCAR (value), target_type)
		   && mac_valid_selection_value_p (XCDR (value), target_type))
	    err = mac_put_selection_value (sel, target_type, XCDR (value));
	}

      unbind_to (count, Qnil);
    }

  unblock_input ();

  UNGCPRO;

  if (sel && err != noErr)
    error ("Can't set selection");

  /* Now update the local cache */
  {
    Lisp_Object selection_data;
    Lisp_Object ownership_info;
    Lisp_Object prev_value;

    if (sel)
      {
	block_input ();
	ownership_info = mac_get_selection_ownership_info (sel);
	unblock_input ();
      }
    else
      ownership_info = Qnil; 	/* dummy value for local-only selection */
    selection_data = list5 (selection_name, selection_value,
			    INTEGER_TO_CONS (timestamp), frame, ownership_info);
    prev_value = LOCAL_SELECTION (selection_name, dpyinfo);

    tset_selection_alist
      (dpyinfo->terminal,
       Fcons (selection_data, dpyinfo->terminal->Vselection_alist));

    /* If we already owned the selection, remove the old selection
       data.  Don't use Fdelq as that may QUIT.  */
    if (!NILP (prev_value))
      {
	/* We know it's not the CAR, so it's easy.  */
	Lisp_Object rest = dpyinfo->terminal->Vselection_alist;
	for (; CONSP (rest); rest = XCDR (rest))
	  if (EQ (prev_value, Fcar (XCDR (rest))))
	    {
	      XSETCDR (rest, XCDR (XCDR (rest)));
	      break;
	    }
      }
  }
}
Exemple #13
0
Lisp_Object
directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, int attrs, Lisp_Object id_format)
{
  DIR *d;
  int directory_nbytes;
  Lisp_Object list, dirfilename, encoded_directory;
  struct re_pattern_buffer *bufp = NULL;
  int needsep = 0;
  int count = SPECPDL_INDEX ();
  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
  DIRENTRY *dp;
#ifdef WINDOWSNT
  Lisp_Object w32_save = Qnil;
#endif

  /* Because of file name handlers, these functions might call
     Ffuncall, and cause a GC.  */
  list = encoded_directory = dirfilename = Qnil;
  GCPRO5 (match, directory, list, dirfilename, encoded_directory);
  dirfilename = Fdirectory_file_name (directory);

  if (!NILP (match))
    {
      CHECK_STRING (match);

      /* MATCH might be a flawed regular expression.  Rather than
	 catching and signaling our own errors, we just call
	 compile_pattern to do the work for us.  */
      /* Pass 1 for the MULTIBYTE arg
	 because we do make multibyte strings if the contents warrant.  */
# ifdef WINDOWSNT
      /* Windows users want case-insensitive wildcards.  */
      bufp = compile_pattern (match, 0,
			      buffer_defaults.case_canon_table, 0, 1);
# else	/* !WINDOWSNT */
      bufp = compile_pattern (match, 0, Qnil, 0, 1);
# endif	 /* !WINDOWSNT */
    }

  /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
     run_pre_post_conversion_on_str which calls Lisp directly and
     indirectly.  */
  if (STRING_MULTIBYTE (dirfilename))
    dirfilename = ENCODE_FILE (dirfilename);
  encoded_directory = (STRING_MULTIBYTE (directory)
		       ? ENCODE_FILE (directory) : directory);

  /* Now *bufp is the compiled form of MATCH; don't call anything
     which might compile a new regexp until we're done with the loop!  */

  BLOCK_INPUT;
  d = opendir (SDATA (dirfilename));
  UNBLOCK_INPUT;
  if (d == NULL)
    report_file_error ("Opening directory", Fcons (directory, Qnil));

  /* Unfortunately, we can now invoke expand-file-name and
     file-attributes on filenames, both of which can throw, so we must
     do a proper unwind-protect.  */
  record_unwind_protect (directory_files_internal_unwind,
			 make_save_value (d, 0));

#ifdef WINDOWSNT
  if (attrs)
    {
      extern int is_slow_fs (const char *);

      /* Do this only once to avoid doing it (in w32.c:stat) for each
	 file in the directory, when we call Ffile_attributes below.  */
      record_unwind_protect (directory_files_internal_w32_unwind,
			     Vw32_get_true_file_attributes);
      w32_save = Vw32_get_true_file_attributes;
      if (EQ (Vw32_get_true_file_attributes, Qlocal))
	{
	  /* w32.c:stat will notice these bindings and avoid calling
	     GetDriveType for each file.  */
	  if (is_slow_fs (SDATA (dirfilename)))
	    Vw32_get_true_file_attributes = Qnil;
	  else
	    Vw32_get_true_file_attributes = Qt;
	}
    }
#endif

  directory_nbytes = SBYTES (directory);
  re_match_object = Qt;

  /* Decide whether we need to add a directory separator.  */
  if (directory_nbytes == 0
      || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
    needsep = 1;

  /* Loop reading blocks until EOF or error.  */
  for (;;)
    {
      errno = 0;
      dp = readdir (d);

      if (dp == NULL && (0
#ifdef EAGAIN
			 || errno == EAGAIN
#endif
#ifdef EINTR
			 || errno == EINTR
#endif
			 ))
	{ QUIT; continue; }

      if (dp == NULL)
	break;

      if (DIRENTRY_NONEMPTY (dp))
	{
	  int len;
	  int wanted = 0;
	  Lisp_Object name, finalname;
	  struct gcpro gcpro1, gcpro2;

	  len = NAMLEN (dp);
	  name = finalname = make_unibyte_string (dp->d_name, len);
	  GCPRO2 (finalname, name);

	  /* Note: DECODE_FILE can GC; it should protect its argument,
	     though.  */
	  name = DECODE_FILE (name);
	  len = SBYTES (name);

	  /* Now that we have unwind_protect in place, we might as well
             allow matching to be interrupted.  */
	  immediate_quit = 1;
	  QUIT;

	  if (NILP (match)
	      || (0 <= re_search (bufp, SDATA (name), len, 0, len, 0)))
	    wanted = 1;

	  immediate_quit = 0;

	  if (wanted)
	    {
	      if (!NILP (full))
		{
		  Lisp_Object fullname;
		  int nbytes = len + directory_nbytes + needsep;
		  int nchars;

		  fullname = make_uninit_multibyte_string (nbytes, nbytes);
		  memcpy (SDATA (fullname), SDATA (directory),
			  directory_nbytes);

		  if (needsep)
		    SSET (fullname, directory_nbytes, DIRECTORY_SEP);

		  memcpy (SDATA (fullname) + directory_nbytes + needsep,
			  SDATA (name), len);

		  nchars = chars_in_text (SDATA (fullname), nbytes);

		  /* Some bug somewhere.  */
		  if (nchars > nbytes)
		    abort ();

		  STRING_SET_CHARS (fullname, nchars);
		  if (nchars == nbytes)
		    STRING_SET_UNIBYTE (fullname);

		  finalname = fullname;
		}
	      else
		finalname = name;

	      if (attrs)
		{
		  /* Construct an expanded filename for the directory entry.
		     Use the decoded names for input to Ffile_attributes.  */
		  Lisp_Object decoded_fullname, fileattrs;
		  struct gcpro gcpro1, gcpro2;

		  decoded_fullname = fileattrs = Qnil;
		  GCPRO2 (decoded_fullname, fileattrs);

		  /* Both Fexpand_file_name and Ffile_attributes can GC.  */
		  decoded_fullname = Fexpand_file_name (name, directory);
		  fileattrs = Ffile_attributes (decoded_fullname, id_format);

		  list = Fcons (Fcons (finalname, fileattrs), list);
		  UNGCPRO;
		}
	      else
		list = Fcons (finalname, list);
	    }

	  UNGCPRO;
	}
    }

  BLOCK_INPUT;
  closedir (d);
  UNBLOCK_INPUT;
#ifdef WINDOWSNT
  if (attrs)
    Vw32_get_true_file_attributes = w32_save;
#endif

  /* Discard the unwind protect.  */
  specpdl_ptr = specpdl + count;

  if (NILP (nosort))
    list = Fsort (Fnreverse (list),
		  attrs ? Qfile_attributes_lessp : Qstring_lessp);

  RETURN_UNGCPRO (list);
}