Mercurial > hg > xemacs-beta
comparison src/fns.c @ 416:ebe98a74bd68 r21-2-16
Import from CVS: tag r21-2-16
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:22:23 +0200 |
parents | da8ed4261e83 |
children | 41dbb7a9d5f2 |
comparison
equal
deleted
inserted
replaced
415:a27f76b40c83 | 416:ebe98a74bd68 |
---|---|
337 /* There is no hope of this working under Mule. Even if we converted | 337 /* There is no hope of this working under Mule. Even if we converted |
338 the data into an external format so that strcoll() processed it | 338 the data into an external format so that strcoll() processed it |
339 properly, it would still not work because strcoll() does not | 339 properly, it would still not work because strcoll() does not |
340 handle multiple locales. This is the fundamental flaw in the | 340 handle multiple locales. This is the fundamental flaw in the |
341 locale model. */ | 341 locale model. */ |
342 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); | 342 { |
343 /* Compare strings using collation order of locale. */ | 343 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); |
344 /* Need to be tricky to handle embedded nulls. */ | 344 /* Compare strings using collation order of locale. */ |
345 | 345 /* Need to be tricky to handle embedded nulls. */ |
346 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) | 346 |
347 { | 347 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) |
348 int val = strcoll ((char *) string_data (p1) + i, | 348 { |
349 (char *) string_data (p2) + i); | 349 int val = strcoll ((char *) string_data (p1) + i, |
350 if (val < 0) | 350 (char *) string_data (p2) + i); |
351 return Qt; | 351 if (val < 0) |
352 if (val > 0) | 352 return Qt; |
353 return Qnil; | 353 if (val > 0) |
354 } | 354 return Qnil; |
355 } | |
356 } | |
355 #else /* not I18N2, or MULE */ | 357 #else /* not I18N2, or MULE */ |
356 /* #### It is not really necessary to do this: We could compare | 358 { |
357 byte-by-byte and still get a reasonable comparison, since this | 359 Bufbyte *ptr1 = string_data (p1); |
358 would compare characters with a charset in the same way. | 360 Bufbyte *ptr2 = string_data (p2); |
359 With a little rearrangement of the leading bytes, we could | 361 |
360 make most inter-charset comparisons work out the same, too; | 362 /* #### It is not really necessary to do this: We could compare |
361 even if some don't, this is not a big deal because inter-charset | 363 byte-by-byte and still get a reasonable comparison, since this |
362 comparisons aren't really well-defined anyway. */ | 364 would compare characters with a charset in the same way. With |
363 for (i = 0; i < end; i++) | 365 a little rearrangement of the leading bytes, we could make most |
364 { | 366 inter-charset comparisons work out the same, too; even if some |
365 if (string_char (p1, i) != string_char (p2, i)) | 367 don't, this is not a big deal because inter-charset comparisons |
366 return string_char (p1, i) < string_char (p2, i) ? Qt : Qnil; | 368 aren't really well-defined anyway. */ |
367 } | 369 for (i = 0; i < end; i++) |
370 { | |
371 if (charptr_emchar (ptr1) != charptr_emchar (ptr2)) | |
372 return charptr_emchar (ptr1) < charptr_emchar (ptr2) ? Qt : Qnil; | |
373 INC_CHARPTR (ptr1); | |
374 INC_CHARPTR (ptr2); | |
375 } | |
376 } | |
368 #endif /* not I18N2, or MULE */ | 377 #endif /* not I18N2, or MULE */ |
369 /* Can't do i < len2 because then comparison between "foo" and "foo^@" | 378 /* Can't do i < len2 because then comparison between "foo" and "foo^@" |
370 won't work right in I18N2 case */ | 379 won't work right in I18N2 case */ |
371 return end < len2 ? Qt : Qnil; | 380 return end < len2 ? Qt : Qnil; |
372 } | 381 } |
3380 return unbind_to (speccount, feature); | 3389 return unbind_to (speccount, feature); |
3381 } | 3390 } |
3382 } | 3391 } |
3383 | 3392 |
3384 /* base64 encode/decode functions. | 3393 /* base64 encode/decode functions. |
3385 Based on code from GNU recode. */ | 3394 |
3386 | 3395 Originally based on code from GNU recode. Ported to FSF Emacs by |
3387 #define MIME_LINE_LENGTH 76 | 3396 Lars Magne Ingebrigtsen and Karl Heuer. Ported to XEmacs and |
3397 subsequently heavily hacked by Hrvoje Niksic. */ | |
3398 | |
3399 #define MIME_LINE_LENGTH 72 | |
3388 | 3400 |
3389 #define IS_ASCII(Character) \ | 3401 #define IS_ASCII(Character) \ |
3390 ((Character) < 128) | 3402 ((Character) < 128) |
3391 #define IS_BASE64(Character) \ | 3403 #define IS_BASE64(Character) \ |
3392 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) | 3404 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) |
3502 | 3514 |
3503 return e - to; | 3515 return e - to; |
3504 } | 3516 } |
3505 #undef ADVANCE_INPUT | 3517 #undef ADVANCE_INPUT |
3506 | 3518 |
3507 /* Semantically identical to ADVANCE_INPUT above, only no >255 | 3519 /* Get next character from the stream, except that non-base64 |
3508 checking is needed for decoding -- checking is covered by IS_BASE64 | 3520 characters are ignored. This is in accordance with rfc2045. EC |
3509 below. */ | 3521 should be an Emchar, so that it can hold -1 as the value for EOF. */ |
3510 #define ADVANCE_INPUT(c, stream) \ | 3522 #define ADVANCE_INPUT_IGNORE_NONBASE64(ec, stream, streampos) do { \ |
3511 (ec = Lstream_get_emchar (stream), \ | 3523 ec = Lstream_get_emchar (stream); \ |
3512 ec == -1 ? 0 : (c = (Bufbyte)ec, 1)) | 3524 ++streampos; \ |
3513 | 3525 /* IS_BASE64 may not be called with negative arguments so check for \ |
3514 /* Get next character from the stream, but ignore it if it's | 3526 EOF first. */ \ |
3515 whitespace. ENDP is set to 1 if EOF is hit. */ | 3527 if (ec < 0 || IS_BASE64 (ec) || ec == '=') \ |
3516 #define ADVANCE_INPUT_IGNORE_WHITESPACE(c, endp, stream) do { \ | 3528 break; \ |
3517 endp = 0; \ | 3529 } while (1) |
3518 do { \ | 3530 |
3519 if (!ADVANCE_INPUT (c, stream)) \ | 3531 #define STORE_BYTE(pos, val, ccnt) do { \ |
3520 endp = 1; \ | |
3521 } while (!endp && (c == ' ' || c == '\t' || c == '\r' || c == '\n' \ | |
3522 || c == '\f' || c == '\v')); \ | |
3523 } while (0) | |
3524 | |
3525 #define STORE_BYTE(pos, val) do { \ | |
3526 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \ | 3532 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \ |
3527 ++*ccptr; \ | 3533 ++ccnt; \ |
3528 } while (0) | 3534 } while (0) |
3529 | 3535 |
3530 static Bytind | 3536 static Bytind |
3531 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr) | 3537 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr) |
3532 { | 3538 { |
3539 Charcount ccnt = 0; | |
3533 Bufbyte *e = to; | 3540 Bufbyte *e = to; |
3534 unsigned long value; | 3541 EMACS_INT streampos = 0; |
3535 | 3542 |
3536 *ccptr = 0; | |
3537 while (1) | 3543 while (1) |
3538 { | 3544 { |
3539 Bufbyte c; | |
3540 Emchar ec; | 3545 Emchar ec; |
3541 int endp; | 3546 unsigned long value; |
3542 | 3547 |
3543 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); | 3548 /* Process first byte of a quadruplet. */ |
3544 if (endp) | 3549 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); |
3550 if (ec < 0) | |
3545 break; | 3551 break; |
3546 | 3552 if (ec == '=') |
3547 /* Process first byte of a quadruplet. */ | 3553 signal_simple_error ("Illegal `=' character while decoding base64", |
3548 if (!IS_BASE64 (c)) | 3554 make_int (streampos)); |
3549 return -1; | 3555 value = base64_char_to_value[ec] << 18; |
3550 value = base64_char_to_value[c] << 18; | |
3551 | 3556 |
3552 /* Process second byte of a quadruplet. */ | 3557 /* Process second byte of a quadruplet. */ |
3553 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); | 3558 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); |
3554 if (endp) | 3559 if (ec < 0) |
3555 return -1; | 3560 error ("Premature EOF while decoding base64"); |
3556 | 3561 if (ec == '=') |
3557 if (!IS_BASE64 (c)) | 3562 signal_simple_error ("Illegal `=' character while decoding base64", |
3558 return -1; | 3563 make_int (streampos)); |
3559 value |= base64_char_to_value[c] << 12; | 3564 value |= base64_char_to_value[ec] << 12; |
3560 | 3565 STORE_BYTE (e, value >> 16, ccnt); |
3561 STORE_BYTE (e, value >> 16); | |
3562 | 3566 |
3563 /* Process third byte of a quadruplet. */ | 3567 /* Process third byte of a quadruplet. */ |
3564 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); | 3568 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); |
3565 if (endp) | 3569 if (ec < 0) |
3566 return -1; | 3570 error ("Premature EOF while decoding base64"); |
3567 | 3571 |
3568 if (c == '=') | 3572 if (ec == '=') |
3569 { | 3573 { |
3570 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); | 3574 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); |
3571 if (endp) | 3575 if (ec < 0) |
3572 return -1; | 3576 error ("Premature EOF while decoding base64"); |
3573 if (c != '=') | 3577 if (ec != '=') |
3574 return -1; | 3578 signal_simple_error ("Padding `=' expected but not found while decoding base64", |
3579 make_int (streampos)); | |
3575 continue; | 3580 continue; |
3576 } | 3581 } |
3577 | 3582 |
3578 if (!IS_BASE64 (c)) | 3583 value |= base64_char_to_value[ec] << 6; |
3579 return -1; | 3584 STORE_BYTE (e, 0xff & value >> 8, ccnt); |
3580 value |= base64_char_to_value[c] << 6; | |
3581 | |
3582 STORE_BYTE (e, 0xff & value >> 8); | |
3583 | 3585 |
3584 /* Process fourth byte of a quadruplet. */ | 3586 /* Process fourth byte of a quadruplet. */ |
3585 ADVANCE_INPUT_IGNORE_WHITESPACE (c, endp, istream); | 3587 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); |
3586 if (endp) | 3588 if (ec < 0) |
3587 return -1; | 3589 error ("Premature EOF while decoding base64"); |
3588 | 3590 if (ec == '=') |
3589 if (c == '=') | |
3590 continue; | 3591 continue; |
3591 | 3592 |
3592 if (!IS_BASE64 (c)) | 3593 value |= base64_char_to_value[ec]; |
3593 return -1; | 3594 STORE_BYTE (e, 0xff & value, ccnt); |
3594 value |= base64_char_to_value[c]; | 3595 } |
3595 | 3596 |
3596 STORE_BYTE (e, 0xff & value); | 3597 *ccptr = ccnt; |
3597 } | |
3598 | |
3599 return e - to; | 3598 return e - to; |
3600 } | 3599 } |
3601 #undef ADVANCE_INPUT | 3600 #undef ADVANCE_INPUT |
3602 #undef ADVANCE_INPUT_IGNORE_WHITESPACE | 3601 #undef ADVANCE_INPUT_IGNORE_NONBASE64 |
3603 #undef STORE_BYTE | 3602 #undef STORE_BYTE |
3604 | 3603 |
3605 static Lisp_Object | 3604 static Lisp_Object |
3606 free_malloced_ptr (Lisp_Object unwind_obj) | 3605 free_malloced_ptr (Lisp_Object unwind_obj) |
3607 { | 3606 { |
3675 and delete the old. (Insert first in order to preserve markers.) */ | 3674 and delete the old. (Insert first in order to preserve markers.) */ |
3676 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); | 3675 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); |
3677 XMALLOC_UNBIND (encoded, allength, speccount); | 3676 XMALLOC_UNBIND (encoded, allength, speccount); |
3678 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0); | 3677 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0); |
3679 | 3678 |
3680 /* Simulate FSF Emacs: if point was in the region, place it at the | 3679 /* Simulate FSF Emacs implementation of this function: if point was |
3681 beginning. */ | 3680 in the region, place it at the beginning. */ |
3682 if (old_pt >= begv && old_pt < zv) | 3681 if (old_pt >= begv && old_pt < zv) |
3683 BUF_SET_PT (buf, begv); | 3682 BUF_SET_PT (buf, begv); |
3684 | 3683 |
3685 /* We return the length of the encoded text. */ | 3684 /* We return the length of the encoded text. */ |
3686 return make_int (encoded_length); | 3685 return make_int (encoded_length); |
3717 | 3716 |
3718 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /* | 3717 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /* |
3719 Base64-decode the region between BEG and END. | 3718 Base64-decode the region between BEG and END. |
3720 Return the length of the decoded text. | 3719 Return the length of the decoded text. |
3721 If the region can't be decoded, return nil and don't modify the buffer. | 3720 If the region can't be decoded, return nil and don't modify the buffer. |
3721 Characters out of the base64 alphabet are ignored. | |
3722 */ | 3722 */ |
3723 (beg, end)) | 3723 (beg, end)) |
3724 { | 3724 { |
3725 struct buffer *buf = current_buffer; | 3725 struct buffer *buf = current_buffer; |
3726 Bufpos begv, zv, old_pt = BUF_PT (buf); | 3726 Bufpos begv, zv, old_pt = BUF_PT (buf); |
3741 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); | 3741 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); |
3742 if (decoded_length > length * MAX_EMCHAR_LEN) | 3742 if (decoded_length > length * MAX_EMCHAR_LEN) |
3743 abort (); | 3743 abort (); |
3744 Lstream_delete (XLSTREAM (input)); | 3744 Lstream_delete (XLSTREAM (input)); |
3745 | 3745 |
3746 if (decoded_length < 0) | |
3747 { | |
3748 /* The decoding wasn't possible. */ | |
3749 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | |
3750 return Qnil; | |
3751 } | |
3752 | |
3753 /* Now we have decoded the region, so we insert the new contents | 3746 /* Now we have decoded the region, so we insert the new contents |
3754 and delete the old. (Insert first in order to preserve markers.) */ | 3747 and delete the old. (Insert first in order to preserve markers.) */ |
3755 BUF_SET_PT (buf, begv); | 3748 BUF_SET_PT (buf, begv); |
3756 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0); | 3749 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0); |
3757 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | 3750 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); |
3758 buffer_delete_range (buf, begv + cc_decoded_length, | 3751 buffer_delete_range (buf, begv + cc_decoded_length, |
3759 zv + cc_decoded_length, 0); | 3752 zv + cc_decoded_length, 0); |
3760 | 3753 |
3761 /* Simulate FSF Emacs: if point was in the region, place it at the | 3754 /* Simulate FSF Emacs implementation of this function: if point was |
3762 beginning. */ | 3755 in the region, place it at the beginning. */ |
3763 if (old_pt >= begv && old_pt < zv) | 3756 if (old_pt >= begv && old_pt < zv) |
3764 BUF_SET_PT (buf, begv); | 3757 BUF_SET_PT (buf, begv); |
3765 | 3758 |
3766 return make_int (cc_decoded_length); | 3759 return make_int (cc_decoded_length); |
3767 } | 3760 } |
3768 | 3761 |
3769 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /* | 3762 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /* |
3770 Base64-decode STRING and return the result. | 3763 Base64-decode STRING and return the result. |
3764 Characters out of the base64 alphabet are ignored. | |
3771 */ | 3765 */ |
3772 (string)) | 3766 (string)) |
3773 { | 3767 { |
3774 Bufbyte *decoded; | 3768 Bufbyte *decoded; |
3775 Bytind decoded_length; | 3769 Bytind decoded_length; |
3787 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, | 3781 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, |
3788 &cc_decoded_length); | 3782 &cc_decoded_length); |
3789 if (decoded_length > length * MAX_EMCHAR_LEN) | 3783 if (decoded_length > length * MAX_EMCHAR_LEN) |
3790 abort (); | 3784 abort (); |
3791 Lstream_delete (XLSTREAM (input)); | 3785 Lstream_delete (XLSTREAM (input)); |
3792 | |
3793 if (decoded_length < 0) | |
3794 { | |
3795 /* The decoding wasn't possible. */ | |
3796 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | |
3797 return Qnil; | |
3798 } | |
3799 | 3786 |
3800 result = make_string (decoded, decoded_length); | 3787 result = make_string (decoded, decoded_length); |
3801 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | 3788 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); |
3802 return result; | 3789 return result; |
3803 } | 3790 } |