Mercurial > vim
comparison src/eval.c @ 76:0ef9cebc4f5d v7.0031
updated for version 7.0031
author | vimboss |
---|---|
date | Wed, 05 Jan 2005 22:19:46 +0000 |
parents | 7557b6ea0fb1 |
children | d2796c60ca6f |
comparison
equal
deleted
inserted
replaced
75:388f285bda1b | 76:0ef9cebc4f5d |
---|---|
80 }; | 80 }; |
81 | 81 |
82 typedef struct listitem_S listitem; | 82 typedef struct listitem_S listitem; |
83 | 83 |
84 /* | 84 /* |
85 * Structure to hold the info about a list. | 85 * Struct used by those that are using an item in a list. |
86 */ | |
87 typedef struct listwatch_S | |
88 { | |
89 listitem *lw_item; /* item being watched */ | |
90 struct listwatch_S *lw_next; /* next watcher */ | |
91 } listwatch; | |
92 | |
93 /* | |
94 * Structure to hold info about a list. | |
86 */ | 95 */ |
87 struct listvar_S | 96 struct listvar_S |
88 { | 97 { |
89 int lv_refcount; /* reference count */ | 98 int lv_refcount; /* reference count */ |
90 listitem *lv_first; /* first item, NULL if none */ | 99 listitem *lv_first; /* first item, NULL if none */ |
91 listitem *lv_last; /* last item, NULL if none */ | 100 listitem *lv_last; /* last item, NULL if none */ |
101 listwatch *lv_watch; /* first watcher, NULL if none */ | |
92 }; | 102 }; |
93 | 103 |
94 typedef struct listvar_S listvar; | 104 typedef struct listvar_S listvar; |
95 | 105 |
96 #define VAR_LIST_MAXNEST 100 /* maximum nesting of lists */ | 106 #define VAR_LIST_MAXNEST 100 /* maximum nesting of lists */ |
166 typeval *rettv; /* return value */ | 176 typeval *rettv; /* return value */ |
167 linenr_T breakpoint; /* next line with breakpoint or zero */ | 177 linenr_T breakpoint; /* next line with breakpoint or zero */ |
168 int dbg_tick; /* debug_tick when breakpoint was set */ | 178 int dbg_tick; /* debug_tick when breakpoint was set */ |
169 int level; /* top nesting level of executed function */ | 179 int level; /* top nesting level of executed function */ |
170 }; | 180 }; |
181 | |
182 /* | |
183 * Info used by a ":for" loop. | |
184 */ | |
185 typedef struct forinfo_S | |
186 { | |
187 int fi_semicolon; /* TRUE if ending in '; var]' */ | |
188 int fi_varcount; /* nr of variables in the list */ | |
189 listwatch fi_lw; /* keep an eye on the item used. */ | |
190 listvar *fi_list; /* list being used */ | |
191 } forinfo; | |
192 | |
171 | 193 |
172 /* | 194 /* |
173 * Return the name of the executed function. | 195 * Return the name of the executed function. |
174 */ | 196 */ |
175 char_u * | 197 char_u * |
502 #define get_var_string_buf(p, b) get_tv_string_buf(&(p)->tv, (b)) | 524 #define get_var_string_buf(p, b) get_tv_string_buf(&(p)->tv, (b)) |
503 #define get_var_number(p) get_tv_number(&((p)->tv)) | 525 #define get_var_number(p) get_tv_number(&((p)->tv)) |
504 | 526 |
505 static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end)); | 527 static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end)); |
506 | 528 |
529 static int ex_let_vars __ARGS((char_u *arg, typeval *tv, int copy, int semicolon, int var_count, char_u *nextchars)); | |
530 static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon)); | |
531 static char_u *skip_var_one __ARGS((char_u *arg)); | |
507 static void list_all_vars __ARGS((void)); | 532 static void list_all_vars __ARGS((void)); |
508 static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg)); | 533 static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg)); |
509 static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars)); | 534 static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars)); |
510 static char_u *set_var_idx __ARGS((char_u *name, char_u *ip, typeval *rettv, int copy, char_u *endchars)); | 535 static char_u *set_var_idx __ARGS((char_u *name, char_u *ip, typeval *rettv, int copy, char_u *endchars)); |
536 static void list_add_watch __ARGS((listvar *l, listwatch *lw)); | |
511 | 537 |
512 /* | 538 /* |
513 * Set an internal variable to a string value. Creates the variable if it does | 539 * Set an internal variable to a string value. Creates the variable if it does |
514 * not already exist. | 540 * not already exist. |
515 */ | 541 */ |
1019 char_u *expr = NULL; | 1045 char_u *expr = NULL; |
1020 typeval rettv; | 1046 typeval rettv; |
1021 int i; | 1047 int i; |
1022 int var_count = 0; | 1048 int var_count = 0; |
1023 int semicolon = 0; | 1049 int semicolon = 0; |
1024 listvar *l; | 1050 |
1025 listitem *item; | 1051 expr = skip_var_list(arg, &var_count, &semicolon); |
1026 | 1052 if (expr == NULL) |
1027 if (*arg != '[') | 1053 return; |
1028 expr = vim_strchr(find_name_end(arg, NULL, NULL, TRUE), '='); | 1054 expr = vim_strchr(expr, '='); |
1029 if (*arg != '[' && expr == NULL) | 1055 if (expr == NULL) |
1030 { | 1056 { |
1031 if (!ends_excmd(*arg)) | 1057 if (*arg == '[') |
1058 EMSG(_(e_invarg)); | |
1059 else if (!ends_excmd(*arg)) | |
1032 /* ":let var1 var2" */ | 1060 /* ":let var1 var2" */ |
1033 arg = list_arg_vars(eap, arg); | 1061 arg = list_arg_vars(eap, arg); |
1034 else if (!eap->skip) | 1062 else if (!eap->skip) |
1035 /* ":let" */ | 1063 /* ":let" */ |
1036 list_all_vars(); | 1064 list_all_vars(); |
1037 eap->nextcmd = check_nextcmd(arg); | 1065 eap->nextcmd = check_nextcmd(arg); |
1038 } | 1066 } |
1039 else | 1067 else |
1040 { | 1068 { |
1041 if (*arg == '[') | 1069 expr = skipwhite(expr + 1); |
1042 { | |
1043 /* ":let [a, b] = expr": find the matching ']' to get to the | |
1044 * expression. */ | |
1045 while (1) | |
1046 { | |
1047 arg = skipwhite(arg + 1); | |
1048 if (vim_strchr((char_u *)"$@&", *arg) != NULL) | |
1049 ++arg; | |
1050 expr = find_name_end(arg, NULL, NULL, TRUE); | |
1051 if (expr == arg) | |
1052 { | |
1053 EMSG2(_(e_invarg2), arg); | |
1054 return; | |
1055 } | |
1056 ++var_count; | |
1057 | |
1058 arg = skipwhite(expr); | |
1059 if (*arg == ']') | |
1060 break; | |
1061 else if (*arg == ';') | |
1062 { | |
1063 if (semicolon == 1) | |
1064 { | |
1065 EMSG(_("Double ; in :let")); | |
1066 return; | |
1067 } | |
1068 semicolon = 1; | |
1069 } | |
1070 else if (*arg != ',') | |
1071 { | |
1072 EMSG2(_(e_invarg2), arg); | |
1073 return; | |
1074 } | |
1075 } | |
1076 | |
1077 /* check for '=' after the ']' */ | |
1078 expr = skipwhite(arg + 1); | |
1079 if (*expr != '=') | |
1080 { | |
1081 EMSG(_(e_letunexp)); | |
1082 return; | |
1083 } | |
1084 } | |
1085 | 1070 |
1086 if (eap->skip) | 1071 if (eap->skip) |
1087 ++emsg_skip; | 1072 ++emsg_skip; |
1088 i = eval0(expr + 1, &rettv, &eap->nextcmd, !eap->skip); | 1073 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip); |
1089 if (eap->skip) | 1074 if (eap->skip) |
1090 { | 1075 { |
1091 if (i != FAIL) | 1076 if (i != FAIL) |
1092 clear_tv(&rettv); | 1077 clear_tv(&rettv); |
1093 --emsg_skip; | 1078 --emsg_skip; |
1094 } | 1079 } |
1095 else if (i != FAIL) | 1080 else if (i != FAIL) |
1096 { | 1081 { |
1097 /* Move "arg" back to the variable name(s). */ | 1082 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, |
1098 arg = eap->arg; | 1083 (char_u *)"="); |
1099 if (*arg != '[') | 1084 clear_tv(&rettv); |
1085 } | |
1086 } | |
1087 } | |
1088 | |
1089 /* | |
1090 * Assign the typevalue "tv" to the variable or variables at "arg_start". | |
1091 * Handles both "var" with any type and "[var, var; var]" with a list type. | |
1092 * Returns OK or FAIL; | |
1093 */ | |
1094 static int | |
1095 ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars) | |
1096 char_u *arg_start; | |
1097 typeval *tv; | |
1098 int copy; /* copy values from "tv", don't move */ | |
1099 int semicolon; /* from skip_var_list() */ | |
1100 int var_count; /* from skip_var_list() */ | |
1101 char_u *nextchars; /* characters that must follow or NULL */ | |
1102 { | |
1103 char_u *arg = arg_start; | |
1104 listvar *l; | |
1105 int i; | |
1106 listitem *item; | |
1107 typeval ltv; | |
1108 | |
1109 if (*arg != '[') | |
1110 { | |
1111 /* | |
1112 * ":let var = expr" or ":for var in list" | |
1113 */ | |
1114 if (ex_let_one(arg, tv, copy, nextchars) == NULL) | |
1115 return FAIL; | |
1116 return OK; | |
1117 } | |
1118 | |
1119 /* | |
1120 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist" | |
1121 */ | |
1122 l = tv->vval.v_list; | |
1123 if (tv->v_type != VAR_LIST || l == NULL) | |
1124 { | |
1125 EMSG(_(e_listreq)); | |
1126 return FAIL; | |
1127 } | |
1128 | |
1129 i = list_len(l); | |
1130 if (semicolon == 0 && var_count < i) | |
1131 { | |
1132 EMSG(_("E999: Less targets than List items")); | |
1133 return FAIL; | |
1134 } | |
1135 if (var_count - semicolon > i) | |
1136 { | |
1137 EMSG(_("E999: More targets than List items")); | |
1138 return FAIL; | |
1139 } | |
1140 | |
1141 item = l->lv_first; | |
1142 while (*arg != ']') | |
1143 { | |
1144 arg = skipwhite(arg + 1); | |
1145 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]"); | |
1146 item = item->li_next; | |
1147 if (arg == NULL) | |
1148 return FAIL; | |
1149 | |
1150 arg = skipwhite(arg); | |
1151 if (*arg == ';') | |
1152 { | |
1153 /* Put the rest of the list (may be empty) in the var after ';'. | |
1154 * Create a new list for this. */ | |
1155 l = list_alloc(); | |
1156 if (l == NULL) | |
1157 return FAIL; | |
1158 while (item != NULL) | |
1100 { | 1159 { |
1101 /* ":let var = expr" */ | 1160 list_append_tv(l, &item->li_tv); |
1102 (void)ex_let_one(arg, &rettv, FALSE, (char_u *)"="); | 1161 item = item->li_next; |
1103 } | 1162 } |
1104 else | 1163 |
1164 ltv.v_type = VAR_LIST; | |
1165 ltv.vval.v_list = l; | |
1166 l->lv_refcount = 1; | |
1167 | |
1168 arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, (char_u *)"]"); | |
1169 clear_tv(<v); | |
1170 if (arg == NULL) | |
1171 return FAIL; | |
1172 break; | |
1173 } | |
1174 else if (*arg != ',' && *arg != ']') | |
1175 { | |
1176 EMSG2(_(e_intern2), "ex_let_vars()"); | |
1177 return FAIL; | |
1178 } | |
1179 } | |
1180 | |
1181 return OK; | |
1182 } | |
1183 | |
1184 /* | |
1185 * Skip over assignable variable "var" or list of variables "[var, var]". | |
1186 * Used for ":let varvar = expr" and ":for varvar in expr". | |
1187 * For "[var, var]" increment "*var_count" for each variable. | |
1188 * for "[var, var; var]" set "semicolon". | |
1189 * Return NULL for an error. | |
1190 */ | |
1191 static char_u * | |
1192 skip_var_list(arg, var_count, semicolon) | |
1193 char_u *arg; | |
1194 int *var_count; | |
1195 int *semicolon; | |
1196 { | |
1197 char_u *p, *s; | |
1198 | |
1199 if (*arg == '[') | |
1200 { | |
1201 /* "[var, var]": find the matching ']'. */ | |
1202 p = arg; | |
1203 while (1) | |
1204 { | |
1205 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */ | |
1206 s = skip_var_one(p); | |
1207 if (s == p) | |
1105 { | 1208 { |
1106 /* ":let [v1, v2] = list" */ | 1209 EMSG2(_(e_invarg2), p); |
1107 l = rettv.vval.v_list; | 1210 return NULL; |
1108 if (rettv.v_type != VAR_LIST || l == NULL) | 1211 } |
1109 EMSG(_("E999: List required")); | 1212 ++*var_count; |
1110 else | 1213 |
1214 p = skipwhite(s); | |
1215 if (*p == ']') | |
1216 break; | |
1217 else if (*p == ';') | |
1218 { | |
1219 if (*semicolon == 1) | |
1111 { | 1220 { |
1112 i = list_len(l); | 1221 EMSG(_("Double ; in list of variables")); |
1113 if (semicolon == 0 && var_count < i) | 1222 return NULL; |
1114 EMSG(_("E999: Less targets than List items")); | |
1115 else if (var_count - semicolon > i) | |
1116 EMSG(_("E999: More targets than List items")); | |
1117 else | |
1118 { | |
1119 item = l->lv_first; | |
1120 while (*arg != ']') | |
1121 { | |
1122 arg = skipwhite(arg + 1); | |
1123 arg = ex_let_one(arg, &item->li_tv, | |
1124 TRUE, (char_u *)",;]"); | |
1125 item = item->li_next; | |
1126 if (arg == NULL) | |
1127 break; | |
1128 | |
1129 arg = skipwhite(arg); | |
1130 if (*arg == ';') | |
1131 { | |
1132 /* Put the rest of the list (may be empty) in | |
1133 * the var after ';'. */ | |
1134 l = list_alloc(); | |
1135 if (l == NULL) | |
1136 break; | |
1137 while (item != NULL) | |
1138 { | |
1139 list_append_tv(l, &item->li_tv); | |
1140 item = item->li_next; | |
1141 } | |
1142 list_unref(rettv.vval.v_list); | |
1143 rettv.vval.v_list = l; | |
1144 l->lv_refcount = 1; | |
1145 (void)ex_let_one(skipwhite(arg + 1), &rettv, | |
1146 FALSE, (char_u *)"]"); | |
1147 break; | |
1148 } | |
1149 else if (*arg != ',' && *arg != ']') | |
1150 { | |
1151 EMSG2(_(e_intern2), "ex_let()"); | |
1152 break; | |
1153 } | |
1154 } | |
1155 } | |
1156 } | 1223 } |
1224 *semicolon = 1; | |
1157 } | 1225 } |
1158 clear_tv(&rettv); | 1226 else if (*p != ',') |
1159 } | 1227 { |
1160 } | 1228 EMSG2(_(e_invarg2), p); |
1229 return NULL; | |
1230 } | |
1231 } | |
1232 return p + 1; | |
1233 } | |
1234 else | |
1235 return skip_var_one(arg); | |
1236 } | |
1237 | |
1238 static char_u * | |
1239 skip_var_one(arg) | |
1240 char_u *arg; | |
1241 { | |
1242 if (vim_strchr((char_u *)"$@&", *arg) != NULL) | |
1243 ++arg; | |
1244 return find_name_end(arg, NULL, NULL, TRUE); | |
1161 } | 1245 } |
1162 | 1246 |
1163 static void | 1247 static void |
1164 list_all_vars() | 1248 list_all_vars() |
1165 { | 1249 { |
1307 static char_u * | 1391 static char_u * |
1308 ex_let_one(arg, tv, copy, endchars) | 1392 ex_let_one(arg, tv, copy, endchars) |
1309 char_u *arg; /* points to variable name */ | 1393 char_u *arg; /* points to variable name */ |
1310 typeval *tv; /* value to assign to variable */ | 1394 typeval *tv; /* value to assign to variable */ |
1311 int copy; /* copy value from "tv" */ | 1395 int copy; /* copy value from "tv" */ |
1312 char_u *endchars; /* valid chars after variable name */ | 1396 char_u *endchars; /* valid chars after variable name or NULL */ |
1313 { | 1397 { |
1314 int c1; | 1398 int c1; |
1315 char_u *name; | 1399 char_u *name; |
1316 char_u *p; | 1400 char_u *p; |
1317 char_u *arg_end = NULL; | 1401 char_u *arg_end = NULL; |
1329 len = get_env_len(&arg); | 1413 len = get_env_len(&arg); |
1330 if (len == 0) | 1414 if (len == 0) |
1331 EMSG2(_(e_invarg2), name - 1); | 1415 EMSG2(_(e_invarg2), name - 1); |
1332 else | 1416 else |
1333 { | 1417 { |
1334 if (vim_strchr(endchars, *skipwhite(arg)) == NULL) | 1418 if (endchars != NULL |
1419 && vim_strchr(endchars, *skipwhite(arg)) == NULL) | |
1335 EMSG(_(e_letunexp)); | 1420 EMSG(_(e_letunexp)); |
1336 else | 1421 else |
1337 { | 1422 { |
1338 c1 = name[len]; | 1423 c1 = name[len]; |
1339 name[len] = NUL; | 1424 name[len] = NUL; |
1358 */ | 1443 */ |
1359 else if (*arg == '&') | 1444 else if (*arg == '&') |
1360 { | 1445 { |
1361 /* Find the end of the name. */ | 1446 /* Find the end of the name. */ |
1362 p = find_option_end(&arg, &opt_flags); | 1447 p = find_option_end(&arg, &opt_flags); |
1363 if (p == NULL || vim_strchr(endchars, *skipwhite(p)) == NULL) | 1448 if (p == NULL || (endchars != NULL |
1449 && vim_strchr(endchars, *skipwhite(p)) == NULL)) | |
1364 EMSG(_(e_letunexp)); | 1450 EMSG(_(e_letunexp)); |
1365 else | 1451 else |
1366 { | 1452 { |
1367 c1 = *p; | 1453 c1 = *p; |
1368 *p = NUL; | 1454 *p = NUL; |
1377 * ":let @r = expr": Set register contents. | 1463 * ":let @r = expr": Set register contents. |
1378 */ | 1464 */ |
1379 else if (*arg == '@') | 1465 else if (*arg == '@') |
1380 { | 1466 { |
1381 ++arg; | 1467 ++arg; |
1382 if (vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) | 1468 if (endchars != NULL |
1469 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) | |
1383 EMSG(_(e_letunexp)); | 1470 EMSG(_(e_letunexp)); |
1384 else | 1471 else |
1385 { | 1472 { |
1386 write_reg_contents(*arg == '@' ? '"' : *arg, | 1473 write_reg_contents(*arg == '@' ? '"' : *arg, |
1387 get_tv_string(tv), -1, FALSE); | 1474 get_tv_string(tv), -1, FALSE); |
1413 if (!aborting()) | 1500 if (!aborting()) |
1414 EMSG2(_(e_invarg2), arg); | 1501 EMSG2(_(e_invarg2), arg); |
1415 } | 1502 } |
1416 else if (*p == '[') | 1503 else if (*p == '[') |
1417 arg_end = set_var_idx(arg, p, tv, copy, endchars); | 1504 arg_end = set_var_idx(arg, p, tv, copy, endchars); |
1418 else if (vim_strchr(endchars, *skipwhite(p)) == NULL) | 1505 else if (endchars != NULL |
1506 && vim_strchr(endchars, *skipwhite(p)) == NULL) | |
1419 EMSG(_(e_letunexp)); | 1507 EMSG(_(e_letunexp)); |
1420 else if (STRNCMP(arg, "b:changedtick", 13) == 0 | 1508 else if (STRNCMP(arg, "b:changedtick", 13) == 0 |
1421 && !eval_isnamec(arg[13])) | 1509 && !eval_isnamec(arg[13])) |
1422 EMSG2(_(e_readonlyvar), arg); | 1510 EMSG2(_(e_readonlyvar), arg); |
1423 else | 1511 else |
1503 tv = &item->li_tv; | 1591 tv = &item->li_tv; |
1504 } | 1592 } |
1505 | 1593 |
1506 if (p != NULL) | 1594 if (p != NULL) |
1507 { | 1595 { |
1508 if (vim_strchr(endchars, *p) == NULL) | 1596 if (endchars != NULL && vim_strchr(endchars, *p) == NULL) |
1509 { | 1597 { |
1510 EMSG(_(e_letunexp)); | 1598 EMSG(_(e_letunexp)); |
1511 p = NULL; | 1599 p = NULL; |
1512 } | 1600 } |
1513 else | 1601 else |
1523 } | 1611 } |
1524 } | 1612 } |
1525 return p; | 1613 return p; |
1526 } | 1614 } |
1527 | 1615 |
1616 /* | |
1617 * Add a watcher to a list. | |
1618 */ | |
1619 static void | |
1620 list_add_watch(l, lw) | |
1621 listvar *l; | |
1622 listwatch *lw; | |
1623 { | |
1624 lw->lw_next = l->lv_watch; | |
1625 l->lv_watch = lw; | |
1626 } | |
1627 | |
1628 /* | |
1629 * Remove a watches from a list. | |
1630 * No warning when it isn't found... | |
1631 */ | |
1632 static void | |
1633 list_rem_watch(l, lwrem) | |
1634 listvar *l; | |
1635 listwatch *lwrem; | |
1636 { | |
1637 listwatch *lw, **lwp; | |
1638 | |
1639 lwp = &l->lv_watch; | |
1640 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) | |
1641 { | |
1642 if (lw == lwrem) | |
1643 { | |
1644 *lwp = lw->lw_next; | |
1645 break; | |
1646 } | |
1647 lwp = &lw->lw_next; | |
1648 } | |
1649 } | |
1650 | |
1651 /* | |
1652 * Just before removing an item from a list: advance watchers to the next | |
1653 * item. | |
1654 */ | |
1655 static void | |
1656 list_fix_watch(l, item) | |
1657 listvar *l; | |
1658 listitem *item; | |
1659 { | |
1660 listwatch *lw; | |
1661 | |
1662 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) | |
1663 if (lw->lw_item == item) | |
1664 lw->lw_item = item->li_next; | |
1665 } | |
1666 | |
1667 /* | |
1668 * Evaluate the expression used in a ":for var in expr" command. | |
1669 * "arg" points to "var". | |
1670 * Set "*errp" to TRUE for an error, FALSE otherwise; | |
1671 * Return a pointer that holds the info. Null when there is an error. | |
1672 */ | |
1673 void * | |
1674 eval_for_line(arg, errp, nextcmdp, skip) | |
1675 char_u *arg; | |
1676 int *errp; | |
1677 char_u **nextcmdp; | |
1678 int skip; | |
1679 { | |
1680 forinfo *fi; | |
1681 char_u *expr; | |
1682 typeval tv; | |
1683 listvar *l; | |
1684 | |
1685 *errp = TRUE; /* default: there is an error */ | |
1686 | |
1687 fi = (forinfo *)alloc_clear(sizeof(forinfo)); | |
1688 if (fi == NULL) | |
1689 return NULL; | |
1690 | |
1691 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon); | |
1692 if (expr == NULL) | |
1693 return fi; | |
1694 | |
1695 expr = skipwhite(expr); | |
1696 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2])) | |
1697 { | |
1698 EMSG(_("E999: Missing \"in\" after :for")); | |
1699 return fi; | |
1700 } | |
1701 | |
1702 if (skip) | |
1703 ++emsg_skip; | |
1704 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) | |
1705 { | |
1706 *errp = FALSE; | |
1707 if (!skip) | |
1708 { | |
1709 l = tv.vval.v_list; | |
1710 if (tv.v_type != VAR_LIST || l == NULL) | |
1711 EMSG(_(e_listreq)); | |
1712 else | |
1713 { | |
1714 fi->fi_list = l; | |
1715 list_add_watch(l, &fi->fi_lw); | |
1716 fi->fi_lw.lw_item = l->lv_first; | |
1717 } | |
1718 } | |
1719 } | |
1720 if (skip) | |
1721 --emsg_skip; | |
1722 | |
1723 return fi; | |
1724 } | |
1725 | |
1726 /* | |
1727 * Use the first item in a ":for" list. Advance to the next. | |
1728 * Assign the values to the variable (list). "arg" points to the first one. | |
1729 * Return TRUE when a valid item was found, FALSE when at end of list or | |
1730 * something wrong. | |
1731 */ | |
1732 int | |
1733 next_for_item(fi_void, arg) | |
1734 void *fi_void; | |
1735 char_u *arg; | |
1736 { | |
1737 forinfo *fi = (forinfo *)fi_void; | |
1738 int result; | |
1739 listitem *item; | |
1740 | |
1741 item = fi->fi_lw.lw_item; | |
1742 if (item == NULL) | |
1743 result = FALSE; | |
1744 else | |
1745 { | |
1746 fi->fi_lw.lw_item = item->li_next; | |
1747 result = (ex_let_vars(arg, &item->li_tv, TRUE, | |
1748 fi->fi_semicolon, fi->fi_varcount, NULL) == OK); | |
1749 } | |
1750 return result; | |
1751 } | |
1752 | |
1753 /* | |
1754 * Free the structure used to store info used by ":for". | |
1755 */ | |
1756 void | |
1757 free_for_info(fi_void) | |
1758 void *fi_void; | |
1759 { | |
1760 forinfo *fi = (forinfo *)fi_void; | |
1761 | |
1762 if (fi->fi_list != NULL) | |
1763 list_rem_watch(fi->fi_list, &fi->fi_lw); | |
1764 vim_free(fi); | |
1765 } | |
1766 | |
1528 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) | 1767 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) |
1529 | 1768 |
1530 void | 1769 void |
1531 set_context_for_expression(xp, arg, cmdidx) | 1770 set_context_for_expression(xp, arg, cmdidx) |
1532 expand_T *xp; | 1771 expand_T *xp; |
1533 char_u *arg; | 1772 char_u *arg; |
1534 cmdidx_T cmdidx; | 1773 cmdidx_T cmdidx; |
1535 { | 1774 { |
1536 int got_eq = FALSE; | 1775 int got_eq = FALSE; |
1537 int c; | 1776 int c; |
1538 | 1777 char_u *p; |
1539 xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS | 1778 |
1540 : cmdidx == CMD_call ? EXPAND_FUNCTIONS | 1779 if (cmdidx == CMD_let) |
1541 : EXPAND_EXPRESSION; | 1780 { |
1781 xp->xp_context = EXPAND_USER_VARS; | |
1782 if (vim_strchr(arg, '=') == NULL) | |
1783 { | |
1784 /* ":let var1 var2 ...": find last space. */ | |
1785 for (p = arg + STRLEN(arg); p > arg; ) | |
1786 { | |
1787 xp->xp_pattern = p; | |
1788 p = mb_ptr_back(arg, p); | |
1789 if (vim_iswhite(*p)) | |
1790 break; | |
1791 } | |
1792 return; | |
1793 } | |
1794 } | |
1795 else | |
1796 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS | |
1797 : EXPAND_EXPRESSION; | |
1542 while ((xp->xp_pattern = vim_strpbrk(arg, | 1798 while ((xp->xp_pattern = vim_strpbrk(arg, |
1543 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL) | 1799 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL) |
1544 { | 1800 { |
1545 c = *xp->xp_pattern; | 1801 c = *xp->xp_pattern; |
1546 if (c == '&') | 1802 if (c == '&') |
1599 } | 1855 } |
1600 else | 1856 else |
1601 xp->xp_context = EXPAND_EXPRESSION; | 1857 xp->xp_context = EXPAND_EXPRESSION; |
1602 } | 1858 } |
1603 else | 1859 else |
1604 xp->xp_context = EXPAND_NOTHING; | 1860 /* Doesn't look like something valid, expand as an expression |
1861 * anyway. */ | |
1862 xp->xp_context = EXPAND_EXPRESSION; | |
1605 arg = xp->xp_pattern; | 1863 arg = xp->xp_pattern; |
1606 if (*arg != NUL) | 1864 if (*arg != NUL) |
1607 while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) | 1865 while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) |
1608 /* skip */ ; | 1866 /* skip */ ; |
1609 } | 1867 } |
3301 { | 3559 { |
3302 return (listitem *)alloc(sizeof(listitem)); | 3560 return (listitem *)alloc(sizeof(listitem)); |
3303 } | 3561 } |
3304 | 3562 |
3305 /* | 3563 /* |
3306 * Free a list item. Also clears the value; | 3564 * Free a list item. Also clears the value. Does not notify watchers. |
3307 */ | 3565 */ |
3308 static void | 3566 static void |
3309 listitem_free(item) | 3567 listitem_free(item) |
3310 listitem *item; | 3568 listitem *item; |
3311 { | 3569 { |
3469 listitem *item; | 3727 listitem *item; |
3470 | 3728 |
3471 item = list_find(l, n); | 3729 item = list_find(l, n); |
3472 if (item != NULL) | 3730 if (item != NULL) |
3473 { | 3731 { |
3732 list_fix_watch(l, item); /* notify watchers */ | |
3474 if (item->li_next == NULL) | 3733 if (item->li_next == NULL) |
3475 l->lv_last = item->li_prev; | 3734 l->lv_last = item->li_prev; |
3476 else | 3735 else |
3477 item->li_next->li_prev = item->li_prev; | 3736 item->li_next->li_prev = item->li_prev; |
3478 if (item->li_prev == NULL) | 3737 if (item->li_prev == NULL) |
11804 vir_T *virp; | 12063 vir_T *virp; |
11805 int writing; | 12064 int writing; |
11806 { | 12065 { |
11807 char_u *tab; | 12066 char_u *tab; |
11808 int is_string = FALSE; | 12067 int is_string = FALSE; |
11809 typeval *tvp = NULL; | 12068 typeval tv; |
11810 char_u *val; | |
11811 | 12069 |
11812 if (!writing && (find_viminfo_parameter('!') != NULL)) | 12070 if (!writing && (find_viminfo_parameter('!') != NULL)) |
11813 { | 12071 { |
11814 tab = vim_strchr(virp->vir_line + 1, '\t'); | 12072 tab = vim_strchr(virp->vir_line + 1, '\t'); |
11815 if (tab != NULL) | 12073 if (tab != NULL) |
11819 is_string = TRUE; | 12077 is_string = TRUE; |
11820 | 12078 |
11821 tab = vim_strchr(tab, '\t'); | 12079 tab = vim_strchr(tab, '\t'); |
11822 if (tab != NULL) | 12080 if (tab != NULL) |
11823 { | 12081 { |
11824 /* create a typeval to hold the value */ | |
11825 if (is_string) | 12082 if (is_string) |
11826 { | 12083 { |
11827 val = viminfo_readstring(virp, | 12084 tv.v_type = VAR_STRING; |
12085 tv.vval.v_string = viminfo_readstring(virp, | |
11828 (int)(tab - virp->vir_line + 1), TRUE); | 12086 (int)(tab - virp->vir_line + 1), TRUE); |
11829 if (val != NULL) | |
11830 tvp = alloc_string_tv(val); | |
11831 } | 12087 } |
11832 else | 12088 else |
11833 { | 12089 { |
11834 tvp = alloc_tv(); | 12090 tv.v_type = VAR_NUMBER; |
11835 if (tvp != NULL) | 12091 tv.vval.v_number = atol((char *)tab + 1); |
11836 { | |
11837 tvp->v_type = VAR_NUMBER; | |
11838 tvp->vval.v_number = atol((char *)tab + 1); | |
11839 } | |
11840 } | 12092 } |
11841 /* assign the value to the variable */ | 12093 set_var(virp->vir_line + 1, &tv, FALSE); |
11842 if (tvp != NULL) | 12094 if (is_string) |
11843 { | 12095 vim_free(tv.vval.v_string); |
11844 set_var(virp->vir_line + 1, tvp, FALSE); | |
11845 free_tv(tvp); | |
11846 } | |
11847 } | 12096 } |
11848 } | 12097 } |
11849 } | 12098 } |
11850 | 12099 |
11851 return viminfo_readline(virp); | 12100 return viminfo_readline(virp); |
11876 { | 12125 { |
11877 switch (this_var->tv.v_type) | 12126 switch (this_var->tv.v_type) |
11878 { | 12127 { |
11879 case VAR_STRING: s = "STR"; break; | 12128 case VAR_STRING: s = "STR"; break; |
11880 case VAR_NUMBER: s = "NUM"; break; | 12129 case VAR_NUMBER: s = "NUM"; break; |
11881 case VAR_LIST: s = "LST"; break; | 12130 default: continue; |
11882 case VAR_FUNC: s = "FUN"; break; | |
11883 default: | |
11884 EMSGN(_("E999: Internal error: write_viminfo_varlist(): %ld"), (long)this_var->tv.v_type); | |
11885 s = "ERR"; | |
11886 } | 12131 } |
11887 fprintf(fp, "!%s\t%s\t", this_var->v_name, s); | 12132 fprintf(fp, "!%s\t%s\t", this_var->v_name, s); |
11888 viminfo_writestring(fp, tv2string(&this_var->tv, &tofree)); | 12133 viminfo_writestring(fp, tv2string(&this_var->tv, &tofree)); |
11889 vim_free(tofree); | 12134 vim_free(tofree); |
11890 } | 12135 } |
11903 char_u *p, *t; | 12148 char_u *p, *t; |
11904 | 12149 |
11905 for (i = gap->ga_len; --i >= 0; ) | 12150 for (i = gap->ga_len; --i >= 0; ) |
11906 { | 12151 { |
11907 this_var = &VAR_GAP_ENTRY(i, gap); | 12152 this_var = &VAR_GAP_ENTRY(i, gap); |
11908 if (this_var->v_name != NULL) | 12153 if (this_var->v_name != NULL |
11909 { | 12154 && (this_var->tv.v_type == VAR_NUMBER |
11910 if (var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION) | 12155 || this_var->tv.v_type == VAR_STRING) |
12156 && var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION) | |
12157 { | |
12158 /* Escape special characters with a backslash. Turn a LF and | |
12159 * CR into \n and \r. */ | |
12160 p = vim_strsave_escaped(get_var_string(this_var), | |
12161 (char_u *)"\\\"\n\r"); | |
12162 if (p == NULL) /* out of memory */ | |
12163 continue; | |
12164 for (t = p; *t != NUL; ++t) | |
12165 if (*t == '\n') | |
12166 *t = 'n'; | |
12167 else if (*t == '\r') | |
12168 *t = 'r'; | |
12169 if ((fprintf(fd, "let %s = %c%s%c", | |
12170 this_var->v_name, | |
12171 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ', | |
12172 p, | |
12173 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0) | |
12174 || put_eol(fd) == FAIL) | |
11911 { | 12175 { |
11912 /* Escapse special characters with a backslash. Turn a LF and | |
11913 * CR into \n and \r. */ | |
11914 p = vim_strsave_escaped(get_var_string(this_var), | |
11915 (char_u *)"\\\"\n\r"); | |
11916 if (p == NULL) /* out of memory */ | |
11917 continue; | |
11918 for (t = p; *t != NUL; ++t) | |
11919 if (*t == '\n') | |
11920 *t = 'n'; | |
11921 else if (*t == '\r') | |
11922 *t = 'r'; | |
11923 if ((fprintf(fd, "let %s = %c%s%c", | |
11924 this_var->v_name, | |
11925 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ', | |
11926 p, | |
11927 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0) | |
11928 || put_eol(fd) == FAIL) | |
11929 { | |
11930 vim_free(p); | |
11931 return FAIL; | |
11932 } | |
11933 vim_free(p); | 12176 vim_free(p); |
12177 return FAIL; | |
11934 } | 12178 } |
11935 | 12179 vim_free(p); |
11936 } | 12180 } |
11937 } | 12181 } |
11938 return OK; | 12182 return OK; |
11939 } | 12183 } |
11940 #endif | 12184 #endif |