static void chdir_to_default_directory (void) { Lisp_Object new_cwd; int old_cwd_fd = emacs_open (".", O_RDONLY | O_DIRECTORY, 0); if (old_cwd_fd == -1) error ("could not open current directory: %s", strerror (errno)); record_unwind_protect_int (fchdir_unwind, old_cwd_fd); new_cwd = Funhandled_file_name_directory ( Fexpand_file_name (build_string ("."), Qnil)); if (!STRINGP (new_cwd)) new_cwd = build_string ("/"); if (chdir (SSDATA (ENCODE_FILE (new_cwd)))) error ("could not chdir: %s", strerror (errno)); }
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)); } }