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; }
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)); } }
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)); } }
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; }