Mercurial > vim
comparison src/vim9script.c @ 21146:465d6e40e79c v8.2.1124
patch 8.2.1124: Vim9: no line break allowed in :import command
Commit: https://github.com/vim/vim/commit/1c991144c502ade477e1a32fdfd0f78b6299fdc7
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jul 4 13:15:31 2020 +0200
patch 8.2.1124: Vim9: no line break allowed in :import command
Problem: Vim9: no line break allowed in :import command.
Solution: Skip over line breaks.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 04 Jul 2020 13:30:04 +0200 |
parents | 4d844a65183d |
children | 667192c5938b |
comparison
equal
deleted
inserted
replaced
21145:9761ed6ea124 | 21146:465d6e40e79c |
---|---|
140 * ":import * as Name from 'filename'" | 140 * ":import * as Name from 'filename'" |
141 */ | 141 */ |
142 void | 142 void |
143 ex_import(exarg_T *eap) | 143 ex_import(exarg_T *eap) |
144 { | 144 { |
145 char_u *cmd_end; | 145 char_u *cmd_end; |
146 evalarg_T evalarg; | |
146 | 147 |
147 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) | 148 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) |
148 { | 149 { |
149 emsg(_("E1094: import can only be used in a script")); | 150 emsg(_("E1094: import can only be used in a script")); |
150 return; | 151 return; |
151 } | 152 } |
152 | 153 fill_evalarg_from_eap(&evalarg, eap, eap->skip); |
153 cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, NULL); | 154 |
155 cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, | |
156 &evalarg, NULL); | |
154 if (cmd_end != NULL) | 157 if (cmd_end != NULL) |
155 eap->nextcmd = check_nextcmd(cmd_end); | 158 eap->nextcmd = check_nextcmd(cmd_end); |
159 clear_evalarg(&evalarg, eap); | |
156 } | 160 } |
157 | 161 |
158 /* | 162 /* |
159 * Find an exported item in "sid" matching the name at "*argp". | 163 * Find an exported item in "sid" matching the name at "*argp". |
160 * When it is a variable return the index. | 164 * When it is a variable return the index. |
162 * When not found returns -1 and "*ufunc" is NULL. | 166 * When not found returns -1 and "*ufunc" is NULL. |
163 */ | 167 */ |
164 int | 168 int |
165 find_exported( | 169 find_exported( |
166 int sid, | 170 int sid, |
167 char_u **argp, | 171 char_u *name, |
168 int *name_len, | |
169 ufunc_T **ufunc, | 172 ufunc_T **ufunc, |
170 type_T **type) | 173 type_T **type) |
171 { | 174 { |
172 char_u *name = *argp; | |
173 char_u *arg = *argp; | |
174 int cc; | |
175 int idx = -1; | 175 int idx = -1; |
176 svar_T *sv; | 176 svar_T *sv; |
177 scriptitem_T *script = SCRIPT_ITEM(sid); | 177 scriptitem_T *script = SCRIPT_ITEM(sid); |
178 | 178 |
179 // isolate one name | |
180 while (eval_isnamec(*arg)) | |
181 ++arg; | |
182 *name_len = (int)(arg - name); | |
183 | |
184 // find name in "script" | 179 // find name in "script" |
185 // TODO: also find script-local user function | 180 // TODO: also find script-local user function |
186 cc = *arg; | |
187 *arg = NUL; | |
188 idx = get_script_item_idx(sid, name, FALSE); | 181 idx = get_script_item_idx(sid, name, FALSE); |
189 if (idx >= 0) | 182 if (idx >= 0) |
190 { | 183 { |
191 sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; | 184 sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; |
192 if (!sv->sv_export) | 185 if (!sv->sv_export) |
193 { | 186 { |
194 semsg(_("E1049: Item not exported in script: %s"), name); | 187 semsg(_("E1049: Item not exported in script: %s"), name); |
195 *arg = cc; | |
196 return -1; | 188 return -1; |
197 } | 189 } |
198 *type = sv->sv_type; | 190 *type = sv->sv_type; |
199 *ufunc = NULL; | 191 *ufunc = NULL; |
200 } | 192 } |
208 funcname = buffer; | 200 funcname = buffer; |
209 else | 201 else |
210 { | 202 { |
211 funcname = alloc(STRLEN(name) + 10); | 203 funcname = alloc(STRLEN(name) + 10); |
212 if (funcname == NULL) | 204 if (funcname == NULL) |
213 { | |
214 *arg = cc; | |
215 return -1; | 205 return -1; |
216 } | |
217 } | 206 } |
218 funcname[0] = K_SPECIAL; | 207 funcname[0] = K_SPECIAL; |
219 funcname[1] = KS_EXTRA; | 208 funcname[1] = KS_EXTRA; |
220 funcname[2] = (int)KE_SNR; | 209 funcname[2] = (int)KE_SNR; |
221 sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); | 210 sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); |
224 vim_free(funcname); | 213 vim_free(funcname); |
225 | 214 |
226 if (*ufunc == NULL) | 215 if (*ufunc == NULL) |
227 { | 216 { |
228 semsg(_("E1048: Item not found in script: %s"), name); | 217 semsg(_("E1048: Item not found in script: %s"), name); |
229 *arg = cc; | |
230 return -1; | 218 return -1; |
231 } | 219 } |
232 } | 220 } |
233 *arg = cc; | |
234 arg = skipwhite(arg); | |
235 *argp = arg; | |
236 | 221 |
237 return idx; | 222 return idx; |
238 } | 223 } |
239 | 224 |
240 /* | 225 /* |
241 * Handle an ":import" command and add the resulting imported_T to "gap", when | 226 * Handle an ":import" command and add the resulting imported_T to "gap", when |
242 * not NULL, or script "import_sid" sn_imports. | 227 * not NULL, or script "import_sid" sn_imports. |
243 * Returns a pointer to after the command or NULL in case of failure | 228 * Returns a pointer to after the command or NULL in case of failure |
244 */ | 229 */ |
245 char_u * | 230 char_u * |
246 handle_import(char_u *arg_start, garray_T *gap, int import_sid, void *cctx) | 231 handle_import( |
232 char_u *arg_start, | |
233 garray_T *gap, | |
234 int import_sid, | |
235 evalarg_T *evalarg, | |
236 void *cctx) | |
247 { | 237 { |
248 char_u *arg = arg_start; | 238 char_u *arg = arg_start; |
249 char_u *cmd_end; | 239 char_u *cmd_end = NULL; |
250 char_u *as_ptr = NULL; | 240 char_u *as_name = NULL; |
251 char_u *from_ptr; | |
252 int as_len = 0; | |
253 int ret = FAIL; | 241 int ret = FAIL; |
254 typval_T tv; | 242 typval_T tv; |
255 int sid = -1; | 243 int sid = -1; |
256 int res; | 244 int res; |
257 | 245 garray_T names; |
246 static char e_import_syntax[] = N_("E1047: syntax error in import"); | |
247 | |
248 ga_init2(&names, sizeof(char_u *), 10); | |
258 if (*arg == '{') | 249 if (*arg == '{') |
259 { | 250 { |
260 // skip over {item} list | 251 // "import {item, item} from ..." |
261 while (*arg != NUL && *arg != '}') | 252 arg = skipwhite_and_linebreak(arg + 1, evalarg); |
262 ++arg; | 253 for (;;) |
263 if (*arg == '}') | 254 { |
264 arg = skipwhite(arg + 1); | 255 char_u *p = arg; |
265 } | 256 int had_comma = FALSE; |
266 else | 257 |
267 { | |
268 if (*arg == '*') | |
269 arg = skipwhite(arg + 1); | |
270 else if (eval_isnamec1(*arg)) | |
271 { | |
272 while (eval_isnamec(*arg)) | 258 while (eval_isnamec(*arg)) |
273 ++arg; | 259 ++arg; |
274 arg = skipwhite(arg); | 260 if (p == arg) |
275 } | 261 break; |
276 if (STRNCMP("as", arg, 2) == 0 && VIM_ISWHITE(arg[2])) | 262 if (ga_grow(&names, 1) == FAIL) |
277 { | 263 goto erret; |
278 // skip over "as Name " | 264 ((char_u **)names.ga_data)[names.ga_len] = |
265 vim_strnsave(p, arg - p); | |
266 ++names.ga_len; | |
267 if (*arg == ',') | |
268 { | |
269 had_comma = TRUE; | |
270 ++arg; | |
271 } | |
272 arg = skipwhite_and_linebreak(arg, evalarg); | |
273 if (*arg == '}') | |
274 { | |
275 arg = skipwhite_and_linebreak(arg + 1, evalarg); | |
276 break; | |
277 } | |
278 if (!had_comma) | |
279 { | |
280 emsg(_("E1046: Missing comma in import")); | |
281 goto erret; | |
282 } | |
283 } | |
284 if (names.ga_len == 0) | |
285 { | |
286 emsg(_(e_import_syntax)); | |
287 goto erret; | |
288 } | |
289 } | |
290 else | |
291 { | |
292 // "import Name from ..." | |
293 // "import * as Name from ..." | |
294 // "import item [as Name] from ..." | |
295 arg = skipwhite_and_linebreak(arg, evalarg); | |
296 if (arg[0] == '*' && IS_WHITE_OR_NUL(arg[1])) | |
297 arg = skipwhite_and_linebreak(arg + 1, evalarg); | |
298 else if (eval_isnamec1(*arg)) | |
299 { | |
300 char_u *p = arg; | |
301 | |
302 while (eval_isnamec(*arg)) | |
303 ++arg; | |
304 if (ga_grow(&names, 1) == FAIL) | |
305 goto erret; | |
306 ((char_u **)names.ga_data)[names.ga_len] = | |
307 vim_strnsave(p, arg - p); | |
308 ++names.ga_len; | |
309 arg = skipwhite_and_linebreak(arg, evalarg); | |
310 } | |
311 else | |
312 { | |
313 emsg(_(e_import_syntax)); | |
314 goto erret; | |
315 } | |
316 | |
317 if (STRNCMP("as", arg, 2) == 0 && IS_WHITE_OR_NUL(arg[2])) | |
318 { | |
319 char_u *p; | |
320 | |
321 // skip over "as Name "; no line break allowed after "as" | |
279 arg = skipwhite(arg + 2); | 322 arg = skipwhite(arg + 2); |
280 as_ptr = arg; | 323 p = arg; |
281 if (eval_isnamec1(*arg)) | 324 if (eval_isnamec1(*arg)) |
282 while (eval_isnamec(*arg)) | 325 while (eval_isnamec(*arg)) |
283 ++arg; | 326 ++arg; |
284 as_len = (int)(arg - as_ptr); | 327 if (check_defined(p, (int)(arg - p), cctx) == FAIL) |
285 arg = skipwhite(arg); | 328 goto erret; |
286 if (check_defined(as_ptr, as_len, cctx) == FAIL) | 329 as_name = vim_strnsave(p, arg - p); |
287 return NULL; | 330 arg = skipwhite_and_linebreak(arg, evalarg); |
288 } | 331 } |
289 else if (*arg_start == '*') | 332 else if (*arg_start == '*') |
290 { | 333 { |
291 emsg(_("E1045: Missing \"as\" after *")); | 334 emsg(_("E1045: Missing \"as\" after *")); |
292 return NULL; | 335 goto erret; |
293 } | 336 } |
294 } | 337 } |
295 if (STRNCMP("from", arg, 4) != 0 || !VIM_ISWHITE(arg[4])) | 338 |
339 if (STRNCMP("from", arg, 4) != 0 || !IS_WHITE_OR_NUL(arg[4])) | |
296 { | 340 { |
297 emsg(_("E1070: Missing \"from\"")); | 341 emsg(_("E1070: Missing \"from\"")); |
298 return NULL; | 342 goto erret; |
299 } | 343 } |
300 from_ptr = arg; | 344 |
301 arg = skipwhite(arg + 4); | 345 arg = skipwhite_and_linebreak_keep_string(arg + 4, evalarg); |
302 tv.v_type = VAR_UNKNOWN; | 346 tv.v_type = VAR_UNKNOWN; |
303 // TODO: should we accept any expression? | 347 // TODO: should we accept any expression? |
304 if (*arg == '\'') | 348 if (*arg == '\'') |
305 ret = eval_lit_string(&arg, &tv, TRUE); | 349 ret = eval_lit_string(&arg, &tv, TRUE); |
306 else if (*arg == '"') | 350 else if (*arg == '"') |
307 ret = eval_string(&arg, &tv, TRUE); | 351 ret = eval_string(&arg, &tv, TRUE); |
308 if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) | 352 if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) |
309 { | 353 { |
310 emsg(_("E1071: Invalid string after \"from\"")); | 354 emsg(_("E1071: Invalid string after \"from\"")); |
311 return NULL; | 355 goto erret; |
312 } | 356 } |
313 cmd_end = arg; | 357 cmd_end = arg; |
314 | 358 |
315 // find script tv.vval.v_string | 359 /* |
360 * find script file | |
361 */ | |
316 if (*tv.vval.v_string == '.') | 362 if (*tv.vval.v_string == '.') |
317 { | 363 { |
318 size_t len; | 364 size_t len; |
319 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); | 365 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); |
320 char_u *tail = gettail(si->sn_name); | 366 char_u *tail = gettail(si->sn_name); |
324 len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; | 370 len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; |
325 from_name = alloc((int)len); | 371 from_name = alloc((int)len); |
326 if (from_name == NULL) | 372 if (from_name == NULL) |
327 { | 373 { |
328 clear_tv(&tv); | 374 clear_tv(&tv); |
329 return NULL; | 375 goto erret; |
330 } | 376 } |
331 vim_strncpy(from_name, si->sn_name, tail - si->sn_name); | 377 vim_strncpy(from_name, si->sn_name, tail - si->sn_name); |
332 add_pathsep(from_name); | 378 add_pathsep(from_name); |
333 STRCAT(from_name, tv.vval.v_string); | 379 STRCAT(from_name, tv.vval.v_string); |
334 simplify_filename(from_name); | 380 simplify_filename(from_name); |
349 // Find file in "import" subdirs in 'runtimepath'. | 395 // Find file in "import" subdirs in 'runtimepath'. |
350 from_name = alloc((int)len); | 396 from_name = alloc((int)len); |
351 if (from_name == NULL) | 397 if (from_name == NULL) |
352 { | 398 { |
353 clear_tv(&tv); | 399 clear_tv(&tv); |
354 return NULL; | 400 goto erret; |
355 } | 401 } |
356 vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); | 402 vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); |
357 res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); | 403 res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); |
358 vim_free(from_name); | 404 vim_free(from_name); |
359 } | 405 } |
360 | 406 |
361 if (res == FAIL || sid <= 0) | 407 if (res == FAIL || sid <= 0) |
362 { | 408 { |
363 semsg(_("E1053: Could not import \"%s\""), tv.vval.v_string); | 409 semsg(_("E1053: Could not import \"%s\""), tv.vval.v_string); |
364 clear_tv(&tv); | 410 clear_tv(&tv); |
365 return NULL; | 411 goto erret; |
366 } | 412 } |
367 clear_tv(&tv); | 413 clear_tv(&tv); |
368 | 414 |
369 if (*arg_start == '*') | 415 if (*arg_start == '*') |
370 { | 416 { |
371 imported_T *imported = new_imported(gap != NULL ? gap | 417 imported_T *imported = new_imported(gap != NULL ? gap |
372 : &SCRIPT_ITEM(import_sid)->sn_imports); | 418 : &SCRIPT_ITEM(import_sid)->sn_imports); |
373 | 419 |
374 if (imported == NULL) | 420 if (imported == NULL) |
375 return NULL; | 421 goto erret; |
376 imported->imp_name = vim_strnsave(as_ptr, as_len); | 422 imported->imp_name = as_name; |
423 as_name = NULL; | |
377 imported->imp_sid = sid; | 424 imported->imp_sid = sid; |
378 imported->imp_all = TRUE; | 425 imported->imp_all = TRUE; |
379 } | 426 } |
380 else | 427 else |
381 { | 428 { |
429 int i; | |
430 | |
382 arg = arg_start; | 431 arg = arg_start; |
383 if (*arg == '{') | 432 if (*arg == '{') |
384 arg = skipwhite(arg + 1); | 433 arg = skipwhite(arg + 1); |
385 for (;;) | 434 for (i = 0; i < names.ga_len; ++i) |
386 { | 435 { |
387 char_u *name = arg; | 436 char_u *name = ((char_u **)names.ga_data)[i]; |
388 int name_len; | |
389 int idx; | 437 int idx; |
390 imported_T *imported; | 438 imported_T *imported; |
391 ufunc_T *ufunc = NULL; | 439 ufunc_T *ufunc = NULL; |
392 type_T *type; | 440 type_T *type; |
393 | 441 |
394 idx = find_exported(sid, &arg, &name_len, &ufunc, &type); | 442 idx = find_exported(sid, name, &ufunc, &type); |
395 | 443 |
396 if (idx < 0 && ufunc == NULL) | 444 if (idx < 0 && ufunc == NULL) |
397 return NULL; | 445 goto erret; |
398 | 446 |
399 if (check_defined(name, name_len, cctx) == FAIL) | 447 if (check_defined(name, STRLEN(name), cctx) == FAIL) |
400 return NULL; | 448 goto erret; |
401 | 449 |
402 imported = new_imported(gap != NULL ? gap | 450 imported = new_imported(gap != NULL ? gap |
403 : &SCRIPT_ITEM(import_sid)->sn_imports); | 451 : &SCRIPT_ITEM(import_sid)->sn_imports); |
404 if (imported == NULL) | 452 if (imported == NULL) |
405 return NULL; | 453 goto erret; |
406 | 454 |
407 // TODO: check for "as" following | 455 // TODO: check for "as" following |
408 // imported->imp_name = vim_strnsave(as_ptr, as_len); | 456 // imported->imp_name = vim_strsave(as_name); |
409 imported->imp_name = vim_strnsave(name, name_len); | 457 imported->imp_name = name; |
458 ((char_u **)names.ga_data)[i] = NULL; | |
410 imported->imp_sid = sid; | 459 imported->imp_sid = sid; |
411 if (idx >= 0) | 460 if (idx >= 0) |
412 { | 461 { |
413 imported->imp_type = type; | 462 imported->imp_type = type; |
414 imported->imp_var_vals_idx = idx; | 463 imported->imp_var_vals_idx = idx; |
415 } | 464 } |
416 else | 465 else |
417 imported->imp_funcname = ufunc->uf_name; | 466 imported->imp_funcname = ufunc->uf_name; |
418 | 467 } |
419 arg = skipwhite(arg); | 468 } |
420 if (*arg_start != '{') | 469 erret: |
421 break; | 470 ga_clear_strings(&names); |
422 if (*arg == '}') | 471 vim_free(as_name); |
423 { | |
424 arg = skipwhite(arg + 1); | |
425 break; | |
426 } | |
427 | |
428 if (*arg != ',') | |
429 { | |
430 emsg(_("E1046: Missing comma in import")); | |
431 return NULL; | |
432 } | |
433 arg = skipwhite(arg + 1); | |
434 } | |
435 if (arg != from_ptr) | |
436 { | |
437 // cannot happen, just in case the above has a flaw | |
438 emsg(_("E1047: syntax error in import")); | |
439 return NULL; | |
440 } | |
441 } | |
442 return cmd_end; | 472 return cmd_end; |
443 } | 473 } |
444 | 474 |
445 /* | 475 /* |
446 * Declare a script-local variable without init: "let var: type". | 476 * Declare a script-local variable without init: "let var: type". |