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 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; }
USID event_stream_unixoid_create_stream_pair (void* inhandle, void* outhandle, Lisp_Object* instream, Lisp_Object* outstream, int flags) { int infd, outfd; /* Decode inhandle and outhandle. Their meaning depends on the process implementation being used. */ #if defined (HAVE_WIN32_PROCESSES) /* We're passed in Windows handles. Open new fds for them */ if ((HANDLE)inhandle != INVALID_HANDLE_VALUE) { infd = open_osfhandle ((HANDLE)inhandle, 0); if (infd < 0) return USID_ERROR; } else infd = -1; if ((HANDLE)outhandle != INVALID_HANDLE_VALUE) { outfd = open_osfhandle ((HANDLE)outhandle, 0); if (outfd < 0) { if (infd >= 0) close (infd); return USID_ERROR; } } else outfd = -1; flags = 0; #elif defined (HAVE_UNIX_PROCESSES) /* We are passed plain old file descs */ infd = (int)inhandle; outfd = (int)outhandle; #else # error Which processes do you have? #endif *instream = (infd >= 0 ? make_filedesc_input_stream (infd, 0, -1, 0) : Qnil); *outstream = (outfd >= 0 ? make_filedesc_output_stream (outfd, 0, -1, LSTR_BLOCKED_OK) : Qnil); #if defined(HAVE_UNIX_PROCESSES) && defined(HAVE_PTYS) /* FLAGS is process->pty_flag for UNIX_PROCESSES */ if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0) { Bufbyte eof_char = get_eof_char (outfd); int pty_max_bytes = get_pty_max_bytes (outfd); filedesc_stream_set_pty_flushing (XLSTREAM(*outstream), pty_max_bytes, eof_char); } #endif return FD_TO_USID (infd); }