Beispiel #1
0
/* Generate a file notification event.  */
static void
kqueue_generate_event (Lisp_Object watch_object, Lisp_Object actions,
		       Lisp_Object file, Lisp_Object file1)
{
  Lisp_Object flags, action, entry;
  struct input_event event;

  /* Check, whether all actions shall be monitored.  */
  flags = Fnth (make_number (2), watch_object);
  action = actions;
  do {
    if (NILP (action))
      break;
    entry = XCAR (action);
    if (NILP (Fmember (entry, flags))) {
      action = XCDR (action);
      actions = Fdelq (entry, actions);
    } else
      action = XCDR (action);
  } while (1);

  /* Store it into the input event queue.  */
  if (! NILP (actions)) {
    EVENT_INIT (event);
    event.kind = FILE_NOTIFY_EVENT;
    event.frame_or_window = Qnil;
    event.arg = list2 (Fcons (XCAR (watch_object),
			      Fcons (actions,
				     NILP (file1)
				     ? Fcons (file, Qnil)
				     : list2 (file, file1))),
		       Fnth (make_number (3), watch_object));
    kbd_buffer_store_event (&event);
  }
}
static rep_struct_node *
lookup_or_add (rep_struct *s, repv var)
{
    rep_struct_node *n = lookup (s, var);
    if (n == 0)
    {
	if (s->total_buckets == 0)
	{
	    s->total_buckets = MIN_BUCKETS;
	    s->buckets = rep_alloc (sizeof (rep_struct_node *)
				    * s->total_buckets);
	    memset (s->buckets, 0,
		    sizeof (rep_struct_node *) * s->total_buckets);
	    rep_data_after_gc += sizeof (rep_struct_node *) * s->total_buckets;
	}

	if (s->total_bindings > s->total_buckets * MAX_MULTIPLIER)
	{
	    int new_total = s->total_buckets * 2;
	    rep_struct_node **buckets
		= rep_alloc (new_total * sizeof (rep_struct_node *));
	    int i;
	    memset (buckets, 0, new_total * sizeof (rep_struct_node *));
	    rep_data_after_gc += new_total * sizeof (rep_struct_node *);
	    for (i = 0; i < s->total_buckets; i++)
	    {
		rep_struct_node *next;
		for (n = s->buckets[i]; n != 0; n = next)
		{
		    next = n->next;
		    n->next = buckets[rep_STRUCT_HASH (n->symbol, new_total)];
		    buckets[rep_STRUCT_HASH (n->symbol, new_total)] = n;
		}
	    }
	    s->total_buckets = new_total;
	    rep_free (s->buckets);
	    s->buckets = buckets;
	}

	n = rep_alloc (sizeof (rep_struct_node));
	rep_data_after_gc += sizeof (rep_struct_node);
	n->symbol = var;
	n->is_constant = 0;
	n->is_exported = (s->car & rep_STF_EXPORT_ALL) != 0;
	n->next = s->buckets[rep_STRUCT_HASH (var, s->total_buckets)];
	s->buckets[rep_STRUCT_HASH (var, s->total_buckets)] = n;
	s->total_bindings++;

	if (structure_exports_inherited_p (s, var))
	{
	    n->is_exported = 1;
	    s->inherited = Fdelq (var, s->inherited);
	}

	cache_invalidate_symbol (var);
    }
    return n;
}
Beispiel #3
0
/* This compares two directory listings in case of a `write' event for
   a directory.  Generate resulting file notification events.  The old
   directory listing is retrieved from watch_object, it will be
   replaced by the new directory listing at the end of this
   function.  */
static void
kqueue_compare_dir_list
(Lisp_Object watch_object)
{
  Lisp_Object dir, pending_dl, deleted_dl;
  Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl;

  dir = XCAR (XCDR (watch_object));
  pending_dl = Qnil;
  deleted_dl = Qnil;

  old_directory_files = Fnth (make_number (4), watch_object);
  old_dl = kqueue_directory_listing (old_directory_files);

  /* When the directory is not accessible anymore, it has been deleted.  */
  if (NILP (Ffile_directory_p (dir))) {
    kqueue_generate_event (watch_object, Fcons (Qdelete, Qnil), dir, Qnil);
    return;
  }
  new_directory_files =
    directory_files_internal (dir, Qnil, Qnil, Qnil, 1, Qnil);
  new_dl = kqueue_directory_listing (new_directory_files);

  /* Parse through the old list.  */
  dl = old_dl;
  while (1) {
    Lisp_Object old_entry, new_entry, dl1;
    if (NILP (dl))
      break;

    /* Search for an entry with the same inode.  */
    old_entry = XCAR (dl);
    new_entry = assq_no_quit (XCAR (old_entry), new_dl);
    if (! NILP (Fequal (old_entry, new_entry))) {
      /* Both entries are identical.  Nothing to do.  */
      new_dl = Fdelq (new_entry, new_dl);
      goto the_end;
    }

    /* Both entries have the same inode.  */
    if (! NILP (new_entry)) {
      /* Both entries have the same file name.  */
      if (strcmp (SSDATA (XCAR (XCDR (old_entry))),
		  SSDATA (XCAR (XCDR (new_entry)))) == 0) {
	/* Modification time has been changed, the file has been written.  */
	if (NILP (Fequal (Fnth (make_number (2), old_entry),
			  Fnth (make_number (2), new_entry))))
	  kqueue_generate_event
	    (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (old_entry)), Qnil);
	/* Status change time has been changed, the file attributes
	   have changed.  */
	  if (NILP (Fequal (Fnth (make_number (3), old_entry),
			    Fnth (make_number (3), new_entry))))
	  kqueue_generate_event
	    (watch_object, Fcons (Qattrib, Qnil),
	     XCAR (XCDR (old_entry)), Qnil);

      } else {
	/* The file has been renamed.  */
	kqueue_generate_event
	  (watch_object, Fcons (Qrename, Qnil),
	   XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry)));
	deleted_dl = Fcons (new_entry, deleted_dl);
      }
      new_dl = Fdelq (new_entry, new_dl);
      goto the_end;
    }

    /* Search, whether there is a file with the same name but another
       inode.  */
    for (dl1 = new_dl; ! NILP (dl1); dl1 = XCDR (dl1)) {
      new_entry = XCAR (dl1);
      if (strcmp (SSDATA (XCAR (XCDR (old_entry))),
		  SSDATA (XCAR (XCDR (new_entry)))) == 0) {
	pending_dl = Fcons (new_entry, pending_dl);
	new_dl = Fdelq (new_entry, new_dl);
	goto the_end;
      }
    }

    /* Check, whether this a pending file.  */
    new_entry = assq_no_quit (XCAR (old_entry), pending_dl);

    if (NILP (new_entry)) {
      /* Check, whether this is an already deleted file (by rename).  */
      for (dl1 = deleted_dl; ! NILP (dl1); dl1 = XCDR (dl1)) {
	new_entry = XCAR (dl1);
	if (strcmp (SSDATA (XCAR (XCDR (old_entry))),
		    SSDATA (XCAR (XCDR (new_entry)))) == 0) {
	  deleted_dl = Fdelq (new_entry, deleted_dl);
	  goto the_end;
	}
      }
      /* The file has been deleted.  */
      kqueue_generate_event
	(watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil);

    } else {
      /* The file has been renamed.  */
      kqueue_generate_event
	(watch_object, Fcons (Qrename, Qnil),
	 XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry)));
      pending_dl = Fdelq (new_entry, pending_dl);
    }

  the_end:
    dl = XCDR (dl);
    old_dl = Fdelq (old_entry, old_dl);
  }

  /* Parse through the resulting new list.  */
  dl = new_dl;
  while (1) {
    Lisp_Object entry;
    if (NILP (dl))
      break;

    /* A new file has appeared.  */
    entry = XCAR (dl);
    kqueue_generate_event
      (watch_object, Fcons (Qcreate, Qnil), XCAR (XCDR (entry)), Qnil);

    /* Check size of that file.  */
    Lisp_Object size = Fnth (make_number (4), entry);
    if (FLOATP (size) || (XINT (size) > 0))
      kqueue_generate_event
	(watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil);

    dl = XCDR (dl);
    new_dl = Fdelq (entry, new_dl);
  }

  /* Parse through the resulting pending_dl list.  */
  dl = pending_dl;
  while (1) {
    Lisp_Object entry;
    if (NILP (dl))
      break;

    /* A file is still pending.  Assume it was a write.  */
    entry = XCAR (dl);
    kqueue_generate_event
      (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil);

    dl = XCDR (dl);
    pending_dl = Fdelq (entry, pending_dl);
  }

  /* At this point, old_dl, new_dl and pending_dl shall be empty.
     deleted_dl might not be empty when there was a rename to a
     nonexistent file.  Let's make a check for this (might be removed
     once the code is stable).  */
  if (! NILP (old_dl))
    report_file_error ("Old list not empty", old_dl);
  if (! NILP (new_dl))
    report_file_error ("New list not empty", new_dl);
  if (! NILP (pending_dl))
    report_file_error ("Pending events list not empty", pending_dl);
  //  if (! NILP (deleted_dl))
  //    report_file_error ("Deleted events list not empty", deleted_dl);

  /* Replace old directory listing with the new one.  */
  XSETCDR (Fnthcdr (make_number (3), watch_object),
	   Fcons (new_directory_files, Qnil));
  return;
}