@@ -1864,13 +1864,20 @@ CpcVm.prototype = {
18641864 } ,
18651865
18661866 instr : function ( p1 , p2 , p3 ) { // optional startpos as first parameter
1867- this . vmAssertString ( p2 , "INSTR" ) ;
1868- if ( typeof p1 === "string" ) { // p1=string, p2=search string
1869- return p1 . indexOf ( p2 ) + 1 ;
1867+ var startPos = typeof p1 === "number" ? this . vmInRangeRound ( p1 , 1 , 255 , "INSTR" ) - 1 : 0 , // p1=startpos
1868+ str = typeof p1 === "number" ? p2 : p1 ,
1869+ search = typeof p1 === "number" ? p3 : p2 ;
1870+
1871+ this . vmAssertString ( str , "INSTR" ) ;
1872+ this . vmAssertString ( search , "INSTR" ) ;
1873+
1874+ if ( startPos >= str . length ) {
1875+ return 0 ; // not found
1876+ }
1877+ if ( ! search . length ) {
1878+ return startPos + 1 ;
18701879 }
1871- p1 = this . vmInRangeRound ( p1 , 1 , 255 , "INSTR" ) ; // p1=startpos
1872- this . vmAssertString ( p3 , "INSTR" ) ;
1873- return p2 . indexOf ( p3 , p1 - 1 ) + 1 ; // p2=string, p3=search string
1880+ return str . indexOf ( search , startPos ) + 1 ;
18741881 } ,
18751882
18761883 "int" : function ( n ) {
@@ -3104,11 +3111,19 @@ CpcVm.prototype = {
31043111 } ,
31053112
31063113 round : function ( n , iDecimals ) {
3114+ var iMaxDecimals = 20 - Math . floor ( Math . log10 ( n ) ) ; // limit for JS
3115+
31073116 this . vmAssertNumber ( n , "ROUND" ) ;
31083117 iDecimals = this . vmInRangeRound ( iDecimals || 0 , - 39 , 39 , "ROUND" ) ;
31093118
3119+ if ( iDecimals >= 0 && iDecimals > iMaxDecimals ) {
3120+ iDecimals = iMaxDecimals ;
3121+ }
3122+
31103123 // To avoid rounding errors: https://www.jacklmoore.com/notes/rounding-in-javascript
3111- return Number ( Math . round ( Number ( n + "e" + iDecimals ) ) + "e" + ( ( iDecimals >= 0 ) ? "-" + iDecimals : "+" + - iDecimals ) ) ;
3124+ // Use Math.abs(n) and Math.sign(n) To round negative numbers to larger negative numbers
3125+ return Math . sign ( n ) * Number ( Math . round ( Number ( Math . abs ( n ) + "e" + iDecimals ) ) + "e" + ( ( iDecimals >= 0 ) ? "-" + iDecimals : "+" + - iDecimals ) ) ;
3126+ //return Number(Math.round(Number(n + "e" + iDecimals)) + "e" + ((iDecimals >= 0) ? "-" + iDecimals : "+" + -iDecimals));
31123127 } ,
31133128
31143129 vmRunCallback : function ( sInput , oMeta ) {
@@ -3470,22 +3485,44 @@ CpcVm.prototype = {
34703485 } ,
34713486
34723487 using : function ( sFormat ) { // varargs
3473- var reFormat = / ( ! | & | \\ * \\ | (?: \* \* | \$ \$ | \* \* \$ ) ? \+ ? (?: # | , ) + \. ? # * (?: \^ \^ \^ \^ ) ? [ + - ] ? ) / g,
3488+ var reFormat = / ( _ | ! | & | \\ * \\ | (?: \* \* | \$ \$ | \* \* \$ ) ? \+ ? (?: # | , ) + \. ? # * (?: \^ \^ \^ \^ ) ? [ + - ] ? ) / g,
34743489 s = "" ,
34753490 aFormat = [ ] ,
3476- iIndex , oMatch , sFrmt , iFormat , i , arg ;
3491+ iIndex , aMatch , sFrmt , iFormat , i , arg , nonFormChars , nonFormCharsEnd ;
34773492
34783493 this . vmAssertString ( sFormat , "USING" ) ;
34793494
34803495 // We simulate sFormat.split(reFormat) here since it does not work with IE8
34813496 iIndex = 0 ;
3482- while ( ( oMatch = reFormat . exec ( sFormat ) ) !== null ) {
3483- aFormat . push ( sFormat . substring ( iIndex , oMatch . index ) ) ; // non-format characters at the beginning
3484- aFormat . push ( oMatch [ 0 ] ) ;
3485- iIndex = oMatch . index + oMatch [ 0 ] . length ;
3497+ while ( ( aMatch = reFormat . exec ( sFormat ) ) !== null ) {
3498+ nonFormChars = sFormat . substring ( iIndex , aMatch . index ) ; // non-format characters at the beginning
3499+
3500+ if ( aMatch [ 0 ] === "_" ) { // underscore "_" is escape character
3501+ nonFormChars += sFormat . charAt ( aMatch . index + 1 ) || "_" ; // add escaped character
3502+ }
3503+
3504+ if ( aFormat . length % 2 ) { // odd?
3505+ aFormat [ aFormat . length - 1 ] += nonFormChars ;
3506+ } else {
3507+ aFormat . push ( nonFormChars ) ;
3508+ }
3509+
3510+ if ( aMatch [ 0 ] === "_" ) { // underscore "_" is escape character
3511+ reFormat . lastIndex += 1 ;
3512+ iIndex = reFormat . lastIndex ;
3513+ } else {
3514+ aFormat . push ( aMatch [ 0 ] ) ;
3515+ iIndex = aMatch . index + aMatch [ 0 ] . length ;
3516+ }
34863517 }
34873518 if ( iIndex < sFormat . length ) { // non-format characters at the end
3488- aFormat . push ( sFormat . substr ( iIndex ) ) ;
3519+ nonFormCharsEnd = sFormat . substring ( iIndex ) ;
3520+
3521+ if ( aFormat . length % 2 ) { // odd?
3522+ aFormat [ aFormat . length - 1 ] += nonFormCharsEnd ;
3523+ } else {
3524+ aFormat . push ( nonFormCharsEnd ) ;
3525+ }
34893526 }
34903527
34913528 if ( aFormat . length < 2 ) {
0 commit comments