diff options
Diffstat (limited to 'src/fileio.c')
| -rw-r--r-- | src/fileio.c | 335 |
1 files changed, 187 insertions, 148 deletions
diff --git a/src/fileio.c b/src/fileio.c index 2e2aa1e30e6..e0e568d346b 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3246,6 +3246,26 @@ Lisp_Object Qfind_buffer_file_type; | |||
| 3246 | #define READ_BUF_SIZE (64 << 10) | 3246 | #define READ_BUF_SIZE (64 << 10) |
| 3247 | #endif | 3247 | #endif |
| 3248 | 3248 | ||
| 3249 | /* This function is called when a function bound to | ||
| 3250 | Vset_auto_coding_function causes some error. At that time, a text | ||
| 3251 | of a file has already been inserted in the current buffer, but, | ||
| 3252 | markers has not yet been adjusted. Thus we must adjust markers | ||
| 3253 | here. We are sure that the buffer was empty before the text of the | ||
| 3254 | file was inserted. */ | ||
| 3255 | |||
| 3256 | static Lisp_Object | ||
| 3257 | set_auto_coding_unwind (multibyte) | ||
| 3258 | Lisp_Object multibyte; | ||
| 3259 | { | ||
| 3260 | int inserted = Z_BYTE - BEG_BYTE; | ||
| 3261 | |||
| 3262 | if (!NILP (multibyte)) | ||
| 3263 | inserted = multibyte_chars_in_text (GPT_ADDR - inserted, inserted); | ||
| 3264 | adjust_after_insert (PT, PT_BYTE, Z, Z_BYTE, inserted); | ||
| 3265 | |||
| 3266 | return Qnil; | ||
| 3267 | } | ||
| 3268 | |||
| 3249 | DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, | 3269 | DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, |
| 3250 | 1, 5, 0, | 3270 | 1, 5, 0, |
| 3251 | "Insert contents of file FILENAME after point.\n\ | 3271 | "Insert contents of file FILENAME after point.\n\ |
| @@ -3290,6 +3310,7 @@ actually used.") | |||
| 3290 | unsigned char buffer[1 << 14]; | 3310 | unsigned char buffer[1 << 14]; |
| 3291 | int replace_handled = 0; | 3311 | int replace_handled = 0; |
| 3292 | int set_coding_system = 0; | 3312 | int set_coding_system = 0; |
| 3313 | int coding_system_decided = 0; | ||
| 3293 | 3314 | ||
| 3294 | if (current_buffer->base_buffer && ! NILP (visit)) | 3315 | if (current_buffer->base_buffer && ! NILP (visit)) |
| 3295 | error ("Cannot do file visiting in an indirect buffer"); | 3316 | error ("Cannot do file visiting in an indirect buffer"); |
| @@ -3394,161 +3415,107 @@ actually used.") | |||
| 3394 | } | 3415 | } |
| 3395 | } | 3416 | } |
| 3396 | 3417 | ||
| 3397 | /* Decide the coding-system of the file. */ | 3418 | if (BEG < Z) |
| 3398 | { | 3419 | { |
| 3399 | Lisp_Object val; | 3420 | /* Decide the coding system to use for reading the file now |
| 3400 | val = Qnil; | 3421 | because we can't use an optimized method for handling |
| 3401 | 3422 | `coding:' tag if the current buffer is not empty. */ | |
| 3402 | if (!NILP (Vcoding_system_for_read)) | 3423 | Lisp_Object val; |
| 3403 | val = Vcoding_system_for_read; | 3424 | val = Qnil; |
| 3404 | else if (! NILP (replace)) | ||
| 3405 | /* In REPLACE mode, we can use the same coding system | ||
| 3406 | that was used to visit the file. */ | ||
| 3407 | val = current_buffer->buffer_file_coding_system; | ||
| 3408 | else if (! not_regular) | ||
| 3409 | { | ||
| 3410 | /* Don't try looking inside a file for a coding system specification | ||
| 3411 | if it is not seekable. */ | ||
| 3412 | if (! NILP (Vset_auto_coding_function)) | ||
| 3413 | { | ||
| 3414 | /* Find a coding system specified in the heading two lines | ||
| 3415 | or in the tailing several lines of the file. We assume | ||
| 3416 | that the 1K-byte and 3K-byte for heading and tailing | ||
| 3417 | respectively are sufficient fot this purpose. */ | ||
| 3418 | int nread; | ||
| 3419 | int beginning_of_end, end_of_beginning; | ||
| 3420 | |||
| 3421 | if (st.st_size <= (1024 * 4)) | ||
| 3422 | { | ||
| 3423 | nread = read (fd, read_buf, 1024 * 4); | ||
| 3424 | end_of_beginning = nread; | ||
| 3425 | beginning_of_end = 0; | ||
| 3426 | } | ||
| 3427 | else | ||
| 3428 | { | ||
| 3429 | nread = read (fd, read_buf, 1024); | ||
| 3430 | end_of_beginning = nread; | ||
| 3431 | beginning_of_end = nread; | ||
| 3432 | if (nread >= 0) | ||
| 3433 | { | ||
| 3434 | if (lseek (fd, st.st_size - (1024 * 3), 0) < 0) | ||
| 3435 | report_file_error ("Setting file position", | ||
| 3436 | Fcons (orig_filename, Qnil)); | ||
| 3437 | nread += read (fd, read_buf + nread, 1024 * 3); | ||
| 3438 | } | ||
| 3439 | } | ||
| 3440 | 3425 | ||
| 3441 | if (nread < 0) | 3426 | if (!NILP (Vcoding_system_for_read)) |
| 3442 | error ("IO error reading %s: %s", | 3427 | val = Vcoding_system_for_read; |
| 3443 | XSTRING (orig_filename)->data, strerror (errno)); | 3428 | else if (! NILP (replace)) |
| 3444 | else if (nread > 0) | 3429 | /* In REPLACE mode, we can use the same coding system |
| 3445 | { | 3430 | that was used to visit the file. */ |
| 3446 | int i; | 3431 | val = current_buffer->buffer_file_coding_system; |
| 3447 | int possible_spec = 0; | 3432 | else |
| 3448 | unsigned char *p, *p1; | 3433 | { |
| 3449 | Lisp_Object tem; | 3434 | /* Don't try looking inside a file for a coding system |
| 3450 | unsigned char *copy = (unsigned char *) alloca (nread + 1); | 3435 | specification if it is not seekable. */ |
| 3451 | 3436 | if (! not_regular && ! NILP (Vset_auto_coding_function)) | |
| 3452 | /* Make a copy of the contents of read_buf in COPY, | 3437 | { |
| 3453 | and convert it to lower case so we can compare | 3438 | /* Find a coding system specified in the heading two |
| 3454 | more efficiently. */ | 3439 | lines or in the tailing several lines of the file. |
| 3455 | bcopy (read_buf, copy, nread); | 3440 | We assume that the 1K-byte and 3K-byte for heading |
| 3456 | for (i = 0; i < nread; i++) | 3441 | and tailing respectively are sufficient fot this |
| 3457 | copy[i] = DOWNCASE (copy[i]); | 3442 | purpose. */ |
| 3458 | /* Ensure various comparisons fail at end of data. */ | 3443 | int how_many, nread; |
| 3459 | copy[nread] = 0; | 3444 | |
| 3460 | 3445 | if (st.st_size <= (1024 * 4)) | |
| 3461 | /* Now test quickly whether the file contains a -*- line. */ | 3446 | nread = read (fd, read_buf, 1024 * 4); |
| 3462 | p = copy; | 3447 | else |
| 3463 | while (*p != '\n' && p - copy < end_of_beginning) | 3448 | { |
| 3464 | p++; | 3449 | nread = read (fd, read_buf, 1024); |
| 3465 | if (copy[0] == '#' && copy[1] == '!') | 3450 | if (nread >= 0) |
| 3466 | while (*p != '\n' && p - copy < end_of_beginning) | 3451 | { |
| 3467 | p++; | 3452 | if (lseek (fd, st.st_size - (1024 * 3), 0) < 0) |
| 3468 | p1 = copy; | 3453 | report_file_error ("Setting file position", |
| 3469 | while (p - p1 >= 3) | 3454 | Fcons (orig_filename, Qnil)); |
| 3470 | { | 3455 | nread += read (fd, read_buf + nread, 1024 * 3); |
| 3471 | if (p1[0] == '-' && p1[1] == '*' && p1[2] == '-') | 3456 | } |
| 3472 | { | 3457 | } |
| 3473 | while (p - p1 >= 7) | ||
| 3474 | { | ||
| 3475 | if (! bcmp ("coding:", p1, 7)) | ||
| 3476 | { | ||
| 3477 | possible_spec = 1; | ||
| 3478 | goto win; | ||
| 3479 | } | ||
| 3480 | p1++; | ||
| 3481 | } | ||
| 3482 | break; | ||
| 3483 | } | ||
| 3484 | p1++; | ||
| 3485 | } | ||
| 3486 | 3458 | ||
| 3487 | /* Test quickly whether the file | 3459 | if (nread < 0) |
| 3488 | contains a local variables list. */ | 3460 | error ("IO error reading %s: %s", |
| 3489 | p = ©[nread - 1]; | 3461 | XSTRING (orig_filename)->data, strerror (errno)); |
| 3490 | p1 = ©[beginning_of_end]; | 3462 | else if (nread > 0) |
| 3491 | while (p > p1) | 3463 | { |
| 3492 | { | 3464 | int count = specpdl_ptr - specpdl; |
| 3493 | if (p[0] == '\n' && p[1] == '\f') | 3465 | struct buffer *prev = current_buffer; |
| 3494 | break; | 3466 | |
| 3495 | p--; | 3467 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); |
| 3496 | } | 3468 | temp_output_buffer_setup (" *code-converting-work*"); |
| 3497 | p1 = ©[nread]; | 3469 | set_buffer_internal (XBUFFER (Vstandard_output)); |
| 3498 | while (p1 - p >= 16) | 3470 | current_buffer->enable_multibyte_characters = Qnil; |
| 3499 | { | 3471 | insert_1_both (read_buf, nread, nread, 0, 0, 0); |
| 3500 | if (! bcmp ("local variables:", p, 16)) | 3472 | TEMP_SET_PT_BOTH (BEG, BEG_BYTE); |
| 3501 | { | 3473 | val = call1 (Vset_auto_coding_function, make_number (nread)); |
| 3502 | possible_spec = 1; | 3474 | set_buffer_internal (prev); |
| 3503 | break; | 3475 | /* Discard the unwind protect for recovering the |
| 3504 | } | 3476 | current buffer. */ |
| 3505 | p++; | 3477 | specpdl_ptr--; |
| 3506 | } | 3478 | |
| 3507 | win: | 3479 | /* Rewind the file for the actual read done later. */ |
| 3480 | if (lseek (fd, 0, 0) < 0) | ||
| 3481 | report_file_error ("Setting file position", | ||
| 3482 | Fcons (orig_filename, Qnil)); | ||
| 3483 | } | ||
| 3484 | } | ||
| 3508 | 3485 | ||
| 3509 | if (possible_spec) | 3486 | if (NILP (val)) |
| 3510 | { | 3487 | { |
| 3511 | /* Always make this a unibyte string | 3488 | /* If we have not yet decided a coding system, check |
| 3512 | because we have not yet decoded it. */ | 3489 | file-coding-system-alist. */ |
| 3513 | tem = make_unibyte_string (read_buf, nread); | 3490 | Lisp_Object args[6], coding_systems; |
| 3514 | val = call1 (Vset_auto_coding_function, tem); | 3491 | |
| 3515 | } | 3492 | args[0] = Qinsert_file_contents, args[1] = orig_filename; |
| 3493 | args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace; | ||
| 3494 | coding_systems = Ffind_operation_coding_system (6, args); | ||
| 3495 | if (CONSP (coding_systems)) | ||
| 3496 | val = XCONS (coding_systems)->car; | ||
| 3497 | } | ||
| 3498 | } | ||
| 3516 | 3499 | ||
| 3517 | /* Rewind the file for the actual read done later. */ | 3500 | setup_coding_system (Fcheck_coding_system (val), &coding); |
| 3518 | if (lseek (fd, 0, 0) < 0) | ||
| 3519 | report_file_error ("Setting file position", | ||
| 3520 | Fcons (orig_filename, Qnil)); | ||
| 3521 | } | ||
| 3522 | } | ||
| 3523 | if (NILP (val)) | ||
| 3524 | { | ||
| 3525 | Lisp_Object args[6], coding_systems; | ||
| 3526 | 3501 | ||
| 3527 | args[0] = Qinsert_file_contents, args[1] = orig_filename; | 3502 | if (NILP (Vcoding_system_for_read) |
| 3528 | args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace; | 3503 | && NILP (current_buffer->enable_multibyte_characters)) |
| 3529 | coding_systems = Ffind_operation_coding_system (6, args); | 3504 | { |
| 3530 | if (CONSP (coding_systems)) | 3505 | /* We must suppress all text conversion except for end-of-line |
| 3531 | val = XCONS (coding_systems)->car; | 3506 | conversion. */ |
| 3532 | } | 3507 | int eol_type; |
| 3533 | } | ||
| 3534 | 3508 | ||
| 3535 | if (NILP (Vcoding_system_for_read) | 3509 | eol_type = coding.eol_type; |
| 3536 | && NILP (current_buffer->enable_multibyte_characters)) | 3510 | setup_coding_system (Qraw_text, &coding); |
| 3537 | { | 3511 | coding.eol_type = eol_type; |
| 3538 | /* We must suppress all text conversion except for end-of-line | 3512 | } |
| 3539 | conversion. */ | ||
| 3540 | struct coding_system coding_temp; | ||
| 3541 | 3513 | ||
| 3542 | setup_coding_system (Fcheck_coding_system (val), &coding_temp); | 3514 | coding_system_decided = 1; |
| 3543 | setup_coding_system (Qraw_text, &coding); | 3515 | } |
| 3544 | coding.eol_type = coding_temp.eol_type; | ||
| 3545 | } | ||
| 3546 | else | ||
| 3547 | setup_coding_system (Fcheck_coding_system (val), &coding); | ||
| 3548 | 3516 | ||
| 3549 | /* Ensure we always set Vlast_coding_system_used. */ | 3517 | /* Ensure we always set Vlast_coding_system_used. */ |
| 3550 | set_coding_system = 1; | 3518 | set_coding_system = 1; |
| 3551 | } | ||
| 3552 | 3519 | ||
| 3553 | /* If requested, replace the accessible part of the buffer | 3520 | /* If requested, replace the accessible part of the buffer |
| 3554 | with the file contents. Avoid replacing text at the | 3521 | with the file contents. Avoid replacing text at the |
| @@ -3565,6 +3532,7 @@ actually used.") | |||
| 3565 | But if we discover the need for conversion, we give up on this method | 3532 | But if we discover the need for conversion, we give up on this method |
| 3566 | and let the following if-statement handle the replace job. */ | 3533 | and let the following if-statement handle the replace job. */ |
| 3567 | if (!NILP (replace) | 3534 | if (!NILP (replace) |
| 3535 | && BEGV < ZV | ||
| 3568 | && ! CODING_REQUIRE_DECODING (&coding) | 3536 | && ! CODING_REQUIRE_DECODING (&coding) |
| 3569 | && (coding.eol_type == CODING_EOL_UNDECIDED | 3537 | && (coding.eol_type == CODING_EOL_UNDECIDED |
| 3570 | || coding.eol_type == CODING_EOL_LF)) | 3538 | || coding.eol_type == CODING_EOL_LF)) |
| @@ -3743,7 +3711,7 @@ actually used.") | |||
| 3743 | is needed, in a simple way that needs a lot of memory. | 3711 | is needed, in a simple way that needs a lot of memory. |
| 3744 | The preceding if-statement handles the case of no conversion | 3712 | The preceding if-statement handles the case of no conversion |
| 3745 | in a more optimized way. */ | 3713 | in a more optimized way. */ |
| 3746 | if (!NILP (replace) && ! replace_handled) | 3714 | if (!NILP (replace) && ! replace_handled && BEGV < ZV) |
| 3747 | { | 3715 | { |
| 3748 | int same_at_start = BEGV_BYTE; | 3716 | int same_at_start = BEGV_BYTE; |
| 3749 | int same_at_end = ZV_BYTE; | 3717 | int same_at_end = ZV_BYTE; |
| @@ -3995,6 +3963,77 @@ actually used.") | |||
| 3995 | 3963 | ||
| 3996 | if (inserted > 0) | 3964 | if (inserted > 0) |
| 3997 | { | 3965 | { |
| 3966 | if (! coding_system_decided) | ||
| 3967 | { | ||
| 3968 | /* The coding system is not yet decided. Decide it by an | ||
| 3969 | optimized method for handling `coding:' tag. */ | ||
| 3970 | Lisp_Object val; | ||
| 3971 | val = Qnil; | ||
| 3972 | |||
| 3973 | if (!NILP (Vcoding_system_for_read)) | ||
| 3974 | val = Vcoding_system_for_read; | ||
| 3975 | else | ||
| 3976 | { | ||
| 3977 | if (! NILP (Vset_auto_coding_function)) | ||
| 3978 | { | ||
| 3979 | /* Since we are sure that the current buffer was | ||
| 3980 | empty before the insertion, we can toggle | ||
| 3981 | enable-multibyte-characters directly here without | ||
| 3982 | taking care of marker adjustment and byte | ||
| 3983 | combining problem. */ | ||
| 3984 | Lisp_Object prev_multibyte; | ||
| 3985 | int count = specpdl_ptr - specpdl; | ||
| 3986 | |||
| 3987 | prev_multibyte = current_buffer->enable_multibyte_characters; | ||
| 3988 | current_buffer->enable_multibyte_characters = Qnil; | ||
| 3989 | record_unwind_protect (set_auto_coding_unwind, | ||
| 3990 | prev_multibyte); | ||
| 3991 | val = call1 (Vset_auto_coding_function, | ||
| 3992 | make_number (inserted)); | ||
| 3993 | /* Discard the unwind protect for recovering the | ||
| 3994 | error of Vset_auto_coding_function. */ | ||
| 3995 | specpdl_ptr--; | ||
| 3996 | current_buffer->enable_multibyte_characters = prev_multibyte; | ||
| 3997 | TEMP_SET_PT_BOTH (BEG, BEG_BYTE); | ||
| 3998 | } | ||
| 3999 | |||
| 4000 | if (NILP (val)) | ||
| 4001 | { | ||
| 4002 | /* If the coding system is not yet decided, check | ||
| 4003 | file-coding-system-alist. */ | ||
| 4004 | Lisp_Object args[6], coding_systems; | ||
| 4005 | |||
| 4006 | args[0] = Qinsert_file_contents, args[1] = orig_filename; | ||
| 4007 | args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil; | ||
| 4008 | coding_systems = Ffind_operation_coding_system (6, args); | ||
| 4009 | if (CONSP (coding_systems)) | ||
| 4010 | val = XCONS (coding_systems)->car; | ||
| 4011 | } | ||
| 4012 | } | ||
| 4013 | |||
| 4014 | /* The following kludgy code is to avoid some compiler bug. | ||
| 4015 | We can't simply do | ||
| 4016 | setup_coding_system (val, &coding); | ||
| 4017 | on some system. */ | ||
| 4018 | { | ||
| 4019 | struct coding_system temp_coding; | ||
| 4020 | setup_coding_system (val, &temp_coding); | ||
| 4021 | bcopy (&temp_coding, &coding, sizeof coding); | ||
| 4022 | } | ||
| 4023 | |||
| 4024 | if (NILP (Vcoding_system_for_read) | ||
| 4025 | && NILP (current_buffer->enable_multibyte_characters)) | ||
| 4026 | { | ||
| 4027 | /* We must suppress all text conversion except for | ||
| 4028 | end-of-line conversion. */ | ||
| 4029 | int eol_type; | ||
| 4030 | |||
| 4031 | eol_type = coding.eol_type; | ||
| 4032 | setup_coding_system (Qraw_text, &coding); | ||
| 4033 | coding.eol_type = eol_type; | ||
| 4034 | } | ||
| 4035 | } | ||
| 4036 | |||
| 3998 | if (CODING_MAY_REQUIRE_DECODING (&coding)) | 4037 | if (CODING_MAY_REQUIRE_DECODING (&coding)) |
| 3999 | { | 4038 | { |
| 4000 | /* Here, we don't have to consider byte combining (see the | 4039 | /* Here, we don't have to consider byte combining (see the |