aboutsummaryrefslogtreecommitdiffstats
path: root/src/casefiddle.c
diff options
context:
space:
mode:
authorMichal Nazarewicz2016-09-07 15:26:42 +0200
committerMichal Nazarewicz2017-04-06 20:54:57 +0200
commitec2d002ff663775e453873c38690c68276a93349 (patch)
tree35bd672b1575313f76bd505181c635b55e70475e /src/casefiddle.c
parent4753f3f0af33c5defe3a340f82265db6a6863030 (diff)
downloademacs-ec2d002ff663775e453873c38690c68276a93349.tar.gz
emacs-ec2d002ff663775e453873c38690c68276a93349.zip
Split casify_object into multiple functions
casify_object had three major cases to cover and those were mostly independent of each other. Move those branches to separate function so it’s easier to comprehend each individual case. While at it, use somewhat more descriptive ch and cased variable names rather than c and c1. This commit introduces no functional changes. * src/casefiddle.c (casify_object): Split into… (do_casify_integer, do_casify_multibyte_string, do_casify_unibyte_string): …new functions.
Diffstat (limited to 'src/casefiddle.c')
-rw-r--r--src/casefiddle.c196
1 files changed, 104 insertions, 92 deletions
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 11d59444916..72661979b4d 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -32,108 +32,120 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP}; 32enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
33 33
34static Lisp_Object 34static Lisp_Object
35casify_object (enum case_action flag, Lisp_Object obj) 35do_casify_natnum (enum case_action flag, Lisp_Object obj)
36{
37 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
38 | CHAR_SHIFT | CHAR_CTL | CHAR_META);
39 int flags, ch = XFASTINT (obj), cased;
40 bool multibyte;
41
42 /* If the character has higher bits set above the flags, return it unchanged.
43 It is not a real character. */
44 if (UNSIGNED_CMP (ch, >, flagbits))
45 return obj;
46
47 flags = ch & flagbits;
48 ch = ch & ~flagbits;
49
50 /* FIXME: Even if enable-multibyte-characters is nil, we may manipulate
51 multibyte chars. This means we have a bug for latin-1 chars since when we
52 receive an int 128-255 we can't tell whether it's an eight-bit byte or
53 a latin-1 char. */
54 multibyte = ch >= 256
55 || !NILP (BVAR (current_buffer, enable_multibyte_characters));
56 if (! multibyte)
57 MAKE_CHAR_MULTIBYTE (ch);
58 cased = flag == CASE_DOWN ? downcase (ch) : upcase (ch);
59 if (cased == ch)
60 return obj;
61
62 if (! multibyte)
63 MAKE_CHAR_UNIBYTE (cased);
64 XSETFASTINT (obj, cased | flags);
65 return obj;
66}
67
68static Lisp_Object
69do_casify_multibyte_string (enum case_action flag, Lisp_Object obj)
70{
71 ptrdiff_t i, i_byte, size = SCHARS (obj);
72 bool inword = flag == CASE_DOWN;
73 int len, ch, cased;
74 USE_SAFE_ALLOCA;
75 ptrdiff_t o_size;
76 if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &o_size))
77 o_size = PTRDIFF_MAX;
78 unsigned char *dst = SAFE_ALLOCA (o_size);
79 unsigned char *o = dst;
80
81 for (i = i_byte = 0; i < size; i++, i_byte += len)
82 {
83 if (o_size - MAX_MULTIBYTE_LENGTH < o - dst)
84 string_overflow ();
85 ch = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
86 if (inword && flag != CASE_CAPITALIZE_UP)
87 cased = downcase (ch);
88 else if (!inword || flag != CASE_CAPITALIZE_UP)
89 cased = upcase (ch);
90 else
91 cased = ch;
92 if ((int) flag >= (int) CASE_CAPITALIZE)
93 inword = (SYNTAX (ch) == Sword);
94 o += CHAR_STRING (cased, o);
95 }
96 eassert (o - dst <= o_size);
97 obj = make_multibyte_string ((char *) dst, size, o - dst);
98 SAFE_FREE ();
99 return obj;
100}
101
102static Lisp_Object
103do_casify_unibyte_string (enum case_action flag, Lisp_Object obj)
36{ 104{
37 int c, c1; 105 ptrdiff_t i, size = SCHARS (obj);
38 bool inword = flag == CASE_DOWN; 106 bool inword = flag == CASE_DOWN;
107 int ch, cased;
108
109 obj = Fcopy_sequence (obj);
110 for (i = 0; i < size; i++)
111 {
112 ch = SREF (obj, i);
113 MAKE_CHAR_MULTIBYTE (ch);
114 cased = ch;
115 if (inword && flag != CASE_CAPITALIZE_UP)
116 ch = downcase (ch);
117 else if (!uppercasep (ch)
118 && (!inword || flag != CASE_CAPITALIZE_UP))
119 ch = upcase (cased);
120 if ((int) flag >= (int) CASE_CAPITALIZE)
121 inword = (SYNTAX (ch) == Sword);
122 if (ch == cased)
123 continue;
124 MAKE_CHAR_UNIBYTE (ch);
125 /* If the char can't be converted to a valid byte, just don't change it */
126 if (ch >= 0 && ch < 256)
127 SSET (obj, i, ch);
128 }
129 return obj;
130}
39 131
132static Lisp_Object
133casify_object (enum case_action flag, Lisp_Object obj)
134{
40 /* If the case table is flagged as modified, rescan it. */ 135 /* If the case table is flagged as modified, rescan it. */
41 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1])) 136 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1]))
42 Fset_case_table (BVAR (current_buffer, downcase_table)); 137 Fset_case_table (BVAR (current_buffer, downcase_table));
43 138
44 if (NATNUMP (obj)) 139 if (NATNUMP (obj))
45 { 140 return do_casify_natnum (flag, obj);
46 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER 141 else if (!STRINGP (obj))
47 | CHAR_SHIFT | CHAR_CTL | CHAR_META);
48 int flags = XINT (obj) & flagbits;
49 bool multibyte = ! NILP (BVAR (current_buffer,
50 enable_multibyte_characters));
51
52 /* If the character has higher bits set
53 above the flags, return it unchanged.
54 It is not a real character. */
55 if (UNSIGNED_CMP (XFASTINT (obj), >, flagbits))
56 return obj;
57
58 c1 = XFASTINT (obj) & ~flagbits;
59 /* FIXME: Even if enable-multibyte-characters is nil, we may
60 manipulate multibyte chars. This means we have a bug for latin-1
61 chars since when we receive an int 128-255 we can't tell whether
62 it's an eight-bit byte or a latin-1 char. */
63 if (c1 >= 256)
64 multibyte = 1;
65 if (! multibyte)
66 MAKE_CHAR_MULTIBYTE (c1);
67 c = flag == CASE_DOWN ? downcase (c1) : upcase (c1);
68 if (c != c1)
69 {
70 if (! multibyte)
71 MAKE_CHAR_UNIBYTE (c);
72 XSETFASTINT (obj, c | flags);
73 }
74 return obj;
75 }
76
77 if (!STRINGP (obj))
78 wrong_type_argument (Qchar_or_string_p, obj); 142 wrong_type_argument (Qchar_or_string_p, obj);
79 else if (!STRING_MULTIBYTE (obj)) 143 else if (!SCHARS (obj))
80 { 144 return obj;
81 ptrdiff_t i; 145 else if (STRING_MULTIBYTE (obj))
82 ptrdiff_t size = SCHARS (obj); 146 return do_casify_multibyte_string (flag, obj);
83
84 obj = Fcopy_sequence (obj);
85 for (i = 0; i < size; i++)
86 {
87 c = SREF (obj, i);
88 MAKE_CHAR_MULTIBYTE (c);
89 c1 = c;
90 if (inword && flag != CASE_CAPITALIZE_UP)
91 c = downcase (c);
92 else if (!uppercasep (c)
93 && (!inword || flag != CASE_CAPITALIZE_UP))
94 c = upcase (c1);
95 if ((int) flag >= (int) CASE_CAPITALIZE)
96 inword = (SYNTAX (c) == Sword);
97 if (c != c1)
98 {
99 MAKE_CHAR_UNIBYTE (c);
100 /* If the char can't be converted to a valid byte, just don't
101 change it. */
102 if (c >= 0 && c < 256)
103 SSET (obj, i, c);
104 }
105 }
106 return obj;
107 }
108 else 147 else
109 { 148 return do_casify_unibyte_string (flag, obj);
110 ptrdiff_t i, i_byte, size = SCHARS (obj);
111 int len;
112 USE_SAFE_ALLOCA;
113 ptrdiff_t o_size;
114 if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &o_size))
115 o_size = PTRDIFF_MAX;
116 unsigned char *dst = SAFE_ALLOCA (o_size);
117 unsigned char *o = dst;
118
119 for (i = i_byte = 0; i < size; i++, i_byte += len)
120 {
121 if (o_size - MAX_MULTIBYTE_LENGTH < o - dst)
122 string_overflow ();
123 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
124 if (inword && flag != CASE_CAPITALIZE_UP)
125 c = downcase (c);
126 else if (!inword || flag != CASE_CAPITALIZE_UP)
127 c = upcase (c);
128 if ((int) flag >= (int) CASE_CAPITALIZE)
129 inword = (SYNTAX (c) == Sword);
130 o += CHAR_STRING (c, o);
131 }
132 eassert (o - dst <= o_size);
133 obj = make_multibyte_string ((char *) dst, size, o - dst);
134 SAFE_FREE ();
135 return obj;
136 }
137} 149}
138 150
139DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0, 151DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,