| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2008 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2008 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * NaCl testing shell | 8 * NaCl testing shell |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 arg->tag = NACL_SRPC_ARG_TYPE_INVALID; | 428 arg->tag = NACL_SRPC_ARG_TYPE_INVALID; |
| 429 break; | 429 break; |
| 430 case NACL_SRPC_ARG_TYPE_BOOL: | 430 case NACL_SRPC_ARG_TYPE_BOOL: |
| 431 val = strtol(&token[2], 0, 0); | 431 val = strtol(&token[2], 0, 0); |
| 432 arg->tag = NACL_SRPC_ARG_TYPE_BOOL; | 432 arg->tag = NACL_SRPC_ARG_TYPE_BOOL; |
| 433 arg->u.bval = val; | 433 arg->u.bval = val; |
| 434 break; | 434 break; |
| 435 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: | 435 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: |
| 436 dim = strtol(&token[2], 0, 0); | 436 dim = strtol(&token[2], 0, 0); |
| 437 arg->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY; | 437 arg->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY; |
| 438 arg->u.caval.carr = (char*) calloc(dim, sizeof(char)); | 438 arg->arrays.carr = (char*) calloc(dim, sizeof(char)); |
| 439 if (NULL == arg->u.caval.carr) { | 439 if (NULL == arg->arrays.carr) { |
| 440 return 0; | 440 return 0; |
| 441 } | 441 } |
| 442 arg->u.caval.count = dim; | 442 arg->u.count = dim; |
| 443 comma = strstr(token, ","); | 443 comma = strstr(token, ","); |
| 444 if (comma) { | 444 if (comma) { |
| 445 const char* p = comma + 1; | 445 const char* p = comma + 1; |
| 446 for (i = 0; *p != ')' && i < dim; ++i) { | 446 for (i = 0; *p != ')' && i < dim; ++i) { |
| 447 int ival = ReadOneChar(&p); | 447 int ival = ReadOneChar(&p); |
| 448 if (-1 == ival || ')' == ival) { | 448 if (-1 == ival || ')' == ival) { |
| 449 break; | 449 break; |
| 450 } | 450 } |
| 451 arg->u.caval.carr[i] = ival; | 451 arg->arrays.carr[i] = ival; |
| 452 } | 452 } |
| 453 } | 453 } |
| 454 break; | 454 break; |
| 455 case NACL_SRPC_ARG_TYPE_DOUBLE: | 455 case NACL_SRPC_ARG_TYPE_DOUBLE: |
| 456 arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE; | 456 arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE; |
| 457 arg->u.dval = strtod(&token[2], 0); | 457 arg->u.dval = strtod(&token[2], 0); |
| 458 break; | 458 break; |
| 459 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: | 459 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: |
| 460 dim = strtol(&token[2], 0, 0); | 460 dim = strtol(&token[2], 0, 0); |
| 461 arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY; | 461 arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY; |
| 462 arg->u.daval.darr = (double*) calloc(dim, sizeof(double)); | 462 arg->arrays.darr = (double*) calloc(dim, sizeof(double)); |
| 463 if (NULL == arg->u.daval.darr) { | 463 if (NULL == arg->arrays.darr) { |
| 464 return 0; | 464 return 0; |
| 465 } | 465 } |
| 466 arg->u.daval.count = dim; | 466 arg->u.count = dim; |
| 467 comma = token; | 467 comma = token; |
| 468 for (i = 0; i < dim; ++i) { | 468 for (i = 0; i < dim; ++i) { |
| 469 comma = strstr(comma, ","); | 469 comma = strstr(comma, ","); |
| 470 if (!comma) break; | 470 if (!comma) break; |
| 471 ++comma; | 471 ++comma; |
| 472 arg->u.daval.darr[i] = strtod(comma, 0); | 472 arg->arrays.darr[i] = strtod(comma, 0); |
| 473 } | 473 } |
| 474 break; | 474 break; |
| 475 case NACL_SRPC_ARG_TYPE_HANDLE: | 475 case NACL_SRPC_ARG_TYPE_HANDLE: |
| 476 val = strtol(&token[2], 0, 0); | 476 val = strtol(&token[2], 0, 0); |
| 477 arg->tag = NACL_SRPC_ARG_TYPE_HANDLE; | 477 arg->tag = NACL_SRPC_ARG_TYPE_HANDLE; |
| 478 arg->u.hval = LookupDesc(val); | 478 arg->u.hval = LookupDesc(val); |
| 479 break; | 479 break; |
| 480 case NACL_SRPC_ARG_TYPE_INT: | 480 case NACL_SRPC_ARG_TYPE_INT: |
| 481 val = strtol(&token[2], 0, 0); | 481 val = strtol(&token[2], 0, 0); |
| 482 arg->tag = NACL_SRPC_ARG_TYPE_INT; | 482 arg->tag = NACL_SRPC_ARG_TYPE_INT; |
| 483 arg->u.ival = val; | 483 arg->u.ival = val; |
| 484 break; | 484 break; |
| 485 case NACL_SRPC_ARG_TYPE_INT_ARRAY: | 485 case NACL_SRPC_ARG_TYPE_INT_ARRAY: |
| 486 dim = strtol(&token[2], 0, 0); | 486 dim = strtol(&token[2], 0, 0); |
| 487 arg->tag = NACL_SRPC_ARG_TYPE_INT_ARRAY; | 487 arg->tag = NACL_SRPC_ARG_TYPE_INT_ARRAY; |
| 488 arg->u.iaval.iarr = (int32_t*) calloc(dim, sizeof(int32_t)); | 488 arg->arrays.iarr = (int32_t*) calloc(dim, sizeof(int32_t)); |
| 489 if (NULL == arg->u.iaval.iarr) { | 489 if (NULL == arg->arrays.iarr) { |
| 490 return 0; | 490 return 0; |
| 491 } | 491 } |
| 492 arg->u.iaval.count = dim; | 492 arg->u.count = dim; |
| 493 comma = token; | 493 comma = token; |
| 494 for (i = 0; i < dim; ++i) { | 494 for (i = 0; i < dim; ++i) { |
| 495 comma = strstr(comma, ","); | 495 comma = strstr(comma, ","); |
| 496 if (!comma) break; | 496 if (!comma) break; |
| 497 ++comma; | 497 ++comma; |
| 498 arg->u.iaval.iarr[i] = strtol(comma, 0, 0); | 498 arg->arrays.iarr[i] = strtol(comma, 0, 0); |
| 499 } | 499 } |
| 500 break; | 500 break; |
| 501 case NACL_SRPC_ARG_TYPE_LONG: | 501 case NACL_SRPC_ARG_TYPE_LONG: |
| 502 lval = STRTOLL(&token[2], 0, 0); | 502 lval = STRTOLL(&token[2], 0, 0); |
| 503 arg->tag = NACL_SRPC_ARG_TYPE_LONG; | 503 arg->tag = NACL_SRPC_ARG_TYPE_LONG; |
| 504 arg->u.lval = lval; | 504 arg->u.lval = lval; |
| 505 break; | 505 break; |
| 506 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: | 506 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: |
| 507 /* | 507 /* |
| 508 * dim is the count of the elements in the array, which is a 32-bit value. | 508 * dim is the count of the elements in the array, which is a 32-bit value. |
| 509 */ | 509 */ |
| 510 dim = strtol(&token[2], 0, 0); | 510 dim = strtol(&token[2], 0, 0); |
| 511 arg->tag = NACL_SRPC_ARG_TYPE_LONG_ARRAY; | 511 arg->tag = NACL_SRPC_ARG_TYPE_LONG_ARRAY; |
| 512 arg->u.laval.larr = (int64_t*) calloc(dim, sizeof(int64_t)); | 512 arg->arrays.larr = (int64_t*) calloc(dim, sizeof(int64_t)); |
| 513 if (NULL == arg->u.laval.larr) { | 513 if (NULL == arg->arrays.larr) { |
| 514 return 0; | 514 return 0; |
| 515 } | 515 } |
| 516 arg->u.laval.count = dim; | 516 arg->u.count = dim; |
| 517 comma = token; | 517 comma = token; |
| 518 for (i = 0; i < dim; ++i) { | 518 for (i = 0; i < dim; ++i) { |
| 519 comma = strstr(comma, ","); | 519 comma = strstr(comma, ","); |
| 520 if (!comma) break; | 520 if (!comma) break; |
| 521 ++comma; | 521 ++comma; |
| 522 arg->u.laval.larr[i] = STRTOLL(comma, 0, 0); | 522 arg->arrays.larr[i] = STRTOLL(comma, 0, 0); |
| 523 } | 523 } |
| 524 break; | 524 break; |
| 525 case NACL_SRPC_ARG_TYPE_STRING: | 525 case NACL_SRPC_ARG_TYPE_STRING: |
| 526 arg->tag = NACL_SRPC_ARG_TYPE_STRING; | 526 arg->tag = NACL_SRPC_ARG_TYPE_STRING; |
| 527 /* | 527 /* |
| 528 * This is a conservative estimate of the length, as it includes the | 528 * This is a conservative estimate of the length, as it includes the |
| 529 * quotes and possibly some escape characters. | 529 * quotes and possibly some escape characters. |
| 530 */ | 530 */ |
| 531 arg->u.sval.str = malloc(strlen(token)); | 531 arg->arrays.str = malloc(strlen(token)); |
| 532 if (NULL == arg->u.sval.str) { | 532 if (NULL == arg->arrays.str) { |
| 533 return 0; | 533 return 0; |
| 534 } | 534 } |
| 535 ScanEscapeString(arg->u.sval.str, token + 2); | 535 ScanEscapeString(arg->arrays.str, token + 2); |
| 536 break; | 536 break; |
| 537 /* | 537 /* |
| 538 * The two cases below are added to avoid warnings, they are only used | 538 * The two cases below are added to avoid warnings, they are only used |
| 539 * in the plugin code | 539 * in the plugin code |
| 540 */ | 540 */ |
| 541 case NACL_SRPC_ARG_TYPE_OBJECT: | 541 case NACL_SRPC_ARG_TYPE_OBJECT: |
| 542 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: | 542 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: |
| 543 default: | 543 default: |
| 544 return 0; | 544 return 0; |
| 545 } | 545 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 char* p; | 609 char* p; |
| 610 | 610 |
| 611 switch(arg->tag) { | 611 switch(arg->tag) { |
| 612 case NACL_SRPC_ARG_TYPE_INVALID: | 612 case NACL_SRPC_ARG_TYPE_INVALID: |
| 613 printf("X()"); | 613 printf("X()"); |
| 614 break; | 614 break; |
| 615 case NACL_SRPC_ARG_TYPE_BOOL: | 615 case NACL_SRPC_ARG_TYPE_BOOL: |
| 616 printf("b(%d)", arg->u.bval); | 616 printf("b(%d)", arg->u.bval); |
| 617 break; | 617 break; |
| 618 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: | 618 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: |
| 619 for (i = 0; i < arg->u.caval.count; ++i) | 619 for (i = 0; i < arg->u.count; ++i) |
| 620 PrintOneChar(arg->u.caval.carr[i]); | 620 PrintOneChar(arg->arrays.carr[i]); |
| 621 break; | 621 break; |
| 622 case NACL_SRPC_ARG_TYPE_DOUBLE: | 622 case NACL_SRPC_ARG_TYPE_DOUBLE: |
| 623 printf("d("); | 623 printf("d("); |
| 624 DumpDouble(&arg->u.dval); | 624 DumpDouble(&arg->u.dval); |
| 625 printf(")"); | 625 printf(")"); |
| 626 break; | 626 break; |
| 627 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: | 627 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: |
| 628 count = arg->u.daval.count; | 628 count = arg->u.count; |
| 629 printf("D(%"NACL_PRIu32"", count); | 629 printf("D(%"NACL_PRIu32"", count); |
| 630 for (i = 0; i < count; ++i) { | 630 for (i = 0; i < count; ++i) { |
| 631 printf(","); | 631 printf(","); |
| 632 DumpDouble(&(arg->u.daval.darr[i])); | 632 DumpDouble(&(arg->arrays.darr[i])); |
| 633 } | 633 } |
| 634 printf(")"); | 634 printf(")"); |
| 635 break; | 635 break; |
| 636 case NACL_SRPC_ARG_TYPE_HANDLE: | 636 case NACL_SRPC_ARG_TYPE_HANDLE: |
| 637 printf("h(%d)", AddDescToList(arg->u.hval, "imported")); | 637 printf("h(%d)", AddDescToList(arg->u.hval, "imported")); |
| 638 break; | 638 break; |
| 639 case NACL_SRPC_ARG_TYPE_INT: | 639 case NACL_SRPC_ARG_TYPE_INT: |
| 640 printf("i(%"NACL_PRId32")", arg->u.ival); | 640 printf("i(%"NACL_PRId32")", arg->u.ival); |
| 641 break; | 641 break; |
| 642 case NACL_SRPC_ARG_TYPE_INT_ARRAY: | 642 case NACL_SRPC_ARG_TYPE_INT_ARRAY: |
| 643 count = arg->u.iaval.count; | 643 count = arg->u.count; |
| 644 printf("I(%"NACL_PRIu32"", count); | 644 printf("I(%"NACL_PRIu32"", count); |
| 645 for (i = 0; i < count; ++i) | 645 for (i = 0; i < count; ++i) |
| 646 printf(",%"NACL_PRId32, arg->u.iaval.iarr[i]); | 646 printf(",%"NACL_PRId32, arg->arrays.iarr[i]); |
| 647 printf(")"); | 647 printf(")"); |
| 648 break; | 648 break; |
| 649 case NACL_SRPC_ARG_TYPE_LONG: | 649 case NACL_SRPC_ARG_TYPE_LONG: |
| 650 printf("l(%"NACL_PRId64")", arg->u.lval); | 650 printf("l(%"NACL_PRId64")", arg->u.lval); |
| 651 break; | 651 break; |
| 652 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: | 652 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: |
| 653 count = arg->u.laval.count; | 653 count = arg->u.count; |
| 654 printf("L(%"NACL_PRIu32"", count); | 654 printf("L(%"NACL_PRIu32"", count); |
| 655 for (i = 0; i < count; ++i) | 655 for (i = 0; i < count; ++i) |
| 656 printf(",%"NACL_PRId64, arg->u.laval.larr[i]); | 656 printf(",%"NACL_PRId64, arg->arrays.larr[i]); |
| 657 printf(")"); | 657 printf(")"); |
| 658 break; | 658 break; |
| 659 case NACL_SRPC_ARG_TYPE_STRING: | 659 case NACL_SRPC_ARG_TYPE_STRING: |
| 660 printf("s(\""); | 660 printf("s(\""); |
| 661 for (p = arg->u.sval.str; '\0' != *p; ++p) | 661 for (p = arg->arrays.str; '\0' != *p; ++p) |
| 662 PrintOneChar(*p); | 662 PrintOneChar(*p); |
| 663 printf("\")"); | 663 printf("\")"); |
| 664 break; | 664 break; |
| 665 /* | 665 /* |
| 666 * The two cases below are added to avoid warnings, they are only used | 666 * The two cases below are added to avoid warnings, they are only used |
| 667 * in the plugin code | 667 * in the plugin code |
| 668 */ | 668 */ |
| 669 case NACL_SRPC_ARG_TYPE_OBJECT: | 669 case NACL_SRPC_ARG_TYPE_OBJECT: |
| 670 /* this is a pointer that NaCl module can do nothing with */ | 670 /* this is a pointer that NaCl module can do nothing with */ |
| 671 printf("o(%p)", arg->u.oval); | 671 printf("o(%p)", arg->arrays.oval); |
| 672 break; | 672 break; |
| 673 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: | 673 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: |
| 674 count = arg->u.vaval.count; | 674 count = arg->u.count; |
| 675 printf("A(%"NACL_PRIu32"", count); | 675 printf("A(%"NACL_PRIu32"", count); |
| 676 for (i = 0; i < count; ++i) { | 676 for (i = 0; i < count; ++i) { |
| 677 printf(","); | 677 printf(","); |
| 678 DumpArg(&arg->u.vaval.varr[i]); | 678 DumpArg(&arg->arrays.varr[i]); |
| 679 } | 679 } |
| 680 printf(")"); | 680 printf(")"); |
| 681 break; | 681 break; |
| 682 default: | 682 default: |
| 683 break; | 683 break; |
| 684 } | 684 } |
| 685 } | 685 } |
| 686 | 686 |
| 687 static void DumpArgs(const NaClSrpcArg* arg, int n) { | 687 static void DumpArgs(const NaClSrpcArg* arg, int n) { |
| 688 int i; | 688 int i; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 699 argv[i] = &arg[i]; | 699 argv[i] = &arg[i]; |
| 700 } | 700 } |
| 701 argv[count] = NULL; | 701 argv[count] = NULL; |
| 702 } | 702 } |
| 703 | 703 |
| 704 void FreeArrayArgs(NaClSrpcArg arg[], int count) { | 704 void FreeArrayArgs(NaClSrpcArg arg[], int count) { |
| 705 int i; | 705 int i; |
| 706 for (i = 0; i < count; ++i) { | 706 for (i = 0; i < count; ++i) { |
| 707 switch(arg[i].tag) { | 707 switch(arg[i].tag) { |
| 708 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: | 708 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: |
| 709 free(arg[i].u.caval.carr); | 709 free(arg[i].arrays.carr); |
| 710 break; | 710 break; |
| 711 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: | 711 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: |
| 712 free(arg[i].u.daval.darr); | 712 free(arg[i].arrays.darr); |
| 713 break; | 713 break; |
| 714 case NACL_SRPC_ARG_TYPE_INT_ARRAY: | 714 case NACL_SRPC_ARG_TYPE_INT_ARRAY: |
| 715 free(arg[i].u.iaval.iarr); | 715 free(arg[i].arrays.iarr); |
| 716 break; | 716 break; |
| 717 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: | 717 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: |
| 718 free(arg[i].u.laval.larr); | 718 free(arg[i].arrays.larr); |
| 719 break; | 719 break; |
| 720 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: | 720 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: |
| 721 FreeArrayArgs(arg[i].u.vaval.varr, arg[i].u.vaval.count); | 721 FreeArrayArgs(arg[i].arrays.varr, arg[i].u.count); |
| 722 break; | 722 break; |
| 723 case NACL_SRPC_ARG_TYPE_INVALID: | 723 case NACL_SRPC_ARG_TYPE_INVALID: |
| 724 case NACL_SRPC_ARG_TYPE_BOOL: | 724 case NACL_SRPC_ARG_TYPE_BOOL: |
| 725 case NACL_SRPC_ARG_TYPE_DOUBLE: | 725 case NACL_SRPC_ARG_TYPE_DOUBLE: |
| 726 case NACL_SRPC_ARG_TYPE_HANDLE: | 726 case NACL_SRPC_ARG_TYPE_HANDLE: |
| 727 case NACL_SRPC_ARG_TYPE_INT: | 727 case NACL_SRPC_ARG_TYPE_INT: |
| 728 case NACL_SRPC_ARG_TYPE_LONG: | 728 case NACL_SRPC_ARG_TYPE_LONG: |
| 729 case NACL_SRPC_ARG_TYPE_STRING: | 729 case NACL_SRPC_ARG_TYPE_STRING: |
| 730 case NACL_SRPC_ARG_TYPE_OBJECT: | 730 case NACL_SRPC_ARG_TYPE_OBJECT: |
| 731 default: | 731 default: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 755 printf(" ?\n"); | 755 printf(" ?\n"); |
| 756 printf(" print this menu\n"); | 756 printf(" print this menu\n"); |
| 757 /* TODO(sehr,robertm): we should have a syntax description option */ | 757 /* TODO(sehr,robertm): we should have a syntax description option */ |
| 758 } | 758 } |
| 759 | 759 |
| 760 static void UpcallString(NaClSrpcRpc* rpc, | 760 static void UpcallString(NaClSrpcRpc* rpc, |
| 761 NaClSrpcArg** ins, | 761 NaClSrpcArg** ins, |
| 762 NaClSrpcArg** outs, | 762 NaClSrpcArg** outs, |
| 763 NaClSrpcClosure* done) { | 763 NaClSrpcClosure* done) { |
| 764 UNREFERENCED_PARAMETER(outs); | 764 UNREFERENCED_PARAMETER(outs); |
| 765 printf("UpcallString: called with '%s'\n", ins[0]->u.sval.str); | 765 printf("UpcallString: called with '%s'\n", ins[0]->arrays.str); |
| 766 rpc->result = NACL_SRPC_RESULT_OK; | 766 rpc->result = NACL_SRPC_RESULT_OK; |
| 767 done->Run(done); | 767 done->Run(done); |
| 768 } | 768 } |
| 769 | 769 |
| 770 static char* BuildSignature(const char* name, | 770 static char* BuildSignature(const char* name, |
| 771 NaClSrpcArg** inputs, | 771 NaClSrpcArg** inputs, |
| 772 NaClSrpcArg** outputs) { | 772 NaClSrpcArg** outputs) { |
| 773 char* buffer; | 773 char* buffer; |
| 774 size_t i; | 774 size_t i; |
| 775 size_t current_offset; | 775 size_t current_offset; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 free(service); | 999 free(service); |
| 1000 return 0; | 1000 return 0; |
| 1001 } | 1001 } |
| 1002 /* | 1002 /* |
| 1003 * TODO(sehr): Add the descriptor for the default socket address | 1003 * TODO(sehr): Add the descriptor for the default socket address |
| 1004 * message processing loop. | 1004 * message processing loop. |
| 1005 */ | 1005 */ |
| 1006 NaClSrpcCommandLoop(service, NULL, Interpreter, kNaClSrpcInvalidImcDesc); | 1006 NaClSrpcCommandLoop(service, NULL, Interpreter, kNaClSrpcInvalidImcDesc); |
| 1007 return 1; | 1007 return 1; |
| 1008 } | 1008 } |
| OLD | NEW |