diff options
| author | Richard M. Stallman | 1998-01-09 22:34:48 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-01-09 22:34:48 +0000 |
| commit | 1f24f4fdd2b7203aa75728a4437cb0520a8e6877 (patch) | |
| tree | e4605350016c0460fc86a383d2700e54b72f12a6 /src | |
| parent | 6bb762b32476cd8f778a17f225e657f079a41728 (diff) | |
| download | emacs-1f24f4fdd2b7203aa75728a4437cb0520a8e6877.tar.gz emacs-1f24f4fdd2b7203aa75728a4437cb0520a8e6877.zip | |
(Fformat): Do all the work directly--don't use doprnt.
Calculate the right size the first time, so no need to retry.
Count chars and bytes in the result.
Convert single-byte strings to multibyte as needed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 290 |
1 files changed, 157 insertions, 133 deletions
diff --git a/src/editfns.c b/src/editfns.c index 14c908243a1..7f47d596b13 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -132,7 +132,7 @@ DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0, | |||
| 132 | CHECK_NUMBER (character, 0); | 132 | CHECK_NUMBER (character, 0); |
| 133 | 133 | ||
| 134 | len = CHAR_STRING (XFASTINT (character), workbuf, str); | 134 | len = CHAR_STRING (XFASTINT (character), workbuf, str); |
| 135 | return make_string (str, len); | 135 | return make_multibyte_string (str, 1, len); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0, | 138 | DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0, |
| @@ -151,48 +151,6 @@ A multibyte character is handled correctly.") | |||
| 151 | XSETFASTINT (val, 0); | 151 | XSETFASTINT (val, 0); |
| 152 | return val; | 152 | return val; |
| 153 | } | 153 | } |
| 154 | |||
| 155 | DEFUN ("sref", Fsref, Ssref, 2, 2, 0, | ||
| 156 | "Return the character in STRING at INDEX. INDEX starts at 0.\n\ | ||
| 157 | A multibyte character is handled correctly.\n\ | ||
| 158 | INDEX not pointing at character boundary is an error.") | ||
| 159 | (str, idx) | ||
| 160 | Lisp_Object str, idx; | ||
| 161 | { | ||
| 162 | register int idxval, len, i; | ||
| 163 | register unsigned char *p, *q; | ||
| 164 | register Lisp_Object val; | ||
| 165 | |||
| 166 | CHECK_STRING (str, 0); | ||
| 167 | CHECK_NUMBER (idx, 1); | ||
| 168 | idxval = XINT (idx); | ||
| 169 | if (idxval < 0 || idxval >= (len = XVECTOR (str)->size)) | ||
| 170 | args_out_of_range (str, idx); | ||
| 171 | |||
| 172 | p = XSTRING (str)->data + idxval; | ||
| 173 | if (!NILP (current_buffer->enable_multibyte_characters) | ||
| 174 | && !CHAR_HEAD_P (*p) | ||
| 175 | && idxval > 0) | ||
| 176 | { | ||
| 177 | /* We must check if P points to a tailing byte of a multibyte | ||
| 178 | form. If so, we signal error. */ | ||
| 179 | i = idxval - 1; | ||
| 180 | q = p - 1; | ||
| 181 | while (i > 0 && *q >= 0xA0) i--, q--; | ||
| 182 | |||
| 183 | if (*q == LEADING_CODE_COMPOSITION) | ||
| 184 | i = multibyte_form_length (XSTRING (str)->data + i, len - i); | ||
| 185 | else | ||
| 186 | i = BYTES_BY_CHAR_HEAD (*q); | ||
| 187 | if (q + i > p) | ||
| 188 | error ("Not character boundary"); | ||
| 189 | } | ||
| 190 | |||
| 191 | len = XSTRING (str)->size - idxval; | ||
| 192 | XSETFASTINT (val, STRING_CHAR (p, len)); | ||
| 193 | return val; | ||
| 194 | } | ||
| 195 | |||
| 196 | 154 | ||
| 197 | static Lisp_Object | 155 | static Lisp_Object |
| 198 | buildmark (charpos, bytepos) | 156 | buildmark (charpos, bytepos) |
| @@ -887,7 +845,7 @@ DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0, | |||
| 887 | error ("Invalid time specification"); | 845 | error ("Invalid time specification"); |
| 888 | 846 | ||
| 889 | /* This is probably enough. */ | 847 | /* This is probably enough. */ |
| 890 | size = XSTRING (format_string)->size * 6 + 50; | 848 | size = XSTRING (format_string)->size_byte * 6 + 50; |
| 891 | 849 | ||
| 892 | while (1) | 850 | while (1) |
| 893 | { | 851 | { |
| @@ -1288,7 +1246,7 @@ void | |||
| 1288 | general_insert_function (insert_func, insert_from_string_func, | 1246 | general_insert_function (insert_func, insert_from_string_func, |
| 1289 | inherit, nargs, args) | 1247 | inherit, nargs, args) |
| 1290 | void (*insert_func) P_ ((unsigned char *, int)); | 1248 | void (*insert_func) P_ ((unsigned char *, int)); |
| 1291 | void (*insert_from_string_func) P_ ((Lisp_Object, int, int, int)); | 1249 | void (*insert_from_string_func) P_ ((Lisp_Object, int, int, int, int, int)); |
| 1292 | int inherit, nargs; | 1250 | int inherit, nargs; |
| 1293 | register Lisp_Object *args; | 1251 | register Lisp_Object *args; |
| 1294 | { | 1252 | { |
| @@ -1312,7 +1270,10 @@ general_insert_function (insert_func, insert_from_string_func, | |||
| 1312 | } | 1270 | } |
| 1313 | else if (STRINGP (val)) | 1271 | else if (STRINGP (val)) |
| 1314 | { | 1272 | { |
| 1315 | (*insert_from_string_func) (val, 0, XSTRING (val)->size, inherit); | 1273 | (*insert_from_string_func) (val, 0, 0, |
| 1274 | XSTRING (val)->size, | ||
| 1275 | XSTRING (val)->size_byte, | ||
| 1276 | inherit); | ||
| 1316 | } | 1277 | } |
| 1317 | else | 1278 | else |
| 1318 | { | 1279 | { |
| @@ -1469,7 +1430,7 @@ make_buffer_string (start, end, props) | |||
| 1469 | if (start < GPT && GPT < end) | 1430 | if (start < GPT && GPT < end) |
| 1470 | move_gap (start); | 1431 | move_gap (start); |
| 1471 | 1432 | ||
| 1472 | result = make_uninit_string (end_byte - start_byte); | 1433 | result = make_uninit_multibyte_string (end - start, end_byte - start_byte); |
| 1473 | bcopy (BYTE_POS_ADDR (start_byte), XSTRING (result)->data, | 1434 | bcopy (BYTE_POS_ADDR (start_byte), XSTRING (result)->data, |
| 1474 | end_byte - start_byte); | 1435 | end_byte - start_byte); |
| 1475 | 1436 | ||
| @@ -1873,7 +1834,9 @@ Both characters must have the same length of multi-byte form.") | |||
| 1873 | DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0, | 1834 | DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0, |
| 1874 | "From START to END, translate characters according to TABLE.\n\ | 1835 | "From START to END, translate characters according to TABLE.\n\ |
| 1875 | TABLE is a string; the Nth character in it is the mapping\n\ | 1836 | TABLE is a string; the Nth character in it is the mapping\n\ |
| 1876 | for the character with code N. Returns the number of characters changed.") | 1837 | for the character with code N.\n\ |
| 1838 | This function does not alter multibyte characters.\n\ | ||
| 1839 | It returns the number of characters changed.") | ||
| 1877 | (start, end, table) | 1840 | (start, end, table) |
| 1878 | Lisp_Object start; | 1841 | Lisp_Object start; |
| 1879 | Lisp_Object end; | 1842 | Lisp_Object end; |
| @@ -1884,38 +1847,40 @@ for the character with code N. Returns the number of characters changed.") | |||
| 1884 | register int nc; /* New character. */ | 1847 | register int nc; /* New character. */ |
| 1885 | int cnt; /* Number of changes made. */ | 1848 | int cnt; /* Number of changes made. */ |
| 1886 | int size; /* Size of translate table. */ | 1849 | int size; /* Size of translate table. */ |
| 1887 | int charpos; | 1850 | int pos; |
| 1888 | 1851 | ||
| 1889 | validate_region (&start, &end); | 1852 | validate_region (&start, &end); |
| 1890 | CHECK_STRING (table, 2); | 1853 | CHECK_STRING (table, 2); |
| 1891 | 1854 | ||
| 1892 | size = XSTRING (table)->size; | 1855 | size = XSTRING (table)->size_byte; |
| 1893 | tt = XSTRING (table)->data; | 1856 | tt = XSTRING (table)->data; |
| 1894 | 1857 | ||
| 1895 | pos_byte = CHAR_TO_BYTE (XINT (start)); | 1858 | pos_byte = CHAR_TO_BYTE (XINT (start)); |
| 1896 | stop = CHAR_TO_BYTE (XINT (end)); | 1859 | stop = CHAR_TO_BYTE (XINT (end)); |
| 1897 | modify_region (current_buffer, XINT (start), XINT (end)); | 1860 | modify_region (current_buffer, XINT (start), XINT (end)); |
| 1898 | charpos = XINT (start); | 1861 | pos = XINT (start); |
| 1899 | 1862 | ||
| 1900 | cnt = 0; | 1863 | cnt = 0; |
| 1901 | for (; pos_byte < stop; ++pos_byte) | 1864 | for (; pos_byte < stop; ) |
| 1902 | { | 1865 | { |
| 1903 | register unsigned char *p = BYTE_POS_ADDR (pos_byte); | 1866 | register unsigned char *p = BYTE_POS_ADDR (pos_byte); |
| 1904 | register int oc = *p; /* Old character. */ | 1867 | int len; |
| 1905 | if (CHAR_HEAD_P (*p)) | 1868 | int oc; |
| 1906 | charpos++; | ||
| 1907 | 1869 | ||
| 1908 | if (oc < size) | 1870 | oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len); |
| 1871 | if (oc < size && len == 1) | ||
| 1909 | { | 1872 | { |
| 1910 | nc = tt[oc]; | 1873 | nc = tt[oc]; |
| 1911 | if (nc != oc) | 1874 | if (nc != oc) |
| 1912 | { | 1875 | { |
| 1913 | record_change (charpos, 1); | 1876 | record_change (pos, 1); |
| 1914 | *p = nc; | 1877 | *p = nc; |
| 1915 | signal_after_change (charpos, 1, 1); | 1878 | signal_after_change (pos, 1, 1); |
| 1916 | ++cnt; | 1879 | ++cnt; |
| 1917 | } | 1880 | } |
| 1918 | } | 1881 | } |
| 1882 | pos_byte += len; | ||
| 1883 | pos++; | ||
| 1919 | } | 1884 | } |
| 1920 | 1885 | ||
| 1921 | return make_number (cnt); | 1886 | return make_number (cnt); |
| @@ -2103,11 +2068,12 @@ minibuffer contents show.") | |||
| 2103 | } | 2068 | } |
| 2104 | if (XSTRING (val)->size > message_length) | 2069 | if (XSTRING (val)->size > message_length) |
| 2105 | { | 2070 | { |
| 2106 | message_length = XSTRING (val)->size; | 2071 | message_length = XSTRING (val)->size_byte; |
| 2107 | message_text = (char *)xrealloc (message_text, message_length); | 2072 | message_text = (char *)xrealloc (message_text, message_length); |
| 2108 | } | 2073 | } |
| 2109 | bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size); | 2074 | bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size_byte); |
| 2110 | message2 (message_text, XSTRING (val)->size); | 2075 | message2 (message_text, XSTRING (val)->size_byte, |
| 2076 | STRING_MULTIBYTE (val)); | ||
| 2111 | return val; | 2077 | return val; |
| 2112 | } | 2078 | } |
| 2113 | } | 2079 | } |
| @@ -2151,13 +2117,13 @@ minibuffer contents show.") | |||
| 2151 | message_text = (char *)xmalloc (80); | 2117 | message_text = (char *)xmalloc (80); |
| 2152 | message_length = 80; | 2118 | message_length = 80; |
| 2153 | } | 2119 | } |
| 2154 | if (XSTRING (val)->size > message_length) | 2120 | if (XSTRING (val)->size_byte > message_length) |
| 2155 | { | 2121 | { |
| 2156 | message_length = XSTRING (val)->size; | 2122 | message_length = XSTRING (val)->size_byte; |
| 2157 | message_text = (char *)xrealloc (message_text, message_length); | 2123 | message_text = (char *)xrealloc (message_text, message_length); |
| 2158 | } | 2124 | } |
| 2159 | bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size); | 2125 | bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size_byte); |
| 2160 | message2 (message_text, XSTRING (val)->size); | 2126 | message2 (message_text, XSTRING (val)->size_byte); |
| 2161 | return val; | 2127 | return val; |
| 2162 | #endif /* not HAVE_MENUS */ | 2128 | #endif /* not HAVE_MENUS */ |
| 2163 | } | 2129 | } |
| @@ -2195,6 +2161,15 @@ DEFUN ("current-message", Fcurrent_message, Scurrent_message, 0, 0, 0, | |||
| 2195 | : Qnil); | 2161 | : Qnil); |
| 2196 | } | 2162 | } |
| 2197 | 2163 | ||
| 2164 | /* Number of bytes that STRING will occupy when put into the result. | ||
| 2165 | MULTIBYTE is nonzero if the result should be multibyte. */ | ||
| 2166 | |||
| 2167 | #define CONVERTED_BYTE_SIZE(MULTIBYTE, STRING) \ | ||
| 2168 | (((MULTIBYTE) && ! STRING_MULTIBYTE (STRING)) \ | ||
| 2169 | ? XSTRING (STRING)->size_byte \ | ||
| 2170 | : count_size_as_multibyte (XSTRING (STRING)->data, \ | ||
| 2171 | XSTRING (STRING)->size_byte)) | ||
| 2172 | |||
| 2198 | DEFUN ("format", Fformat, Sformat, 1, MANY, 0, | 2173 | DEFUN ("format", Fformat, Sformat, 1, MANY, 0, |
| 2199 | "Format a string out of a control-string and arguments.\n\ | 2174 | "Format a string out of a control-string and arguments.\n\ |
| 2200 | The first argument is a control string.\n\ | 2175 | The first argument is a control string.\n\ |
| @@ -2216,22 +2191,39 @@ Use %% to put a single % into the output.") | |||
| 2216 | { | 2191 | { |
| 2217 | register int n; /* The number of the next arg to substitute */ | 2192 | register int n; /* The number of the next arg to substitute */ |
| 2218 | register int total = 5; /* An estimate of the final length */ | 2193 | register int total = 5; /* An estimate of the final length */ |
| 2219 | char *buf; | 2194 | char *buf, *p; |
| 2220 | register unsigned char *format, *end; | 2195 | register unsigned char *format, *end; |
| 2221 | int length; | 2196 | int length, nchars; |
| 2197 | /* Nonzero if the output should be a multibyte string, | ||
| 2198 | which is true if any of the inputs is one. */ | ||
| 2199 | int multibyte = 0; | ||
| 2200 | unsigned char *this_format; | ||
| 2201 | int longest_format = 0; | ||
| 2202 | |||
| 2222 | extern char *index (); | 2203 | extern char *index (); |
| 2204 | |||
| 2223 | /* It should not be necessary to GCPRO ARGS, because | 2205 | /* It should not be necessary to GCPRO ARGS, because |
| 2224 | the caller in the interpreter should take care of that. */ | 2206 | the caller in the interpreter should take care of that. */ |
| 2225 | 2207 | ||
| 2208 | for (n = 0; n < nargs; n++) | ||
| 2209 | if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n])) | ||
| 2210 | multibyte = 1; | ||
| 2211 | |||
| 2226 | CHECK_STRING (args[0], 0); | 2212 | CHECK_STRING (args[0], 0); |
| 2227 | format = XSTRING (args[0])->data; | 2213 | format = XSTRING (args[0])->data; |
| 2228 | end = format + XSTRING (args[0])->size; | 2214 | end = format + XSTRING (args[0])->size_byte; |
| 2215 | |||
| 2216 | /* Make room in result for all the non-%-codes in the control string. */ | ||
| 2217 | total += CONVERTED_BYTE_SIZE (multibyte, args[0]); | ||
| 2218 | |||
| 2219 | /* Add to TOTAL enough space to hold the converted arguments. */ | ||
| 2229 | 2220 | ||
| 2230 | n = 0; | 2221 | n = 0; |
| 2231 | while (format != end) | 2222 | while (format != end) |
| 2232 | if (*format++ == '%') | 2223 | if (*format++ == '%') |
| 2233 | { | 2224 | { |
| 2234 | int minlen; | 2225 | int minlen, thissize = 0; |
| 2226 | unsigned char *this_format_start = format - 1; | ||
| 2235 | 2227 | ||
| 2236 | /* Process a numeric arg and skip it. */ | 2228 | /* Process a numeric arg and skip it. */ |
| 2237 | minlen = atoi (format); | 2229 | minlen = atoi (format); |
| @@ -2242,6 +2234,9 @@ Use %% to put a single % into the output.") | |||
| 2242 | || *format == '-' || *format == ' ' || *format == '.') | 2234 | || *format == '-' || *format == ' ' || *format == '.') |
| 2243 | format++; | 2235 | format++; |
| 2244 | 2236 | ||
| 2237 | if (format - this_format_start + 1 > longest_format) | ||
| 2238 | longest_format = format - this_format_start + 1; | ||
| 2239 | |||
| 2245 | if (*format == '%') | 2240 | if (*format == '%') |
| 2246 | format++; | 2241 | format++; |
| 2247 | else if (++n >= nargs) | 2242 | else if (++n >= nargs) |
| @@ -2264,11 +2259,7 @@ Use %% to put a single % into the output.") | |||
| 2264 | string: | 2259 | string: |
| 2265 | if (*format != 's' && *format != 'S') | 2260 | if (*format != 's' && *format != 'S') |
| 2266 | error ("format specifier doesn't match argument type"); | 2261 | error ("format specifier doesn't match argument type"); |
| 2267 | total += XSTRING (args[n])->size; | 2262 | thissize = CONVERTED_BYTE_SIZE (multibyte, args[n]); |
| 2268 | /* We have to put an arbitrary limit on minlen | ||
| 2269 | since otherwise it could make alloca fail. */ | ||
| 2270 | if (minlen < XSTRING (args[n])->size + 1000) | ||
| 2271 | total += minlen; | ||
| 2272 | } | 2263 | } |
| 2273 | /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */ | 2264 | /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */ |
| 2274 | else if (INTEGERP (args[n]) && *format != 's') | 2265 | else if (INTEGERP (args[n]) && *format != 's') |
| @@ -2281,22 +2272,14 @@ Use %% to put a single % into the output.") | |||
| 2281 | if (*format == 'e' || *format == 'f' || *format == 'g') | 2272 | if (*format == 'e' || *format == 'f' || *format == 'g') |
| 2282 | args[n] = Ffloat (args[n]); | 2273 | args[n] = Ffloat (args[n]); |
| 2283 | #endif | 2274 | #endif |
| 2284 | total += 30; | 2275 | thissize = 30; |
| 2285 | /* We have to put an arbitrary limit on minlen | ||
| 2286 | since otherwise it could make alloca fail. */ | ||
| 2287 | if (minlen < 1000) | ||
| 2288 | total += minlen; | ||
| 2289 | } | 2276 | } |
| 2290 | #ifdef LISP_FLOAT_TYPE | 2277 | #ifdef LISP_FLOAT_TYPE |
| 2291 | else if (FLOATP (args[n]) && *format != 's') | 2278 | else if (FLOATP (args[n]) && *format != 's') |
| 2292 | { | 2279 | { |
| 2293 | if (! (*format == 'e' || *format == 'f' || *format == 'g')) | 2280 | if (! (*format == 'e' || *format == 'f' || *format == 'g')) |
| 2294 | args[n] = Ftruncate (args[n], Qnil); | 2281 | args[n] = Ftruncate (args[n], Qnil); |
| 2295 | total += 30; | 2282 | thissize = 60; |
| 2296 | /* We have to put an arbitrary limit on minlen | ||
| 2297 | since otherwise it could make alloca fail. */ | ||
| 2298 | if (minlen < 1000) | ||
| 2299 | total += minlen; | ||
| 2300 | } | 2283 | } |
| 2301 | #endif | 2284 | #endif |
| 2302 | else | 2285 | else |
| @@ -2307,64 +2290,106 @@ Use %% to put a single % into the output.") | |||
| 2307 | args[n] = tem; | 2290 | args[n] = tem; |
| 2308 | goto string; | 2291 | goto string; |
| 2309 | } | 2292 | } |
| 2293 | |||
| 2294 | if (thissize < minlen) | ||
| 2295 | thissize = minlen; | ||
| 2296 | |||
| 2297 | total += thissize + 4; | ||
| 2310 | } | 2298 | } |
| 2311 | 2299 | ||
| 2312 | { | 2300 | this_format = (unsigned char *) alloca (longest_format + 1); |
| 2313 | register int nstrings = n + 1; | ||
| 2314 | 2301 | ||
| 2315 | /* Allocate twice as many strings as we have %-escapes; floats occupy | 2302 | /* Allocate the space for the result. |
| 2316 | two slots, and we're not sure how many of those we have. */ | 2303 | Note that TOTAL is an overestimate. */ |
| 2317 | register unsigned char **strings | 2304 | if (total < 1000) |
| 2318 | = (unsigned char **) alloca (2 * nstrings * sizeof (unsigned char *)); | 2305 | buf = (unsigned char *) alloca (total + 1); |
| 2319 | int i; | 2306 | else |
| 2307 | buf = (unsigned char *) xmalloc (total + 1); | ||
| 2320 | 2308 | ||
| 2321 | i = 0; | 2309 | p = buf; |
| 2322 | for (n = 0; n < nstrings; n++) | 2310 | nchars = 0; |
| 2323 | { | 2311 | n = 0; |
| 2324 | if (n >= nargs) | ||
| 2325 | strings[i++] = (unsigned char *) ""; | ||
| 2326 | else if (INTEGERP (args[n])) | ||
| 2327 | /* We checked above that the corresponding format effector | ||
| 2328 | isn't %s, which would cause MPV. */ | ||
| 2329 | strings[i++] = (unsigned char *) XINT (args[n]); | ||
| 2330 | #ifdef LISP_FLOAT_TYPE | ||
| 2331 | else if (FLOATP (args[n])) | ||
| 2332 | { | ||
| 2333 | union { double d; char *half[2]; } u; | ||
| 2334 | 2312 | ||
| 2335 | u.d = XFLOAT (args[n])->data; | 2313 | /* Scan the format and store result in BUF. */ |
| 2336 | strings[i++] = (unsigned char *) u.half[0]; | 2314 | format = XSTRING (args[0])->data; |
| 2337 | strings[i++] = (unsigned char *) u.half[1]; | 2315 | while (format != end) |
| 2338 | } | 2316 | { |
| 2339 | #endif | 2317 | if (*format == '%') |
| 2340 | else if (i == 0) | 2318 | { |
| 2341 | /* The first string is treated differently | 2319 | int minlen; |
| 2342 | because it is the format string. */ | 2320 | unsigned char *this_format_start = format; |
| 2343 | strings[i++] = XSTRING (args[n])->data; | ||
| 2344 | else | ||
| 2345 | strings[i++] = (unsigned char *) XSTRING (args[n]); | ||
| 2346 | } | ||
| 2347 | 2321 | ||
| 2348 | /* Make room in result for all the non-%-codes in the control string. */ | 2322 | format++; |
| 2349 | total += XSTRING (args[0])->size; | ||
| 2350 | 2323 | ||
| 2351 | /* Format it in bigger and bigger buf's until it all fits. */ | 2324 | /* Process a numeric arg and skip it. */ |
| 2352 | while (1) | 2325 | minlen = atoi (format); |
| 2353 | { | 2326 | if (minlen < 0) |
| 2354 | buf = (char *) alloca (total + 1); | 2327 | minlen = - minlen; |
| 2355 | buf[total - 1] = 0; | ||
| 2356 | 2328 | ||
| 2357 | length = doprnt_lisp (buf, total + 1, strings[0], | 2329 | while ((*format >= '0' && *format <= '9') |
| 2358 | end, i-1, (char **) strings + 1); | 2330 | || *format == '-' || *format == ' ' || *format == '.') |
| 2359 | if (buf[total - 1] == 0) | 2331 | format++; |
| 2360 | break; | ||
| 2361 | 2332 | ||
| 2362 | total *= 2; | 2333 | if (*format++ == '%') |
| 2363 | } | 2334 | { |
| 2364 | } | 2335 | *p++ = '%'; |
| 2336 | nchars++; | ||
| 2337 | continue; | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | ++n; | ||
| 2341 | |||
| 2342 | if (STRINGP (args[n])) | ||
| 2343 | { | ||
| 2344 | int padding, nbytes; | ||
| 2345 | |||
| 2346 | nbytes = copy_text (XSTRING (args[n])->data, p, | ||
| 2347 | XSTRING (args[n])->size_byte, | ||
| 2348 | STRING_MULTIBYTE (args[n]), multibyte); | ||
| 2349 | p += nbytes; | ||
| 2350 | nchars += XSTRING (args[n])->size; | ||
| 2351 | |||
| 2352 | /* If spec requires it, pad on right with spaces. */ | ||
| 2353 | padding = minlen - XSTRING (args[n])->size; | ||
| 2354 | while (padding-- > 0) | ||
| 2355 | { | ||
| 2356 | *p++ = ' '; | ||
| 2357 | nchars++; | ||
| 2358 | } | ||
| 2359 | } | ||
| 2360 | else if (INTEGERP (args[n]) || FLOATP (args[n])) | ||
| 2361 | { | ||
| 2362 | int this_nchars; | ||
| 2363 | |||
| 2364 | bcopy (this_format_start, this_format, | ||
| 2365 | format - this_format_start); | ||
| 2366 | this_format[format - this_format_start] = 0; | ||
| 2367 | |||
| 2368 | sprintf (p, this_format, XINT (args[n])); | ||
| 2369 | |||
| 2370 | this_nchars = strlen (p); | ||
| 2371 | p += this_nchars; | ||
| 2372 | nchars += this_nchars; | ||
| 2373 | } | ||
| 2374 | } | ||
| 2375 | else if (multibyte && !STRING_MULTIBYTE (args[0])) | ||
| 2376 | { | ||
| 2377 | /* Convert a single-byte character to multibyte. */ | ||
| 2378 | int len = copy_text (format, p, 1, 0, 1); | ||
| 2379 | |||
| 2380 | p += len; | ||
| 2381 | format++; | ||
| 2382 | nchars++; | ||
| 2383 | } | ||
| 2384 | else | ||
| 2385 | *p++ = *format++, nchars++; | ||
| 2386 | } | ||
| 2387 | |||
| 2388 | /* If we allocated BUF with malloc, free it too. */ | ||
| 2389 | if (total >= 1000) | ||
| 2390 | xfree (buf); | ||
| 2365 | 2391 | ||
| 2366 | /* UNGCPRO; */ | 2392 | return make_multibyte_string (buf, nchars, p - buf); |
| 2367 | return make_string (buf, length); | ||
| 2368 | } | 2393 | } |
| 2369 | 2394 | ||
| 2370 | /* VARARGS 1 */ | 2395 | /* VARARGS 1 */ |
| @@ -2823,7 +2848,6 @@ functions if all the text being accessed has this property."); | |||
| 2823 | defsubr (&Sgoto_char); | 2848 | defsubr (&Sgoto_char); |
| 2824 | defsubr (&Sstring_to_char); | 2849 | defsubr (&Sstring_to_char); |
| 2825 | defsubr (&Schar_to_string); | 2850 | defsubr (&Schar_to_string); |
| 2826 | defsubr (&Ssref); | ||
| 2827 | defsubr (&Sbuffer_substring); | 2851 | defsubr (&Sbuffer_substring); |
| 2828 | defsubr (&Sbuffer_substring_no_properties); | 2852 | defsubr (&Sbuffer_substring_no_properties); |
| 2829 | defsubr (&Sbuffer_string); | 2853 | defsubr (&Sbuffer_string); |