comparison src/scriptfile.c @ 27043:15f40772e10a v8.2.4050

patch 8.2.4050: Vim9: need to prefix every item in an autoload script Commit: https://github.com/vim/vim/commit/dc4451df61a6aa12a0661817b7094fb32f09e11d Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 9 21:36:37 2022 +0000 patch 8.2.4050: Vim9: need to prefix every item in an autoload script Problem: Vim9: need to prefix every item in an autoload script. Solution: First step in supporting "vim9script autoload" and "import autoload".
author Bram Moolenaar <Bram@vim.org>
date Sun, 09 Jan 2022 22:45:04 +0100
parents c9474ae175f4
children d31bd8607975
comparison
equal deleted inserted replaced
27042:8fc14d120630 27043:15f40772e10a
237 source_callback(char_u *fname, void *cookie) 237 source_callback(char_u *fname, void *cookie)
238 { 238 {
239 (void)do_source(fname, FALSE, DOSO_NONE, cookie); 239 (void)do_source(fname, FALSE, DOSO_NONE, cookie);
240 } 240 }
241 241
242 #ifdef FEAT_EVAL
243 /*
244 * Find an already loaded script "name".
245 * If found returns its script ID. If not found returns -1.
246 */
247 static int
248 find_script_by_name(char_u *name)
249 {
250 int sid;
251 scriptitem_T *si;
252
253 for (sid = script_items.ga_len; sid > 0; --sid)
254 {
255 // We used to check inode here, but that doesn't work:
256 // - If a script is edited and written, it may get a different
257 // inode number, even though to the user it is the same script.
258 // - If a script is deleted and another script is written, with a
259 // different name, the inode may be re-used.
260 si = SCRIPT_ITEM(sid);
261 if (si->sn_name != NULL && fnamecmp(si->sn_name, name) == 0)
262 return sid;
263 }
264 return -1;
265 }
266
267 /*
268 * Add a new scriptitem with all items initialized.
269 * When running out of memory "error" is set to FAIL.
270 * Returns the script ID.
271 */
272 static int
273 get_new_scriptitem(int *error)
274 {
275 static scid_T last_current_SID = 0;
276 int sid = ++last_current_SID;
277 scriptitem_T *si;
278
279 if (ga_grow(&script_items, (int)(sid - script_items.ga_len)) == FAIL)
280 {
281 *error = FAIL;
282 return sid;
283 }
284 while (script_items.ga_len < sid)
285 {
286 si = ALLOC_CLEAR_ONE(scriptitem_T);
287 if (si == NULL)
288 {
289 *error = FAIL;
290 return sid;
291 }
292 ++script_items.ga_len;
293 SCRIPT_ITEM(script_items.ga_len) = si;
294 si->sn_name = NULL;
295 si->sn_version = 1;
296
297 // Allocate the local script variables to use for this script.
298 new_script_vars(script_items.ga_len);
299 ga_init2(&si->sn_var_vals, sizeof(svar_T), 10);
300 hash_init(&si->sn_all_vars.dv_hashtab);
301 ga_init2(&si->sn_imports, sizeof(imported_T), 10);
302 ga_init2(&si->sn_type_list, sizeof(type_T), 10);
303 # ifdef FEAT_PROFILE
304 si->sn_prof_on = FALSE;
305 # endif
306 }
307
308 // Used to check script variable index is still valid.
309 si->sn_script_seq = current_sctx.sc_seq;
310
311 return sid;
312 }
313
314 static void
315 find_script_callback(char_u *fname, void *cookie)
316 {
317 int sid;
318 int error = OK;
319 int *ret_sid = cookie;
320
321 sid = find_script_by_name(fname);
322 if (sid < 0)
323 {
324 // script does not exist yet, create a new scriptitem
325 sid = get_new_scriptitem(&error);
326 if (error == OK)
327 {
328 scriptitem_T *si = SCRIPT_ITEM(sid);
329
330 si->sn_name = vim_strsave(fname);
331 si->sn_state = SN_STATE_NOT_LOADED;
332 }
333 }
334 *ret_sid = sid;
335 }
336 #endif
337
242 /* 338 /*
243 * Find the file "name" in all directories in "path" and invoke 339 * Find the file "name" in all directories in "path" and invoke
244 * "callback(fname, cookie)". 340 * "callback(fname, cookie)".
245 * "name" can contain wildcards. 341 * "name" can contain wildcards.
246 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 342 * When "flags" has DIP_ALL: source all files, otherwise only the first one.
453 { 549 {
454 return source_in_path(p_rtp, name, flags, NULL); 550 return source_in_path(p_rtp, name, flags, NULL);
455 } 551 }
456 552
457 /* 553 /*
458 * Just like source_runtime(), but use "path" instead of 'runtimepath'. 554 * Just like source_runtime(), but use "path" instead of 'runtimepath'
555 * and return the script ID in "ret_sid".
459 */ 556 */
460 int 557 int
461 source_in_path(char_u *path, char_u *name, int flags, int *ret_sid) 558 source_in_path(char_u *path, char_u *name, int flags, int *ret_sid)
462 { 559 {
463 return do_in_path_and_pp(path, name, flags, source_callback, ret_sid); 560 return do_in_path_and_pp(path, name, flags, source_callback, ret_sid);
464 } 561 }
465 562
466
467 #if defined(FEAT_EVAL) || defined(PROTO) 563 #if defined(FEAT_EVAL) || defined(PROTO)
564
565 /*
566 * Find "name" in 'runtimepath'. If found a new scriptitem is created for it
567 * and it's script ID is returned.
568 * If not found returns -1.
569 */
570 int
571 find_script_in_rtp(char_u *name)
572 {
573 int sid = -1;
574
575 (void)do_in_path_and_pp(p_rtp, name, DIP_NOAFTER,
576 find_script_callback, &sid);
577 return sid;
578 }
468 579
469 /* 580 /*
470 * Expand wildcards in "pat" and invoke do_source() for each match. 581 * Expand wildcards in "pat" and invoke do_source() for each match.
471 */ 582 */
472 static void 583 static void
1125 char_u *fname_exp; 1236 char_u *fname_exp;
1126 char_u *firstline = NULL; 1237 char_u *firstline = NULL;
1127 int retval = FAIL; 1238 int retval = FAIL;
1128 sctx_T save_current_sctx; 1239 sctx_T save_current_sctx;
1129 #ifdef FEAT_EVAL 1240 #ifdef FEAT_EVAL
1130 static scid_T last_current_SID = 0;
1131 static int last_current_SID_seq = 0; 1241 static int last_current_SID_seq = 0;
1132 funccal_entry_T funccalp_entry; 1242 funccal_entry_T funccalp_entry;
1133 int save_debug_break_level = debug_break_level; 1243 int save_debug_break_level = debug_break_level;
1134 int sid; 1244 int sid;
1135 scriptitem_T *si = NULL; 1245 scriptitem_T *si = NULL;
1159 } 1269 }
1160 #ifdef FEAT_EVAL 1270 #ifdef FEAT_EVAL
1161 estack_compiling = FALSE; 1271 estack_compiling = FALSE;
1162 1272
1163 // See if we loaded this script before. 1273 // See if we loaded this script before.
1164 for (sid = script_items.ga_len; sid > 0; --sid) 1274 sid = find_script_by_name(fname_exp);
1165 {
1166 // We used to check inode here, but that doesn't work:
1167 // - If a script is edited and written, it may get a different
1168 // inode number, even though to the user it is the same script.
1169 // - If a script is deleted and another script is written, with a
1170 // different name, the inode may be re-used.
1171 si = SCRIPT_ITEM(sid);
1172 if (si->sn_name != NULL && fnamecmp(si->sn_name, fname_exp) == 0)
1173 // Found it!
1174 break;
1175 }
1176 if (sid > 0 && ret_sid != NULL) 1275 if (sid > 0 && ret_sid != NULL)
1177 { 1276 {
1178 // Already loaded and no need to load again, return here. 1277 // Already loaded and no need to load again, return here.
1179 *ret_sid = sid; 1278 *ret_sid = sid;
1180 retval = OK; 1279 retval = OK;
1316 int todo; 1415 int todo;
1317 hashitem_T *hi; 1416 hashitem_T *hi;
1318 dictitem_T *di; 1417 dictitem_T *di;
1319 1418
1320 // loading the same script again 1419 // loading the same script again
1321 si->sn_state = SN_STATE_RELOAD;
1322 current_sctx.sc_sid = sid; 1420 current_sctx.sc_sid = sid;
1323 1421 si = SCRIPT_ITEM(sid);
1324 // Script-local variables remain but "const" can be set again. 1422 if (si->sn_state == SN_STATE_NOT_LOADED)
1325 // In Vim9 script variables will be cleared when "vim9script" is 1423 {
1326 // encountered without the "noclear" argument. 1424 // this script was found but not loaded yet
1327 ht = &SCRIPT_VARS(sid); 1425 si->sn_state = SN_STATE_NEW;
1328 todo = (int)ht->ht_used; 1426 }
1329 for (hi = ht->ht_array; todo > 0; ++hi) 1427 else
1330 if (!HASHITEM_EMPTY(hi)) 1428 {
1331 { 1429 si->sn_state = SN_STATE_RELOAD;
1332 --todo; 1430
1333 di = HI2DI(hi); 1431 // Script-local variables remain but "const" can be set again.
1334 di->di_flags |= DI_FLAGS_RELOAD; 1432 // In Vim9 script variables will be cleared when "vim9script" is
1335 } 1433 // encountered without the "noclear" argument.
1336 // imports can be redefined once 1434 ht = &SCRIPT_VARS(sid);
1337 mark_imports_for_reload(sid); 1435 todo = (int)ht->ht_used;
1338 1436 for (hi = ht->ht_array; todo > 0; ++hi)
1339 // reset version, "vim9script" may have been added or removed. 1437 if (!HASHITEM_EMPTY(hi))
1340 si->sn_version = 1; 1438 {
1439 --todo;
1440 di = HI2DI(hi);
1441 di->di_flags |= DI_FLAGS_RELOAD;
1442 }
1443 // imports can be redefined once
1444 mark_imports_for_reload(sid);
1445
1446 // reset version, "vim9script" may have been added or removed.
1447 si->sn_version = 1;
1448 }
1341 } 1449 }
1342 else 1450 else
1343 { 1451 {
1344 // It's new, generate a new SID. 1452 int error = OK;
1345 current_sctx.sc_sid = ++last_current_SID; 1453
1346 if (ga_grow(&script_items, 1454 // It's new, generate a new SID and initialize the scriptitem.
1347 (int)(current_sctx.sc_sid - script_items.ga_len)) == FAIL) 1455 current_sctx.sc_sid = get_new_scriptitem(&error);
1456 if (error == FAIL)
1348 goto almosttheend; 1457 goto almosttheend;
1349 while (script_items.ga_len < current_sctx.sc_sid)
1350 {
1351 si = ALLOC_CLEAR_ONE(scriptitem_T);
1352 if (si == NULL)
1353 goto almosttheend;
1354 ++script_items.ga_len;
1355 SCRIPT_ITEM(script_items.ga_len) = si;
1356 si->sn_name = NULL;
1357 si->sn_version = 1;
1358
1359 // Allocate the local script variables to use for this script.
1360 new_script_vars(script_items.ga_len);
1361 ga_init2(&si->sn_var_vals, sizeof(svar_T), 10);
1362 hash_init(&si->sn_all_vars.dv_hashtab);
1363 ga_init2(&si->sn_imports, sizeof(imported_T), 10);
1364 ga_init2(&si->sn_type_list, sizeof(type_T), 10);
1365 # ifdef FEAT_PROFILE
1366 si->sn_prof_on = FALSE;
1367 # endif
1368 }
1369 si = SCRIPT_ITEM(current_sctx.sc_sid); 1458 si = SCRIPT_ITEM(current_sctx.sc_sid);
1370 si->sn_name = fname_exp; 1459 si->sn_name = fname_exp;
1371 fname_exp = vim_strsave(si->sn_name); // used for autocmd 1460 fname_exp = vim_strsave(si->sn_name); // used for autocmd
1372 if (ret_sid != NULL) 1461 if (ret_sid != NULL)
1373 *ret_sid = current_sctx.sc_sid; 1462 *ret_sid = current_sctx.sc_sid;
1374 1463
1375 // Remember the "is_vimrc" flag for when the file is sourced again. 1464 // Remember the "is_vimrc" flag for when the file is sourced again.
1376 si->sn_is_vimrc = is_vimrc; 1465 si->sn_is_vimrc = is_vimrc;
1377
1378 // Used to check script variable index is still valid.
1379 si->sn_script_seq = current_sctx.sc_seq;
1380 } 1466 }
1381 1467
1382 # ifdef FEAT_PROFILE 1468 # ifdef FEAT_PROFILE
1383 if (do_profiling == PROF_YES) 1469 if (do_profiling == PROF_YES)
1384 { 1470 {
2029 && ((source_cookie_T *)getline_cookie( 2115 && ((source_cookie_T *)getline_cookie(
2030 fgetline, cookie))->finished); 2116 fgetline, cookie))->finished);
2031 } 2117 }
2032 2118
2033 /* 2119 /*
2120 * Find the path of a script below the "autoload" directory.
2121 * Returns NULL if there is no "/autoload/" in the script name.
2122 */
2123 char_u *
2124 script_name_after_autoload(scriptitem_T *si)
2125 {
2126 char_u *p = si->sn_name;
2127 char_u *res = NULL;
2128
2129 for (;;)
2130 {
2131 char_u *n = (char_u *)strstr((char *)p, "autoload");
2132
2133 if (n == NULL)
2134 break;
2135 if (n > p && vim_ispathsep(n[-1]) && vim_ispathsep(n[8]))
2136 res = n + 9;
2137 p = n + 8;
2138 }
2139 return res;
2140 }
2141
2142 /*
2143 * If in a Vim9 autoload script return "name" with the autoload prefix for the
2144 * script. If successful "name" is freed, the returned name is allocated.
2145 * Otherwise it returns "name" unmodified.
2146 */
2147 char_u *
2148 may_prefix_autoload(char_u *name)
2149 {
2150 if (SCRIPT_ID_VALID(current_sctx.sc_sid))
2151 {
2152 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
2153
2154 if (si->sn_is_autoload)
2155 {
2156 char_u *p = script_name_after_autoload(si);
2157
2158 if (p != NULL)
2159 {
2160 char_u *tail = vim_strsave(p);
2161
2162 if (tail != NULL)
2163 {
2164 for (p = tail; *p != NUL; p += mb_ptr2len(p))
2165 {
2166 if (vim_ispathsep(*p))
2167 *p = '#';
2168 else if (STRCMP(p, ".vim"))
2169 {
2170 size_t len = (p - tail) + STRLEN(name) + 2;
2171 char_u *res = alloc(len);
2172
2173 if (res == NULL)
2174 break;
2175 *p = NUL;
2176 vim_snprintf((char *)res, len, "%s#%s", tail, name);
2177 vim_free(name);
2178 vim_free(tail);
2179 return res;
2180 }
2181 }
2182 }
2183 // did not find ".vim" at the end
2184 vim_free(tail);
2185 }
2186 }
2187 }
2188 return name;
2189 }
2190
2191 /*
2034 * Return the autoload script name for a function or variable name. 2192 * Return the autoload script name for a function or variable name.
2035 * Returns NULL when out of memory. 2193 * Returns NULL when out of memory.
2036 * Caller must make sure that "name" contains AUTOLOAD_CHAR. 2194 * Caller must make sure that "name" contains AUTOLOAD_CHAR.
2037 */ 2195 */
2038 char_u * 2196 char_u *