]> git.eshelyaron.com Git - emacs.git/commitdiff
* fileio.c (Finsert_file_contents): Revert code introduced at
authorDmitry Antipov <dmantipov@yandex.ru>
Mon, 21 Jan 2013 17:01:09 +0000 (21:01 +0400)
committerDmitry Antipov <dmantipov@yandex.ru>
Mon, 21 Jan 2013 17:01:09 +0000 (21:01 +0400)
2013-01-18 in favor of the simpler and generally better fix.
Save stack space by removing 'buffer' and reusing 'read_buf'
where appropriate.

src/ChangeLog
src/fileio.c

index 1383b12ed68c8d316bace4df5f801c25d94bdfba..658febcd21cde44a0f6683bd4b31ee0c73540e82 100644 (file)
@@ -1,3 +1,10 @@
+2013-01-21  Dmitry Antipov  <dmantipov@yandex.ru>
+
+       * fileio.c (Finsert_file_contents): Revert code introduced at
+       2013-01-18 in favor of the simpler and generally better fix.
+       Save stack space by removing 'buffer' and reusing 'read_buf'
+       where appropriate.
+
 2013-01-19  Paul Eggert  <eggert@cs.ucla.edu>
 
        * lisp.h (eabs): Define unconditionally (Bug#13419).
index 51f966787b99bb79760e7b63fc28abb3bd0c6725..175f363ec9210941f9b1ad84038051a056f762ad 100644 (file)
@@ -3413,13 +3413,13 @@ decide_coding_unwind (Lisp_Object unwind_data)
   return Qnil;
 }
 
-/* Check quit and read from the file.  STATE is a Lisp_Save_Value
+/* Read from a non-regular file.  STATE is a Lisp_Save_Value
    object where slot 0 is the file descriptor, slot 1 specifies
    an offset to put the read bytes, and slot 2 is the maximum
    amount of bytes to read.  Value is the number of bytes read.  */
 
 static Lisp_Object
-read_contents (Lisp_Object state)
+read_non_regular (Lisp_Object state)
 {
   int nbytes;
 
@@ -3435,10 +3435,12 @@ read_contents (Lisp_Object state)
   return make_number (nbytes);
 }
 
-/* Condition-case handler used when reading files in insert-file-contents.  */
+
+/* Condition-case handler used when reading from non-regular files
+   in insert-file-contents.  */
 
 static Lisp_Object
-read_contents_quit (Lisp_Object ignore)
+read_non_regular_quit (Lisp_Object ignore)
 {
   return Qnil;
 }
@@ -3516,10 +3518,9 @@ by calling `format-decode', which see.  */)
   Lisp_Object p;
   ptrdiff_t total = 0;
   bool not_regular = 0;
-  int save_errno = 0, read_errno = 0;
+  int save_errno = 0;
   char read_buf[READ_BUF_SIZE];
   struct coding_system coding;
-  char buffer[1 << 14];
   bool replace_handled = 0;
   bool set_coding_system = 0;
   Lisp_Object coding_system;
@@ -3822,7 +3823,7 @@ by calling `format-decode', which see.  */)
        {
          int nread, bufpos;
 
-         nread = emacs_read (fd, buffer, sizeof buffer);
+         nread = emacs_read (fd, read_buf, sizeof read_buf);
          if (nread < 0)
            error ("IO error reading %s: %s",
                   SSDATA (orig_filename), emacs_strerror (errno));
@@ -3831,7 +3832,7 @@ by calling `format-decode', which see.  */)
 
          if (CODING_REQUIRE_DETECTION (&coding))
            {
-             coding_system = detect_coding_system ((unsigned char *) buffer,
+             coding_system = detect_coding_system ((unsigned char *) read_buf,
                                                    nread, nread, 1, 0,
                                                    coding_system);
              setup_coding_system (coding_system, &coding);
@@ -3847,7 +3848,7 @@ by calling `format-decode', which see.  */)
 
          bufpos = 0;
          while (bufpos < nread && same_at_start < ZV_BYTE
-                && FETCH_BYTE (same_at_start) == buffer[bufpos])
+                && FETCH_BYTE (same_at_start) == read_buf[bufpos])
            same_at_start++, bufpos++;
          /* If we found a discrepancy, stop the scan.
             Otherwise loop around and scan the next bufferful.  */
@@ -3881,7 +3882,7 @@ by calling `format-decode', which see.  */)
          if (curpos == 0)
            break;
          /* How much can we scan in the next step?  */
-         trial = min (curpos, sizeof buffer);
+         trial = min (curpos, sizeof read_buf);
          if (lseek (fd, curpos - trial, SEEK_SET) < 0)
            report_file_error ("Setting file position",
                               Fcons (orig_filename, Qnil));
@@ -3889,7 +3890,7 @@ by calling `format-decode', which see.  */)
          total_read = nread = 0;
          while (total_read < trial)
            {
-             nread = emacs_read (fd, buffer + total_read, trial - total_read);
+             nread = emacs_read (fd, read_buf + total_read, trial - total_read);
              if (nread < 0)
                error ("IO error reading %s: %s",
                       SDATA (orig_filename), emacs_strerror (errno));
@@ -3905,7 +3906,7 @@ by calling `format-decode', which see.  */)
          /* Compare with same_at_start to avoid counting some buffer text
             as matching both at the file's beginning and at the end.  */
          while (bufpos > 0 && same_at_end > same_at_start
-                && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
+                && FETCH_BYTE (same_at_end - 1) == read_buf[bufpos - 1])
            same_at_end--, bufpos--;
 
          /* If we found a discrepancy, stop the scan.
@@ -4197,68 +4198,85 @@ by calling `format-decode', which see.  */)
                           Fcons (orig_filename, Qnil));
     }
 
-  /* In the following loop, HOW_MUCH contains the total bytes read
-     so far for a regular file, and not changed for a special file.  */
+  /* In the following loop, HOW_MUCH contains the total bytes read so
+     far for a regular file, and not changed for a special file.  But,
+     before exiting the loop, it is set to a negative value if I/O
+     error occurs.  */
   how_much = 0;
 
   /* Total bytes inserted.  */
   inserted = 0;
 
-  /* Here we don't do code conversion in the loop.  It is done by
-     decode_coding_gap after all data are read into the buffer, or
-     reading loop is interrupted with quit or due to I/O error.  */
+  /* Here, we don't do code conversion in the loop.  It is done by
+     decode_coding_gap after all data are read into the buffer.  */
+  {
+    ptrdiff_t gap_size = GAP_SIZE;
 
-  while (how_much < total)
-    {
-      ptrdiff_t nread, maxread = min (total - how_much, READ_BUF_SIZE);
-      Lisp_Object result;
-
-      /* For a special file, gap is enlarged as we read,
-        so GAP_SIZE should be checked every time.  */
-      if (not_regular && (GAP_SIZE < maxread))
-       make_gap (maxread - GAP_SIZE);
-
-      /* Read from the file, capturing `quit'.  */
-      result = internal_condition_case_1
-       (read_contents,
-        make_save_value ("iii", (ptrdiff_t) fd, inserted, maxread),
-        Qerror, read_contents_quit);
-      if (NILP (result))
-       {
-         /* Quit is signaled.  End the loop and arrange
-            real quit after decoding the text we read.  */
-         read_quit = 1;
-         break;
-       }
-      nread = XINT (result);
-      if (nread <= 0)
-       {
-         /* End of file or I/O error.  End the loop and
-            save error code in case of I/O error.  */
-         if (nread < 0)
-           read_errno = errno;
-         break;
-       }
+    while (how_much < total)
+      {
+       /* try is reserved in some compilers (Microsoft C) */
+       ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE);
+       ptrdiff_t this;
 
-      /* Adjust gap and end positions.  */
-      GAP_SIZE -= nread;
-      GPT += nread;
-      ZV += nread;
-      Z += nread;
-      GPT_BYTE += nread;
-      ZV_BYTE += nread;
-      Z_BYTE += nread;
-      if (GAP_SIZE > 0)
-       *(GPT_ADDR) = 0;
-
-      /* For a regular file, where TOTAL is the real size, count HOW_MUCH to
-        compare with it.  For a special file, where TOTAL is just a buffer
-        size, don't bother counting in HOW_MUCH, but always accumulate the
-        number of bytes read in INSERTED.  */
-      if (!not_regular)
-       how_much += nread;
-      inserted += nread;
-    }
+       if (not_regular)
+         {
+           Lisp_Object nbytes;
+
+           /* Maybe make more room.  */
+           if (gap_size < trytry)
+             {
+               make_gap (trytry - gap_size);
+               gap_size = GAP_SIZE - inserted;
+             }
+
+           /* Read from the file, capturing `quit'.  When an
+              error occurs, end the loop, and arrange for a quit
+              to be signaled after decoding the text we read.  */
+           nbytes = internal_condition_case_1
+             (read_non_regular,
+              make_save_value ("iii", (ptrdiff_t) fd, inserted, trytry),
+              Qerror, read_non_regular_quit);
+
+           if (NILP (nbytes))
+             {
+               read_quit = 1;
+               break;
+             }
+
+           this = XINT (nbytes);
+         }
+       else
+         {
+           /* Allow quitting out of the actual I/O.  We don't make text
+              part of the buffer until all the reading is done, so a C-g
+              here doesn't do any harm.  */
+           immediate_quit = 1;
+           QUIT;
+           this = emacs_read (fd,
+                              ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
+                               + inserted),
+                              trytry);
+           immediate_quit = 0;
+         }
+
+       if (this <= 0)
+         {
+           how_much = this;
+           break;
+         }
+
+       gap_size -= this;
+
+       /* For a regular file, where TOTAL is the real size,
+          count HOW_MUCH to compare with it.
+          For a special file, where TOTAL is just a buffer size,
+          so don't bother counting in HOW_MUCH.
+          (INSERTED is where we count the number of characters inserted.)  */
+       if (! not_regular)
+         how_much += this;
+       inserted += this;
+      }
+  }
 
   /* Now we have either read all the file data into the gap,
      or stop reading on I/O error or quit.  If nothing was
@@ -4280,6 +4298,23 @@ by calling `format-decode', which see.  */)
   /* Discard the unwind protect for closing the file.  */
   specpdl_ptr--;
 
+  if (how_much < 0)
+    error ("IO error reading %s: %s",
+          SDATA (orig_filename), emacs_strerror (errno));
+
+  /* Make the text read part of the buffer.  */
+  GAP_SIZE -= inserted;
+  GPT      += inserted;
+  GPT_BYTE += inserted;
+  ZV       += inserted;
+  ZV_BYTE  += inserted;
+  Z        += inserted;
+  Z_BYTE   += inserted;
+
+  if (GAP_SIZE > 0)
+    /* Put an anchor to ensure multi-byte form ends at gap.  */
+    *GPT_ADDR = 0;
+
  notfound:
 
   if (NILP (coding_system))
@@ -4568,15 +4603,10 @@ by calling `format-decode', which see.  */)
       report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
     }
 
-  /* There was an error reading file.  */
-  if (read_errno)
-    error ("IO error reading %s: %s",
-          SDATA (orig_filename), emacs_strerror (read_errno));
-
-  /* Quit was signaled.  */
   if (read_quit)
     Fsignal (Qquit, Qnil);
 
+  /* Retval needs to be dealt with in all cases consistently.  */
   if (NILP (val))
     val = list2 (orig_filename, make_number (inserted));