Beispiel #1
0
static char *
gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end)
{
  register char *end;
  register int nread;
  register char *buf = bufp->beg;

  if (!append_end)
    append_end = bufp->ptr;

  while (1)
    {
      end = append_end;
      while (*end && *end != '\n') end++;
      if (*end)
        break;
      if (bufp->ateof)
	return buf + bufp->full;
      if (bufp->ptr == buf)
	{
	  if (bufp->full == bufp->size)
	    {
	      ptrdiff_t ptr_offset = bufp->ptr - buf;
	      ptrdiff_t append_end_offset = append_end - buf;
	      /* Add 1 to size to ensure room for terminating null.  */
	      ptrdiff_t size = bufp->size + 1;
	      bufp->beg = buf = xpalloc (buf, &size, 1, -1, 1);
	      bufp->size = size - 1;
	      bufp->ptr = buf + ptr_offset;
	      append_end = buf + append_end_offset;
	    }
	}
      else
	{
	  append_end -= bufp->ptr - buf;
	  memcpy (buf, bufp->ptr, bufp->full -= bufp->ptr - buf);
	  bufp->ptr = buf;
	}
      if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
	bufp->ateof = 1;
      bufp->full += nread;
      buf[bufp->full] = '\0';
    }
  return end + 1;
}
Beispiel #2
0
Lisp_Object
get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
{
  char *from, *to, *name, *p, *p1;
  int fd;
  int offset;
  EMACS_INT position;
  Lisp_Object file, tem, pos;
  ptrdiff_t count;
  USE_SAFE_ALLOCA;

  if (INTEGERP (filepos))
    {
      file = Vdoc_file_name;
      pos = filepos;
    }
  else if (CONSP (filepos))
    {
      file = XCAR (filepos);
      pos = XCDR (filepos);
    }
  else
    return Qnil;

  position = eabs (XINT (pos));

  if (!STRINGP (Vdoc_directory))
    return Qnil;

  if (!STRINGP (file))
    return Qnil;

  /* Put the file name in NAME as a C string.
     If it is relative, combine it with Vdoc_directory.  */

  tem = Ffile_name_absolute_p (file);
  file = ENCODE_FILE (file);
  Lisp_Object docdir
    = NILP (tem) ? ENCODE_FILE (Vdoc_directory) : empty_unibyte_string;
  ptrdiff_t docdir_sizemax = SBYTES (docdir) + 1;
#ifndef CANNOT_DUMP
  docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc);
#endif
  name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file));
  lispstpcpy (lispstpcpy (name, docdir), file);

  fd = emacs_open (name, O_RDONLY, 0);
  if (fd < 0)
    {
#ifndef CANNOT_DUMP
      if (!NILP (Vpurify_flag))
	{
	  /* Preparing to dump; DOC file is probably not installed.
	     So check in ../etc.  */
	  lispstpcpy (stpcpy (name, sibling_etc), file);

	  fd = emacs_open (name, O_RDONLY, 0);
	}
#endif
      if (fd < 0)
	{
	  if (errno == EMFILE || errno == ENFILE)
	    report_file_error ("Read error on documentation file", file);

	  SAFE_FREE ();
	  AUTO_STRING (cannot_open, "Cannot open doc string file \"");
	  AUTO_STRING (quote_nl, "\"\n");
	  return concat3 (cannot_open, file, quote_nl);
	}
    }
  count = SPECPDL_INDEX ();
  record_unwind_protect_int (close_file_unwind, fd);

  /* Seek only to beginning of disk block.  */
  /* Make sure we read at least 1024 bytes before `position'
     so we can check the leading text for consistency.  */
  offset = min (position, max (1024, position % (8 * 1024)));
  if (TYPE_MAXIMUM (off_t) < position
      || lseek (fd, position - offset, 0) < 0)
    error ("Position %"pI"d out of range in doc string file \"%s\"",
	   position, name);

  /* Read the doc string into get_doc_string_buffer.
     P points beyond the data just read.  */

  p = get_doc_string_buffer;
  while (1)
    {
      ptrdiff_t space_left = (get_doc_string_buffer_size - 1
			      - (p - get_doc_string_buffer));
      int nread;

      /* Allocate or grow the buffer if we need to.  */
      if (space_left <= 0)
	{
	  ptrdiff_t in_buffer = p - get_doc_string_buffer;
	  get_doc_string_buffer
	    = xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size,
		       16 * 1024, -1, 1);
	  p = get_doc_string_buffer + in_buffer;
	  space_left = (get_doc_string_buffer_size - 1
			- (p - get_doc_string_buffer));
	}

      /* Read a disk block at a time.
         If we read the same block last time, maybe skip this?  */
      if (space_left > 1024 * 8)
	space_left = 1024 * 8;
      nread = emacs_read (fd, p, space_left);
      if (nread < 0)
	report_file_error ("Read error on documentation file", file);
      p[nread] = 0;
      if (!nread)
	break;
      if (p == get_doc_string_buffer)
	p1 = strchr (p + offset, '\037');
      else
	p1 = strchr (p, '\037');
      if (p1)
	{
	  *p1 = 0;
	  p = p1;
	  break;
	}
      p += nread;
    }
  unbind_to (count, Qnil);
  SAFE_FREE ();

  /* Sanity checking.  */
  if (CONSP (filepos))
    {
      int test = 1;
      /* A dynamic docstring should be either at the very beginning of a "#@
	 comment" or right after a dynamic docstring delimiter (in case we
	 pack several such docstrings within the same comment).  */
      if (get_doc_string_buffer[offset - test] != '\037')
	{
	  if (get_doc_string_buffer[offset - test++] != ' ')
	    return Qnil;
	  while (get_doc_string_buffer[offset - test] >= '0'
		 && get_doc_string_buffer[offset - test] <= '9')
	    test++;
	  if (get_doc_string_buffer[offset - test++] != '@'
	      || get_doc_string_buffer[offset - test] != '#')
	    return Qnil;
	}
    }
  else
    {
      int test = 1;
      if (get_doc_string_buffer[offset - test++] != '\n')
	return Qnil;
      while (get_doc_string_buffer[offset - test] > ' ')
	test++;
      if (get_doc_string_buffer[offset - test] != '\037')
	return Qnil;
    }

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

	  from++;
	  c = *from++;
	  if (c == 1)
	    *to++ = c;
	  else if (c == '0')
	    *to++ = 0;
	  else if (c == '_')
	    *to++ = 037;
	  else
	    {
	      unsigned char uc = c;
	      error ("\
Invalid data in documentation file -- %c followed by code %03o",
		     1, uc);
	    }
	}
      else
	*to++ = *from++;
    }

  /* If DEFINITION, read from this buffer
     the same way we would read bytes from a file.  */
  if (definition)
    {
      read_bytecode_pointer = (unsigned char *) get_doc_string_buffer + offset;
      return Fread (Qlambda);
    }

  if (unibyte)
    return make_unibyte_string (get_doc_string_buffer + offset,
				to - (get_doc_string_buffer + offset));
  else
    {
      /* The data determines whether the string is multibyte.  */
      ptrdiff_t nchars
	= multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer
				    + offset),
				   to - (get_doc_string_buffer + offset));
      return make_string_from_bytes (get_doc_string_buffer + offset,
				     nchars,
				     to - (get_doc_string_buffer + offset));
    }
}
Beispiel #3
0
Lisp_Object
get_doc_string (Lisp_Object filepos, int unibyte, int definition)
{
    char *from, *to;
    register int fd;
    register char *name;
    register char *p, *p1;
    EMACS_INT minsize;
    EMACS_INT offset, position;
    Lisp_Object file, tem;

    if (INTEGERP (filepos))
    {
        file = Vdoc_file_name;
        position = XINT (filepos);
    }
    else if (CONSP (filepos))
    {
        file = XCAR (filepos);
        position = XINT (XCDR (filepos));
    }
    else
        return Qnil;

    if (position < 0)
        position = - position;

    if (!STRINGP (Vdoc_directory))
        return Qnil;

    if (!STRINGP (file))
        return Qnil;

    /* Put the file name in NAME as a C string.
       If it is relative, combine it with Vdoc_directory.  */

    tem = Ffile_name_absolute_p (file);
    file = ENCODE_FILE (file);
    if (NILP (tem))
    {
        Lisp_Object docdir = ENCODE_FILE (Vdoc_directory);
        minsize = SCHARS (docdir);
        /* sizeof ("../etc/") == 8 */
        if (minsize < 8)
            minsize = 8;
        name = (char *) alloca (minsize + SCHARS (file) + 8);
        strcpy (name, SSDATA (docdir));
        strcat (name, SSDATA (file));
    }
    else
    {
        name = SSDATA (file);
    }

    fd = emacs_open (name, O_RDONLY, 0);
    if (fd < 0)
    {
#ifndef CANNOT_DUMP
        if (!NILP (Vpurify_flag))
        {
            /* Preparing to dump; DOC file is probably not installed.
               So check in ../etc.  */
            strcpy (name, "../etc/");
            strcat (name, SSDATA (file));

            fd = emacs_open (name, O_RDONLY, 0);
        }
#endif
        if (fd < 0)
            error ("Cannot open doc string file \"%s\"", name);
    }

    /* Seek only to beginning of disk block.  */
    /* Make sure we read at least 1024 bytes before `position'
       so we can check the leading text for consistency.  */
    offset = min (position, max (1024, position % (8 * 1024)));
    if (0 > lseek (fd, position - offset, 0))
    {
        emacs_close (fd);
        error ("Position %"pI"d out of range in doc string file \"%s\"",
               position, name);
    }

    /* Read the doc string into get_doc_string_buffer.
       P points beyond the data just read.  */

    p = get_doc_string_buffer;
    while (1)
    {
        ptrdiff_t space_left = (get_doc_string_buffer_size - 1
                                - (p - get_doc_string_buffer));
        int nread;

        /* Allocate or grow the buffer if we need to.  */
        if (space_left <= 0)
        {
            ptrdiff_t in_buffer = p - get_doc_string_buffer;
            get_doc_string_buffer =
                xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size,
                         16 * 1024, -1, 1);
            p = get_doc_string_buffer + in_buffer;
            space_left = (get_doc_string_buffer_size - 1
                          - (p - get_doc_string_buffer));
        }

        /* Read a disk block at a time.
           If we read the same block last time, maybe skip this?  */
        if (space_left > 1024 * 8)
            space_left = 1024 * 8;
        nread = emacs_read (fd, p, space_left);
        if (nread < 0)
        {
            emacs_close (fd);
            error ("Read error on documentation file");
        }
        p[nread] = 0;
        if (!nread)
            break;
        if (p == get_doc_string_buffer)
            p1 = strchr (p + offset, '\037');
        else
            p1 = strchr (p, '\037');
        if (p1)
        {
            *p1 = 0;
            p = p1;
            break;
        }
        p += nread;
    }
    emacs_close (fd);

    /* Sanity checking.  */
    if (CONSP (filepos))
    {
        int test = 1;
        if (get_doc_string_buffer[offset - test++] != ' ')
            return Qnil;
        while (get_doc_string_buffer[offset - test] >= '0'
                && get_doc_string_buffer[offset - test] <= '9')
            test++;
        if (get_doc_string_buffer[offset - test++] != '@'
                || get_doc_string_buffer[offset - test] != '#')
            return Qnil;
    }
    else
    {
        int test = 1;
        if (get_doc_string_buffer[offset - test++] != '\n')
            return Qnil;
        while (get_doc_string_buffer[offset - test] > ' ')
            test++;
        if (get_doc_string_buffer[offset - test] != '\037')
            return Qnil;
    }

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

            from++;
            c = *from++;
            if (c == 1)
                *to++ = c;
            else if (c == '0')
                *to++ = 0;
            else if (c == '_')
                *to++ = 037;
            else
            {
                unsigned char uc = c;
                error ("\
Invalid data in documentation file -- %c followed by code %03o",
                       1, uc);
            }
        }
        else
            *to++ = *from++;
    }

    /* If DEFINITION, read from this buffer
       the same way we would read bytes from a file.  */
    if (definition)
    {
        read_bytecode_pointer = (unsigned char *) get_doc_string_buffer + offset;
        return Fread (Qlambda);
    }

    if (unibyte)
        return make_unibyte_string (get_doc_string_buffer + offset,
                                    to - (get_doc_string_buffer + offset));
    else
    {
        /* The data determines whether the string is multibyte.  */
        EMACS_INT nchars =
            multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer
                                      + offset),
                                     to - (get_doc_string_buffer + offset));
        return make_string_from_bytes (get_doc_string_buffer + offset,
                                       nchars,
                                       to - (get_doc_string_buffer + offset));
    }
}
Beispiel #4
0
int
xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
	   EMACS_TIME *timeout)
{
  SELECT_TYPE all_rfds, all_wfds;
  EMACS_TIME tmo, *tmop = timeout;

  GMainContext *context = g_main_context_default ();
  int have_wfds = wfds != NULL;
  int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0;
  int i, nfds, tmo_in_millisec;

  if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds));
  else FD_ZERO (&all_rfds);
  if (wfds) memcpy (&all_wfds, wfds, sizeof (all_rfds));
  else FD_ZERO (&all_wfds);

  /* Update event sources in GLib. */
  g_main_context_pending (context);

  do {
    if (n_gfds > gfds_size)
      {
        xfree (gfds);
	gfds = xpalloc (0, &gfds_size, n_gfds - gfds_size, INT_MAX,
			sizeof *gfds);
      }

    n_gfds = g_main_context_query (context,
                                   G_PRIORITY_LOW,
                                   &tmo_in_millisec,
                                   gfds,
                                   gfds_size);
  } while (n_gfds > gfds_size);

  for (i = 0; i < n_gfds; ++i)
    {
      if (gfds[i].events & G_IO_IN)
        {
          FD_SET (gfds[i].fd, &all_rfds);
          if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
        }
      if (gfds[i].events & G_IO_OUT)
        {
          FD_SET (gfds[i].fd, &all_wfds);
          if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
          have_wfds = 1;
        }
    }

  if (tmo_in_millisec >= 0)
    {
      EMACS_SET_SECS_USECS (tmo, tmo_in_millisec/1000,
                            1000 * (tmo_in_millisec % 1000));
      if (!timeout) our_tmo = 1;
      else
        {
          EMACS_TIME difference;

          EMACS_SUB_TIME (difference, tmo, *timeout);
          if (EMACS_TIME_NEG_P (difference)) our_tmo = 1;
        }

      if (our_tmo) tmop = &tmo;
    }

  nfds = select (max_fds+1, &all_rfds, have_wfds ? &all_wfds : NULL,
                 efds, tmop);

  if (nfds < 0)
    retval = nfds;
  else if (nfds > 0)
    {
      for (i = 0; i < max_fds+1; ++i)
        {
          if (FD_ISSET (i, &all_rfds))
            {
              if (rfds && FD_ISSET (i, rfds)) ++retval;
              else ++our_fds;
            }
          else if (rfds)
            FD_CLR (i, rfds);

          if (have_wfds && FD_ISSET (i, &all_wfds))
            {
              if (wfds && FD_ISSET (i, wfds)) ++retval;
              else ++our_fds;
            }
          else if (wfds)
            FD_CLR (i, wfds);

          if (efds && FD_ISSET (i, efds))
            ++retval;
        }
    }

  if (our_fds > 0 || (nfds == 0 && our_tmo))
    {

      /* If Gtk+ is in use eventually gtk_main_iteration will be called,
         unless retval is zero.  */
#ifdef USE_GTK
      if (retval == 0)
#endif
        while (g_main_context_pending (context))
          g_main_context_dispatch (context);

      /* To not have to recalculate timeout, return like this.  */
      if (retval == 0)
        {
          retval = -1;
          errno = EINTR;
        }
    }

  return retval;
}