comparison src/fns.c @ 5039:f8ae1031c706

merge
author Ben Wing <ben@xemacs.org>
date Sat, 20 Feb 2010 19:04:55 -0600
parents 9624523604c5
children c3d372419e09 b5df3737028a
comparison
equal deleted inserted replaced
5038:9410323e4b0d 5039:f8ae1031c706
1051 return Qnil; 1051 return Qnil;
1052 } 1052 }
1053 } 1053 }
1054 1054
1055 /* Split STRING into a list of substrings. The substrings are the 1055 /* Split STRING into a list of substrings. The substrings are the
1056 parts of original STRING separated by SEPCHAR. */ 1056 parts of original STRING separated by SEPCHAR.
1057
1058 If UNESCAPE is non-zero, ESCAPECHAR specifies a character that will quote
1059 SEPCHAR, and cause it not to split STRING. A double ESCAPECHAR is
1060 necessary for ESCAPECHAR to appear once in a substring. */
1061
1057 static Lisp_Object 1062 static Lisp_Object
1058 split_string_by_ichar_1 (const Ibyte *string, Bytecount size, 1063 split_string_by_ichar_1 (const Ibyte *string, Bytecount size,
1059 Ichar sepchar) 1064 Ichar sepchar, int unescape, Ichar escapechar)
1060 { 1065 {
1061 Lisp_Object result = Qnil; 1066 Lisp_Object result = Qnil;
1062 const Ibyte *end = string + size; 1067 const Ibyte *end = string + size;
1063 1068
1064 while (1) 1069 if (unescape)
1065 { 1070 {
1066 const Ibyte *p = string; 1071 Ibyte unescape_buffer[64], *unescape_buffer_ptr = unescape_buffer,
1067 while (p < end) 1072 escaped[MAX_ICHAR_LEN], *unescape_cursor;
1068 { 1073 Bytecount unescape_buffer_size = countof (unescape_buffer),
1069 if (itext_ichar (p) == sepchar) 1074 escaped_len = set_itext_ichar (escaped, escapechar);
1070 break; 1075 Boolint deleting_escapes, previous_escaped;
1071 INC_IBYTEPTR (p); 1076 Ichar pchar;
1072 } 1077
1073 result = Fcons (make_string (string, p - string), result); 1078 while (1)
1074 if (p < end) 1079 {
1075 { 1080 const Ibyte *p = string, *cursor;
1076 string = p; 1081 deleting_escapes = 0;
1077 INC_IBYTEPTR (string); /* skip sepchar */ 1082 previous_escaped = 0;
1078 } 1083
1079 else 1084 while (p < end)
1080 break; 1085 {
1086 pchar = itext_ichar (p);
1087
1088 if (pchar == sepchar)
1089 {
1090 if (!previous_escaped)
1091 {
1092 break;
1093 }
1094 }
1095 else if (pchar == escapechar
1096 /* Doubled escapes don't escape: */
1097 && !previous_escaped)
1098 {
1099 ++deleting_escapes;
1100 previous_escaped = 1;
1101 }
1102 else
1103 {
1104 previous_escaped = 0;
1105 }
1106
1107 INC_IBYTEPTR (p);
1108 }
1109
1110 if (deleting_escapes)
1111 {
1112 if (((p - string) - (escaped_len * deleting_escapes))
1113 > unescape_buffer_size)
1114 {
1115 unescape_buffer_size =
1116 ((p - string) - (escaped_len * deleting_escapes)) * 1.5;
1117 unescape_buffer_ptr = alloca_ibytes (unescape_buffer_size);
1118 }
1119
1120 cursor = string;
1121 unescape_cursor = unescape_buffer_ptr;
1122 previous_escaped = 0;
1123
1124 while (cursor < p)
1125 {
1126 pchar = itext_ichar (cursor);
1127
1128 if (pchar != escapechar || previous_escaped)
1129 {
1130 memcpy (unescape_cursor, cursor,
1131 itext_ichar_len (cursor));
1132 INC_IBYTEPTR (unescape_cursor);
1133 }
1134
1135 previous_escaped = !previous_escaped
1136 && (pchar == escapechar);
1137
1138 INC_IBYTEPTR (cursor);
1139 }
1140
1141 result = Fcons (make_string (unescape_buffer_ptr,
1142 unescape_cursor
1143 - unescape_buffer_ptr),
1144 result);
1145 }
1146 else
1147 {
1148 result = Fcons (make_string (string, p - string), result);
1149 }
1150 if (p < end)
1151 {
1152 string = p;
1153 INC_IBYTEPTR (string); /* skip sepchar */
1154 }
1155 else
1156 break;
1157 }
1158 }
1159 else
1160 {
1161 while (1)
1162 {
1163 const Ibyte *p = string;
1164 while (p < end)
1165 {
1166 if (itext_ichar (p) == sepchar)
1167 break;
1168 INC_IBYTEPTR (p);
1169 }
1170 result = Fcons (make_string (string, p - string), result);
1171 if (p < end)
1172 {
1173 string = p;
1174 INC_IBYTEPTR (string); /* skip sepchar */
1175 }
1176 else
1177 break;
1178 }
1081 } 1179 }
1082 return Fnreverse (result); 1180 return Fnreverse (result);
1083 } 1181 }
1084 1182
1085 /* The same as the above, except PATH is an external C string (it is 1183 /* The same as the above, except PATH is an external C string (it is
1100 depend on split_external_path("") returning nil instead of an empty 1198 depend on split_external_path("") returning nil instead of an empty
1101 string? */ 1199 string? */
1102 if (!newlen) 1200 if (!newlen)
1103 return Qnil; 1201 return Qnil;
1104 1202
1105 return split_string_by_ichar_1 (newpath, newlen, SEPCHAR); 1203 return split_string_by_ichar_1 (newpath, newlen, SEPCHAR, 0, 0);
1106 } 1204 }
1107 1205
1108 Lisp_Object 1206 Lisp_Object
1109 split_env_path (const CIbyte *evarname, const Ibyte *default_) 1207 split_env_path (const CIbyte *evarname, const Ibyte *default_)
1110 { 1208 {
1113 path = egetenv (evarname); 1211 path = egetenv (evarname);
1114 if (!path) 1212 if (!path)
1115 path = default_; 1213 path = default_;
1116 if (!path) 1214 if (!path)
1117 return Qnil; 1215 return Qnil;
1118 return split_string_by_ichar_1 (path, qxestrlen (path), SEPCHAR); 1216 return split_string_by_ichar_1 (path, qxestrlen (path), SEPCHAR, 0, 0);
1119 } 1217 }
1120 1218
1121 /* Ben thinks this function should not exist or be exported to Lisp. 1219 /* Ben thinks this function should not exist or be exported to Lisp.
1122 We use it to define split-path-string in subr.el (not!). */ 1220 We use it to define split-path-string in subr.el (not!). */
1123 1221
1124 DEFUN ("split-string-by-char", Fsplit_string_by_char, 2, 2, 0, /* 1222 DEFUN ("split-string-by-char", Fsplit_string_by_char, 2, 3, 0, /*
1125 Split STRING into a list of substrings originally separated by SEPCHAR. 1223 Split STRING into a list of substrings originally separated by SEPCHAR.
1126 */ 1224
1127 (string, sepchar)) 1225 With optional ESCAPE-CHAR, any instances of SEPCHAR preceded by that
1128 { 1226 character will not split the string, and a double instance of ESCAPE-CHAR
1227 will be necessary for a single ESCAPE-CHAR to appear in the output string.
1228 */
1229 (string, sepchar, escape_char))
1230 {
1231 Ichar escape_ichar = 0;
1232
1129 CHECK_STRING (string); 1233 CHECK_STRING (string);
1130 CHECK_CHAR (sepchar); 1234 CHECK_CHAR (sepchar);
1235 if (!NILP (escape_char))
1236 {
1237 CHECK_CHAR (escape_char);
1238 escape_ichar = XCHAR (escape_char);
1239 }
1131 return split_string_by_ichar_1 (XSTRING_DATA (string), 1240 return split_string_by_ichar_1 (XSTRING_DATA (string),
1132 XSTRING_LENGTH (string), 1241 XSTRING_LENGTH (string),
1133 XCHAR (sepchar)); 1242 XCHAR (sepchar),
1243 !NILP (escape_char), escape_ichar);
1134 } 1244 }
1135 1245
1136 /* #### This was supposed to be in subr.el, but is used VERY early in 1246 /* #### This was supposed to be in subr.el, but is used VERY early in
1137 the bootstrap process, so it goes here. Damn. */ 1247 the bootstrap process, so it goes here. Damn. */
1138 1248
1152 "`path-separator' should be set to a single-character string", 1262 "`path-separator' should be set to a single-character string",
1153 Vpath_separator); 1263 Vpath_separator);
1154 1264
1155 return (split_string_by_ichar_1 1265 return (split_string_by_ichar_1
1156 (XSTRING_DATA (path), XSTRING_LENGTH (path), 1266 (XSTRING_DATA (path), XSTRING_LENGTH (path),
1157 itext_ichar (XSTRING_DATA (Vpath_separator)))); 1267 itext_ichar (XSTRING_DATA (Vpath_separator)), 0, 0));
1158 } 1268 }
1159 1269
1160 1270
1161 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /* 1271 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /*
1162 Take cdr N times on LIST, and return the result. 1272 Take cdr N times on LIST, and return the result.
3229 3339
3230 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time, 3340 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time,
3231 taking the elements from SEQUENCES. If VALS is non-NULL, store the 3341 taking the elements from SEQUENCES. If VALS is non-NULL, store the
3232 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is 3342 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is
3233 non-nil, store the results into LISP_VALS, a sequence with sufficient 3343 non-nil, store the results into LISP_VALS, a sequence with sufficient
3234 room for CALL_COUNT results. Else, do not accumulate any result. 3344 room for CALL_COUNT results (but see the documentation of SOME_OR_EVERY.)
3345 Else, do not accumulate any result.
3235 3346
3236 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons, 3347 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons,
3237 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them, 3348 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them,
3238 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off 3349 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off
3239 mapcarX. 3350 mapcarX.
3244 destructively modifies SEQUENCES in a way that might affect the ongoing 3355 destructively modifies SEQUENCES in a way that might affect the ongoing
3245 traversal operation. 3356 traversal operation.
3246 3357
3247 If SOME_OR_EVERY is SOME_OR_EVERY_SOME, return the (possibly multiple) 3358 If SOME_OR_EVERY is SOME_OR_EVERY_SOME, return the (possibly multiple)
3248 values given by FUNCTION the first time it is non-nil, and abandon the 3359 values given by FUNCTION the first time it is non-nil, and abandon the
3249 iterations. LISP_VALS in this case must be an object created by 3360 iterations. LISP_VALS must be a cons, and the return value will be
3250 make_opaque_ptr, dereferenced as pointing to a Lisp object. If 3361 stored in its car. If SOME_OR_EVERY is SOME_OR_EVERY_EVERY, store Qnil
3251 SOME_OR_EVERY is SOME_OR_EVERY_EVERY, store Qnil at the Lisp_Object 3362 in the car of LISP_VALS if FUNCTION gives nil; otherwise leave it
3252 pointer address provided by LISP_VALS if FUNCTION gives nil; otherwise 3363 alone. */
3253 leave it alone. */
3254 3364
3255 #define SOME_OR_EVERY_NEITHER 0 3365 #define SOME_OR_EVERY_NEITHER 0
3256 #define SOME_OR_EVERY_SOME 1 3366 #define SOME_OR_EVERY_SOME 1
3257 #define SOME_OR_EVERY_EVERY 2 3367 #define SOME_OR_EVERY_EVERY 2
3258 3368
3304 gcpro2.nvars = call_count; 3414 gcpro2.nvars = call_count;
3305 3415
3306 for (i = 0; i < call_count; ++i) 3416 for (i = 0; i < call_count; ++i)
3307 { 3417 {
3308 args[1] = vals[i]; 3418 args[1] = vals[i];
3309 vals[i] = Ffuncall (nsequences + 1, args); 3419 vals[i] = IGNORE_MULTIPLE_VALUES (Ffuncall (nsequences + 1, args));
3310 } 3420 }
3311 } 3421 }
3312 else 3422 else
3313 { 3423 {
3314 Binbyte *sequence_types = alloca_array (Binbyte, nsequences); 3424 Binbyte *sequence_types = alloca_array (Binbyte, nsequences);
3411 return; 3521 return;
3412 } 3522 }
3413 break; 3523 break;
3414 } 3524 }
3415 3525
3416 goto bad_show_or_every_flag; 3526 goto bad_some_or_every_flag;
3417 } 3527 }
3418 case lrecord_type_vector: 3528 case lrecord_type_vector:
3419 { 3529 {
3420 called = IGNORE_MULTIPLE_VALUES (called); 3530 called = IGNORE_MULTIPLE_VALUES (called);
3421 i < XVECTOR_LENGTH (lisp_vals) ? 3531 i < XVECTOR_LENGTH (lisp_vals) ?
3441 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i, 3551 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i,
3442 XINT (called)) : 3552 XINT (called)) :
3443 (void) Faset (lisp_vals, make_int (i), called); 3553 (void) Faset (lisp_vals, make_int (i), called);
3444 break; 3554 break;
3445 } 3555 }
3446 bad_show_or_every_flag: 3556 bad_some_or_every_flag:
3447 default: 3557 default:
3448 { 3558 {
3449 ABORT(); 3559 ABORT();
3450 break; 3560 break;
3451 } 3561 }