comparison src/fileio.c @ 38450:8416a4627a13

(unwind_read): Function removed. (read_non_regular, read_non_regular_quit): New functions. (Finsert_file_contents): When reading from non-regular files, arrange to catch a `quit' and terminate the loop. Rearrange code so that a `quit' when reading from a regular file doesn't insert text in the buffer.
author Gerd Moellmann <gerd@gnu.org>
date Mon, 16 Jul 2001 15:59:43 +0000
parents bcff6c46ee05
children 879c6b736b9f
comparison
equal deleted inserted replaced
38449:2f7725eae50d 38450:8416a4627a13
3417 3417
3418 return Qnil; 3418 return Qnil;
3419 } 3419 }
3420 3420
3421 3421
3422 /* Unwind-function for reading from a file in insert-file-contents. 3422 /* Used to pass values from insert-file-contents to read_non_regular. */
3423 3423
3424 INSERTED_BYTES is the number of bytes successfully inserted into 3424 static int non_regular_fd;
3425 current_buffer. 3425 static int non_regular_inserted;
3426 3426 static int non_regular_nbytes;
3427 When reading is interrupted by C-g, this leaves the newly read part 3427
3428 of the current buffer undecoded. If this happens in a multibyte 3428
3429 buffer, prevent invalid characters by either discarding what has 3429 /* Read from a non-regular file.
3430 been read or switching the buffer to unibyte. 3430 Read non_regular_trytry bytes max from non_regular_fd.
3431 3431 Non_regular_inserted specifies where to put the read bytes.
3432 PT GPT 3432 Value is the number of bytes read. */
3433 +-----------------------------------------------------+
3434 | | inserted bytes | GAP_SIZE | |
3435 +-----------------------------------------------------+
3436 \ /
3437 +--------- the gap ---------+ */
3438 3433
3439 static Lisp_Object 3434 static Lisp_Object
3440 unwind_read (inserted_bytes) 3435 read_non_regular ()
3441 Lisp_Object inserted_bytes; 3436 {
3442 { 3437 int nbytes;
3443 if (!NILP (current_buffer->enable_multibyte_characters)) 3438
3444 { 3439 immediate_quit = 1;
3445 int nbytes = XINT (inserted_bytes); 3440 QUIT;
3446 Lisp_Object args[3]; 3441 nbytes = emacs_read (non_regular_fd,
3447 char *action; 3442 BEG_ADDR + PT_BYTE - 1 + non_regular_inserted,
3448 3443 non_regular_nbytes);
3449 if (Z == nbytes) 3444 Fsignal (Qquit, Qnil);
3450 { 3445 immediate_quit = 0;
3451 /* Buffer was previously empty. Switch it to unibyte 3446 return make_number (nbytes);
3452 because newly inserted text is not decoded. */ 3447 }
3453 current_buffer->enable_multibyte_characters = Qnil; 3448
3454 action = "buffer made unibyte"; 3449
3455 } 3450 /* Condition-case handler used when reading from non-regular files
3456 else 3451 in insert-file-contents. */
3457 { 3452
3458 ZV -= nbytes; 3453 static Lisp_Object
3459 ZV_BYTE -= nbytes; 3454 read_non_regular_quit ()
3460 Z -= nbytes; 3455 {
3461 Z_BYTE -= nbytes;
3462
3463 GPT = PT;
3464 GPT_BYTE = PT_BYTE;
3465 GAP_SIZE = nbytes + GAP_SIZE;
3466
3467 action = "no text inserted";
3468 }
3469
3470
3471 args[0] = build_string ("Quit while inserting text in buffer `%s': %s");
3472 args[1] = current_buffer->name;
3473 args[2] = build_string (action);
3474 Fmessage (3, args);
3475 }
3476
3477 return Qnil; 3456 return Qnil;
3478 } 3457 }
3479 3458
3480 3459
3481 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, 3460 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
3521 struct coding_system coding; 3500 struct coding_system coding;
3522 unsigned char buffer[1 << 14]; 3501 unsigned char buffer[1 << 14];
3523 int replace_handled = 0; 3502 int replace_handled = 0;
3524 int set_coding_system = 0; 3503 int set_coding_system = 0;
3525 int coding_system_decided = 0; 3504 int coding_system_decided = 0;
3505 int gap_size;
3506 int read_quit = 0;
3526 3507
3527 if (current_buffer->base_buffer && ! NILP (visit)) 3508 if (current_buffer->base_buffer && ! NILP (visit))
3528 error ("Cannot do file visiting in an indirect buffer"); 3509 error ("Cannot do file visiting in an indirect buffer");
3529 3510
3530 if (!NILP (current_buffer->read_only)) 3511 if (!NILP (current_buffer->read_only))
4180 /* In the following loop, HOW_MUCH contains the total bytes read so 4161 /* In the following loop, HOW_MUCH contains the total bytes read so
4181 far for a regular file, and not changed for a special file. But, 4162 far for a regular file, and not changed for a special file. But,
4182 before exiting the loop, it is set to a negative value if I/O 4163 before exiting the loop, it is set to a negative value if I/O
4183 error occurs. */ 4164 error occurs. */
4184 how_much = 0; 4165 how_much = 0;
4166
4185 /* Total bytes inserted. */ 4167 /* Total bytes inserted. */
4186 inserted = 0; 4168 inserted = 0;
4169
4187 /* Here, we don't do code conversion in the loop. It is done by 4170 /* Here, we don't do code conversion in the loop. It is done by
4188 code_convert_region after all data are read into the buffer. */ 4171 code_convert_region after all data are read into the buffer. */
4189 while (how_much < total) 4172 {
4190 { 4173 int gap_size = GAP_SIZE;
4174
4175 while (how_much < total)
4176 {
4191 /* try is reserved in some compilers (Microsoft C) */ 4177 /* try is reserved in some compilers (Microsoft C) */
4192 int trytry = min (total - how_much, READ_BUF_SIZE); 4178 int trytry = min (total - how_much, READ_BUF_SIZE);
4193 int this; 4179 int this;
4194 int count = BINDING_STACK_SIZE (); 4180
4195 4181 if (not_regular)
4196 /* For a special file, GAP_SIZE should be checked every time. */ 4182 {
4197 if (not_regular && GAP_SIZE < trytry) 4183 Lisp_Object val;
4198 make_gap (total - GAP_SIZE); 4184
4199 4185 /* Maybe make more room. */
4200 /* Allow quitting out of the actual I/O. If a C-g interrupts 4186 if (gap_size < trytry)
4201 this, make sure that no invalid characters remain 4187 {
4202 in the undecoded part read. */ 4188 make_gap (total - gap_size);
4203 record_unwind_protect (unwind_read, make_number (inserted)); 4189 gap_size = GAP_SIZE;
4204 immediate_quit = 1; 4190 }
4205 QUIT; 4191
4206 this = emacs_read (fd, BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1, 4192 /* Read from the file, capturing `quit'. When an
4207 trytry); 4193 error occurs, end the loop, and arrange for a quit
4208 immediate_quit = 0; 4194 to be signaled after decoding the text we read. */
4209 --specpdl_ptr; 4195 non_regular_fd = fd;
4210 4196 non_regular_inserted = inserted;
4211 if (this <= 0) 4197 non_regular_nbytes = trytry;
4212 { 4198 val = internal_condition_case_1 (read_non_regular, Qnil, Qerror,
4213 how_much = this; 4199 read_non_regular_quit);
4214 break; 4200 if (NILP (val))
4215 } 4201 {
4216 4202 read_quit = 1;
4217 GAP_SIZE -= this; 4203 break;
4218 GPT_BYTE += this; 4204 }
4219 ZV_BYTE += this; 4205
4220 Z_BYTE += this; 4206 this = XINT (val);
4221 GPT += this; 4207 }
4222 ZV += this; 4208 else
4223 Z += this; 4209 {
4224 4210 /* Allow quitting out of the actual I/O. We don't make text
4225 /* For a regular file, where TOTAL is the real size, 4211 part of the buffer until all the reading is done, so a C-g
4226 count HOW_MUCH to compare with it. 4212 here doesn't do any harm. */
4227 For a special file, where TOTAL is just a buffer size, 4213 immediate_quit = 1;
4228 so don't bother counting in HOW_MUCH. 4214 QUIT;
4229 (INSERTED is where we count the number of characters inserted.) */ 4215 this = emacs_read (fd, BEG_ADDR + PT_BYTE - 1 + inserted, trytry);
4230 if (! not_regular) 4216 immediate_quit = 0;
4231 how_much += this; 4217 }
4232 inserted += this; 4218
4233 } 4219 if (this <= 0)
4220 {
4221 how_much = this;
4222 break;
4223 }
4224
4225 gap_size -= this;
4226
4227 /* For a regular file, where TOTAL is the real size,
4228 count HOW_MUCH to compare with it.
4229 For a special file, where TOTAL is just a buffer size,
4230 so don't bother counting in HOW_MUCH.
4231 (INSERTED is where we count the number of characters inserted.) */
4232 if (! not_regular)
4233 how_much += this;
4234 inserted += this;
4235 }
4236 }
4237
4238 /* Make the text read part of the buffer. */
4239 GAP_SIZE -= inserted;
4240 GPT += inserted;
4241 GPT_BYTE += inserted;
4242 ZV += inserted;
4243 ZV_BYTE += inserted;
4244 Z += inserted;
4245 Z_BYTE += inserted;
4234 4246
4235 if (GAP_SIZE > 0) 4247 if (GAP_SIZE > 0)
4236 /* Put an anchor to ensure multi-byte form ends at gap. */ 4248 /* Put an anchor to ensure multi-byte form ends at gap. */
4237 *GPT_ADDR = 0; 4249 *GPT_ADDR = 0;
4238 4250
4443 && current_buffer->modtime == -1) 4455 && current_buffer->modtime == -1)
4444 { 4456 {
4445 /* If visiting nonexistent file, return nil. */ 4457 /* If visiting nonexistent file, return nil. */
4446 report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); 4458 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
4447 } 4459 }
4460
4461 if (read_quit)
4462 Fsignal (Qquit, Qnil);
4448 4463
4449 /* ??? Retval needs to be dealt with in all cases consistently. */ 4464 /* ??? Retval needs to be dealt with in all cases consistently. */
4450 if (NILP (val)) 4465 if (NILP (val))
4451 val = Fcons (orig_filename, 4466 val = Fcons (orig_filename,
4452 Fcons (make_number (inserted), 4467 Fcons (make_number (inserted),