Mercurial > emacs
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), |