Mercurial > vim
comparison src/userfunc.c @ 17606:ff097edaae89 v8.1.1800
patch 8.1.1800: function call functions have too many arguments
commit https://github.com/vim/vim/commit/c6538bcc1cdd1fb83732f22fdc69bd9bb66f968a
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Aug 3 18:17:11 2019 +0200
patch 8.1.1800: function call functions have too many arguments
Problem: Function call functions have too many arguments.
Solution: Pass values in a funcexe_T struct.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 03 Aug 2019 18:30:07 +0200 |
parents | 9088fafff9b3 |
children | e259d11e2900 |
comparison
equal
deleted
inserted
replaced
17605:bb1b495f4e05 | 17606:ff097edaae89 |
---|---|
430 get_func_tv( | 430 get_func_tv( |
431 char_u *name, // name of the function | 431 char_u *name, // name of the function |
432 int len, // length of "name" or -1 to use strlen() | 432 int len, // length of "name" or -1 to use strlen() |
433 typval_T *rettv, | 433 typval_T *rettv, |
434 char_u **arg, // argument, pointing to the '(' | 434 char_u **arg, // argument, pointing to the '(' |
435 linenr_T firstline, // first line of range | 435 funcexe_T *funcexe) // various values |
436 linenr_T lastline, // last line of range | |
437 int *doesrange, // return: function handled range | |
438 int evaluate, | |
439 partial_T *partial, // for extra arguments | |
440 dict_T *selfdict) // Dictionary for "self" | |
441 { | 436 { |
442 char_u *argp; | 437 char_u *argp; |
443 int ret = OK; | 438 int ret = OK; |
444 typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */ | 439 typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */ |
445 int argcount = 0; /* number of arguments found */ | 440 int argcount = 0; /* number of arguments found */ |
446 | 441 |
447 /* | 442 /* |
448 * Get the arguments. | 443 * Get the arguments. |
449 */ | 444 */ |
450 argp = *arg; | 445 argp = *arg; |
451 while (argcount < MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc)) | 446 while (argcount < MAX_FUNC_ARGS - (funcexe->partial == NULL ? 0 |
447 : funcexe->partial->pt_argc)) | |
452 { | 448 { |
453 argp = skipwhite(argp + 1); /* skip the '(' or ',' */ | 449 argp = skipwhite(argp + 1); /* skip the '(' or ',' */ |
454 if (*argp == ')' || *argp == ',' || *argp == NUL) | 450 if (*argp == ')' || *argp == ',' || *argp == NUL) |
455 break; | 451 break; |
456 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL) | 452 if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) |
457 { | 453 { |
458 ret = FAIL; | 454 ret = FAIL; |
459 break; | 455 break; |
460 } | 456 } |
461 ++argcount; | 457 ++argcount; |
481 if (ga_grow(&funcargs, 1) == OK) | 477 if (ga_grow(&funcargs, 1) == OK) |
482 ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = | 478 ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = |
483 &argvars[i]; | 479 &argvars[i]; |
484 } | 480 } |
485 | 481 |
486 ret = call_func(name, len, rettv, argcount, argvars, NULL, | 482 ret = call_func(name, len, rettv, argcount, argvars, funcexe); |
487 firstline, lastline, doesrange, evaluate, partial, selfdict); | |
488 | 483 |
489 funcargs.ga_len -= i; | 484 funcargs.ga_len -= i; |
490 } | 485 } |
491 else if (!aborting()) | 486 else if (!aborting()) |
492 { | 487 { |
1414 typval_T *rettv) | 1409 typval_T *rettv) |
1415 { | 1410 { |
1416 listitem_T *item; | 1411 listitem_T *item; |
1417 typval_T argv[MAX_FUNC_ARGS + 1]; | 1412 typval_T argv[MAX_FUNC_ARGS + 1]; |
1418 int argc = 0; | 1413 int argc = 0; |
1419 int dummy; | |
1420 int r = 0; | 1414 int r = 0; |
1421 | 1415 |
1422 for (item = args->vval.v_list->lv_first; item != NULL; | 1416 for (item = args->vval.v_list->lv_first; item != NULL; |
1423 item = item->li_next) | 1417 item = item->li_next) |
1424 { | 1418 { |
1432 */ | 1426 */ |
1433 copy_tv(&item->li_tv, &argv[argc++]); | 1427 copy_tv(&item->li_tv, &argv[argc++]); |
1434 } | 1428 } |
1435 | 1429 |
1436 if (item == NULL) | 1430 if (item == NULL) |
1437 r = call_func(name, -1, rettv, argc, argv, NULL, | 1431 { |
1438 curwin->w_cursor.lnum, curwin->w_cursor.lnum, | 1432 funcexe_T funcexe; |
1439 &dummy, TRUE, partial, selfdict); | 1433 |
1434 funcexe.argv_func = NULL; | |
1435 funcexe.firstline = curwin->w_cursor.lnum; | |
1436 funcexe.lastline = curwin->w_cursor.lnum; | |
1437 funcexe.doesrange = NULL; | |
1438 funcexe.evaluate = TRUE; | |
1439 funcexe.partial = partial; | |
1440 funcexe.selfdict = selfdict; | |
1441 r = call_func(name, -1, rettv, argc, argv, &funcexe); | |
1442 } | |
1440 | 1443 |
1441 /* Free the arguments. */ | 1444 /* Free the arguments. */ |
1442 while (argc > 0) | 1445 while (argc > 0) |
1443 clear_tv(&argv[--argc]); | 1446 clear_tv(&argv[--argc]); |
1444 | 1447 |
1452 call_callback( | 1455 call_callback( |
1453 callback_T *callback, | 1456 callback_T *callback, |
1454 int len, // length of "name" or -1 to use strlen() | 1457 int len, // length of "name" or -1 to use strlen() |
1455 typval_T *rettv, // return value goes here | 1458 typval_T *rettv, // return value goes here |
1456 int argcount, // number of "argvars" | 1459 int argcount, // number of "argvars" |
1457 typval_T *argvars, // vars for arguments, must have "argcount" | 1460 typval_T *argvars) // vars for arguments, must have "argcount" |
1458 // PLUS ONE elements! | 1461 // PLUS ONE elements! |
1459 int (* argv_func)(int, typval_T *, int), | 1462 { |
1460 // function to fill in argvars | 1463 funcexe_T funcexe; |
1461 linenr_T firstline, // first line of range | 1464 |
1462 linenr_T lastline, // last line of range | 1465 vim_memset(&funcexe, 0, sizeof(funcexe)); |
1463 int *doesrange, // return: function handled range | 1466 funcexe.evaluate = TRUE; |
1464 int evaluate, | 1467 funcexe.partial = callback->cb_partial; |
1465 dict_T *selfdict) // Dictionary for "self" | |
1466 { | |
1467 return call_func(callback->cb_name, len, rettv, argcount, argvars, | 1468 return call_func(callback->cb_name, len, rettv, argcount, argvars, |
1468 argv_func, firstline, lastline, doesrange, evaluate, | 1469 &funcexe); |
1469 callback->cb_partial, selfdict); | |
1470 } | 1470 } |
1471 | 1471 |
1472 /* | 1472 /* |
1473 * Call a function with its resolved parameters | 1473 * Call a function with its resolved parameters |
1474 * | |
1475 * "argv_func", when not NULL, can be used to fill in arguments only when the | |
1476 * invoked function uses them. It is called like this: | |
1477 * new_argcount = argv_func(current_argcount, argv, called_func_argcount) | |
1478 * | 1474 * |
1479 * Return FAIL when the function can't be called, OK otherwise. | 1475 * Return FAIL when the function can't be called, OK otherwise. |
1480 * Also returns OK when an error was encountered while executing the function. | 1476 * Also returns OK when an error was encountered while executing the function. |
1481 */ | 1477 */ |
1482 int | 1478 int |
1485 int len, // length of "name" or -1 to use strlen() | 1481 int len, // length of "name" or -1 to use strlen() |
1486 typval_T *rettv, // return value goes here | 1482 typval_T *rettv, // return value goes here |
1487 int argcount_in, // number of "argvars" | 1483 int argcount_in, // number of "argvars" |
1488 typval_T *argvars_in, // vars for arguments, must have "argcount" | 1484 typval_T *argvars_in, // vars for arguments, must have "argcount" |
1489 // PLUS ONE elements! | 1485 // PLUS ONE elements! |
1490 int (* argv_func)(int, typval_T *, int), | 1486 funcexe_T *funcexe) // more arguments |
1491 // function to fill in argvars | |
1492 linenr_T firstline, // first line of range | |
1493 linenr_T lastline, // last line of range | |
1494 int *doesrange, // return: function handled range | |
1495 int evaluate, | |
1496 partial_T *partial, // optional, can be NULL | |
1497 dict_T *selfdict_in) // Dictionary for "self" | |
1498 { | 1487 { |
1499 int ret = FAIL; | 1488 int ret = FAIL; |
1500 int error = ERROR_NONE; | 1489 int error = ERROR_NONE; |
1501 int i; | 1490 int i; |
1502 ufunc_T *fp; | 1491 ufunc_T *fp; |
1504 char_u *tofree = NULL; | 1493 char_u *tofree = NULL; |
1505 char_u *fname; | 1494 char_u *fname; |
1506 char_u *name; | 1495 char_u *name; |
1507 int argcount = argcount_in; | 1496 int argcount = argcount_in; |
1508 typval_T *argvars = argvars_in; | 1497 typval_T *argvars = argvars_in; |
1509 dict_T *selfdict = selfdict_in; | 1498 dict_T *selfdict = funcexe->selfdict; |
1510 typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */ | 1499 typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */ |
1511 int argv_clear = 0; | 1500 int argv_clear = 0; |
1501 partial_T *partial = funcexe->partial; | |
1512 | 1502 |
1513 // Make a copy of the name, if it comes from a funcref variable it could | 1503 // Make a copy of the name, if it comes from a funcref variable it could |
1514 // be changed or deleted in the called function. | 1504 // be changed or deleted in the called function. |
1515 name = len > 0 ? vim_strnsave(funcname, len) : vim_strsave(funcname); | 1505 name = len > 0 ? vim_strnsave(funcname, len) : vim_strsave(funcname); |
1516 if (name == NULL) | 1506 if (name == NULL) |
1517 return ret; | 1507 return ret; |
1518 | 1508 |
1519 fname = fname_trans_sid(name, fname_buf, &tofree, &error); | 1509 fname = fname_trans_sid(name, fname_buf, &tofree, &error); |
1520 | 1510 |
1521 *doesrange = FALSE; | 1511 if (funcexe->doesrange != NULL) |
1512 *funcexe->doesrange = FALSE; | |
1522 | 1513 |
1523 if (partial != NULL) | 1514 if (partial != NULL) |
1524 { | 1515 { |
1525 /* When the function has a partial with a dict and there is a dict | 1516 /* When the function has a partial with a dict and there is a dict |
1526 * argument, use the dict argument. That is backwards compatible. | 1517 * argument, use the dict argument. That is backwards compatible. |
1527 * When the dict was bound explicitly use the one from the partial. */ | 1518 * When the dict was bound explicitly use the one from the partial. */ |
1528 if (partial->pt_dict != NULL | 1519 if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto)) |
1529 && (selfdict_in == NULL || !partial->pt_auto)) | |
1530 selfdict = partial->pt_dict; | 1520 selfdict = partial->pt_dict; |
1531 if (error == ERROR_NONE && partial->pt_argc > 0) | 1521 if (error == ERROR_NONE && partial->pt_argc > 0) |
1532 { | 1522 { |
1533 for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear) | 1523 for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear) |
1534 copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]); | 1524 copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]); |
1540 } | 1530 } |
1541 | 1531 |
1542 /* | 1532 /* |
1543 * Execute the function if executing and no errors were detected. | 1533 * Execute the function if executing and no errors were detected. |
1544 */ | 1534 */ |
1545 if (!evaluate) | 1535 if (!funcexe->evaluate) |
1546 { | 1536 { |
1547 // Not evaluating, which means the return value is unknown. This | 1537 // Not evaluating, which means the return value is unknown. This |
1548 // matters for giving error messages. | 1538 // matters for giving error messages. |
1549 rettv->v_type = VAR_UNKNOWN; | 1539 rettv->v_type = VAR_UNKNOWN; |
1550 } | 1540 } |
1588 | 1578 |
1589 if (fp != NULL && (fp->uf_flags & FC_DELETED)) | 1579 if (fp != NULL && (fp->uf_flags & FC_DELETED)) |
1590 error = ERROR_DELETED; | 1580 error = ERROR_DELETED; |
1591 else if (fp != NULL) | 1581 else if (fp != NULL) |
1592 { | 1582 { |
1593 if (argv_func != NULL) | 1583 if (funcexe->argv_func != NULL) |
1594 argcount = argv_func(argcount, argvars, fp->uf_args.ga_len); | 1584 argcount = funcexe->argv_func(argcount, argvars, |
1595 | 1585 fp->uf_args.ga_len); |
1596 if (fp->uf_flags & FC_RANGE) | 1586 |
1597 *doesrange = TRUE; | 1587 if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL) |
1588 *funcexe->doesrange = TRUE; | |
1598 if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) | 1589 if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) |
1599 error = ERROR_TOOFEW; | 1590 error = ERROR_TOOFEW; |
1600 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) | 1591 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) |
1601 error = ERROR_TOOMANY; | 1592 error = ERROR_TOOMANY; |
1602 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) | 1593 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) |
1619 saveRedobuff(&save_redo); | 1610 saveRedobuff(&save_redo); |
1620 did_save_redo = TRUE; | 1611 did_save_redo = TRUE; |
1621 } | 1612 } |
1622 ++fp->uf_calls; | 1613 ++fp->uf_calls; |
1623 call_user_func(fp, argcount, argvars, rettv, | 1614 call_user_func(fp, argcount, argvars, rettv, |
1624 firstline, lastline, | 1615 funcexe->firstline, funcexe->lastline, |
1625 (fp->uf_flags & FC_DICT) ? selfdict : NULL); | 1616 (fp->uf_flags & FC_DICT) ? selfdict : NULL); |
1626 if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) | 1617 if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) |
1627 /* Function was unreferenced while being used, free it | 1618 /* Function was unreferenced while being used, free it |
1628 * now. */ | 1619 * now. */ |
1629 func_clear_free(fp, FALSE); | 1620 func_clear_free(fp, FALSE); |
3110 } | 3101 } |
3111 else | 3102 else |
3112 lnum = eap->line1; | 3103 lnum = eap->line1; |
3113 for ( ; lnum <= eap->line2; ++lnum) | 3104 for ( ; lnum <= eap->line2; ++lnum) |
3114 { | 3105 { |
3106 funcexe_T funcexe; | |
3107 | |
3115 if (!eap->skip && eap->addr_count > 0) | 3108 if (!eap->skip && eap->addr_count > 0) |
3116 { | 3109 { |
3117 if (lnum > curbuf->b_ml.ml_line_count) | 3110 if (lnum > curbuf->b_ml.ml_line_count) |
3118 { | 3111 { |
3119 // If the function deleted lines or switched to another buffer | 3112 // If the function deleted lines or switched to another buffer |
3124 curwin->w_cursor.lnum = lnum; | 3117 curwin->w_cursor.lnum = lnum; |
3125 curwin->w_cursor.col = 0; | 3118 curwin->w_cursor.col = 0; |
3126 curwin->w_cursor.coladd = 0; | 3119 curwin->w_cursor.coladd = 0; |
3127 } | 3120 } |
3128 arg = startarg; | 3121 arg = startarg; |
3129 if (get_func_tv(name, -1, &rettv, &arg, | 3122 |
3130 eap->line1, eap->line2, &doesrange, | 3123 funcexe.argv_func = NULL; |
3131 !eap->skip, partial, fudi.fd_dict) == FAIL) | 3124 funcexe.firstline = eap->line1; |
3125 funcexe.lastline = eap->line2; | |
3126 funcexe.doesrange = &doesrange; | |
3127 funcexe.evaluate = !eap->skip; | |
3128 funcexe.partial = partial; | |
3129 funcexe.selfdict = fudi.fd_dict; | |
3130 if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL) | |
3132 { | 3131 { |
3133 failed = TRUE; | 3132 failed = TRUE; |
3134 break; | 3133 break; |
3135 } | 3134 } |
3136 if (has_watchexpr()) | 3135 if (has_watchexpr()) |